diff --git a/public/images/device/button.png b/public/images/device/instance/button.png similarity index 100% rename from public/images/device/button.png rename to public/images/device/instance/button.png diff --git a/src/api/device/instance.ts b/src/api/device/instance.ts index b1d01908..ceb17116 100644 --- a/src/api/device/instance.ts +++ b/src/api/device/instance.ts @@ -120,3 +120,50 @@ export const update = (data: Partial) => data.id ? server.patch( * @returns */ export const getConfigMetadata = (id: string) => server.get(`/device-instance/${id}/config-metadata`) + +/** + * 断开连接 + * @param id 设备id + * @returns + */ +export const _disconnect = (id: string) => server.post(`/device-instance/${id}/disconnect`) + +/** + * 查询用户列表 + * @returns + */ +export const queryUserListNoPaging = () => server.post(`/user/_query/no-paging`, { + paging: false, + sorts: [{name: 'name', order: "asc"}] +}) + +/** + * 保存设备关系 + * @param id 设备id + * @param data + * @returns + */ +export const saveRelations = (id: string, data: Record) => server.patch(`/device/instance/${id}/relations`, data) + +/** + * 修改标签 + * @param id 设备id + * @param data + * @returns + */ +export const saveTags = (id: string, data: Record) => server.patch(`/device/instance/${id}/tag`, data) + +/** + * 删除标签 + * @param deviceId 设备id + * @param id 标签id + * @returns + */ +export const delTags = (deviceId: string, id: string) => server.remove(`/device/instance/${deviceId}/tag/${id}`) + +/** + * 恢复默认配置 + * @param deviceId 设备id + * @returns + */ +export const configurationReset = (deviceId: string) => server.put(`/device-instance/${deviceId}/configuration/_reset`) \ No newline at end of file diff --git a/src/api/device/product.ts b/src/api/device/product.ts index 6ae11030..9d29476b 100644 --- a/src/api/device/product.ts +++ b/src/api/device/product.ts @@ -108,7 +108,7 @@ export const deleteProduct = (id: string) => server.patch(`/device-product/${id} * 检测产品Id唯一性 * @param id 产品ID */ - export const queryProductId = (id: string) => server.post(`/device-product/${id}/exists`) + export const queryProductId = (id: string) => server.get(`/device-product/${id}/exists`) /** * 保存产品 * @param data 产品信息 diff --git a/src/api/initHome.ts b/src/api/initHome.ts index 658a3394..daf6d767 100644 --- a/src/api/initHome.ts +++ b/src/api/initHome.ts @@ -1,7 +1,7 @@ import server from '@/utils/request'; // 更新全部菜单 -export const updateMenus = (data: any) => server.path(`/menu/iot/_all`, data) +export const updateMenus = (data: any) => server.patch(`/menu/iot/_all`, data) // 添加角色 export const addRole = (data: any) => server.post(`/role`, data) diff --git a/src/api/iot-card/cardManagement.ts b/src/api/iot-card/cardManagement.ts index 51a77294..0a4f53d5 100644 --- a/src/api/iot-card/cardManagement.ts +++ b/src/api/iot-card/cardManagement.ts @@ -97,4 +97,40 @@ export const _import = (configId: any, params: any) => server.get(`/network/card * @param format 类型 xlsx、csv * @param params */ -export const _export = (format: string, data: any) => server.post(`/network/card/download.${format}/_query`, data, 'blob'); \ No newline at end of file +export const _export = (format: string, data: any) => server.post(`/network/card/download.${format}/_query`, data, 'blob'); + +/** + * 验证iccid + * @param id + */ +export const validateId = (id: string) => server.get(`/network/card/id/_validate?id=${id}`); + +/** + * 新增物联卡 + * @param data + */ +export const add = (data: any) => server.patch(`/network/card`, data); + +/** + * 编辑物联卡 + * @param data + */ +export const edit = (data: any) => server.put(`/network/card/${data.id}`, data); + +/** + * 根据id查看详情 + * @param id + */ +export const queryDetail = (id: any) => server.get(`/network/card/${id}`); + +/** + * 查询物联卡充值缴费日志 + * @param data + */ +export const queryRechargeList = (data: any) => server.post(`/network/card/recharge/_log`, data) + +/** + * 充值 + * @param data + */ +export const recharge = (data: any) => server.post(`/network/card/_recharge`, data) \ No newline at end of file diff --git a/src/components/CardBox/index.vue b/src/components/CardBox/index.vue index cb958ce7..0915064a 100644 --- a/src/components/CardBox/index.vue +++ b/src/components/CardBox/index.vue @@ -231,6 +231,13 @@ const handleClick = () => { :deep(.card-item-content-title) { cursor: pointer; + font-size: 16px; + font-weight: 700; + color: @primary-color; + width: calc(100% - 100px); + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; } :deep(.card-item-heard-name) { diff --git a/src/components/Layout/BasicLayoutPage.vue b/src/components/Layout/BasicLayoutPage.vue index 054f54ad..ebc3adc4 100644 --- a/src/components/Layout/BasicLayoutPage.vue +++ b/src/components/Layout/BasicLayoutPage.vue @@ -21,6 +21,7 @@ import { ProLayout } from '@/components/Layout' import DefaultSetting from '../../../config/config' import { useMenuStore } from '@/store/menu' +import { clearMenuItem } from 'components/Layout/utils' type StateType = { collapsed: boolean @@ -39,7 +40,7 @@ const layoutConf = reactive({ siderWidth: DefaultSetting.layout.siderWidth, logo: DefaultSetting.layout.logo, title: DefaultSetting.layout.title, - menuData: menu.menus, + menuData: clearMenuItem(menu.siderMenus), }); const state = reactive({ diff --git a/src/components/Layout/components/Header/index.tsx b/src/components/Layout/components/Header/index.tsx index c4bfc014..a804a3a2 100644 --- a/src/components/Layout/components/Header/index.tsx +++ b/src/components/Layout/components/Header/index.tsx @@ -32,7 +32,7 @@ export const HeaderView = defineComponent({ height: `${headerHeight.value}px`, lineHeight: `${headerHeight.value}px`, width: `100%`, - + background: 'transparent' }} /> { automaticLayout: true, scrollBeyondLastLine: false, theme: props.theme, // 主题色: vs(默认高亮), vs-dark(黑色), hc-black(高亮黑色) + formatOnPaste: true, }); instance.onDidChangeModelContent(() => { diff --git a/src/components/Table/index.tsx b/src/components/Table/index.tsx index 1a37be86..fb778495 100644 --- a/src/components/Table/index.tsx +++ b/src/components/Table/index.tsx @@ -333,7 +333,7 @@ const JTable = defineComponent({ total={total.value} showQuickJumper={false} showSizeChanger={true} - current={pageIndex.value} + current={pageIndex.value + 1} pageSize={pageSize.value} pageSizeOptions={['12', '24', '48', '60', '100']} showTotal={(num) => { @@ -345,7 +345,7 @@ const JTable = defineComponent({ handleSearch({ ...props.params, pageSize: size, - pageIndex: pageSize.value === size ? page : 0 + pageIndex: pageSize.value === size ? (page ? page - 1 : 0) : 0 }) }} /> diff --git a/src/main.ts b/src/main.ts index c69804cf..8452514e 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,17 +1,14 @@ import { createApp } from 'vue' import App from './App.vue' import store from './store' -import router from './router' import components from './components' +import router from './router' import './style.less' import 'ant-design-vue/es/notification/style/css'; -import Antd from 'ant-design-vue/es' const app = createApp(App) app.use(store) -app.use(router) -app.use(components) -app.use(Antd) - -app.mount('#app') + .use(router) + .use(components) + .mount('#app') diff --git a/src/router/index.ts b/src/router/index.ts index 91ae60a0..abe29a44 100644 --- a/src/router/index.ts +++ b/src/router/index.ts @@ -3,6 +3,8 @@ import menus, { LoginPath } from './menu' import { cleanToken, getToken } from '@/utils/comm' import { useUserInfo } from '@/store/userInfo' import { useSystem } from '@/store/system' +import NotFindPage from '@/views/404.vue' +import { useMenuStore } from 'store/menu' const router = createRouter({ history: createWebHashHistory(), @@ -27,22 +29,23 @@ router.beforeEach((to, from, next) => { } else { const userInfo = useUserInfo() const system = useSystem() + const menu = useMenuStore() - if (!userInfo.userInfos.username) { + if (!menu.menuData.length) { userInfo.getUserInfo().then(() => { system.getSystemVersion().then((menuData: any[]) => { menuData.forEach(r => { - router.addRoute('main', r) + router.addRoute('base', r) }) - const redirect = decodeURIComponent((from.query.redirect as string) || to.path) - if(to.path === redirect) { - next({ ...to, replace: true }) - } else { - next({ path: redirect }) - } + router.addRoute('base',{ + path: '/:pathMatch(.*)', + name: 'error', + component: () => NotFindPage + }) + + next({ ...to, replace: true }) }) }).catch(() => { - console.log('userInfo', userInfo) cleanToken() next({ path: LoginPath }) }) diff --git a/src/router/menu.ts b/src/router/menu.ts index 234bcabf..2a043f4f 100644 --- a/src/router/menu.ts +++ b/src/router/menu.ts @@ -1,24 +1,7 @@ export const LoginPath = '/login' export default [ - // { - // path: '/', - // redirect: LoginPath - // }, - // { - // path: '/init', - // component: () => import('@/view/InitPage.vue') - // }, - // { - // path: LoginPath, - // name: 'login', - // component: () => import('@/view/Login/index.vue') - // }, - // { - // path: '/initsetting', - // component: () => import('@/view/Login/initSet.vue') - // } - + { path: '/*', redirect: '/'}, // start: 测试用, 可删除 { path: '/login', @@ -32,10 +15,6 @@ export default [ path: '/account/center/bind', component: () => import('@/views/account/Center/bind/index.vue') }, - { - path: '/iot/home', - component: () => import('@/views/home/index.vue') - }, { path: '/table', component: () => import('@/views/demo/table/index.vue') @@ -48,121 +27,13 @@ export default [ path: '/search', component: () => import('@/views/demo/Search.vue') }, - { - path: '/notice/Config', - component: () => import('@/views/notice/Config/index.vue') - }, - { - path: '/notice/Config/detail/:id', - component: () => import('@/views/notice/Config/Detail/index.vue') - }, - { - path: '/notice/Template', - component: () => import('@/views/notice/Template/index.vue') - }, - { - path: '/notice/Template/detail/:id', - component: () => import('@/views/notice/Template/Detail/index.vue') - }, + // end: 测试用, 可删除 - // 设备管理 - { - path: '/device/instance', - component: () => import('@/views/device/Instance/index.vue') - }, - { - // path: '/device/Instance/detail/:id', - // component: () => import('@/views/device/Instance/detail.vue') - path: '/device/instance/detail/:id', - component: () => import('@/views/device/Instance/Detail/index.vue') - }, - // link 运维管理 - { - path: '/link/log', - component: () => import('@/views/link/Log/index.vue') - }, - { - path: '/link/certificate', - component: () => import('@/views/link/Certificate/index.vue') - }, - { - path: '/link/certificate/detail/:type/:id', - component: () => import('@/views/link/Certificate/Detail/index.vue') - }, - { - path: '/link/accessConfig', - component: () => import('@/views/link/AccessConfig/index.vue') - }, - { - path: '/link/accessConfig/detail/add', - component: () => import('@/views/link/AccessConfig/Detail/index.vue') - }, - // system 系统管理 - { - path:'/system/Basis', - component: ()=>import('@/views/system/Basis/index.vue') - }, - { - path:'/system/api', - component: ()=>import('@/views/system/apiPage/index.vue') - }, - { - path:'/system/Role', - component: ()=>import('@/views/system/Role/index.vue') - }, - { - path:'/system/Role/detail/:id', - component: ()=>import('@/views/system/Role/Detail/index.vue') - }, - { - path:'/system/Permission', - component: ()=>import('@/views/system/Permission/index.vue') - }, - { - path:'/system/Menu', - component: ()=>import('@/views/system/Menu/index.vue') - }, - { - path:'/system/Menu/detail/:id', - component: ()=>import('@/views/system/Menu/Detail/index.vue') - }, // 初始化 { path: '/init-home', component: () => import('@/views/init-home/index.vue') }, - // 物联卡 iot-card - { - path: '/iot-card/Home', - component: () => import('@/views/iot-card/Home/index.vue') - }, - { - path: '/iot-card/Dashboard', - component: () => import('@/views/iot-card/Dashboard/index.vue') - }, - { - path: '/iot-card/CardManagement', - component: () => import('@/views/iot-card/CardManagement/index.vue') - }, - // 北向输出 - { - path: '/northbound/DuerOS', - component: () => import('@/views/northbound/DuerOS/index.vue') - }, - { - path: '/northbound/AliCloud', - component: () => import('@/views/northbound/AliCloud/index.vue') - }, - // 产品分类 - { - path: '/iot/device/Category', - component: () => import('@/views/device/Category/index.vue') - } , - // 产品 - { - path: '/iot/device/Product', - component: () => import('@/views/device/Product/index.vue') - } ] \ No newline at end of file diff --git a/src/store/menu.ts b/src/store/menu.ts index 42f1946d..7d1a675e 100644 --- a/src/store/menu.ts +++ b/src/store/menu.ts @@ -1,11 +1,14 @@ import { defineStore } from "pinia"; import { queryOwnThree } from '@/api/system/menu' import { filterAsnycRouter } from '@/utils/menu' +import { cloneDeep } from 'lodash-es' export const useMenuStore = defineStore({ id: 'menu', state: () => ({ menus: {}, + menuData: [], + siderMenus: [], menusKey: [] }), getters: { @@ -51,7 +54,8 @@ export const useMenuStore = defineStore({ ]; const resp = await queryOwnThree({ paging: false, terms: params }) if (resp.success) { - const menus = filterAsnycRouter(resp.result) + const silderMenus = filterAsnycRouter(cloneDeep(resp.result)) + const menus = filterAsnycRouter(cloneDeep(resp.result)) menus.push({ path: '/', redirect: menus[0]?.path, @@ -59,7 +63,9 @@ export const useMenuStore = defineStore({ hideInMenu: true } }) - this.menus = menus + this.menuData = menus + this.siderMenus = silderMenus + console.log('silderMenus', silderMenus) res(menus) } }) diff --git a/src/utils/menu.ts b/src/utils/menu.ts index 22230e84..2907f1c2 100644 --- a/src/utils/menu.ts +++ b/src/utils/menu.ts @@ -1,11 +1,99 @@ -const pagesComponent = import.meta.glob('../views/system/**/*.vue', { eager: true }); +const pagesComponent = import.meta.glob('../views/**/*.vue', { eager: true }); import { BlankLayoutPage, BasicLayoutPage } from 'components/Layout' -type ExtraRouteItem = { - code: string - name: string - url?: string -} +/** + * 权限信息 + */ +export type PermissionInfo = { + permission: string; + actions: string[]; +}; + +/** + * 按钮信息 + */ +export type MenuButtonInfo = { + id: string; + name: string; + permissions: PermissionInfo; + createTime: number; + describe?: string; + options: Record; +}; + + +export type MenuItem = { + id: string; + /** + * 名称 + */ + name: string; + /** + * 编码 + */ + code: string; + /** + * 所属应用 + */ + application: string; + /** + * 描述 + */ + describe: string; + /** + * url,路由 + */ + url: string; + /** + * 图标 + */ + icon: string; + /** + * 状态, 0为禁用,1为启用 + */ + status: number; + /** + * 绑定权限信息 + */ + permissions: PermissionInfo[]; + /** + * 按钮定义信息 + */ + buttons: MenuButtonInfo[]; + /** + * 其他配置信息 + */ + options: Record; + /** + * 父级ID + */ + parentId: string; + /** + * 树结构路径 + */ + path: string; + /** + * 排序序号 + */ + sortIndex: number; + /** + * 树层级 + */ + level: number; + createTime: number; + redirect?: string; + children?: MenuItem[]; + accessSupport?: { text: string; value: string }; + appId?: string; //应用id + isShow?: boolean; + meta?: { + title?: string + icon?: string + [key: string]: any + }, + component?: any +}; + // 额外子级路由 const extraRouteObj = { 'media/Cascade': { @@ -59,53 +147,82 @@ const extraRouteObj = { const resolveComponent = (name: any) => { - // TODO 暂时用system进行测试 const importPage = pagesComponent[`../views/${name}/index.vue`]; - // if (!importPage) { - // throw new Error(`Unknown page ${name}. Is it located under Pages with a .vue extension?`); - // } - + if (!importPage) { + console.warn(`Unknown page ${name}. Is it located under Pages with a .vue extension?`) + } //@ts-ignore - return !importPage ? BlankLayoutPage : importPage.default - // return importPage.default + return !!importPage ? importPage.default : undefined } -const findChildrenRoute = (code: string, url: string): ExtraRouteItem[] => { +const findChildrenRoute = (code: string, url: string): MenuItem[] => { if (extraRouteObj[code]) { - return extraRouteObj[code].children.map((route: ExtraRouteItem) => { + return extraRouteObj[code].children.map((route: MenuItem) => { return { url: `${url}/${route.code}`, code: route.code, - name: route.name + name: route.name, + isShow: false } }) } return [] } +const findDetailRouteItem = (code: string, url: string): Partial | null => { + const detailComponent = resolveComponent(`${code}/Detail`) + if (detailComponent) { + return { + url: `${url}/Detail/:id`, + component: detailComponent, + name: '详情信息', + isShow: false + } + } + return null +} + +const findDetailRoutes = (routes: any[]): any[] => { + const newRoutes: any[] = [] + routes.forEach((route: any) => { + newRoutes.push(route) + const detail = findDetailRouteItem(route.code, route.url) + if (detail) { + newRoutes.push(detail) + } + }) + return newRoutes +} + export function filterAsnycRouter(asyncRouterMap: any, parentCode = '', level = 1) { + return asyncRouterMap.map((route: any) => { route.path = `${route.url}` route.meta = { icon: route.icon, - title: route.name + title: route.name, + hideInMenu: route.isShow === false } // 查看是否有隐藏子路由 - route.children = route.children && route.children.length ? [...route.children, ...findChildrenRoute(route.code, route.url)] : findChildrenRoute(route.code, route.url) - - // TODO 查看是否具有详情页 - // route.children = [...route.children, ] - + const extraChildren = findChildrenRoute(route.code, route.url) + route.children = route.children && route.children.length ? [...route.children, ...extraChildren] : extraChildren + route.children = findDetailRoutes(route.children) if (route.children && route.children.length) { - route.component = () => level === 1 ? BasicLayoutPage : BlankLayoutPage + // TODO 查看是否具有详情页 route.children = filterAsnycRouter(route.children, `${parentCode}/${route.code}`, level + 1) - route.redirect = route.children[0].url + const showChildren = route.children.some((r: any) => !r.meta.hideInMenu) + if (showChildren) { + route.component = () => level === 1 ? BasicLayoutPage : BlankLayoutPage + route.redirect = route.children[0].url + } else { + route.component = resolveComponent(route.code) || BlankLayoutPage; + } } else { - route.component = resolveComponent(route.code); + route.component = resolveComponent(route.code) || BlankLayoutPage; } - console.log(route.code, route) + delete route.name return route }) } \ No newline at end of file diff --git a/src/utils/regular.ts b/src/utils/regular.ts index 9d88336f..7e7fa9cc 100644 --- a/src/utils/regular.ts +++ b/src/utils/regular.ts @@ -1,4 +1,10 @@ // 用于校验 url export const urlReg = /(((^https?:(?:\/\/)?)(?:[-;:&=\+\$,\w]+@)?[A-Za-z0-9.-]+(?::\d+)?|(?:www.|[-;:&=\+\$,\w]+@)[A-Za-z0-9.-]+)((?:\/[\+~%\/.\w-_]*)?\??(?:[-\+=&;%@.\w_]*)#?(?:[\w]*))?)$/; -export const isUrl = (path: string): boolean => urlReg.test(path) \ No newline at end of file +export const isUrl = (path: string): boolean => urlReg.test(path) + +// 用于校验只允许输入英文或者数字或者-或者_ + +export const inputReg = /^[a-zA-Z0-9_\-]+$/ + +export const isInput = (value: string) => inputReg.test(value) \ No newline at end of file diff --git a/src/views/404.vue b/src/views/404.vue new file mode 100644 index 00000000..7794d959 --- /dev/null +++ b/src/views/404.vue @@ -0,0 +1,14 @@ + + + + + \ No newline at end of file diff --git a/src/views/device/Instance/Detail/Info/components/Config/index.vue b/src/views/device/Instance/Detail/Info/components/Config/index.vue index f22eabaa..4d7b0d78 100644 --- a/src/views/device/Instance/Detail/Info/components/Config/index.vue +++ b/src/views/device/Instance/Detail/Info/components/Config/index.vue @@ -4,8 +4,12 @@
配置
编辑 - 应用配置 - 恢复默认 + + 应用配置 + + + 恢复默认 + @@ -28,7 +32,8 @@ \ No newline at end of file diff --git a/src/views/device/Instance/Detail/Info/components/Relation/Save.vue b/src/views/device/Instance/Detail/Info/components/Relation/Save.vue new file mode 100644 index 00000000..bf7db937 --- /dev/null +++ b/src/views/device/Instance/Detail/Info/components/Relation/Save.vue @@ -0,0 +1,125 @@ + + + \ No newline at end of file diff --git a/src/views/device/Instance/Detail/Info/components/Relation/index.vue b/src/views/device/Instance/Detail/Info/components/Relation/index.vue index 2fa91436..293fddd2 100644 --- a/src/views/device/Instance/Detail/Info/components/Relation/index.vue +++ b/src/views/device/Instance/Detail/Info/components/Relation/index.vue @@ -7,17 +7,27 @@ {{ item?.related ? (item?.related || []).map(i => i.name).join(',') : '' }} + diff --git a/src/views/device/Instance/Detail/Info/components/Tags/Save.vue b/src/views/device/Instance/Detail/Info/components/Tags/Save.vue new file mode 100644 index 00000000..dafe416a --- /dev/null +++ b/src/views/device/Instance/Detail/Info/components/Tags/Save.vue @@ -0,0 +1,117 @@ + + + \ No newline at end of file diff --git a/src/views/device/Instance/Detail/Info/components/Tags/index.vue b/src/views/device/Instance/Detail/Info/components/Tags/index.vue index b672f699..f197d60f 100644 --- a/src/views/device/Instance/Detail/Info/components/Tags/index.vue +++ b/src/views/device/Instance/Detail/Info/components/Tags/index.vue @@ -1,3 +1,34 @@ \ No newline at end of file +
+ + + {{ item?.value }} + + +
+ + + diff --git a/src/views/device/Instance/Detail/index.vue b/src/views/device/Instance/Detail/index.vue index b4c055b5..d9f2f0e5 100644 --- a/src/views/device/Instance/Detail/index.vue +++ b/src/views/device/Instance/Detail/index.vue @@ -1,7 +1,40 @@ @@ -9,9 +42,18 @@ import { useInstanceStore } from '@/store/instance'; import Info from './Info/index.vue'; import Metadata from '../../components/Metadata/index.vue'; +import { _deploy, _disconnect } from '@/api/device/instance' +import { message } from 'ant-design-vue'; +import { getImage } from '@/utils/comm'; + const route = useRoute(); const instanceStore = useInstanceStore() +const statusMap = new Map(); +statusMap.set('online', 'processing'); +statusMap.set('offline', 'error'); +statusMap.set('notActive', 'warning'); + const list = [ { key: 'Info', @@ -46,4 +88,35 @@ const onBack = () => { const onTabChange = (e: string) => { instanceStore.tabActiveKey = e } + +const handleAction = async () => { + if(instanceStore.current.id){ + const resp = await _deploy(instanceStore.current.id) + if(resp.status === 200){ + message.success('操作成功!') + instanceStore.refresh(instanceStore.current.id) + } + } +} + +const handleDisconnect = async () => { + if(instanceStore.current.id){ + const resp = await _disconnect(instanceStore.current.id) + if(resp.status === 200){ + message.success('操作成功!') + instanceStore.refresh(instanceStore.current.id) + } + } +} + +const handleRefresh = async () => { + if(instanceStore.current.id){ + await instanceStore.refresh(instanceStore.current.id) + message.success('操作成功') + } +} + +const jumpProduct = () => { + message.warn('暂未开发') +} \ No newline at end of file diff --git a/src/views/device/Instance/index.vue b/src/views/device/Instance/index.vue index fb842bec..11656160 100644 --- a/src/views/device/Instance/index.vue +++ b/src/views/device/Instance/index.vue @@ -1,4 +1,5 @@ @@ -176,8 +177,8 @@ + diff --git a/src/views/iot-card/CardManagement/Save.vue b/src/views/iot-card/CardManagement/Save.vue new file mode 100644 index 00000000..9e62a69f --- /dev/null +++ b/src/views/iot-card/CardManagement/Save.vue @@ -0,0 +1,246 @@ + + + diff --git a/src/views/iot-card/CardManagement/index.vue b/src/views/iot-card/CardManagement/index.vue index 3cf85c36..1ac18f80 100644 --- a/src/views/iot-card/CardManagement/index.vue +++ b/src/views/iot-card/CardManagement/index.vue @@ -151,11 +151,18 @@ {{ slotProps.totalFlow }} - M 使用流量 + + M 使用流量
-
{{ slotProps.totalFlow - slotProps.usedFlow }} %
+
+ {{ + slotProps.totalFlow - slotProps.usedFlow + }} + % +
总共 {{ slotProps.totalFlow }} M
@@ -163,7 +170,9 @@
@@ -307,6 +316,13 @@ :cardId="cardId" @change="bindDevice" /> + +
@@ -333,6 +349,9 @@ import { getImage } from '@/utils/comm'; import BindDevice from './BindDevice.vue'; import Import from './Import.vue'; import Export from './Export.vue'; +import Save from './Save.vue'; + +const router = useRouter(); const cardManageRef = ref>({}); const params = ref>({}); @@ -344,6 +363,7 @@ const exportVisible = ref(false); const importVisible = ref(false); const cardId = ref(); const current = ref>({}); +const saveType = ref(''); const columns = [ { @@ -504,6 +524,11 @@ const getActions = ( title: '编辑', }, icon: 'EditOutlined', + onClick: () => { + visible.value = true; + current.value = data; + saveType.value = 'edit'; + }, }, { key: 'view', @@ -512,6 +537,14 @@ const getActions = ( title: '查看', }, icon: 'EyeOutlined', + onClick: () => { + router.push({ + path: '/iot-card/CardManagement/Detail', + query: { + id: data.id, + }, + }); + }, }, { key: 'bindDevice', @@ -651,10 +684,27 @@ const handleView = (id: string) => { /** * 新增 */ -const handleAdd = () => {}; +const handleAdd = () => { + visible.value = true; + current.value = {}; + saveType.value = 'add'; +}; + +/** + * 新增、编辑关闭弹窗 + * @param val 加载表格 + */ +const saveChange = (val: any) => { + visible.value = false; + current.value = {}; + if (val) { + cardManageRef.value?.reload(); + } +}; /** * 绑定设备关闭窗口 + * @param val */ const bindDevice = (val: boolean) => { bindDeviceVisible.value = false; diff --git a/src/views/iot-card/Recharge/Save.vue b/src/views/iot-card/Recharge/Save.vue new file mode 100644 index 00000000..4199d358 --- /dev/null +++ b/src/views/iot-card/Recharge/Save.vue @@ -0,0 +1,191 @@ + + + + + diff --git a/src/views/iot-card/Recharge/index.vue b/src/views/iot-card/Recharge/index.vue new file mode 100644 index 00000000..27fdab16 --- /dev/null +++ b/src/views/iot-card/Recharge/index.vue @@ -0,0 +1,170 @@ + + + + + + diff --git a/src/views/iot-card/data.ts b/src/views/iot-card/data.ts new file mode 100644 index 00000000..cf9a9fc3 --- /dev/null +++ b/src/views/iot-card/data.ts @@ -0,0 +1,76 @@ +import { getImage } from '@/utils/comm'; + +// 平台类型 +export const PlatformTypeList = [ + { + label: '移动OneLink', + value: 'OneLinkPB', + imgUrl: getImage('/iot-card/onelink.png'), + }, + { + label: '电信Ctwing', + value: 'CtwingCmp', + imgUrl: getImage('/iot-card/ctwingcmp.png'), + }, + { + label: '联通Unicom', + value: 'UnicomCmp', + imgUrl: getImage('/iot-card/unicom.png'), + }, +]; + +//运营商 +export const OperatorList = [ + { + label: '移动', + value: '移动', + }, + { + label: '电信', + value: '电信', + }, + { + label: '联通', + value: '联通', + }, +]; + +// 类型 +export const TypeList = [ + { + label: '年卡', + value: 'year', + }, + { + label: '季卡', + value: 'season', + }, + { + label: '月卡', + value: 'month', + }, + { + label: '其他', + value: 'other', + }, +]; + +// 支付方式 +export const PaymentMethod = [ + { + label: '支付宝手机网站支付', + value: 'ALIPAY_WAP', + }, + { + label: '支付宝网页及时到账支付', + value: 'ALIPAY_WEB', + }, + { + label: '微信公众号支付', + value: 'WEIXIN_JSAPI', + }, + { + label: '微信扫码支付', + value: 'WEIXIN_NATIVE', + }, +]; diff --git a/src/views/northbound/DuerOS/Save/index.vue b/src/views/northbound/DuerOS/Save/index.vue new file mode 100644 index 00000000..9573a57f --- /dev/null +++ b/src/views/northbound/DuerOS/Save/index.vue @@ -0,0 +1,3 @@ + \ No newline at end of file diff --git a/src/views/northbound/DuerOS/index.vue b/src/views/northbound/DuerOS/index.vue index f8ab376f..520d60bd 100644 --- a/src/views/northbound/DuerOS/index.vue +++ b/src/views/northbound/DuerOS/index.vue @@ -148,7 +148,7 @@ const getActions = (data: Partial>): ActionsType[] => { } const add = () => { - message.warn('123') + // router.push(`/northbound/DuerOS/detail/:id`) } \ No newline at end of file diff --git a/src/views/notice/Config/Detail/index.vue b/src/views/notice/Config/Detail/index.vue index 700c6d89..abfc22a5 100644 --- a/src/views/notice/Config/Detail/index.vue +++ b/src/views/notice/Config/Detail/index.vue @@ -311,31 +311,42 @@ const msgType = ref([ // 表单数据 const formData = ref({ configuration: { - appKey: '', - appSecret: '', + host: '', + port: 25, + ssl: false, + sender: '', + username: '', + password: '', }, description: '', name: '', - provider: 'dingTalkMessage', - type: 'dingTalk', + provider: 'embedded', + type: 'email', }); // 根据通知方式展示对应的字段 watch( () => formData.value.type, (val) => { - // formData.value.configuration = Object.values(CONFIG_FIELD_MAP[val])[0]; msgType.value = MSG_TYPE[val]; formData.value.provider = msgType.value[0].value; + + formData.value.configuration = + CONFIG_FIELD_MAP[val][formData.value.provider]; + + clearValid(); }, ); -computed(() => - Object.assign( - formData.value.configuration, - CONFIG_FIELD_MAP[formData.value.type][formData.value.provider], - ), +watch( + () => formData.value.provider, + (val) => { + formData.value.configuration = + CONFIG_FIELD_MAP[formData.value.type][val]; + + clearValid(); + }, ); // 验证规则 @@ -405,15 +416,15 @@ const { resetFields, validate, validateInfos, clearValidate } = useForm( formData.value, formRules.value, ); -watch( - () => formData.value.type, - () => { + +const clearValid = () => { + setTimeout(() => { clearValidate(); - }, - { deep: true }, -); + }, 200); +}; const getDetail = async () => { + if (route.params.id === ':id') return; const res = await configApi.detail(route.params.id as string); // console.log('res: ', res); formData.value = res.result; @@ -441,10 +452,12 @@ const handleSubmit = () => { message.success('保存成功'); router.back(); } - btnLoading.value = false; }) .catch((err) => { console.log('err: ', err); + }) + .finally(() => { + btnLoading.value = false; }); }; diff --git a/src/views/notice/Template/Detail/index.vue b/src/views/notice/Template/Detail/index.vue index 82ce27eb..93415894 100644 --- a/src/views/notice/Template/Detail/index.vue +++ b/src/views/notice/Template/Detail/index.vue @@ -120,15 +120,15 @@ ] " > - + /> - + @@ -456,7 +475,7 @@ diff --git a/src/views/notice/Template/index.vue b/src/views/notice/Template/index.vue index 7af08260..87c20444 100644 --- a/src/views/notice/Template/index.vue +++ b/src/views/notice/Template/index.vue @@ -256,7 +256,7 @@ const getMethodTxt = (type: string) => { * 新增 */ const handleAdd = () => { - router.push(`/notice/Config/detail/:id`); + router.push(`/notice/Template/detail/:id`); }; /** @@ -323,7 +323,7 @@ const getActions = ( onClick: () => { // visible.value = true; // current.value = data; - router.push(`/notice/Config/detail/${data.id}`); + router.push(`/notice/Template/detail/${data.id}`); }, }, {