Merge branch 'dev' of github.com:jetlinks/jetlinks-ui-vue into dev
This commit is contained in:
commit
e09eda6b41
|
@ -1,7 +1,7 @@
|
||||||
import server from '@/utils/request';
|
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)
|
export const addRole = (data: any) => server.post(`/role`, data)
|
||||||
|
|
||||||
|
|
|
@ -121,4 +121,16 @@ export const edit = (data: any) => server.put(`/network/card/${data.id}`, data);
|
||||||
* 根据id查看详情
|
* 根据id查看详情
|
||||||
* @param id
|
* @param id
|
||||||
*/
|
*/
|
||||||
export const queryDetail = (id: any) => server.get(`/network/card/${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)
|
|
@ -36,7 +36,7 @@ export const undeploy = (id: string) =>
|
||||||
export const deploy = (id: string) =>
|
export const deploy = (id: string) =>
|
||||||
server.post(`/gateway/device/${id}/_startup`);
|
server.post(`/gateway/device/${id}/_startup`);
|
||||||
|
|
||||||
export const del = (id: string) => server.remove(`/gateway/device/${id}`);
|
export const remove = (id: string) => server.remove(`/gateway/device/${id}`);
|
||||||
|
|
||||||
export const getResourcesCurrent = () =>
|
export const getResourcesCurrent = () =>
|
||||||
server.get(`/network/resources/alive/_current`);
|
server.get(`/network/resources/alive/_current`);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { patch, post, get, remove } from '@/utils/request'
|
import { patch, post, get, remove } from '@/utils/request'
|
||||||
import { TemplateFormData } from '@/views/notice/Template/types'
|
import type { TemplateFormData } from '@/views/notice/Template/types'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
// 列表
|
// 列表
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { patch, post, get, remove } from '@/utils/request'
|
import { patch, post, get, remove } from '@/utils/request'
|
||||||
import { BindConfig } from '@/views/notice/Template/types'
|
import type { BindConfig } from '@/views/notice/Template/types'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
// 列表
|
// 列表
|
||||||
|
|
|
@ -231,6 +231,13 @@ const handleClick = () => {
|
||||||
|
|
||||||
:deep(.card-item-content-title) {
|
:deep(.card-item-content-title) {
|
||||||
cursor: pointer;
|
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) {
|
:deep(.card-item-heard-name) {
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
import { ProLayout } from '@/components/Layout'
|
import { ProLayout } from '@/components/Layout'
|
||||||
import DefaultSetting from '../../../config/config'
|
import DefaultSetting from '../../../config/config'
|
||||||
import { useMenuStore } from '@/store/menu'
|
import { useMenuStore } from '@/store/menu'
|
||||||
|
import { clearMenuItem } from 'components/Layout/utils'
|
||||||
|
|
||||||
type StateType = {
|
type StateType = {
|
||||||
collapsed: boolean
|
collapsed: boolean
|
||||||
|
@ -39,7 +40,7 @@ const layoutConf = reactive({
|
||||||
siderWidth: DefaultSetting.layout.siderWidth,
|
siderWidth: DefaultSetting.layout.siderWidth,
|
||||||
logo: DefaultSetting.layout.logo,
|
logo: DefaultSetting.layout.logo,
|
||||||
title: DefaultSetting.layout.title,
|
title: DefaultSetting.layout.title,
|
||||||
menuData: menu.menus,
|
menuData: clearMenuItem(menu.siderMenus),
|
||||||
});
|
});
|
||||||
|
|
||||||
const state = reactive<StateType>({
|
const state = reactive<StateType>({
|
||||||
|
|
|
@ -32,7 +32,7 @@ export const HeaderView = defineComponent({
|
||||||
height: `${headerHeight.value}px`,
|
height: `${headerHeight.value}px`,
|
||||||
lineHeight: `${headerHeight.value}px`,
|
lineHeight: `${headerHeight.value}px`,
|
||||||
width: `100%`,
|
width: `100%`,
|
||||||
|
background: 'transparent'
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<Layout.Header
|
<Layout.Header
|
||||||
|
|
|
@ -14,10 +14,10 @@
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
.children-full-height {
|
//.children-full-height {
|
||||||
> :nth-child(1) {
|
// > :nth-child(1) {
|
||||||
min-height: 100%;
|
// min-height: 100%;
|
||||||
}
|
// }
|
||||||
}
|
//}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -13,4 +13,8 @@
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ant-menu-inline {
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -286,6 +286,7 @@ handleItems()
|
||||||
.JSearch-warp {
|
.JSearch-warp {
|
||||||
padding: 24px;
|
padding: 24px;
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
|
margin-bottom: 24px;
|
||||||
|
|
||||||
.JSearch-content {
|
.JSearch-content {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
|
@ -10,17 +10,23 @@
|
||||||
.jtable-body-header-right {
|
.jtable-body-header-right {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
.jtable-setting-item {
|
align-items: center;
|
||||||
color: rgba(0, 0, 0, 0.75);
|
.jtable-body-header-right-button {
|
||||||
font-size: 16px;
|
display: flex;
|
||||||
cursor: pointer;
|
margin-left: 10px;
|
||||||
|
gap: 8px;
|
||||||
|
.jtable-setting-item {
|
||||||
|
color: rgba(0, 0, 0, 0.75);
|
||||||
|
font-size: 16px;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
color: @primary-color-hover;
|
color: @primary-color-hover;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.active {
|
&.active {
|
||||||
color: @primary-color-active;
|
color: @primary-color-active;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,6 +73,7 @@ const JTable = defineComponent<JTableProps>({
|
||||||
slots: [
|
slots: [
|
||||||
'headerTitle', // 顶部左边插槽
|
'headerTitle', // 顶部左边插槽
|
||||||
'card', // 卡片内容
|
'card', // 卡片内容
|
||||||
|
'rightExtraRender'
|
||||||
],
|
],
|
||||||
emits: [
|
emits: [
|
||||||
'modelChange', // 切换卡片和表格
|
'modelChange', // 切换卡片和表格
|
||||||
|
@ -254,16 +255,22 @@ const JTable = defineComponent<JTableProps>({
|
||||||
{slots.headerTitle && slots.headerTitle()}
|
{slots.headerTitle && slots.headerTitle()}
|
||||||
</div>
|
</div>
|
||||||
<div class={styles["jtable-body-header-right"]}>
|
<div class={styles["jtable-body-header-right"]}>
|
||||||
<div class={[styles["jtable-setting-item"], ModelEnum.CARD === _model.value ? styles['active'] : '']} onClick={() => {
|
{/* 顶部右边插槽 */}
|
||||||
_model.value = ModelEnum.CARD
|
{slots.rightExtraRender && slots.rightExtraRender()}
|
||||||
}}>
|
{
|
||||||
<AppstoreOutlined />
|
!props.model && <div class={styles["jtable-body-header-right-button"]}>
|
||||||
</div>
|
<div class={[styles["jtable-setting-item"], ModelEnum.CARD === _model.value ? styles['active'] : '']} onClick={() => {
|
||||||
<div class={[styles["jtable-setting-item"], ModelEnum.TABLE === _model.value ? styles['active'] : '']} onClick={() => {
|
_model.value = ModelEnum.CARD
|
||||||
_model.value = ModelEnum.TABLE
|
}}>
|
||||||
}}>
|
<AppstoreOutlined />
|
||||||
<UnorderedListOutlined />
|
</div>
|
||||||
</div>
|
<div class={[styles["jtable-setting-item"], ModelEnum.TABLE === _model.value ? styles['active'] : '']} onClick={() => {
|
||||||
|
_model.value = ModelEnum.TABLE
|
||||||
|
}}>
|
||||||
|
<UnorderedListOutlined />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{/* content */}
|
{/* content */}
|
||||||
|
|
11
src/main.ts
11
src/main.ts
|
@ -1,17 +1,14 @@
|
||||||
import { createApp } from 'vue'
|
import { createApp } from 'vue'
|
||||||
import App from './App.vue'
|
import App from './App.vue'
|
||||||
import store from './store'
|
import store from './store'
|
||||||
import router from './router'
|
|
||||||
import components from './components'
|
import components from './components'
|
||||||
|
import router from './router'
|
||||||
import './style.less'
|
import './style.less'
|
||||||
import 'ant-design-vue/es/notification/style/css';
|
import 'ant-design-vue/es/notification/style/css';
|
||||||
import Antd from 'ant-design-vue/es'
|
|
||||||
|
|
||||||
const app = createApp(App)
|
const app = createApp(App)
|
||||||
|
|
||||||
app.use(store)
|
app.use(store)
|
||||||
app.use(router)
|
.use(router)
|
||||||
app.use(components)
|
.use(components)
|
||||||
app.use(Antd)
|
.mount('#app')
|
||||||
|
|
||||||
app.mount('#app')
|
|
||||||
|
|
|
@ -3,6 +3,8 @@ import menus, { LoginPath } from './menu'
|
||||||
import { cleanToken, getToken } from '@/utils/comm'
|
import { cleanToken, getToken } from '@/utils/comm'
|
||||||
import { useUserInfo } from '@/store/userInfo'
|
import { useUserInfo } from '@/store/userInfo'
|
||||||
import { useSystem } from '@/store/system'
|
import { useSystem } from '@/store/system'
|
||||||
|
import NotFindPage from '@/views/404.vue'
|
||||||
|
import { useMenuStore } from 'store/menu'
|
||||||
|
|
||||||
const router = createRouter({
|
const router = createRouter({
|
||||||
history: createWebHashHistory(),
|
history: createWebHashHistory(),
|
||||||
|
@ -27,22 +29,23 @@ router.beforeEach((to, from, next) => {
|
||||||
} else {
|
} else {
|
||||||
const userInfo = useUserInfo()
|
const userInfo = useUserInfo()
|
||||||
const system = useSystem()
|
const system = useSystem()
|
||||||
|
const menu = useMenuStore()
|
||||||
|
|
||||||
if (!userInfo.userInfos.username) {
|
if (!menu.menuData.length) {
|
||||||
userInfo.getUserInfo().then(() => {
|
userInfo.getUserInfo().then(() => {
|
||||||
system.getSystemVersion().then((menuData: any[]) => {
|
system.getSystemVersion().then((menuData: any[]) => {
|
||||||
menuData.forEach(r => {
|
menuData.forEach(r => {
|
||||||
router.addRoute('main', r)
|
router.addRoute('base', r)
|
||||||
})
|
})
|
||||||
const redirect = decodeURIComponent((from.query.redirect as string) || to.path)
|
router.addRoute('base',{
|
||||||
if(to.path === redirect) {
|
path: '/:pathMatch(.*)',
|
||||||
next({ ...to, replace: true })
|
name: 'error',
|
||||||
} else {
|
component: () => NotFindPage
|
||||||
next({ path: redirect })
|
})
|
||||||
}
|
|
||||||
|
next({ ...to, replace: true })
|
||||||
})
|
})
|
||||||
}).catch(() => {
|
}).catch(() => {
|
||||||
console.log('userInfo', userInfo)
|
|
||||||
cleanToken()
|
cleanToken()
|
||||||
next({ path: LoginPath })
|
next({ path: LoginPath })
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,24 +1,7 @@
|
||||||
export const LoginPath = '/login'
|
export const LoginPath = '/login'
|
||||||
|
|
||||||
export default [
|
export default [
|
||||||
// {
|
{ path: '/*', redirect: '/'},
|
||||||
// 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')
|
|
||||||
// }
|
|
||||||
|
|
||||||
// start: 测试用, 可删除
|
// start: 测试用, 可删除
|
||||||
{
|
{
|
||||||
path: '/login',
|
path: '/login',
|
||||||
|
@ -32,10 +15,6 @@ export default [
|
||||||
path: '/account/center/bind',
|
path: '/account/center/bind',
|
||||||
component: () => import('@/views/account/Center/bind/index.vue')
|
component: () => import('@/views/account/Center/bind/index.vue')
|
||||||
},
|
},
|
||||||
{
|
|
||||||
path: '/iot/home',
|
|
||||||
component: () => import('@/views/home/index.vue')
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
path: '/table',
|
path: '/table',
|
||||||
component: () => import('@/views/demo/table/index.vue')
|
component: () => import('@/views/demo/table/index.vue')
|
||||||
|
@ -48,129 +27,13 @@ export default [
|
||||||
path: '/search',
|
path: '/search',
|
||||||
component: () => import('@/views/demo/Search.vue')
|
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: 测试用, 可删除
|
// 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',
|
path: '/init-home',
|
||||||
component: () => import('@/views/init-home/index.vue')
|
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: '/iot-card/CardManagement/Detail',
|
|
||||||
component: () => import('@/views/iot-card/CardManagement/Detail/index.vue')
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: '/iot-card/Recharge',
|
|
||||||
component: () => import('@/views/iot-card/Recharge/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')
|
|
||||||
}
|
|
||||||
]
|
]
|
|
@ -1,11 +1,14 @@
|
||||||
import { defineStore } from "pinia";
|
import { defineStore } from "pinia";
|
||||||
import { queryOwnThree } from '@/api/system/menu'
|
import { queryOwnThree } from '@/api/system/menu'
|
||||||
import { filterAsnycRouter } from '@/utils/menu'
|
import { filterAsnycRouter } from '@/utils/menu'
|
||||||
|
import { cloneDeep } from 'lodash-es'
|
||||||
|
|
||||||
export const useMenuStore = defineStore({
|
export const useMenuStore = defineStore({
|
||||||
id: 'menu',
|
id: 'menu',
|
||||||
state: () => ({
|
state: () => ({
|
||||||
menus: {},
|
menus: {},
|
||||||
|
menuData: [],
|
||||||
|
siderMenus: [],
|
||||||
menusKey: []
|
menusKey: []
|
||||||
}),
|
}),
|
||||||
getters: {
|
getters: {
|
||||||
|
@ -51,7 +54,8 @@ export const useMenuStore = defineStore({
|
||||||
];
|
];
|
||||||
const resp = await queryOwnThree({ paging: false, terms: params })
|
const resp = await queryOwnThree({ paging: false, terms: params })
|
||||||
if (resp.success) {
|
if (resp.success) {
|
||||||
const menus = filterAsnycRouter(resp.result)
|
const silderMenus = filterAsnycRouter(cloneDeep(resp.result))
|
||||||
|
const menus = filterAsnycRouter(cloneDeep(resp.result))
|
||||||
menus.push({
|
menus.push({
|
||||||
path: '/',
|
path: '/',
|
||||||
redirect: menus[0]?.path,
|
redirect: menus[0]?.path,
|
||||||
|
@ -59,7 +63,9 @@ export const useMenuStore = defineStore({
|
||||||
hideInMenu: true
|
hideInMenu: true
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
this.menus = menus
|
this.menuData = menus
|
||||||
|
this.siderMenus = silderMenus
|
||||||
|
console.log('silderMenus', silderMenus)
|
||||||
res(menus)
|
res(menus)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
@ -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'
|
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<string, any>;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
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<string, any>;
|
||||||
|
/**
|
||||||
|
* 父级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 = {
|
const extraRouteObj = {
|
||||||
'media/Cascade': {
|
'media/Cascade': {
|
||||||
|
@ -59,53 +147,83 @@ const extraRouteObj = {
|
||||||
|
|
||||||
|
|
||||||
const resolveComponent = (name: any) => {
|
const resolveComponent = (name: any) => {
|
||||||
// TODO 暂时用system进行测试
|
|
||||||
const importPage = pagesComponent[`../views/${name}/index.vue`];
|
const importPage = pagesComponent[`../views/${name}/index.vue`];
|
||||||
// if (!importPage) {
|
if (!importPage) {
|
||||||
// throw new Error(`Unknown page ${name}. Is it located under Pages with a .vue extension?`);
|
console.warn(`Unknown page ${name}. Is it located under Pages with a .vue extension?`)
|
||||||
// }
|
}
|
||||||
|
|
||||||
//@ts-ignore
|
//@ts-ignore
|
||||||
return !importPage ? BlankLayoutPage : importPage.default
|
return !!importPage ? importPage.default : undefined
|
||||||
// return importPage.default
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const findChildrenRoute = (code: string, url: string): ExtraRouteItem[] => {
|
const findChildrenRoute = (code: string, url: string): MenuItem[] => {
|
||||||
if (extraRouteObj[code]) {
|
if (extraRouteObj[code]) {
|
||||||
return extraRouteObj[code].children.map((route: ExtraRouteItem) => {
|
return extraRouteObj[code].children.map((route: MenuItem) => {
|
||||||
return {
|
return {
|
||||||
url: `${url}/${route.code}`,
|
url: `${url}/${route.code}`,
|
||||||
code: route.code,
|
code: route.code,
|
||||||
name: route.name
|
name: route.name,
|
||||||
|
isShow: false
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const findDetailRouteItem = (code: string, url: string): Partial<MenuItem> | 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) {
|
export function filterAsnycRouter(asyncRouterMap: any, parentCode = '', level = 1) {
|
||||||
|
|
||||||
return asyncRouterMap.map((route: any) => {
|
return asyncRouterMap.map((route: any) => {
|
||||||
|
|
||||||
route.path = `${route.url}`
|
route.path = `${route.url}`
|
||||||
route.meta = {
|
route.meta = {
|
||||||
icon: route.icon,
|
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)
|
const extraChildren = findChildrenRoute(route.code, route.url)
|
||||||
|
route.children = route.children && route.children.length ? [...route.children, ...extraChildren] : extraChildren
|
||||||
// TODO 查看是否具有详情页
|
route.children = findDetailRoutes(route.children)
|
||||||
// route.children = [...route.children, ]
|
|
||||||
|
|
||||||
if (route.children && route.children.length) {
|
if (route.children && route.children.length) {
|
||||||
route.component = () => level === 1 ? BasicLayoutPage : BlankLayoutPage
|
// TODO 查看是否具有详情页
|
||||||
route.children = filterAsnycRouter(route.children, `${parentCode}/${route.code}`, level + 1)
|
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 {
|
} else {
|
||||||
route.component = resolveComponent(route.code);
|
console.log(route.code)
|
||||||
|
route.component = route.component || resolveComponent(route.code) || BlankLayoutPage;
|
||||||
}
|
}
|
||||||
console.log(route.code, route)
|
delete route.name
|
||||||
return route
|
return route
|
||||||
})
|
})
|
||||||
}
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
<template>
|
||||||
|
<a-result status="404" title="404" sub-title="Sorry, the page you visited does not exist.">
|
||||||
|
</a-result>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: '404.vue'
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
|
@ -1,221 +1,234 @@
|
||||||
<template>
|
<template>
|
||||||
<JTable
|
<page-container>
|
||||||
ref="instanceRef"
|
<Search :columns="columns" target="device-instance" />
|
||||||
:columns="columns"
|
<JTable
|
||||||
:request="query"
|
ref="instanceRef"
|
||||||
:defaultParams="{ sorts: [{ name: 'createTime', order: 'desc' }] }"
|
:columns="columns"
|
||||||
:rowSelection="{
|
:request="query"
|
||||||
selectedRowKeys: _selectedRowKeys,
|
:defaultParams="{ sorts: [{ name: 'createTime', order: 'desc' }] }"
|
||||||
onChange: onSelectChange,
|
:rowSelection="{
|
||||||
}"
|
selectedRowKeys: _selectedRowKeys,
|
||||||
@cancelSelect="cancelSelect"
|
onChange: onSelectChange,
|
||||||
:params="params"
|
}"
|
||||||
>
|
@cancelSelect="cancelSelect"
|
||||||
<template #headerTitle>
|
:params="params"
|
||||||
<a-space>
|
>
|
||||||
<a-button type="primary" @click="handleAdd">新增</a-button>
|
<template #headerTitle>
|
||||||
<a-dropdown>
|
<a-space>
|
||||||
<a-button>批量操作 <AIcon type="DownOutlined" /></a-button>
|
<a-button type="primary" @click="handleAdd">新增</a-button>
|
||||||
<template #overlay>
|
<a-dropdown>
|
||||||
<a-menu>
|
<a-button
|
||||||
<a-menu-item>
|
>批量操作 <AIcon type="DownOutlined"
|
||||||
<a-button @click="exportVisible = true"
|
/></a-button>
|
||||||
><AIcon
|
<template #overlay>
|
||||||
type="ExportOutlined"
|
<a-menu>
|
||||||
/>批量导出设备</a-button
|
<a-menu-item>
|
||||||
>
|
<a-button @click="exportVisible = true"
|
||||||
</a-menu-item>
|
|
||||||
<a-menu-item>
|
|
||||||
<a-button @click="importVisible = true"
|
|
||||||
><AIcon
|
|
||||||
type="ImportOutlined"
|
|
||||||
/>批量导入设备</a-button
|
|
||||||
>
|
|
||||||
</a-menu-item>
|
|
||||||
<a-menu-item>
|
|
||||||
<a-popconfirm
|
|
||||||
@confirm="activeAllDevice"
|
|
||||||
title="确认激活全部设备?"
|
|
||||||
>
|
|
||||||
<a-button type="primary" ghost
|
|
||||||
><AIcon
|
><AIcon
|
||||||
type="CheckCircleOutlined"
|
type="ExportOutlined"
|
||||||
/>激活全部设备</a-button
|
/>批量导出设备</a-button
|
||||||
>
|
>
|
||||||
</a-popconfirm>
|
</a-menu-item>
|
||||||
</a-menu-item>
|
<a-menu-item>
|
||||||
<a-menu-item>
|
<a-button @click="importVisible = true"
|
||||||
<a-button
|
|
||||||
@click="syncDeviceStatus"
|
|
||||||
type="primary"
|
|
||||||
><AIcon
|
|
||||||
type="SyncOutlined"
|
|
||||||
/>同步设备状态</a-button
|
|
||||||
>
|
|
||||||
</a-menu-item>
|
|
||||||
<a-menu-item v-if="_selectedRowKeys.length">
|
|
||||||
<a-popconfirm
|
|
||||||
@confirm="delSelectedDevice"
|
|
||||||
title="已启用的设备无法删除,确认删除选中的禁用状态设备?"
|
|
||||||
>
|
|
||||||
<a-button type="primary" danger
|
|
||||||
><AIcon
|
><AIcon
|
||||||
type="DeleteOutlined"
|
type="ImportOutlined"
|
||||||
/>删除选中设备</a-button
|
/>批量导入设备</a-button
|
||||||
>
|
>
|
||||||
</a-popconfirm>
|
</a-menu-item>
|
||||||
</a-menu-item>
|
<a-menu-item>
|
||||||
<a-menu-item
|
<a-popconfirm
|
||||||
v-if="_selectedRowKeys.length"
|
@confirm="activeAllDevice"
|
||||||
title="确认激活选中设备?"
|
title="确认激活全部设备?"
|
||||||
>
|
>
|
||||||
<a-popconfirm @confirm="activeSelectedDevice">
|
<a-button type="primary" ghost
|
||||||
<a-button type="primary"
|
><AIcon
|
||||||
|
type="CheckCircleOutlined"
|
||||||
|
/>激活全部设备</a-button
|
||||||
|
>
|
||||||
|
</a-popconfirm>
|
||||||
|
</a-menu-item>
|
||||||
|
<a-menu-item>
|
||||||
|
<a-button
|
||||||
|
@click="syncDeviceStatus"
|
||||||
|
type="primary"
|
||||||
><AIcon
|
><AIcon
|
||||||
type="CheckOutlined"
|
type="SyncOutlined"
|
||||||
/>激活选中设备</a-button
|
/>同步设备状态</a-button
|
||||||
>
|
>
|
||||||
</a-popconfirm>
|
</a-menu-item>
|
||||||
</a-menu-item>
|
<a-menu-item v-if="_selectedRowKeys.length">
|
||||||
<a-menu-item v-if="_selectedRowKeys.length">
|
<a-popconfirm
|
||||||
<a-popconfirm
|
@confirm="delSelectedDevice"
|
||||||
@confirm="disabledSelectedDevice"
|
title="已启用的设备无法删除,确认删除选中的禁用状态设备?"
|
||||||
title="确认禁用选中设备?"
|
>
|
||||||
|
<a-button type="primary" danger
|
||||||
|
><AIcon
|
||||||
|
type="DeleteOutlined"
|
||||||
|
/>删除选中设备</a-button
|
||||||
|
>
|
||||||
|
</a-popconfirm>
|
||||||
|
</a-menu-item>
|
||||||
|
<a-menu-item
|
||||||
|
v-if="_selectedRowKeys.length"
|
||||||
|
title="确认激活选中设备?"
|
||||||
>
|
>
|
||||||
<a-button type="primary" danger
|
<a-popconfirm
|
||||||
><AIcon
|
@confirm="activeSelectedDevice"
|
||||||
type="StopOutlined"
|
|
||||||
/>禁用选中设备</a-button
|
|
||||||
>
|
>
|
||||||
</a-popconfirm>
|
<a-button type="primary"
|
||||||
</a-menu-item>
|
><AIcon
|
||||||
</a-menu>
|
type="CheckOutlined"
|
||||||
|
/>激活选中设备</a-button
|
||||||
|
>
|
||||||
|
</a-popconfirm>
|
||||||
|
</a-menu-item>
|
||||||
|
<a-menu-item v-if="_selectedRowKeys.length">
|
||||||
|
<a-popconfirm
|
||||||
|
@confirm="disabledSelectedDevice"
|
||||||
|
title="确认禁用选中设备?"
|
||||||
|
>
|
||||||
|
<a-button type="primary" danger
|
||||||
|
><AIcon
|
||||||
|
type="StopOutlined"
|
||||||
|
/>禁用选中设备</a-button
|
||||||
|
>
|
||||||
|
</a-popconfirm>
|
||||||
|
</a-menu-item>
|
||||||
|
</a-menu>
|
||||||
|
</template>
|
||||||
|
</a-dropdown>
|
||||||
|
</a-space>
|
||||||
|
</template>
|
||||||
|
<template #card="slotProps">
|
||||||
|
<CardBox
|
||||||
|
:value="slotProps"
|
||||||
|
@click="handleClick"
|
||||||
|
:actions="getActions(slotProps, 'card')"
|
||||||
|
v-bind="slotProps"
|
||||||
|
:active="_selectedRowKeys.includes(slotProps.id)"
|
||||||
|
:status="slotProps.state?.value"
|
||||||
|
:statusText="slotProps.state?.text"
|
||||||
|
:statusNames="{
|
||||||
|
online: 'success',
|
||||||
|
offline: 'error',
|
||||||
|
notActive: 'warning',
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<template #img>
|
||||||
|
<slot name="img">
|
||||||
|
<img
|
||||||
|
:src="
|
||||||
|
getImage('/device/instance/device-card.png')
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
</slot>
|
||||||
</template>
|
</template>
|
||||||
</a-dropdown>
|
<template #content>
|
||||||
</a-space>
|
<h3
|
||||||
</template>
|
class="card-item-content-title"
|
||||||
<template #card="slotProps">
|
@click.stop="handleView(slotProps.id)"
|
||||||
<CardBox
|
>
|
||||||
:value="slotProps"
|
{{ slotProps.name }}
|
||||||
@click="handleClick"
|
</h3>
|
||||||
:actions="getActions(slotProps, 'card')"
|
<a-row>
|
||||||
v-bind="slotProps"
|
<a-col :span="12">
|
||||||
:active="_selectedRowKeys.includes(slotProps.id)"
|
<div class="card-item-content-text">
|
||||||
:status="slotProps.state?.value"
|
设备类型
|
||||||
:statusText="slotProps.state?.text"
|
</div>
|
||||||
:statusNames="{
|
<div>{{ slotProps.deviceType?.text }}</div>
|
||||||
online: 'success',
|
</a-col>
|
||||||
offline: 'error',
|
<a-col :span="12">
|
||||||
notActive: 'warning',
|
<div class="card-item-content-text">
|
||||||
}"
|
产品名称
|
||||||
>
|
</div>
|
||||||
<template #img>
|
<div>{{ slotProps.productName }}</div>
|
||||||
<slot name="img">
|
</a-col>
|
||||||
<img
|
</a-row>
|
||||||
:src="getImage('/device/instance/device-card.png')"
|
</template>
|
||||||
/>
|
<template #actions="item">
|
||||||
</slot>
|
<a-tooltip
|
||||||
</template>
|
v-bind="item.tooltip"
|
||||||
<template #content>
|
:title="item.disabled && item.tooltip.title"
|
||||||
<h3
|
>
|
||||||
class="card-item-content-title"
|
<a-popconfirm
|
||||||
@click.stop="handleView(slotProps.id)"
|
v-if="item.popConfirm"
|
||||||
>
|
v-bind="item.popConfirm"
|
||||||
{{ slotProps.name }}
|
:disabled="item.disabled"
|
||||||
</h3>
|
>
|
||||||
<a-row>
|
<a-button :disabled="item.disabled">
|
||||||
<a-col :span="12">
|
<AIcon
|
||||||
<div class="card-item-content-text">设备类型</div>
|
type="DeleteOutlined"
|
||||||
<div>{{ slotProps.deviceType?.text }}</div>
|
v-if="item.key === 'delete'"
|
||||||
</a-col>
|
/>
|
||||||
<a-col :span="12">
|
<template v-else>
|
||||||
<div class="card-item-content-text">产品名称</div>
|
<AIcon :type="item.icon" />
|
||||||
<div>{{ slotProps.productName }}</div>
|
<span>{{ item?.text }}</span>
|
||||||
</a-col>
|
</template>
|
||||||
</a-row>
|
</a-button>
|
||||||
</template>
|
</a-popconfirm>
|
||||||
<template #actions="item">
|
<template v-else>
|
||||||
|
<a-button
|
||||||
|
:disabled="item.disabled"
|
||||||
|
@click="item.onClick"
|
||||||
|
>
|
||||||
|
<AIcon
|
||||||
|
type="DeleteOutlined"
|
||||||
|
v-if="item.key === 'delete'"
|
||||||
|
/>
|
||||||
|
<template v-else>
|
||||||
|
<AIcon :type="item.icon" />
|
||||||
|
<span>{{ item?.text }}</span>
|
||||||
|
</template>
|
||||||
|
</a-button>
|
||||||
|
</template>
|
||||||
|
</a-tooltip>
|
||||||
|
</template>
|
||||||
|
</CardBox>
|
||||||
|
</template>
|
||||||
|
<template #state="slotProps">
|
||||||
|
<a-badge
|
||||||
|
:text="slotProps.state?.text"
|
||||||
|
:status="statusMap.get(slotProps.state?.value)"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<template #action="slotProps">
|
||||||
|
<a-space :size="16">
|
||||||
<a-tooltip
|
<a-tooltip
|
||||||
v-bind="item.tooltip"
|
v-for="i in getActions(slotProps, 'table')"
|
||||||
:title="item.disabled && item.tooltip.title"
|
:key="i.key"
|
||||||
|
v-bind="i.tooltip"
|
||||||
>
|
>
|
||||||
<a-popconfirm
|
<a-popconfirm
|
||||||
v-if="item.popConfirm"
|
v-if="i.popConfirm"
|
||||||
v-bind="item.popConfirm"
|
v-bind="i.popConfirm"
|
||||||
:disabled="item.disabled"
|
:disabled="i.disabled"
|
||||||
>
|
>
|
||||||
<a-button :disabled="item.disabled">
|
|
||||||
<AIcon
|
|
||||||
type="DeleteOutlined"
|
|
||||||
v-if="item.key === 'delete'"
|
|
||||||
/>
|
|
||||||
<template v-else>
|
|
||||||
<AIcon :type="item.icon" />
|
|
||||||
<span>{{ item?.text }}</span>
|
|
||||||
</template>
|
|
||||||
</a-button>
|
|
||||||
</a-popconfirm>
|
|
||||||
<template v-else>
|
|
||||||
<a-button
|
<a-button
|
||||||
:disabled="item.disabled"
|
:disabled="i.disabled"
|
||||||
@click="item.onClick"
|
style="padding: 0"
|
||||||
>
|
type="link"
|
||||||
<AIcon
|
><AIcon :type="i.icon"
|
||||||
type="DeleteOutlined"
|
/></a-button>
|
||||||
v-if="item.key === 'delete'"
|
</a-popconfirm>
|
||||||
/>
|
<a-button
|
||||||
<template v-else>
|
style="padding: 0"
|
||||||
<AIcon :type="item.icon" />
|
type="link"
|
||||||
<span>{{ item?.text }}</span>
|
v-else
|
||||||
</template>
|
@click="i.onClick && i.onClick(slotProps)"
|
||||||
</a-button>
|
>
|
||||||
</template>
|
<a-button
|
||||||
|
:disabled="i.disabled"
|
||||||
|
style="padding: 0"
|
||||||
|
type="link"
|
||||||
|
><AIcon :type="i.icon"
|
||||||
|
/></a-button>
|
||||||
|
</a-button>
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
</template>
|
</a-space>
|
||||||
</CardBox>
|
</template>
|
||||||
</template>
|
</JTable>
|
||||||
<template #state="slotProps">
|
</page-container>
|
||||||
<a-badge
|
|
||||||
:text="slotProps.state?.text"
|
|
||||||
:status="statusMap.get(slotProps.state?.value)"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
<template #action="slotProps">
|
|
||||||
<a-space :size="16">
|
|
||||||
<a-tooltip
|
|
||||||
v-for="i in getActions(slotProps, 'table')"
|
|
||||||
:key="i.key"
|
|
||||||
v-bind="i.tooltip"
|
|
||||||
>
|
|
||||||
<a-popconfirm
|
|
||||||
v-if="i.popConfirm"
|
|
||||||
v-bind="i.popConfirm"
|
|
||||||
:disabled="i.disabled"
|
|
||||||
>
|
|
||||||
<a-button
|
|
||||||
:disabled="i.disabled"
|
|
||||||
style="padding: 0"
|
|
||||||
type="link"
|
|
||||||
><AIcon :type="i.icon"
|
|
||||||
/></a-button>
|
|
||||||
</a-popconfirm>
|
|
||||||
<a-button
|
|
||||||
style="padding: 0"
|
|
||||||
type="link"
|
|
||||||
v-else
|
|
||||||
@click="i.onClick && i.onClick(slotProps)"
|
|
||||||
>
|
|
||||||
<a-button
|
|
||||||
:disabled="i.disabled"
|
|
||||||
style="padding: 0"
|
|
||||||
type="link"
|
|
||||||
><AIcon :type="i.icon"
|
|
||||||
/></a-button>
|
|
||||||
</a-button>
|
|
||||||
</a-tooltip>
|
|
||||||
</a-space>
|
|
||||||
</template>
|
|
||||||
</JTable>
|
|
||||||
<Import v-if="importVisible" @close="importVisible = false" />
|
<Import v-if="importVisible" @close="importVisible = false" />
|
||||||
<Export
|
<Export
|
||||||
v-if="exportVisible"
|
v-if="exportVisible"
|
||||||
|
@ -228,7 +241,12 @@
|
||||||
:api="api"
|
:api="api"
|
||||||
:type="type"
|
:type="type"
|
||||||
/>
|
/>
|
||||||
<Save v-if="visible" :data="current" @close="visible = false" @save="saveBtn" />
|
<Save
|
||||||
|
v-if="visible"
|
||||||
|
:data="current"
|
||||||
|
@close="visible = false"
|
||||||
|
@save="saveBtn"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
@ -367,8 +385,8 @@ const handleAdd = () => {
|
||||||
* 查看
|
* 查看
|
||||||
*/
|
*/
|
||||||
const handleView = (id: string) => {
|
const handleView = (id: string) => {
|
||||||
router.push('/device/instance/detail/' + id)
|
router.push('/device/instance/detail/' + id);
|
||||||
}
|
};
|
||||||
|
|
||||||
const getActions = (
|
const getActions = (
|
||||||
data: Partial<Record<string, any>>,
|
data: Partial<Record<string, any>>,
|
||||||
|
@ -519,10 +537,10 @@ const disabledSelectedDevice = async () => {
|
||||||
_selectedRowKeys.value = [];
|
_selectedRowKeys.value = [];
|
||||||
instanceRef.value?.reload();
|
instanceRef.value?.reload();
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
const saveBtn = () => {
|
const saveBtn = () => {
|
||||||
visible.value = false
|
visible.value = false;
|
||||||
instanceRef.value?.reload()
|
instanceRef.value?.reload();
|
||||||
}
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -33,7 +33,7 @@ const BaseColumns: JColumnProps[] = [
|
||||||
const EventColumns: JColumnProps[] = BaseColumns.concat([
|
const EventColumns: JColumnProps[] = BaseColumns.concat([
|
||||||
{
|
{
|
||||||
title: '事件级别',
|
title: '事件级别',
|
||||||
dataIndex: 'expands',
|
dataIndex: 'level',
|
||||||
scopedSlots: true,
|
scopedSlots: true,
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
@ -59,12 +59,12 @@ const PropertyColumns: JColumnProps[] = BaseColumns.concat([
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '属性来源',
|
title: '属性来源',
|
||||||
dataIndex: 'expands',
|
dataIndex: 'source',
|
||||||
scopedSlots: true,
|
scopedSlots: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '读写类型',
|
title: '读写类型',
|
||||||
dataIndex: 'expands',
|
dataIndex: 'type',
|
||||||
scopedSlots: true,
|
scopedSlots: true,
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
@ -77,7 +77,7 @@ const TagColumns: JColumnProps[] = BaseColumns.concat([
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '读写类型',
|
title: '读写类型',
|
||||||
dataIndex: 'expands',
|
dataIndex: 'type',
|
||||||
scopedSlots: true,
|
scopedSlots: true,
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<JTable :loading="loading" :data-source="data" size="small" :columns="columns" row-key="id">
|
<JTable :loading="loading" :data-source="data" size="small" :columns="columns" row-key="id" model="TABLE">
|
||||||
<template #headerTitle>
|
<template #headerTitle>
|
||||||
<a-input-search v-model:value="searchValue" placeholder="请输入名称" @search="handleSearch"></a-input-search>
|
<a-input-search v-model:value="searchValue" placeholder="请输入名称" @search="handleSearch"></a-input-search>
|
||||||
<PermissionButton :has-permission="permission" key="add" @click="handleAddClick"
|
<PermissionButton :has-permission="permission" key="add" @click="handleAddClick"
|
||||||
|
@ -11,11 +11,24 @@
|
||||||
</template>
|
</template>
|
||||||
新增
|
新增
|
||||||
</PermissionButton>
|
</PermissionButton>
|
||||||
<Edit
|
<Edit v-if="metadataStore.model.edit" :type="target" :tabs="type"></Edit>
|
||||||
v-if="metadataStore.model.edit"
|
</template>
|
||||||
:type="target"
|
<template #level="slotProps">
|
||||||
:tabs="type"
|
{{ levelMap[slotProps.expands?.level] || '-' }}
|
||||||
></Edit>
|
</template>
|
||||||
|
<template #async="slotProps">
|
||||||
|
{{ slotProps.async ? '是' : '否' }}
|
||||||
|
</template>
|
||||||
|
<template #valueType="slotProps">
|
||||||
|
{{ slotProps.valueType?.type }}
|
||||||
|
</template>
|
||||||
|
<template #source="slotProps">
|
||||||
|
{{ sourceMap[slotProps.expands?.source] }}
|
||||||
|
</template>
|
||||||
|
<template #type="slotProps">
|
||||||
|
<a-tag v-for="item in (slotProps.expands?.type || [])" :key="item">
|
||||||
|
{{ expandsType[item] }}
|
||||||
|
</a-tag>
|
||||||
</template>
|
</template>
|
||||||
</JTable>
|
</JTable>
|
||||||
</template>
|
</template>
|
||||||
|
@ -42,6 +55,21 @@ const productStore = useProductStore()
|
||||||
const loading = ref(false)
|
const loading = ref(false)
|
||||||
const data = ref<MetadataItem[]>([])
|
const data = ref<MetadataItem[]>([])
|
||||||
const { type, target = 'product' } = props
|
const { type, target = 'product' } = props
|
||||||
|
const levelMap = ref({
|
||||||
|
ordinary: '普通',
|
||||||
|
warn: '警告',
|
||||||
|
urgent: '紧急',
|
||||||
|
})
|
||||||
|
const sourceMap = ref({
|
||||||
|
device: '设备',
|
||||||
|
manual: '手动',
|
||||||
|
rule: '规则',
|
||||||
|
});
|
||||||
|
const expandsType = ref({
|
||||||
|
read: '读',
|
||||||
|
write: '写',
|
||||||
|
report: '上报',
|
||||||
|
});
|
||||||
const actions: JColumnProps[] = [
|
const actions: JColumnProps[] = [
|
||||||
{
|
{
|
||||||
title: '操作',
|
title: '操作',
|
||||||
|
@ -97,4 +125,5 @@ const operateLimits = (action: 'add' | 'updata', types: MetadataType) => {
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
<style scoped lang="less">
|
<style scoped lang="less">
|
||||||
|
|
||||||
</style>
|
</style>
|
|
@ -19,7 +19,7 @@
|
||||||
<a-tab-pane v-for="item in codecs" :key="item.id" :tab="item.name">
|
<a-tab-pane v-for="item in codecs" :key="item.id" :tab="item.name">
|
||||||
<div class="cat-panel">
|
<div class="cat-panel">
|
||||||
<!-- TODO 代码编辑器 -->
|
<!-- TODO 代码编辑器 -->
|
||||||
{{ value }}
|
<MonacoEditor v-model="value" theme="vs" style="height: 100%"></MonacoEditor>
|
||||||
</div>
|
</div>
|
||||||
</a-tab-pane>
|
</a-tab-pane>
|
||||||
</a-tabs>
|
</a-tabs>
|
||||||
|
|
|
@ -36,7 +36,7 @@
|
||||||
<template #addonAfter>
|
<template #addonAfter>
|
||||||
<a-upload v-model:file-list="fileList" :before-upload="beforeUpload" accept=".json"
|
<a-upload v-model:file-list="fileList" :before-upload="beforeUpload" accept=".json"
|
||||||
:show-upload-list="false" :action="FILE_UPLOAD" @change="fileChange"
|
:show-upload-list="false" :action="FILE_UPLOAD" @change="fileChange"
|
||||||
:headers="{ 'X-Access-Token': token }">
|
:headers="{ 'X-Access-Token': getToken()}">
|
||||||
<upload-outlined class="upload-button"/>
|
<upload-outlined class="upload-button"/>
|
||||||
<!-- <button id="uploadFile" style="display: none;"></button> -->
|
<!-- <button id="uploadFile" style="display: none;"></button> -->
|
||||||
</a-upload>
|
</a-upload>
|
||||||
|
@ -45,7 +45,7 @@
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="物模型" v-bind="validateInfos.import" v-if="formModel.metadataType === 'script'">
|
<a-form-item label="物模型" v-bind="validateInfos.import" v-if="formModel.metadataType === 'script'">
|
||||||
<!-- TODO代码编辑器 -->
|
<!-- TODO代码编辑器 -->
|
||||||
<a-textarea v-model:value="formModel.import"></a-textarea>
|
<MonacoEditor v-model="formModel.import" theme="vs" style="height: 300px"></MonacoEditor>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-form>
|
</a-form>
|
||||||
</a-modal>
|
</a-modal>
|
||||||
|
@ -64,8 +64,8 @@ import { useInstanceStore } from '@/store/instance'
|
||||||
import { useProductStore } from '@/store/product';
|
import { useProductStore } from '@/store/product';
|
||||||
import { UploadOutlined, ExclamationCircleOutlined } from '@ant-design/icons-vue';
|
import { UploadOutlined, ExclamationCircleOutlined } from '@ant-design/icons-vue';
|
||||||
import { FILE_UPLOAD } from '@/api/comm';
|
import { FILE_UPLOAD } from '@/api/comm';
|
||||||
import { LocalStore } from '@/utils/comm';
|
import { LocalStore, getToken } from '@/utils/comm';
|
||||||
import { TOKEN_KEY } from '@/utils/variable';
|
import MonacoEditor from '@/components/MonacoEditor/index.vue'
|
||||||
|
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
const instanceStore = useInstanceStore()
|
const instanceStore = useInstanceStore()
|
||||||
|
@ -147,7 +147,6 @@ const onSubmit = () => {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
const fileList = ref<UploadFile[]>([])
|
const fileList = ref<UploadFile[]>([])
|
||||||
const token = ref(LocalStore.get(TOKEN_KEY));
|
|
||||||
|
|
||||||
const productList = ref<DefaultOptionType[]>([])
|
const productList = ref<DefaultOptionType[]>([])
|
||||||
|
|
||||||
|
|
|
@ -32,16 +32,16 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<a-tab-pane tab="属性定义" key="properties">
|
<a-tab-pane tab="属性定义" key="properties">
|
||||||
<BaseMetadata target={props.type} type="properties" :permission="permission" />
|
<BaseMetadata :target="type" type="properties" :permission="permission" />
|
||||||
</a-tab-pane>
|
</a-tab-pane>
|
||||||
<a-tab-pane tab="功能定义" key="functions">
|
<a-tab-pane tab="功能定义" key="functions">
|
||||||
<BaseMetadata target={props.type} type="functions" :permission="permission" />
|
<BaseMetadata :target="type" type="functions" :permission="permission" />
|
||||||
</a-tab-pane>
|
</a-tab-pane>
|
||||||
<a-tab-pane tab="事件定义" key="events">
|
<a-tab-pane tab="事件定义" key="events">
|
||||||
<BaseMetadata target={props.type} type="events" :permission="permission" />
|
<BaseMetadata :target="type" type="events" :permission="permission" />
|
||||||
</a-tab-pane>
|
</a-tab-pane>
|
||||||
<a-tab-pane tab="标签定义" key="tags">
|
<a-tab-pane tab="标签定义" key="tags">
|
||||||
<BaseMetadata target={props.type} type="tags" :permission="permission" />
|
<BaseMetadata :target="type" type="tags" :permission="permission" />
|
||||||
</a-tab-pane>
|
</a-tab-pane>
|
||||||
</a-tabs>
|
</a-tabs>
|
||||||
<Import v-model:visible="visible" :type="type" @close="visible = false" />
|
<Import v-model:visible="visible" :type="type" @close="visible = false" />
|
||||||
|
@ -58,6 +58,7 @@ import { SystemConst } from '@/utils/consts'
|
||||||
import { useInstanceStore } from '@/store/instance'
|
import { useInstanceStore } from '@/store/instance'
|
||||||
import Import from './Import/index.vue'
|
import Import from './Import/index.vue'
|
||||||
import Cat from './Cat/index.vue'
|
import Cat from './Cat/index.vue'
|
||||||
|
import BaseMetadata from './Base/index.vue'
|
||||||
|
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
const instanceStore = useInstanceStore()
|
const instanceStore = useInstanceStore()
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
ref="bindDeviceRef"
|
ref="bindDeviceRef"
|
||||||
:columns="columns"
|
:columns="columns"
|
||||||
:request="queryUnbounded"
|
:request="queryUnbounded"
|
||||||
|
model="TABLE"
|
||||||
:defaultParams="{
|
:defaultParams="{
|
||||||
sorts: [{ name: 'createTime', order: 'desc' }],
|
sorts: [{ name: 'createTime', order: 'desc' }],
|
||||||
}"
|
}"
|
||||||
|
|
|
@ -0,0 +1,63 @@
|
||||||
|
<template>
|
||||||
|
<a-modal
|
||||||
|
:maskClosable="false"
|
||||||
|
width="1000px"
|
||||||
|
:visible="true"
|
||||||
|
title="详情"
|
||||||
|
okText="确定"
|
||||||
|
cancelText="取消"
|
||||||
|
@ok="handleCancel"
|
||||||
|
@cancel="handleCancel"
|
||||||
|
>
|
||||||
|
<div style="margin-top: 10px">
|
||||||
|
<a-descriptions
|
||||||
|
:column="2"
|
||||||
|
bordered
|
||||||
|
:contentStyle="{ minWidth: '300px' }"
|
||||||
|
:labelStyle="{ minWidth: '120px' }"
|
||||||
|
>
|
||||||
|
<a-descriptions-item label="充值金额">{{
|
||||||
|
data.chargeMoney
|
||||||
|
}}</a-descriptions-item>
|
||||||
|
<a-descriptions-item label="账户id">{{
|
||||||
|
data?.rechargeId
|
||||||
|
}}</a-descriptions-item>
|
||||||
|
<a-descriptions-item label="平台对接">{{
|
||||||
|
data.configName
|
||||||
|
}}</a-descriptions-item>
|
||||||
|
<a-descriptions-item label="订单号">{{
|
||||||
|
data.orderNumber
|
||||||
|
}}</a-descriptions-item>
|
||||||
|
<a-descriptions-item label="支付方式">{{
|
||||||
|
data.paymentType
|
||||||
|
}}</a-descriptions-item>
|
||||||
|
<a-descriptions-item label="支付URL">
|
||||||
|
<div style="height: 100px; overflow: auto">
|
||||||
|
{{ data.url ? data.url : '' }}
|
||||||
|
</div>
|
||||||
|
</a-descriptions-item>
|
||||||
|
<a-descriptions-item label="订单时间">{{
|
||||||
|
data.createTime
|
||||||
|
? moment(data.createTime).format('YYYY-MM-DD HH:mm:ss')
|
||||||
|
: '-'
|
||||||
|
}}</a-descriptions-item>
|
||||||
|
</a-descriptions>
|
||||||
|
</div>
|
||||||
|
</a-modal>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import moment from 'moment';
|
||||||
|
const emit = defineEmits(['close']);
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
data: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const handleCancel = () => {
|
||||||
|
emit('close');
|
||||||
|
};
|
||||||
|
</script>
|
|
@ -0,0 +1,191 @@
|
||||||
|
<template>
|
||||||
|
<a-modal
|
||||||
|
:maskClosable="false"
|
||||||
|
width="600px"
|
||||||
|
:visible="true"
|
||||||
|
title="充值"
|
||||||
|
@ok="handleOk"
|
||||||
|
@cancel="handleCancel"
|
||||||
|
:confirmLoading="btnLoading"
|
||||||
|
>
|
||||||
|
<div>
|
||||||
|
<div class="modal-info">
|
||||||
|
<AIcon
|
||||||
|
type="ExclamationCircleOutlined"
|
||||||
|
style="margin-right: 6px"
|
||||||
|
/>暂只支持移动OneLink平台
|
||||||
|
</div>
|
||||||
|
<a-form
|
||||||
|
layout="vertical"
|
||||||
|
ref="formRef"
|
||||||
|
:rules="rules"
|
||||||
|
:model="modelRef"
|
||||||
|
>
|
||||||
|
<a-form-item label="平台对接" name="configId">
|
||||||
|
<a-select
|
||||||
|
v-model:value="modelRef.configId"
|
||||||
|
:options="configList"
|
||||||
|
allowClear
|
||||||
|
show-search
|
||||||
|
style="width: 100%"
|
||||||
|
placeholder="请选择平台对接"
|
||||||
|
>
|
||||||
|
</a-select>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="账户id" name="rechargeId">
|
||||||
|
<a-input
|
||||||
|
v-model:value="modelRef.rechargeId"
|
||||||
|
placeholder="请输入账户id"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="充值金额" name="chargeMoney">
|
||||||
|
<a-input-number
|
||||||
|
allowClear
|
||||||
|
:precision="2"
|
||||||
|
style="width: 100%"
|
||||||
|
v-model:value="modelRef.chargeMoney"
|
||||||
|
:min="1"
|
||||||
|
:max="500"
|
||||||
|
placeholder="请输入1~500之间的金额"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
|
||||||
|
<a-form-item label="支付方式" name="paymentType">
|
||||||
|
<a-select
|
||||||
|
allowClear
|
||||||
|
:options="PaymentMethod"
|
||||||
|
v-model:value="modelRef.paymentType"
|
||||||
|
placeholder="请选择支付方式"
|
||||||
|
>
|
||||||
|
</a-select>
|
||||||
|
</a-form-item>
|
||||||
|
</a-form>
|
||||||
|
</div>
|
||||||
|
</a-modal>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { queryPlatformNoPage, recharge } from '@/api/iot-card/cardManagement';
|
||||||
|
import { message } from 'ant-design-vue';
|
||||||
|
import { PaymentMethod } from '@/views/iot-card/data';
|
||||||
|
|
||||||
|
const emit = defineEmits(['change']);
|
||||||
|
|
||||||
|
const btnLoading = ref<boolean>(false);
|
||||||
|
const configList = ref<Record<string, any>[]>([]);
|
||||||
|
|
||||||
|
const formRef = ref();
|
||||||
|
|
||||||
|
const modelRef = reactive({
|
||||||
|
configId: undefined,
|
||||||
|
rechargeId: '',
|
||||||
|
chargeMoney: undefined,
|
||||||
|
paymentType: undefined,
|
||||||
|
});
|
||||||
|
|
||||||
|
const rules = {
|
||||||
|
configId: [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: '请选择平台对接',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
max: 64,
|
||||||
|
message: '最多输入64个字符',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
rechargeId: [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: '请输入账户id',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
max: 64,
|
||||||
|
message: '最多输入64个字符',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
chargeMoney: [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: '请输入充值金额',
|
||||||
|
},
|
||||||
|
// {
|
||||||
|
// min: 1,
|
||||||
|
// max: 500,
|
||||||
|
// message: '请输入1~500之间的数字',
|
||||||
|
// },
|
||||||
|
],
|
||||||
|
paymentType: [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: '请选择支付方式',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
const queryProvidersList = () => {
|
||||||
|
queryPlatformNoPage({
|
||||||
|
paging: false,
|
||||||
|
terms: [
|
||||||
|
{
|
||||||
|
terms: [
|
||||||
|
{
|
||||||
|
column: 'operatorName',
|
||||||
|
termType: 'eq',
|
||||||
|
value: 'onelink',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
column: 'state',
|
||||||
|
termType: 'eq',
|
||||||
|
value: 'enabled',
|
||||||
|
type: 'and',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}).then((res: any) => {
|
||||||
|
configList.value = res.result.map((item: any) => ({
|
||||||
|
label: item.name,
|
||||||
|
value: item.id,
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleCancel = () => {
|
||||||
|
emit('change');
|
||||||
|
formRef.value.resetFields();
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleOk = () => {
|
||||||
|
formRef.value
|
||||||
|
.validate()
|
||||||
|
.then(async () => {
|
||||||
|
btnLoading.value = true;
|
||||||
|
const resp: any = await recharge(toRaw(modelRef));
|
||||||
|
btnLoading.value = false;
|
||||||
|
if (resp.status === 200) {
|
||||||
|
if (resp.result === '失败') {
|
||||||
|
message.error('缴费失败');
|
||||||
|
} else {
|
||||||
|
window.open(resp.result);
|
||||||
|
}
|
||||||
|
emit('change');
|
||||||
|
formRef.value.resetFields();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((err: any) => {
|
||||||
|
console.log('error', err);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
queryProvidersList();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="less">
|
||||||
|
.modal-info {
|
||||||
|
color: rgba(0, 0, 0, 0.55);
|
||||||
|
background-color: #f6f6f6;
|
||||||
|
padding: 6px 12px;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -1,8 +1,184 @@
|
||||||
<!-- 充值管理 -->
|
<!-- 充值管理 -->
|
||||||
<template>
|
<template>
|
||||||
<div class="page-container">充值管理</div>
|
<div class="page-container">
|
||||||
|
<Search
|
||||||
|
:columns="columns"
|
||||||
|
target="iot-card-management-search"
|
||||||
|
@search="handleSearch"
|
||||||
|
/>
|
||||||
|
<JTable
|
||||||
|
ref="rechargeRef"
|
||||||
|
:columns="columns"
|
||||||
|
:request="queryRechargeList"
|
||||||
|
model="TABLE"
|
||||||
|
:defaultParams="{ sorts: [{ name: 'createTime', order: 'desc' }] }"
|
||||||
|
:params="params"
|
||||||
|
>
|
||||||
|
<template #headerTitle>
|
||||||
|
<a-space>
|
||||||
|
<a-button type="primary" @click="visible = true">
|
||||||
|
充值
|
||||||
|
</a-button>
|
||||||
|
<div class="tips-text">
|
||||||
|
<span style="margin-right: 8px; font-size: 16px">
|
||||||
|
<AIcon type="ExclamationCircleOutlined"></AIcon>
|
||||||
|
</span>
|
||||||
|
本平台仅提供充值入口,具体充值结果需以运营商的充值结果为准
|
||||||
|
</div>
|
||||||
|
</a-space>
|
||||||
|
</template>
|
||||||
|
<template #createTime="slotProps">
|
||||||
|
{{
|
||||||
|
slotProps.createTime
|
||||||
|
? moment(slotProps.createTime).format(
|
||||||
|
'YYYY-MM-DD HH:mm:ss',
|
||||||
|
)
|
||||||
|
: ''
|
||||||
|
}}
|
||||||
|
</template>
|
||||||
|
<template #action="slotProps">
|
||||||
|
<a-space :size="16">
|
||||||
|
<a-tooltip
|
||||||
|
v-for="i in getActions(slotProps)"
|
||||||
|
:key="i.key"
|
||||||
|
v-bind="i.tooltip"
|
||||||
|
>
|
||||||
|
<a-popconfirm v-if="i.popConfirm" v-bind="i.popConfirm">
|
||||||
|
<a-button
|
||||||
|
:disabled="i.disabled"
|
||||||
|
style="padding: 0"
|
||||||
|
type="link"
|
||||||
|
><AIcon :type="i.icon"
|
||||||
|
/></a-button>
|
||||||
|
</a-popconfirm>
|
||||||
|
<a-button
|
||||||
|
style="padding: 0"
|
||||||
|
type="link"
|
||||||
|
v-else
|
||||||
|
@click="i.onClick && i.onClick(slotProps)"
|
||||||
|
>
|
||||||
|
<a-button
|
||||||
|
:disabled="i.disabled"
|
||||||
|
style="padding: 0"
|
||||||
|
type="link"
|
||||||
|
><AIcon :type="i.icon"
|
||||||
|
/></a-button>
|
||||||
|
</a-button>
|
||||||
|
</a-tooltip>
|
||||||
|
</a-space>
|
||||||
|
</template>
|
||||||
|
</JTable>
|
||||||
|
<!-- 充值 -->
|
||||||
|
<Save v-if="visible" @change="saveChange" />
|
||||||
|
<Detail v-if="detailVisible" :data="current" @close="close" />
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts"></script>
|
<script setup lang="ts">
|
||||||
|
import moment from 'moment';
|
||||||
|
import type { ActionsType } from '@/components/Table';
|
||||||
|
import { queryRechargeList } from '@/api/iot-card/cardManagement';
|
||||||
|
import Save from './Save.vue';
|
||||||
|
import Detail from './Detail.vue';
|
||||||
|
|
||||||
<style scoped lang="less"></style>
|
const rechargeRef = ref<Record<string, any>>({});
|
||||||
|
const params = ref<Record<string, any>>({});
|
||||||
|
const visible = ref<boolean>(false);
|
||||||
|
const detailVisible = ref<boolean>(false);
|
||||||
|
const current = ref<Record<string, any>>({});
|
||||||
|
|
||||||
|
const columns = [
|
||||||
|
{
|
||||||
|
title: '充值金额',
|
||||||
|
dataIndex: 'chargeMoney',
|
||||||
|
key: 'chargeMoney',
|
||||||
|
ellipsis: true,
|
||||||
|
search: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '支付方式',
|
||||||
|
dataIndex: 'paymentType',
|
||||||
|
key: 'paymentType',
|
||||||
|
search: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '订单号',
|
||||||
|
dataIndex: 'orderNumber',
|
||||||
|
key: 'orderNumber',
|
||||||
|
ellipsis: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '支付URL',
|
||||||
|
dataIndex: 'url',
|
||||||
|
key: 'url',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '订单时间',
|
||||||
|
dataIndex: 'createTime',
|
||||||
|
key: 'createTime',
|
||||||
|
scopedSlots: true,
|
||||||
|
search: {
|
||||||
|
type: 'date',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '操作',
|
||||||
|
key: 'action',
|
||||||
|
fixed: 'right',
|
||||||
|
scopedSlots: true,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const getActions = (data: Partial<Record<string, any>>): ActionsType[] => {
|
||||||
|
if (!data) return [];
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
key: 'view',
|
||||||
|
text: '查看',
|
||||||
|
tooltip: {
|
||||||
|
title: '查看',
|
||||||
|
},
|
||||||
|
icon: 'EyeOutlined',
|
||||||
|
onClick: () => {
|
||||||
|
detailVisible.value = true;
|
||||||
|
current.value = data;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSearch = (params: any) => {
|
||||||
|
console.log(params);
|
||||||
|
params.value = params;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 充值关闭弹窗
|
||||||
|
* @param val 加载表格
|
||||||
|
*/
|
||||||
|
const saveChange = (val: any) => {
|
||||||
|
visible.value = false;
|
||||||
|
if (val) {
|
||||||
|
rechargeRef.value?.reload();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查看详情弹窗关闭
|
||||||
|
*/
|
||||||
|
const close = () => {
|
||||||
|
detailVisible.value = false;
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="less">
|
||||||
|
.tips-text {
|
||||||
|
padding-left: 24px;
|
||||||
|
background: #fff;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<template>
|
<template>
|
||||||
<a-spin :spinning="loading">
|
<a-spin :spinning="loading">
|
||||||
<a-card :bordered="false">
|
<a-card :bordered="false">
|
||||||
<div v-if="type">
|
<div v-if="type && modeType === 'add'">
|
||||||
<Provider
|
<Provider
|
||||||
@onClick="goProviders"
|
@onClick="goProviders"
|
||||||
:dataSource="dataSource"
|
:dataSource="dataSource"
|
||||||
|
@ -14,9 +14,21 @@
|
||||||
:provider="provider"
|
:provider="provider"
|
||||||
:data="data"
|
:data="data"
|
||||||
/>
|
/>
|
||||||
<Media v-if="showType === 'media'" :provider="provider" />
|
<Media
|
||||||
<Channel v-if="showType === 'channel'" :provider="provider" />
|
v-if="showType === 'media'"
|
||||||
<Edge v-if="showType === 'edge'" :provider="provider" />
|
:provider="provider"
|
||||||
|
:data="data"
|
||||||
|
/>
|
||||||
|
<Channel
|
||||||
|
v-if="showType === 'channel'"
|
||||||
|
:provider="provider"
|
||||||
|
:data="data"
|
||||||
|
/>
|
||||||
|
<Edge
|
||||||
|
v-if="showType === 'edge'"
|
||||||
|
:provider="provider"
|
||||||
|
:data="data"
|
||||||
|
/>
|
||||||
<Cloud
|
<Cloud
|
||||||
v-if="showType === 'cloud'"
|
v-if="showType === 'cloud'"
|
||||||
:provider="provider"
|
:provider="provider"
|
||||||
|
@ -37,10 +49,10 @@ import Channel from '../components/Channel/index.vue';
|
||||||
import Edge from '../components/Edge/index.vue';
|
import Edge from '../components/Edge/index.vue';
|
||||||
import Cloud from '../components/Cloud/index.vue';
|
import Cloud from '../components/Cloud/index.vue';
|
||||||
|
|
||||||
// const router = useRouter();
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
|
|
||||||
const id = route.query.id;
|
const modeType = route.params.type as string;
|
||||||
|
const id = route.params.id as string;
|
||||||
|
|
||||||
const dataSource = ref([]);
|
const dataSource = ref([]);
|
||||||
const type = ref(false);
|
const type = ref(false);
|
||||||
|
@ -53,7 +65,6 @@ const goProviders = (param: object) => {
|
||||||
showType.value = param.type;
|
showType.value = param.type;
|
||||||
provider.value = param;
|
provider.value = param;
|
||||||
type.value = false;
|
type.value = false;
|
||||||
console.log(1123, showType.value, param);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const goBack = () => {
|
const goBack = () => {
|
||||||
|
@ -61,80 +72,77 @@ const goBack = () => {
|
||||||
type.value = true;
|
type.value = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const getTypeList = (result: any[]) => {
|
||||||
|
const list = [];
|
||||||
|
const media: any[] = [];
|
||||||
|
const network: any[] = [];
|
||||||
|
const cloud: any[] = [];
|
||||||
|
const channel: any[] = [];
|
||||||
|
const edge: any[] = [];
|
||||||
|
result.map((item) => {
|
||||||
|
if (item.id === 'fixed-media' || item.id === 'gb28181-2016') {
|
||||||
|
item.type = 'media';
|
||||||
|
media.push(item);
|
||||||
|
} else if (item.id === 'OneNet' || item.id === 'Ctwing') {
|
||||||
|
item.type = 'cloud';
|
||||||
|
cloud.push(item);
|
||||||
|
} else if (item.id === 'modbus-tcp' || item.id === 'opc-ua') {
|
||||||
|
item.type = 'channel';
|
||||||
|
channel.push(item);
|
||||||
|
} else if (
|
||||||
|
item.id === 'official-edge-gateway' ||
|
||||||
|
item.id === 'edge-child-device'
|
||||||
|
) {
|
||||||
|
item.type = 'edge';
|
||||||
|
edge.push(item);
|
||||||
|
} else {
|
||||||
|
item.type = 'network';
|
||||||
|
network.push(item);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
network.length &&
|
||||||
|
list.push({
|
||||||
|
list: [...network],
|
||||||
|
title: '自定义设备接入',
|
||||||
|
});
|
||||||
|
media.length &&
|
||||||
|
list.push({
|
||||||
|
list: [...media],
|
||||||
|
title: '视频类设备接入',
|
||||||
|
});
|
||||||
|
cloud.length &&
|
||||||
|
list.push({
|
||||||
|
list: [...cloud],
|
||||||
|
title: '云平台接入',
|
||||||
|
});
|
||||||
|
channel.length &&
|
||||||
|
list.push({
|
||||||
|
list: [...channel],
|
||||||
|
title: '通道类设备接入',
|
||||||
|
});
|
||||||
|
edge.length &&
|
||||||
|
list.push({
|
||||||
|
list: [...edge],
|
||||||
|
title: '官方接入',
|
||||||
|
});
|
||||||
|
|
||||||
|
return list;
|
||||||
|
};
|
||||||
|
|
||||||
const queryProviders = async () => {
|
const queryProviders = async () => {
|
||||||
const resp = await getProviders();
|
const resp = await getProviders();
|
||||||
if (resp.status === 200) {
|
if (resp.status === 200) {
|
||||||
const media: any[] = [];
|
dataSource.value = getTypeList(resp.result);
|
||||||
const network: any[] = [];
|
|
||||||
const cloud: any[] = [];
|
|
||||||
const channel: any[] = [];
|
|
||||||
const edge: any[] = [];
|
|
||||||
resp.result.map((item) => {
|
|
||||||
if (item.id === 'fixed-media' || item.id === 'gb28181-2016') {
|
|
||||||
item.type = 'media';
|
|
||||||
media.push(item);
|
|
||||||
} else if (item.id === 'OneNet' || item.id === 'Ctwing') {
|
|
||||||
item.type = 'cloud';
|
|
||||||
cloud.push(item);
|
|
||||||
} else if (item.id === 'modbus-tcp' || item.id === 'opc-ua') {
|
|
||||||
item.type = 'channel';
|
|
||||||
channel.push(item);
|
|
||||||
} else if (
|
|
||||||
item.id === 'official-edge-gateway' ||
|
|
||||||
item.id === 'edge-child-device'
|
|
||||||
) {
|
|
||||||
item.type = 'edge';
|
|
||||||
edge.push(item);
|
|
||||||
} else {
|
|
||||||
item.type = 'network';
|
|
||||||
network.push(item);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
const list = [];
|
|
||||||
if (network.length) {
|
|
||||||
list.push({
|
|
||||||
// type: 'network',
|
|
||||||
list: [...network],
|
|
||||||
title: '自定义设备接入',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (media.length) {
|
|
||||||
list.push({
|
|
||||||
// type: 'media',
|
|
||||||
list: [...media],
|
|
||||||
title: '视频类设备接入',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (cloud.length) {
|
|
||||||
list.push({
|
|
||||||
// type: 'cloud',
|
|
||||||
list: [...cloud],
|
|
||||||
title: '云平台接入',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (channel.length) {
|
|
||||||
list.push({
|
|
||||||
// type: 'channel',
|
|
||||||
list: [...channel],
|
|
||||||
title: '通道类设备接入',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (edge.length) {
|
|
||||||
list.push({
|
|
||||||
// type: 'edge',
|
|
||||||
list: [...edge],
|
|
||||||
title: '官方接入',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
dataSource.value = list;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const getProvidersData = async () => {
|
const getProvidersData = async () => {
|
||||||
if (id) {
|
if (id && modeType !== 'add') {
|
||||||
getProviders().then((response) => {
|
getProviders().then((response) => {
|
||||||
if (response.status === 200) {
|
if (response.status === 200) {
|
||||||
dataSource.value = response.result.filter(
|
const list = getTypeList(response.result);
|
||||||
|
dataSource.value = list.filter(
|
||||||
(item) =>
|
(item) =>
|
||||||
item.channel === 'network' ||
|
item.channel === 'network' ||
|
||||||
item.channel === 'child-device',
|
item.channel === 'child-device',
|
||||||
|
@ -144,15 +152,21 @@ const getProvidersData = async () => {
|
||||||
const dt = response.result.find(
|
const dt = response.result.find(
|
||||||
(item) => item?.id === resp.result.provider,
|
(item) => item?.id === resp.result.provider,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
response.result.forEach((item) => {
|
||||||
|
if (item.id === resp.result.provider) {
|
||||||
|
resp.result.type = item.type;
|
||||||
|
showType.value = item.type;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
provider.value = dt;
|
provider.value = dt;
|
||||||
data.value = resp.result;
|
data.value = resp.result;
|
||||||
type.value = false;
|
type.value = false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
loading.value = false;
|
|
||||||
} else {
|
|
||||||
loading.value = false;
|
|
||||||
}
|
}
|
||||||
|
loading.value = false;
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
type.value = true;
|
type.value = true;
|
||||||
|
|
|
@ -39,7 +39,10 @@
|
||||||
/>
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item>
|
<a-form-item>
|
||||||
<a-button type="primary" html-type="submit"
|
<a-button
|
||||||
|
v-if="modeType !== 'view'"
|
||||||
|
type="primary"
|
||||||
|
html-type="submit"
|
||||||
>保存</a-button
|
>保存</a-button
|
||||||
>
|
>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
@ -93,18 +96,23 @@ interface FormState {
|
||||||
description: string;
|
description: string;
|
||||||
}
|
}
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const id = route.query.id;
|
const modeType = route.params.type as string;
|
||||||
|
const id = route.params.id as string;
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
provider: {
|
provider: {
|
||||||
type: Object,
|
type: Object,
|
||||||
default: () => {},
|
default: () => {},
|
||||||
},
|
},
|
||||||
|
data: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {},
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const type = ref(props.provider.type);
|
const type = ref(props.provider.type);
|
||||||
|
|
||||||
const formState = reactive<FormState>({
|
const formState = ref<FormState>({
|
||||||
name: '',
|
name: '',
|
||||||
description: '',
|
description: '',
|
||||||
});
|
});
|
||||||
|
@ -117,7 +125,10 @@ const onFinish = async (values: any) => {
|
||||||
transport: ProtocolMapping.get(providerId),
|
transport: ProtocolMapping.get(providerId),
|
||||||
channel: providerId === 'modbus-tcp' ? 'modbus' : 'opc-ua',
|
channel: providerId === 'modbus-tcp' ? 'modbus' : 'opc-ua',
|
||||||
};
|
};
|
||||||
const resp = !!id ? await update({ ...params, id }) : await save(params);
|
const resp =
|
||||||
|
!!id && modeType !== 'add'
|
||||||
|
? await update({ ...params, id })
|
||||||
|
: await save(params);
|
||||||
if (resp.status === 200) {
|
if (resp.status === 200) {
|
||||||
message.success('操作成功!');
|
message.success('操作成功!');
|
||||||
// if (params.get('save')) {
|
// if (params.get('save')) {
|
||||||
|
@ -132,6 +143,15 @@ const onFinish = async (values: any) => {
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
if (modeType !== 'add') {
|
||||||
|
formState.value = {
|
||||||
|
name: props.data.name,
|
||||||
|
description: props.data?.description || '',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
|
|
|
@ -199,7 +199,7 @@
|
||||||
<title-component data="基本信息" />
|
<title-component data="基本信息" />
|
||||||
<div>
|
<div>
|
||||||
<a-form
|
<a-form
|
||||||
:model="form"
|
:model="formData"
|
||||||
name="basic"
|
name="basic"
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
layout="vertical"
|
layout="vertical"
|
||||||
|
@ -219,14 +219,14 @@
|
||||||
>
|
>
|
||||||
<a-input
|
<a-input
|
||||||
placeholder="请输入名称"
|
placeholder="请输入名称"
|
||||||
v-model:value="form.name"
|
v-model:value="formData.name"
|
||||||
/>
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="说明" name="description">
|
<a-form-item label="说明" name="description">
|
||||||
<a-textarea
|
<a-textarea
|
||||||
placeholder="请输入说明"
|
placeholder="请输入说明"
|
||||||
:rows="4"
|
:rows="4"
|
||||||
v-model:value="form.description"
|
v-model:value="formData.description"
|
||||||
show-count
|
show-count
|
||||||
:maxlength="200"
|
:maxlength="200"
|
||||||
/>
|
/>
|
||||||
|
@ -277,16 +277,20 @@
|
||||||
<a-button
|
<a-button
|
||||||
v-if="[0, 1].includes(current)"
|
v-if="[0, 1].includes(current)"
|
||||||
type="primary"
|
type="primary"
|
||||||
|
style="margin-right: 8px"
|
||||||
@click="next"
|
@click="next"
|
||||||
>
|
>
|
||||||
下一步
|
下一步
|
||||||
</a-button>
|
</a-button>
|
||||||
<a-button v-if="current === 2" type="primary" @click="saveData">
|
<a-button
|
||||||
|
v-if="current === 2 && modeType !== 'view'"
|
||||||
|
type="primary"
|
||||||
|
style="margin-right: 8px"
|
||||||
|
@click="saveData"
|
||||||
|
>
|
||||||
保存
|
保存
|
||||||
</a-button>
|
</a-button>
|
||||||
<a-button v-if="current > 0" style="margin-left: 8px" @click="prev">
|
<a-button v-if="current > 0" @click="prev"> 上一步 </a-button>
|
||||||
上一步
|
|
||||||
</a-button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -379,7 +383,8 @@ interface Form {
|
||||||
description: string;
|
description: string;
|
||||||
}
|
}
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const id = route.query.id;
|
const modeType = route.params.type as string;
|
||||||
|
const id = route.params.id as string;
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
provider: {
|
provider: {
|
||||||
|
@ -396,13 +401,13 @@ const channel = ref(props.provider.channel);
|
||||||
const formRef1 = ref<FormInstance>();
|
const formRef1 = ref<FormInstance>();
|
||||||
const formRef2 = ref<FormInstance>();
|
const formRef2 = ref<FormInstance>();
|
||||||
|
|
||||||
const formState = reactive<FormState>({
|
const formState = ref<FormState>({
|
||||||
apiAddress: 'https://ag-api.ctwing.cn/',
|
apiAddress: 'https://ag-api.ctwing.cn/',
|
||||||
appKey: '',
|
appKey: '',
|
||||||
appSecret: '',
|
appSecret: '',
|
||||||
description: '',
|
description: '',
|
||||||
});
|
});
|
||||||
const form = reactive<Form>({
|
const formData = ref<Form>({
|
||||||
name: '',
|
name: '',
|
||||||
description: '',
|
description: '',
|
||||||
});
|
});
|
||||||
|
@ -415,9 +420,7 @@ const allProcotolList = ref([]);
|
||||||
const procotolCurrent = ref('');
|
const procotolCurrent = ref('');
|
||||||
|
|
||||||
const procotolChange = (id: string) => {
|
const procotolChange = (id: string) => {
|
||||||
if (!props.data?.id) {
|
procotolCurrent.value = id;
|
||||||
procotolCurrent.value = id;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const procotolSearch = (value: string) => {
|
const procotolSearch = (value: string) => {
|
||||||
|
@ -439,7 +442,7 @@ const saveData = async () => {
|
||||||
const params = {
|
const params = {
|
||||||
...data,
|
...data,
|
||||||
configuration: {
|
configuration: {
|
||||||
...formState,
|
...formState.value,
|
||||||
protocol: procotolCurrent.value,
|
protocol: procotolCurrent.value,
|
||||||
},
|
},
|
||||||
protocol: procotolCurrent.value,
|
protocol: procotolCurrent.value,
|
||||||
|
@ -447,7 +450,7 @@ const saveData = async () => {
|
||||||
transport: 'HTTP_SERVER',
|
transport: 'HTTP_SERVER',
|
||||||
};
|
};
|
||||||
const resp =
|
const resp =
|
||||||
props.data && props.data.id
|
!!id && modeType !== 'add'
|
||||||
? await update({
|
? await update({
|
||||||
...props.data,
|
...props.data,
|
||||||
...params,
|
...params,
|
||||||
|
@ -514,7 +517,16 @@ const next = async () => {
|
||||||
const prev = () => {
|
const prev = () => {
|
||||||
current.value = current.value - 1;
|
current.value = current.value - 1;
|
||||||
};
|
};
|
||||||
|
onMounted(() => {
|
||||||
|
if (modeType !== 'add') {
|
||||||
|
formState.value = props.data.configuration;
|
||||||
|
procotolCurrent.value = props.data.protocol;
|
||||||
|
formData.value = {
|
||||||
|
name: props.data.name,
|
||||||
|
description: props.data.description,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
watch(
|
watch(
|
||||||
current,
|
current,
|
||||||
(v) => {
|
(v) => {
|
||||||
|
|
|
@ -292,7 +292,7 @@
|
||||||
<title-component data="基本信息" />
|
<title-component data="基本信息" />
|
||||||
<div>
|
<div>
|
||||||
<a-form
|
<a-form
|
||||||
:model="form"
|
:model="formData"
|
||||||
name="basic"
|
name="basic"
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
layout="vertical"
|
layout="vertical"
|
||||||
|
@ -312,26 +312,18 @@
|
||||||
>
|
>
|
||||||
<a-input
|
<a-input
|
||||||
placeholder="请输入名称"
|
placeholder="请输入名称"
|
||||||
v-model:value="form.name"
|
v-model:value="formData.name"
|
||||||
/>
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="说明" name="description">
|
<a-form-item label="说明" name="description">
|
||||||
<a-textarea
|
<a-textarea
|
||||||
placeholder="请输入说明"
|
placeholder="请输入说明"
|
||||||
:rows="4"
|
:rows="4"
|
||||||
v-model:value="form.description"
|
v-model:value="formData.description"
|
||||||
show-count
|
show-count
|
||||||
:maxlength="200"
|
:maxlength="200"
|
||||||
/>
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<!-- <a-form-item>
|
|
||||||
<a-button
|
|
||||||
v-if="current !== 1"
|
|
||||||
type="primary"
|
|
||||||
html-type="submit"
|
|
||||||
>保存</a-button
|
|
||||||
>
|
|
||||||
</a-form-item> -->
|
|
||||||
</a-form>
|
</a-form>
|
||||||
</div>
|
</div>
|
||||||
</a-col>
|
</a-col>
|
||||||
|
@ -378,16 +370,20 @@
|
||||||
<a-button
|
<a-button
|
||||||
v-if="[0, 1].includes(current)"
|
v-if="[0, 1].includes(current)"
|
||||||
type="primary"
|
type="primary"
|
||||||
|
style="margin-right: 8px"
|
||||||
@click="next"
|
@click="next"
|
||||||
>
|
>
|
||||||
下一步
|
下一步
|
||||||
</a-button>
|
</a-button>
|
||||||
<a-button v-if="current === 2" type="primary" @click="saveData">
|
<a-button
|
||||||
|
style="margin-right: 8px"
|
||||||
|
v-if="current === 2 && modeType !== 'view'"
|
||||||
|
type="primary"
|
||||||
|
@click="saveData"
|
||||||
|
>
|
||||||
保存
|
保存
|
||||||
</a-button>
|
</a-button>
|
||||||
<a-button v-if="current > 0" style="margin-left: 8px" @click="prev">
|
<a-button v-if="current > 0" @click="prev"> 上一步 </a-button>
|
||||||
上一步
|
|
||||||
</a-button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -483,7 +479,8 @@ interface Form {
|
||||||
description: string;
|
description: string;
|
||||||
}
|
}
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const id = route.query.id;
|
const modeType = route.params.type as string;
|
||||||
|
const id = route.params.id as string;
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
provider: {
|
provider: {
|
||||||
|
@ -500,14 +497,14 @@ const channel = ref(props.provider.channel);
|
||||||
const formRef1 = ref<FormInstance>();
|
const formRef1 = ref<FormInstance>();
|
||||||
const formRef2 = ref<FormInstance>();
|
const formRef2 = ref<FormInstance>();
|
||||||
|
|
||||||
const formState = reactive<FormState>({
|
const formState = ref<FormState>({
|
||||||
apiAddress: 'https://api.heclouds.com/',
|
apiAddress: 'https://api.heclouds.com/',
|
||||||
apiKey: '',
|
apiKey: '',
|
||||||
validateToken: '',
|
validateToken: '',
|
||||||
aesKey: '',
|
aesKey: '',
|
||||||
description: '',
|
description: '',
|
||||||
});
|
});
|
||||||
const form = reactive<Form>({
|
const formData = ref<Form>({
|
||||||
name: '',
|
name: '',
|
||||||
description: '',
|
description: '',
|
||||||
});
|
});
|
||||||
|
@ -520,9 +517,7 @@ const allProcotolList = ref([]);
|
||||||
const procotolCurrent = ref('');
|
const procotolCurrent = ref('');
|
||||||
|
|
||||||
const procotolChange = (id: string) => {
|
const procotolChange = (id: string) => {
|
||||||
if (!props.data?.id) {
|
procotolCurrent.value = id;
|
||||||
procotolCurrent.value = id;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const procotolSearch = (value: string) => {
|
const procotolSearch = (value: string) => {
|
||||||
|
@ -544,7 +539,7 @@ const saveData = async () => {
|
||||||
const params = {
|
const params = {
|
||||||
...data,
|
...data,
|
||||||
configuration: {
|
configuration: {
|
||||||
...formState,
|
...formState.value,
|
||||||
protocol: procotolCurrent.value,
|
protocol: procotolCurrent.value,
|
||||||
},
|
},
|
||||||
protocol: procotolCurrent.value,
|
protocol: procotolCurrent.value,
|
||||||
|
@ -552,7 +547,7 @@ const saveData = async () => {
|
||||||
transport: 'HTTP_SERVER',
|
transport: 'HTTP_SERVER',
|
||||||
};
|
};
|
||||||
const resp =
|
const resp =
|
||||||
props.data && props.data.id
|
!!id && modeType !== 'add'
|
||||||
? await update({
|
? await update({
|
||||||
...props.data,
|
...props.data,
|
||||||
...params,
|
...params,
|
||||||
|
@ -619,6 +614,17 @@ const prev = () => {
|
||||||
current.value = current.value - 1;
|
current.value = current.value - 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
if (modeType !== 'add') {
|
||||||
|
formState.value = props.data.configuration;
|
||||||
|
procotolCurrent.value = props.data.protocol;
|
||||||
|
formData.value = {
|
||||||
|
name: props.data.name,
|
||||||
|
description: props.data.description,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
current,
|
current,
|
||||||
(v) => {
|
(v) => {
|
||||||
|
|
|
@ -17,9 +17,6 @@
|
||||||
import Ctwing from './Ctwing.vue';
|
import Ctwing from './Ctwing.vue';
|
||||||
import OneNet from './OneNet.vue';
|
import OneNet from './OneNet.vue';
|
||||||
|
|
||||||
const route = useRoute();
|
|
||||||
const id = route.query.id;
|
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
provider: {
|
provider: {
|
||||||
type: Object,
|
type: Object,
|
||||||
|
|
|
@ -140,7 +140,7 @@
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item>
|
<a-form-item>
|
||||||
<a-button
|
<a-button
|
||||||
v-if="current !== 1"
|
v-if="current !== 1 && modeType !== 'view'"
|
||||||
type="primary"
|
type="primary"
|
||||||
html-type="submit"
|
html-type="submit"
|
||||||
>保存</a-button
|
>保存</a-button
|
||||||
|
@ -171,15 +171,22 @@
|
||||||
v-if="channel !== 'edge-child-device'"
|
v-if="channel !== 'edge-child-device'"
|
||||||
:class="current !== 1 ? 'steps-action' : 'steps-action-save'"
|
:class="current !== 1 ? 'steps-action' : 'steps-action-save'"
|
||||||
>
|
>
|
||||||
<a-button v-if="[0].includes(current)" @click="next">
|
<a-button
|
||||||
|
v-if="[0].includes(current)"
|
||||||
|
style="margin-right: 8px"
|
||||||
|
@click="next"
|
||||||
|
>
|
||||||
下一步
|
下一步
|
||||||
</a-button>
|
</a-button>
|
||||||
<a-button v-if="current === 1" type="primary" @click="saveData">
|
<a-button
|
||||||
|
v-if="current === 1 && modeType !== 'view'"
|
||||||
|
type="primary"
|
||||||
|
style="margin-right: 8px"
|
||||||
|
@click="saveData"
|
||||||
|
>
|
||||||
保存
|
保存
|
||||||
</a-button>
|
</a-button>
|
||||||
<a-button v-if="current > 0" style="margin-left: 8px" @click="prev">
|
<a-button v-if="current > 0" @click="prev"> 上一步 </a-button>
|
||||||
上一步
|
|
||||||
</a-button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -290,19 +297,25 @@ interface FormState {
|
||||||
description: string;
|
description: string;
|
||||||
}
|
}
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const id = route.query.id;
|
const modeType = route.params.type as string;
|
||||||
|
const id = route.params.id as string;
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
provider: {
|
provider: {
|
||||||
type: Object,
|
type: Object,
|
||||||
default: () => {},
|
default: () => {},
|
||||||
},
|
},
|
||||||
|
data: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {},
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const type = ref(props.provider.type);
|
const type = props.provider.type;
|
||||||
|
|
||||||
const channel = ref(props.provider.channel);
|
const channel = ref(props.provider.channel);
|
||||||
|
|
||||||
const formState = reactive<FormState>({
|
const formState = ref<FormState>({
|
||||||
name: '',
|
name: '',
|
||||||
description: '',
|
description: '',
|
||||||
});
|
});
|
||||||
|
@ -324,9 +337,10 @@ const onFinish = async (values: any) => {
|
||||||
transport: ProtocolMapping.get(providerId),
|
transport: ProtocolMapping.get(providerId),
|
||||||
};
|
};
|
||||||
if (networkCurrent.value) params.channelId = networkCurrent.value;
|
if (networkCurrent.value) params.channelId = networkCurrent.value;
|
||||||
console.log(1112, networkCurrent.value, params);
|
const resp =
|
||||||
|
!!id && modeType !== 'add'
|
||||||
const resp = !!id ? await update({ ...params, id }) : await save(params);
|
? await update({ ...params, id })
|
||||||
|
: await save(params);
|
||||||
if (resp.status === 200) {
|
if (resp.status === 200) {
|
||||||
message.success('操作成功!');
|
message.success('操作成功!');
|
||||||
// if (params.get('save')) {
|
// if (params.get('save')) {
|
||||||
|
@ -407,6 +421,13 @@ onMounted(() => {
|
||||||
if (props.provider.id === 'official-edge-gateway') {
|
if (props.provider.id === 'official-edge-gateway') {
|
||||||
queryNetworkList(props.provider.id, '');
|
queryNetworkList(props.provider.id, '');
|
||||||
}
|
}
|
||||||
|
if (modeType !== 'add') {
|
||||||
|
formState.value = {
|
||||||
|
name: props.data.name,
|
||||||
|
description: props.data?.description || '',
|
||||||
|
};
|
||||||
|
networkCurrent.value = props.data.channelId;
|
||||||
|
}
|
||||||
}),
|
}),
|
||||||
watch(
|
watch(
|
||||||
current,
|
current,
|
||||||
|
|
|
@ -436,17 +436,18 @@
|
||||||
<a-col :span="12">
|
<a-col :span="12">
|
||||||
<title-component data="基本信息" />
|
<title-component data="基本信息" />
|
||||||
<div>
|
<div>
|
||||||
<a-form :model="form" layout="vertical">
|
<a-form :model="formData" layout="vertical">
|
||||||
<a-form-item
|
<a-form-item
|
||||||
label="名称"
|
label="名称"
|
||||||
v-bind="validateInfos.name"
|
v-bind="validateInfos.name"
|
||||||
>
|
>
|
||||||
<a-input
|
<a-input
|
||||||
v-model:value="form.name"
|
v-model:value="formData.name"
|
||||||
allowClear
|
allowClear
|
||||||
placeholder="请输入名称"
|
placeholder="请输入名称"
|
||||||
/>
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
|
||||||
<a-form-item
|
<a-form-item
|
||||||
label="说明"
|
label="说明"
|
||||||
v-bind="validateInfos.description"
|
v-bind="validateInfos.description"
|
||||||
|
@ -454,7 +455,7 @@
|
||||||
<a-textarea
|
<a-textarea
|
||||||
placeholder="请输入说明"
|
placeholder="请输入说明"
|
||||||
:rows="4"
|
:rows="4"
|
||||||
v-model:value="form.description"
|
v-model:value="formData.description"
|
||||||
show-count
|
show-count
|
||||||
:maxlength="200"
|
:maxlength="200"
|
||||||
/>
|
/>
|
||||||
|
@ -494,15 +495,22 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="steps-action">
|
<div class="steps-action">
|
||||||
<a-button v-if="[0].includes(current)" @click="next">
|
<a-button
|
||||||
|
v-if="[0].includes(current)"
|
||||||
|
style="margin-right: 8px"
|
||||||
|
@click="next"
|
||||||
|
>
|
||||||
下一步
|
下一步
|
||||||
</a-button>
|
</a-button>
|
||||||
<a-button v-if="current === 1" type="primary" @click="saveData">
|
<a-button
|
||||||
|
v-if="current === 1 && modeType !== 'view'"
|
||||||
|
type="primary"
|
||||||
|
style="margin-right: 8px"
|
||||||
|
@click="saveData"
|
||||||
|
>
|
||||||
保存
|
保存
|
||||||
</a-button>
|
</a-button>
|
||||||
<a-button v-if="current > 0" style="margin-left: 8px" @click="prev">
|
<a-button v-if="current > 0" @click="prev"> 上一步 </a-button>
|
||||||
上一步
|
|
||||||
</a-button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -544,10 +552,15 @@ const props = defineProps({
|
||||||
type: Object,
|
type: Object,
|
||||||
default: () => {},
|
default: () => {},
|
||||||
},
|
},
|
||||||
|
data: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {},
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const id = route.query.id;
|
const modeType = route.params.type as string;
|
||||||
|
const id = route.params.id as string;
|
||||||
|
|
||||||
const activeKey: any = ref([]);
|
const activeKey: any = ref([]);
|
||||||
const clientHeight = document.body.clientHeight;
|
const clientHeight = document.body.clientHeight;
|
||||||
|
@ -559,11 +572,11 @@ const useForm = Form.useForm;
|
||||||
const current = ref(0);
|
const current = ref(0);
|
||||||
const stepCurrent = ref(0);
|
const stepCurrent = ref(0);
|
||||||
const steps = ref(['信令配置', '完成']);
|
const steps = ref(['信令配置', '完成']);
|
||||||
const form = reactive({
|
const formData = ref({
|
||||||
name: '',
|
name: '',
|
||||||
description: '',
|
description: '',
|
||||||
});
|
});
|
||||||
const formState = reactive<FormState>({
|
let formState = ref<FormState>({
|
||||||
domain: '',
|
domain: '',
|
||||||
sipId: '',
|
sipId: '',
|
||||||
shareCluster: true,
|
shareCluster: true,
|
||||||
|
@ -574,6 +587,7 @@ const formState = reactive<FormState>({
|
||||||
publicHost: '',
|
publicHost: '',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
let params = {
|
let params = {
|
||||||
configuration: {},
|
configuration: {},
|
||||||
};
|
};
|
||||||
|
@ -628,12 +642,13 @@ const handleChangeForm2Sip = (index: number) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const { resetFields, validate, validateInfos } = useForm(
|
const { resetFields, validate, validateInfos } = useForm(
|
||||||
form,
|
formData,
|
||||||
reactive({
|
reactive({
|
||||||
name: [
|
name: [
|
||||||
{ required: true, message: '请输入名称', trigger: 'blur' },
|
{ required: true, message: '请输入名称', trigger: 'blur' },
|
||||||
{ max: 64, message: '最多可输入64个字符' },
|
{ max: 64, message: '最多可输入64个字符' },
|
||||||
],
|
],
|
||||||
|
description: [{ max: 200, message: '最多可输入200个字符' }],
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -646,9 +661,11 @@ const saveData = () => {
|
||||||
transport: 'SIP',
|
transport: 'SIP',
|
||||||
channel: 'gb28181',
|
channel: 'gb28181',
|
||||||
};
|
};
|
||||||
const resp = !!id
|
|
||||||
? await update({ ...params, id })
|
const resp =
|
||||||
: await save(params);
|
!!id && modeType !== 'add'
|
||||||
|
? await update({ ...params, id })
|
||||||
|
: await save(params);
|
||||||
if (resp.status === 200) {
|
if (resp.status === 200) {
|
||||||
message.success('操作成功!');
|
message.success('操作成功!');
|
||||||
// if (params.get('save')) {
|
// if (params.get('save')) {
|
||||||
|
@ -723,6 +740,14 @@ onMounted(() => {
|
||||||
clustersList.value = list;
|
clustersList.value = list;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (modeType !== 'add') {
|
||||||
|
formState.value = props.data.configuration;
|
||||||
|
formData.value = {
|
||||||
|
name: props.data.name,
|
||||||
|
description: props.data?.description || '',
|
||||||
|
};
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
|
|
|
@ -39,7 +39,10 @@
|
||||||
/>
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item>
|
<a-form-item>
|
||||||
<a-button type="primary" html-type="submit"
|
<a-button
|
||||||
|
v-if="modeType !== 'view'"
|
||||||
|
type="primary"
|
||||||
|
html-type="submit"
|
||||||
>保存</a-button
|
>保存</a-button
|
||||||
>
|
>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
@ -72,7 +75,7 @@
|
||||||
</a-row>
|
</a-row>
|
||||||
</div>
|
</div>
|
||||||
<div v-else-if="channel === 'gb28181'">
|
<div v-else-if="channel === 'gb28181'">
|
||||||
<GB28181 :provider="props.provider"></GB28181>
|
<GB28181 :provider="props.provider" :data="props.data"></GB28181>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -88,18 +91,23 @@ interface FormState {
|
||||||
description: string;
|
description: string;
|
||||||
}
|
}
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const id = route.query.id;
|
const modeType = route.params.type as string;
|
||||||
|
const id = route.params.id as string;
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
provider: {
|
provider: {
|
||||||
type: Object,
|
type: Object,
|
||||||
default: () => {},
|
default: () => {},
|
||||||
},
|
},
|
||||||
|
data: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {},
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const channel = ref(props.provider.channel);
|
const channel = ref(props.provider.channel);
|
||||||
|
|
||||||
const formState = reactive<FormState>({
|
const formState = ref<FormState>({
|
||||||
name: '',
|
name: '',
|
||||||
description: '',
|
description: '',
|
||||||
});
|
});
|
||||||
|
@ -110,7 +118,10 @@ const onFinish = async (values: any) => {
|
||||||
transport: 'URL',
|
transport: 'URL',
|
||||||
channel: 'fixed-media',
|
channel: 'fixed-media',
|
||||||
};
|
};
|
||||||
const resp = !!id ? await update({ ...params, id }) : await save(params);
|
const resp =
|
||||||
|
!!id && modeType !== 'add'
|
||||||
|
? await update({ ...params, id })
|
||||||
|
: await save(params);
|
||||||
if (resp.status === 200) {
|
if (resp.status === 200) {
|
||||||
message.success('操作成功!');
|
message.success('操作成功!');
|
||||||
// if (params.get('save')) {
|
// if (params.get('save')) {
|
||||||
|
@ -125,6 +136,15 @@ const onFinish = async (values: any) => {
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
if (modeType !== 'add') {
|
||||||
|
formState.value = {
|
||||||
|
name: props.data.name,
|
||||||
|
description: props.data?.description || '',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
|
|
|
@ -138,7 +138,7 @@
|
||||||
<div>
|
<div>
|
||||||
<a-form
|
<a-form
|
||||||
ref="formRef"
|
ref="formRef"
|
||||||
:model="form"
|
:model="formData"
|
||||||
layout="vertical"
|
layout="vertical"
|
||||||
>
|
>
|
||||||
<a-form-item
|
<a-form-item
|
||||||
|
@ -146,7 +146,7 @@
|
||||||
v-bind="validateInfos.name"
|
v-bind="validateInfos.name"
|
||||||
>
|
>
|
||||||
<a-input
|
<a-input
|
||||||
v-model:value="form.name"
|
v-model:value="formData.name"
|
||||||
allowClear
|
allowClear
|
||||||
placeholder="请输入名称"
|
placeholder="请输入名称"
|
||||||
/>
|
/>
|
||||||
|
@ -158,7 +158,7 @@
|
||||||
<a-textarea
|
<a-textarea
|
||||||
placeholder="请输入说明"
|
placeholder="请输入说明"
|
||||||
:rows="4"
|
:rows="4"
|
||||||
v-model:value="form.description"
|
v-model:value="formData.description"
|
||||||
show-count
|
show-count
|
||||||
:maxlength="200"
|
:maxlength="200"
|
||||||
/>
|
/>
|
||||||
|
@ -295,13 +295,26 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="steps-action">
|
<div class="steps-action">
|
||||||
<a-button v-if="[0, 1].includes(current)" @click="next">
|
<a-button
|
||||||
|
v-if="[0, 1].includes(current)"
|
||||||
|
type="primary"
|
||||||
|
style="margin-right: 8px"
|
||||||
|
@click="next"
|
||||||
|
>
|
||||||
下一步
|
下一步
|
||||||
</a-button>
|
</a-button>
|
||||||
<a-button v-if="current === 2" type="primary" @click="saveData">
|
<a-button
|
||||||
|
v-if="current === 2 && modeType !== 'view'"
|
||||||
|
type="primary"
|
||||||
|
style="margin-right: 8px"
|
||||||
|
@click="saveData"
|
||||||
|
>
|
||||||
保存
|
保存
|
||||||
</a-button>
|
</a-button>
|
||||||
<a-button v-if="current > 0" style="margin-left: 8px" @click="prev">
|
<a-button
|
||||||
|
v-if="type === 'child-device' ? current > 1 : current > 0"
|
||||||
|
@click="prev"
|
||||||
|
>
|
||||||
上一步
|
上一步
|
||||||
</a-button>
|
</a-button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -524,7 +537,204 @@ const result2 = {
|
||||||
'### 认证说明\r\n\r\nCONNECT报文:\r\n```text\r\nclientId: 设备ID\r\nusername: secureId+"|"+timestamp\r\npassword: md5(secureId+"|"+timestamp+"|"+secureKey)\r\n ```\r\n\r\n说明: secureId以及secureKey在创建设备产品或设备实例时进行配置. \r\ntimestamp为当前时间戳(毫秒),与服务器时间不能相差5分钟.\r\nmd5为32位,不区分大小写.',
|
'### 认证说明\r\n\r\nCONNECT报文:\r\n```text\r\nclientId: 设备ID\r\nusername: secureId+"|"+timestamp\r\npassword: md5(secureId+"|"+timestamp+"|"+secureKey)\r\n ```\r\n\r\n说明: secureId以及secureKey在创建设备产品或设备实例时进行配置. \r\ntimestamp为当前时间戳(毫秒),与服务器时间不能相差5分钟.\r\nmd5为32位,不区分大小写.',
|
||||||
metadata: '',
|
metadata: '',
|
||||||
};
|
};
|
||||||
|
//测试数据
|
||||||
|
const networkData = {
|
||||||
|
COAP_SERVER: [
|
||||||
|
{
|
||||||
|
id: '1620352949679960064',
|
||||||
|
name: '前端测试1',
|
||||||
|
description: '前端测试1',
|
||||||
|
addresses: [
|
||||||
|
{
|
||||||
|
address: 'coap://111.0.0:88',
|
||||||
|
health: 1,
|
||||||
|
ok: true,
|
||||||
|
bad: false,
|
||||||
|
disabled: false,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '1613071630619607040',
|
||||||
|
name: '1',
|
||||||
|
addresses: [
|
||||||
|
{
|
||||||
|
address: 'coap://120.77.179.54:9000',
|
||||||
|
health: 1,
|
||||||
|
ok: true,
|
||||||
|
bad: false,
|
||||||
|
disabled: false,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
UDP: [
|
||||||
|
{
|
||||||
|
id: '1590553821093437440',
|
||||||
|
name: '194',
|
||||||
|
addresses: [
|
||||||
|
{
|
||||||
|
address: 'udp://139.217.130.194:1883',
|
||||||
|
health: 1,
|
||||||
|
ok: true,
|
||||||
|
bad: false,
|
||||||
|
disabled: false,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '1585831257204301824',
|
||||||
|
name: '测试隐藏集群',
|
||||||
|
description: '111',
|
||||||
|
addresses: [
|
||||||
|
{
|
||||||
|
address: 'udp://127.0.0.1:8080',
|
||||||
|
health: 1,
|
||||||
|
ok: true,
|
||||||
|
bad: false,
|
||||||
|
disabled: false,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '1584825665263149056',
|
||||||
|
name: '1',
|
||||||
|
addresses: [
|
||||||
|
{
|
||||||
|
address: 'udp://120.77.179.54:9000',
|
||||||
|
health: 1,
|
||||||
|
ok: true,
|
||||||
|
bad: false,
|
||||||
|
disabled: false,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '1551761481741672448',
|
||||||
|
name: '0726UDP',
|
||||||
|
description: '测试',
|
||||||
|
addresses: [
|
||||||
|
{
|
||||||
|
address: 'udp://120.77.179.54:8088',
|
||||||
|
health: 1,
|
||||||
|
ok: true,
|
||||||
|
bad: false,
|
||||||
|
disabled: false,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
TCP_SERVER: [
|
||||||
|
{
|
||||||
|
id: '1603206069979918336',
|
||||||
|
name: '测试A',
|
||||||
|
addresses: [
|
||||||
|
{
|
||||||
|
address: 'tcp://120.77.179.54:8106',
|
||||||
|
health: -1,
|
||||||
|
ok: false,
|
||||||
|
bad: false,
|
||||||
|
disabled: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '1603206069979918330',
|
||||||
|
name: '测试AA',
|
||||||
|
addresses: [
|
||||||
|
{
|
||||||
|
address: 'tcp://120.77.179.54:8106',
|
||||||
|
health: -1,
|
||||||
|
ok: false,
|
||||||
|
bad: false,
|
||||||
|
disabled: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
MQTT_SERVER: [
|
||||||
|
{
|
||||||
|
id: '1585192878304051200',
|
||||||
|
name: 'MQTT网络组件',
|
||||||
|
addresses: [
|
||||||
|
{
|
||||||
|
address: 'mqtt://120.77.179.54:8101',
|
||||||
|
health: 1,
|
||||||
|
ok: true,
|
||||||
|
bad: false,
|
||||||
|
disabled: false,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '1583268266806009856',
|
||||||
|
name: '我的第一个MQTT服务组件',
|
||||||
|
description: '',
|
||||||
|
addresses: [
|
||||||
|
{
|
||||||
|
address: 'mqtt://120.77.179.54:8100',
|
||||||
|
health: 1,
|
||||||
|
ok: true,
|
||||||
|
bad: false,
|
||||||
|
disabled: false,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '1570335308902912000',
|
||||||
|
name: '0915MQTT网络组件_勿动',
|
||||||
|
description: '测试,勿动!',
|
||||||
|
addresses: [
|
||||||
|
{
|
||||||
|
address: 'mqtt://120.77.179.54:8083',
|
||||||
|
health: 1,
|
||||||
|
ok: true,
|
||||||
|
bad: false,
|
||||||
|
disabled: false,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '1567062350140858368',
|
||||||
|
name: '网络组件20220906160907',
|
||||||
|
addresses: [
|
||||||
|
{
|
||||||
|
address: 'mqtt://120.77.179.54:8083',
|
||||||
|
health: 1,
|
||||||
|
ok: true,
|
||||||
|
bad: false,
|
||||||
|
disabled: false,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '1556563257890742272',
|
||||||
|
name: 'MQTT网络组件',
|
||||||
|
addresses: [
|
||||||
|
{
|
||||||
|
address: 'mqtt://0.0.0.0:8104',
|
||||||
|
health: 1,
|
||||||
|
ok: true,
|
||||||
|
bad: false,
|
||||||
|
disabled: false,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '1534774770408108032',
|
||||||
|
name: 'MQTT',
|
||||||
|
addresses: [
|
||||||
|
{
|
||||||
|
address: 'mqtt://120.77.179.54:8088',
|
||||||
|
health: 1,
|
||||||
|
ok: true,
|
||||||
|
bad: false,
|
||||||
|
disabled: false,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
function generateUUID() {
|
function generateUUID() {
|
||||||
var d = new Date().getTime();
|
var d = new Date().getTime();
|
||||||
if (
|
if (
|
||||||
|
@ -555,6 +765,10 @@ const props = defineProps({
|
||||||
});
|
});
|
||||||
|
|
||||||
const clientHeight = document.body.clientHeight;
|
const clientHeight = document.body.clientHeight;
|
||||||
|
const type = props.provider.channel;
|
||||||
|
const route = useRoute();
|
||||||
|
const modeType = route.params.type as string;
|
||||||
|
const id = route.params.id as string;
|
||||||
|
|
||||||
const formRef = ref<FormInstance>();
|
const formRef = ref<FormInstance>();
|
||||||
const useForm = Form.useForm;
|
const useForm = Form.useForm;
|
||||||
|
@ -569,29 +783,40 @@ const networkCurrent = ref('');
|
||||||
const procotolCurrent = ref('');
|
const procotolCurrent = ref('');
|
||||||
let config = ref({});
|
let config = ref({});
|
||||||
let columnsMQTT = ref(<TableColumnType>[]);
|
let columnsMQTT = ref(<TableColumnType>[]);
|
||||||
const form = reactive({
|
const formData = ref({
|
||||||
name: '',
|
name: '',
|
||||||
description: '',
|
description: '',
|
||||||
});
|
});
|
||||||
|
|
||||||
const { resetFields, validate, validateInfos } = useForm(
|
const { resetFields, validate, validateInfos } = useForm(
|
||||||
form,
|
formData,
|
||||||
reactive({
|
reactive({
|
||||||
name: [
|
name: [
|
||||||
{ required: true, message: '请输入名称', trigger: 'blur' },
|
{ required: true, message: '请输入名称', trigger: 'blur' },
|
||||||
{ max: 64, message: '最多可输入64个字符' },
|
{ max: 64, message: '最多可输入64个字符' },
|
||||||
],
|
],
|
||||||
|
description: [{ max: 200, message: '最多可输入200个字符' }],
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
const queryNetworkList = async (id: string, include: string, data = {}) => {
|
const queryNetworkList = async (id: string, include: string, data = {}) => {
|
||||||
|
if (NetworkTypeMapping.get(id) === 'MQTT_SERVER') {
|
||||||
|
//使用测试数据
|
||||||
|
networkList.value = networkData[NetworkTypeMapping.get(id)];
|
||||||
|
// return;
|
||||||
|
}
|
||||||
const resp = await getNetworkList(
|
const resp = await getNetworkList(
|
||||||
NetworkTypeMapping.get(id),
|
NetworkTypeMapping.get(id),
|
||||||
include,
|
include,
|
||||||
data,
|
data,
|
||||||
);
|
);
|
||||||
if (resp.status === 200) {
|
if (resp.status === 200) {
|
||||||
networkList.value = resp.result;
|
//使用测试数据
|
||||||
|
// networkList.value = resp.result;
|
||||||
|
networkList.value =
|
||||||
|
resp.result.length === 0
|
||||||
|
? networkData[NetworkTypeMapping.get(id)]
|
||||||
|
: resp.result;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -686,7 +911,7 @@ const saveData = () => {
|
||||||
channel: 'network', // 网络组件
|
channel: 'network', // 网络组件
|
||||||
channelId: networkCurrent.value,
|
channelId: networkCurrent.value,
|
||||||
};
|
};
|
||||||
if (props.data && props.data.id) {
|
if (!!id && modeType !== 'add') {
|
||||||
resp = await update(params);
|
resp = await update(params);
|
||||||
} else {
|
} else {
|
||||||
params = {
|
params = {
|
||||||
|
@ -702,12 +927,13 @@ const saveData = () => {
|
||||||
if (resp.status === 200) {
|
if (resp.status === 200) {
|
||||||
message.success('操作成功!');
|
message.success('操作成功!');
|
||||||
// 回到列表页面
|
// 回到列表页面
|
||||||
if (window.onTabSaveSuccess) {
|
// if (window.onTabSaveSuccess) {
|
||||||
window.onTabSaveSuccess(resp);
|
// window.onTabSaveSuccess(resp);
|
||||||
setTimeout(() => window.close(), 300);
|
// setTimeout(() => window.close(), 300);
|
||||||
} else {
|
// } else {
|
||||||
// this.$store.dispatch('jumpPathByKey', { key: MenuKeys['Link/AccessConfig'] })
|
// // this.$store.dispatch('jumpPathByKey', { key: MenuKeys['Link/AccessConfig'] })
|
||||||
}
|
// }
|
||||||
|
history.back();
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch((err) => {});
|
.catch((err) => {});
|
||||||
|
@ -781,7 +1007,7 @@ const next = async () => {
|
||||||
];
|
];
|
||||||
|
|
||||||
// const resp =
|
// const resp =
|
||||||
// props.provider.channel !== 'child-device'
|
// type !== 'child-device'
|
||||||
// ? await getConfigView(
|
// ? await getConfigView(
|
||||||
// procotolCurrent.value,
|
// procotolCurrent.value,
|
||||||
// ProtocolMapping.get(props.provider.id),
|
// ProtocolMapping.get(props.provider.id),
|
||||||
|
@ -864,7 +1090,7 @@ onMounted(() => {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (props.provider?.id) {
|
if (props.provider?.id) {
|
||||||
if (props.provider.channel !== 'child-device') {
|
if (type !== 'child-device') {
|
||||||
queryNetworkList(props.provider.id, '');
|
queryNetworkList(props.provider.id, '');
|
||||||
steps.value = ['网络组件', '消息协议', '完成'];
|
steps.value = ['网络组件', '消息协议', '完成'];
|
||||||
current.value = 0;
|
current.value = 0;
|
||||||
|
@ -877,14 +1103,20 @@ onMounted(() => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
if (modeType !== 'add') {
|
||||||
|
procotolCurrent.value = props.data.protocol;
|
||||||
|
formData.value = {
|
||||||
|
name: props.data.name,
|
||||||
|
description: props.data.description,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
current,
|
current,
|
||||||
(v) => {
|
(v) => {
|
||||||
if (props.provider.channel !== 'child-device') {
|
stepCurrent.value = type === 'child-device' ? v - 1 : v;
|
||||||
stepCurrent.value = v;
|
|
||||||
} else {
|
|
||||||
stepCurrent.value = v - 1;
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
deep: true,
|
deep: true,
|
||||||
|
|
|
@ -44,8 +44,13 @@
|
||||||
</template>
|
</template>
|
||||||
<template #content>
|
<template #content>
|
||||||
<div class="card-item-content">
|
<div class="card-item-content">
|
||||||
<h3 class="card-item-content-title">
|
<h3
|
||||||
<a href="">{{ slotProps.name }}</a>
|
@click="handlEye(slotProps.id)"
|
||||||
|
class="card-item-content-title"
|
||||||
|
>
|
||||||
|
<a class="card-item-content-title-a">{{
|
||||||
|
slotProps.name
|
||||||
|
}}</a>
|
||||||
</h3>
|
</h3>
|
||||||
<a-row class="card-item-content-box">
|
<a-row class="card-item-content-box">
|
||||||
<a-col
|
<a-col
|
||||||
|
@ -110,19 +115,23 @@
|
||||||
<a-tooltip>
|
<a-tooltip>
|
||||||
<template #title>
|
<template #title>
|
||||||
{{
|
{{
|
||||||
providersList.find(
|
slotProps.description
|
||||||
(item) =>
|
? slotProps.description
|
||||||
item.id ===
|
: providersList.find(
|
||||||
slotProps.provider,
|
(item) =>
|
||||||
)?.description
|
item.id ===
|
||||||
}}</template
|
slotProps.provider,
|
||||||
>
|
)?.description
|
||||||
|
}}
|
||||||
|
</template>
|
||||||
{{
|
{{
|
||||||
providersList.find(
|
slotProps.description
|
||||||
(item) =>
|
? slotProps.description
|
||||||
item.id ===
|
: providersList.find(
|
||||||
slotProps.provider,
|
(item) =>
|
||||||
)?.description
|
item.id ===
|
||||||
|
slotProps.provider,
|
||||||
|
)?.description
|
||||||
}}
|
}}
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
</div>
|
</div>
|
||||||
|
@ -184,7 +193,13 @@
|
||||||
<script lang="ts" setup name="AccessConfigPage">
|
<script lang="ts" setup name="AccessConfigPage">
|
||||||
import type { ActionsType } from '@/components/Table/index.vue';
|
import type { ActionsType } from '@/components/Table/index.vue';
|
||||||
import { getImage } from '@/utils/comm';
|
import { getImage } from '@/utils/comm';
|
||||||
import { list, getProviders } from '@/api/link/accessConfig';
|
import {
|
||||||
|
list,
|
||||||
|
getProviders,
|
||||||
|
remove,
|
||||||
|
undeploy,
|
||||||
|
deploy,
|
||||||
|
} from '@/api/link/accessConfig';
|
||||||
import { message } from 'ant-design-vue';
|
import { message } from 'ant-design-vue';
|
||||||
|
|
||||||
const tableRef = ref<Record<string, any>>({});
|
const tableRef = ref<Record<string, any>>({});
|
||||||
|
@ -261,9 +276,8 @@ const columns = [
|
||||||
];
|
];
|
||||||
|
|
||||||
const getActions = (data: Partial<Record<string, any>>): ActionsType[] => {
|
const getActions = (data: Partial<Record<string, any>>): ActionsType[] => {
|
||||||
if (!data) {
|
if (!data) return [];
|
||||||
return [];
|
const state = data.state.value;
|
||||||
}
|
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
key: 'edit',
|
key: 'edit',
|
||||||
|
@ -276,15 +290,47 @@ const getActions = (data: Partial<Record<string, any>>): ActionsType[] => {
|
||||||
handlEdit(data.id);
|
handlEdit(data.id);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
key: 'action',
|
||||||
|
text: state === 'enabled' ? '禁用' : '启用',
|
||||||
|
tooltip: {
|
||||||
|
title: state === 'enabled' ? '禁用' : '启用',
|
||||||
|
},
|
||||||
|
icon: state === 'enabled' ? 'StopOutlined' : 'CheckCircleOutlined',
|
||||||
|
popConfirm: {
|
||||||
|
title: `确认${state === 'enabled' ? '禁用' : '启用'}?`,
|
||||||
|
onConfirm: async () => {
|
||||||
|
let res =
|
||||||
|
state === 'enabled'
|
||||||
|
? await undeploy(data.id)
|
||||||
|
: await deploy(data.id);
|
||||||
|
|
||||||
|
if (res.success) {
|
||||||
|
message.success('操作成功');
|
||||||
|
tableRef.value?.reload();
|
||||||
|
} else {
|
||||||
|
message.error('操作失败!');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
key: 'delete',
|
key: 'delete',
|
||||||
text: '删除',
|
text: '删除',
|
||||||
|
disabled: state === 'enabled',
|
||||||
|
tooltip: {
|
||||||
|
title: state === 'enabled' ? '已启用的设备不能删除' : '删除',
|
||||||
|
},
|
||||||
popConfirm: {
|
popConfirm: {
|
||||||
title: '确认删除?',
|
title: '确认删除?',
|
||||||
okText: ' 确定',
|
|
||||||
cancelText: '取消',
|
|
||||||
onConfirm: async () => {
|
onConfirm: async () => {
|
||||||
handlDelete(data.id);
|
const res = await remove(data.id);
|
||||||
|
if (res.success) {
|
||||||
|
message.success('操作成功');
|
||||||
|
tableRef.value.reload();
|
||||||
|
} else {
|
||||||
|
message.error('操作失败!');
|
||||||
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
icon: 'DeleteOutlined',
|
icon: 'DeleteOutlined',
|
||||||
|
@ -299,21 +345,13 @@ const getProvidersList = async () => {
|
||||||
getProvidersList();
|
getProvidersList();
|
||||||
|
|
||||||
const handlAdd = () => {
|
const handlAdd = () => {
|
||||||
router.push('/link/accessConfig/detail/add');
|
router.push('/link/accessConfig/detail/add/new');
|
||||||
|
|
||||||
// router.push('/link/certificate/detail/add/new');
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const handlEdit = (id: string) => {
|
const handlEdit = (id: string) => {
|
||||||
router.push(`/link/certificate/detail/edit/${id}`);
|
router.push(`/link/accessConfig/detail/edit/${id}`);
|
||||||
};
|
};
|
||||||
|
const handlEye = (id: string) => {
|
||||||
const handlDelete = async (id: string) => {
|
router.push(`/link/accessConfig/detail/view/${id}`);
|
||||||
const res = await remove(id);
|
|
||||||
if (res.success) {
|
|
||||||
message.success('操作成功');
|
|
||||||
tableRef.value.reload();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -356,6 +394,14 @@ const handleSearch = (e: any) => {
|
||||||
.card-item-content {
|
.card-item-content {
|
||||||
min-height: 100px;
|
min-height: 100px;
|
||||||
|
|
||||||
|
.card-item-content-title-a {
|
||||||
|
// color: #000 !important;
|
||||||
|
font-weight: 700;
|
||||||
|
font-size: 18px;
|
||||||
|
overflow: hidden; //超出的文本隐藏
|
||||||
|
text-overflow: ellipsis; //溢出用省略号显示
|
||||||
|
white-space: nowrap; //溢出不换行
|
||||||
|
}
|
||||||
.card-item-content-box {
|
.card-item-content-box {
|
||||||
min-height: 50px;
|
min-height: 50px;
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,7 +60,7 @@
|
||||||
|
|
||||||
<a-form-item>
|
<a-form-item>
|
||||||
<a-button
|
<a-button
|
||||||
v-if="type !== 'view'"
|
v-if="modeType !== 'view'"
|
||||||
class="form-submit"
|
class="form-submit"
|
||||||
html-type="submit"
|
html-type="submit"
|
||||||
type="primary"
|
type="primary"
|
||||||
|
@ -103,7 +103,7 @@ import { FormDataType, TypeObjType } from '../type';
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const type = route.params.type as string;
|
const modeType = route.params.type as string;
|
||||||
const id = route.params.id as string;
|
const id = route.params.id as string;
|
||||||
|
|
||||||
const useForm = Form.useForm;
|
const useForm = Form.useForm;
|
||||||
|
@ -145,7 +145,7 @@ const onSubmit = () => {
|
||||||
const params = toRaw(formData.value);
|
const params = toRaw(formData.value);
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
const response =
|
const response =
|
||||||
type === 'edit' ? await update(params) : await save(params);
|
modeType === 'edit' ? await update(params) : await save(params);
|
||||||
if (response.status === 200) {
|
if (response.status === 200) {
|
||||||
message.success('操作成功');
|
message.success('操作成功');
|
||||||
router.push('/link/certificate');
|
router.push('/link/certificate');
|
||||||
|
@ -168,7 +168,7 @@ const handleChange = (info: UploadChangeParam) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const detail = async (id: string) => {
|
const detail = async (id: string) => {
|
||||||
if (type !== 'add') {
|
if (modeType !== 'add') {
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
const res = await queryDetail(id);
|
const res = await queryDetail(id);
|
||||||
if (res.success) {
|
if (res.success) {
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
<template>
|
||||||
|
123
|
||||||
|
</template>
|
|
@ -148,7 +148,7 @@ const getActions = (data: Partial<Record<string, any>>): ActionsType[] => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const add = () => {
|
const add = () => {
|
||||||
message.warn('123')
|
// router.push(`/northbound/DuerOS/detail/:id`)
|
||||||
}
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
|
@ -64,7 +64,7 @@
|
||||||
import { Form } from 'ant-design-vue';
|
import { Form } from 'ant-design-vue';
|
||||||
import { PropType } from 'vue';
|
import { PropType } from 'vue';
|
||||||
import ConfigApi from '@/api/notice/config';
|
import ConfigApi from '@/api/notice/config';
|
||||||
import {
|
import type {
|
||||||
TemplateFormData,
|
TemplateFormData,
|
||||||
IVariableDefinitions,
|
IVariableDefinitions,
|
||||||
} from '@/views/notice/Template/types';
|
} from '@/views/notice/Template/types';
|
||||||
|
|
|
@ -36,7 +36,7 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { PlusOutlined, DeleteOutlined } from '@ant-design/icons-vue';
|
import { PlusOutlined, DeleteOutlined } from '@ant-design/icons-vue';
|
||||||
import { PropType } from 'vue';
|
import { PropType } from 'vue';
|
||||||
import { IHeaders } from '../../types';
|
import type { IHeaders } from '../../types';
|
||||||
|
|
||||||
type Emits = {
|
type Emits = {
|
||||||
(e: 'update:headers', data: IHeaders[]): void;
|
(e: 'update:headers', data: IHeaders[]): void;
|
||||||
|
|
|
@ -279,7 +279,7 @@
|
||||||
import { getImage } from '@/utils/comm';
|
import { getImage } from '@/utils/comm';
|
||||||
import { Form } from 'ant-design-vue';
|
import { Form } from 'ant-design-vue';
|
||||||
import { message } from 'ant-design-vue';
|
import { message } from 'ant-design-vue';
|
||||||
import { ConfigFormData } from '../types';
|
import type { ConfigFormData } from '../types';
|
||||||
import {
|
import {
|
||||||
NOTICE_METHOD,
|
NOTICE_METHOD,
|
||||||
CONFIG_FIELD_MAP,
|
CONFIG_FIELD_MAP,
|
||||||
|
|
|
@ -91,7 +91,10 @@
|
||||||
v-for="(o, i) in item.children"
|
v-for="(o, i) in item.children"
|
||||||
:key="i"
|
:key="i"
|
||||||
>
|
>
|
||||||
<a-button type="link" @click="o.onClick">
|
<a-button
|
||||||
|
type="link"
|
||||||
|
@click="o.onClick"
|
||||||
|
>
|
||||||
<AIcon :type="o.icon" />
|
<AIcon :type="o.icon" />
|
||||||
<span>{{ o.text }}</span>
|
<span>{{ o.text }}</span>
|
||||||
</a-button>
|
</a-button>
|
||||||
|
@ -167,9 +170,8 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import ConfigApi from '@/api/notice/config';
|
import ConfigApi from '@/api/notice/config';
|
||||||
import type { ActionsType } from '@/components/Table/index.vue';
|
import type { ActionsType } from '@/components/Table/index.vue';
|
||||||
import { getImage, LocalStore } from '@/utils/comm';
|
|
||||||
import { message } from 'ant-design-vue';
|
import { message } from 'ant-design-vue';
|
||||||
import { BASE_API_PATH, TOKEN_KEY } from '@/utils/variable';
|
|
||||||
|
|
||||||
import { NOTICE_METHOD, MSG_TYPE } from '@/views/notice/const';
|
import { NOTICE_METHOD, MSG_TYPE } from '@/views/notice/const';
|
||||||
import SyncUser from './SyncUser/index.vue';
|
import SyncUser from './SyncUser/index.vue';
|
||||||
|
@ -266,7 +268,7 @@ const getMethodTxt = (type: string) => {
|
||||||
* 新增
|
* 新增
|
||||||
*/
|
*/
|
||||||
const handleAdd = () => {
|
const handleAdd = () => {
|
||||||
router.push(`/notice/Config/detail/:id`);
|
router.push(`/iot/notice/Config/detail/:id`);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -306,13 +308,6 @@ const handleExport = () => {
|
||||||
downloadObject(configRef.value.dataSource, `通知配置`);
|
downloadObject(configRef.value.dataSource, `通知配置`);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* 查看
|
|
||||||
*/
|
|
||||||
const handleView = (id: string) => {
|
|
||||||
message.warn(id + '暂未开发');
|
|
||||||
};
|
|
||||||
|
|
||||||
const syncVis = ref(false);
|
const syncVis = ref(false);
|
||||||
const debugVis = ref(false);
|
const debugVis = ref(false);
|
||||||
const logVis = ref(false);
|
const logVis = ref(false);
|
||||||
|
@ -333,7 +328,7 @@ const getActions = (
|
||||||
onClick: () => {
|
onClick: () => {
|
||||||
// visible.value = true;
|
// visible.value = true;
|
||||||
// current.value = data;
|
// current.value = data;
|
||||||
router.push(`/notice/Config/detail/${data.id}`);
|
router.push(`/iot/notice/Config/detail/${data.id}`);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -360,35 +355,6 @@ const getActions = (
|
||||||
currentConfig.value = data;
|
currentConfig.value = data;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
// {
|
|
||||||
// key: 'others',
|
|
||||||
// text: '其他',
|
|
||||||
// children: [
|
|
||||||
// {
|
|
||||||
// key: 'debug',
|
|
||||||
// text: '导出',
|
|
||||||
// tooltip: {
|
|
||||||
// title: '导出',
|
|
||||||
// },
|
|
||||||
// icon: 'ArrowDownOutlined',
|
|
||||||
// onClick: () => {
|
|
||||||
// downloadObject(data, `通知配置`);
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// key: 'sync',
|
|
||||||
// text: '同步用户',
|
|
||||||
// tooltip: {
|
|
||||||
// title: '同步用户',
|
|
||||||
// },
|
|
||||||
// icon: 'TeamOutlined',
|
|
||||||
// onClick: () => {
|
|
||||||
// syncVis.value = true;
|
|
||||||
// currentConfig.value = data;
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
// ],
|
|
||||||
// },
|
|
||||||
{
|
{
|
||||||
key: 'delete',
|
key: 'delete',
|
||||||
text: '删除',
|
text: '删除',
|
||||||
|
|
|
@ -63,7 +63,7 @@
|
||||||
import { Form } from 'ant-design-vue';
|
import { Form } from 'ant-design-vue';
|
||||||
import { PropType } from 'vue';
|
import { PropType } from 'vue';
|
||||||
import TemplateApi from '@/api/notice/template';
|
import TemplateApi from '@/api/notice/template';
|
||||||
import {
|
import type {
|
||||||
TemplateFormData,
|
TemplateFormData,
|
||||||
IVariableDefinitions,
|
IVariableDefinitions,
|
||||||
BindConfig,
|
BindConfig,
|
||||||
|
|
|
@ -47,7 +47,7 @@ import {
|
||||||
UploadOutlined,
|
UploadOutlined,
|
||||||
} from '@ant-design/icons-vue';
|
} from '@ant-design/icons-vue';
|
||||||
import { PropType } from 'vue';
|
import { PropType } from 'vue';
|
||||||
import { IAttachments } from '../../types';
|
import type { IAttachments } from '../../types';
|
||||||
import { FILE_UPLOAD } from '@/api/comm';
|
import { FILE_UPLOAD } from '@/api/comm';
|
||||||
import { LocalStore } from '@/utils/comm';
|
import { LocalStore } from '@/utils/comm';
|
||||||
import { TOKEN_KEY } from '@/utils/variable';
|
import { TOKEN_KEY } from '@/utils/variable';
|
||||||
|
|
|
@ -477,7 +477,7 @@
|
||||||
import { getImage } from '@/utils/comm';
|
import { getImage } from '@/utils/comm';
|
||||||
import { Form, UploadChangeParam } from 'ant-design-vue';
|
import { Form, UploadChangeParam } from 'ant-design-vue';
|
||||||
import { message } from 'ant-design-vue';
|
import { message } from 'ant-design-vue';
|
||||||
import { IVariableDefinitions, TemplateFormData } from '../types';
|
import type { IVariableDefinitions, TemplateFormData } from '../types';
|
||||||
import {
|
import {
|
||||||
NOTICE_METHOD,
|
NOTICE_METHOD,
|
||||||
TEMPLATE_FIELD_MAP,
|
TEMPLATE_FIELD_MAP,
|
||||||
|
|
|
@ -256,7 +256,7 @@ const getMethodTxt = (type: string) => {
|
||||||
* 新增
|
* 新增
|
||||||
*/
|
*/
|
||||||
const handleAdd = () => {
|
const handleAdd = () => {
|
||||||
router.push(`/notice/Template/detail/:id`);
|
router.push(`/iot/notice/Template/detail/:id`);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -323,7 +323,7 @@ const getActions = (
|
||||||
onClick: () => {
|
onClick: () => {
|
||||||
// visible.value = true;
|
// visible.value = true;
|
||||||
// current.value = data;
|
// current.value = data;
|
||||||
router.push(`/notice/Template/detail/${data.id}`);
|
router.push(`/iot/notice/Template/detail/${data.id}`);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -170,22 +170,18 @@
|
||||||
placeholder="请选择关联菜单"
|
placeholder="请选择关联菜单"
|
||||||
multiple
|
multiple
|
||||||
show-search
|
show-search
|
||||||
tree-default-expand-all
|
|
||||||
:tree-data="form.treeData"
|
:tree-data="form.treeData"
|
||||||
|
:field-names="{
|
||||||
|
children: 'children',
|
||||||
|
label: 'name',
|
||||||
|
value: 'id',
|
||||||
|
}"
|
||||||
>
|
>
|
||||||
<template #title="{ value: val, title }">
|
|
||||||
<b
|
|
||||||
v-if="val === 'parent 1-1'"
|
|
||||||
style="color: #08c"
|
|
||||||
>{{ val }}</b
|
|
||||||
>
|
|
||||||
<template v-else>{{ title }}</template>
|
|
||||||
</template>
|
|
||||||
</a-tree-select>
|
</a-tree-select>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="权限">
|
<a-form-item label="权限">
|
||||||
<PermissChoose v-model:value="form.data.permissions" />
|
<PermissChoose :first-width="3" max-height="350px" v-model:value="form.data.permissions" />
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-form>
|
</a-form>
|
||||||
|
|
||||||
|
@ -245,17 +241,16 @@ const form = reactive({
|
||||||
|
|
||||||
treeData: [], // 关联菜单
|
treeData: [], // 关联菜单
|
||||||
assetsType: [] as assetType[], // 资产类型
|
assetsType: [] as assetType[], // 资产类型
|
||||||
premissonList: [], // 权限列表
|
|
||||||
|
|
||||||
init: () => {
|
init: () => {
|
||||||
// 获取菜单详情
|
// 获取菜单详情
|
||||||
routeParams.id &&
|
routeParams.id &&
|
||||||
getMenuInfo_api(routeParams.id).then((resp) => {
|
getMenuInfo_api(routeParams.id).then((resp) => {
|
||||||
console.log('菜单详情', resp);
|
form.data = resp.result as formType
|
||||||
});
|
});
|
||||||
// 获取关联菜单
|
// 获取关联菜单
|
||||||
getMenuTree_api({ paging: false }).then((resp) => {
|
getMenuTree_api({ paging: false }).then((resp: any) => {
|
||||||
console.log('关联菜单', resp);
|
form.treeData = resp.result;
|
||||||
});
|
});
|
||||||
// 获取资产类型
|
// 获取资产类型
|
||||||
getAssetsType_api().then((resp: any) => {
|
getAssetsType_api().then((resp: any) => {
|
||||||
|
|
|
@ -1,18 +1,134 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="button-mange-container">
|
<div class="button-mange-container">
|
||||||
|
<JTable
|
||||||
|
ref="tableRef"
|
||||||
|
:columns="table.columns"
|
||||||
|
model="TABLE"
|
||||||
|
:dataSource="table.data"
|
||||||
|
>
|
||||||
|
<template #headerTitle>
|
||||||
|
<a-button
|
||||||
|
type="primary"
|
||||||
|
style="margin-right: 10px"
|
||||||
|
@click="() => dialog.openDialog()"
|
||||||
|
><plus-outlined />新增</a-button
|
||||||
|
>
|
||||||
|
</template>
|
||||||
|
<template #action="slotProps">
|
||||||
|
<a-space :size="16">
|
||||||
|
<a-tooltip>
|
||||||
|
<template #title>编辑</template>
|
||||||
|
<a-button
|
||||||
|
style="padding: 0"
|
||||||
|
type="link"
|
||||||
|
@click="() => dialog.openDialog(slotProps)"
|
||||||
|
>
|
||||||
|
<edit-outlined />
|
||||||
|
</a-button>
|
||||||
|
</a-tooltip>
|
||||||
|
<a-tooltip>
|
||||||
|
<template #title>查看</template>
|
||||||
|
<a-button
|
||||||
|
style="padding: 0"
|
||||||
|
type="link"
|
||||||
|
@click="() => dialog.openDialog(slotProps)"
|
||||||
|
>
|
||||||
|
<edit-outlined />
|
||||||
|
</a-button>
|
||||||
|
</a-tooltip>
|
||||||
|
|
||||||
|
<a-popconfirm
|
||||||
|
title="确认删除"
|
||||||
|
ok-text="确定"
|
||||||
|
cancel-text="取消"
|
||||||
|
:disabled="slotProps.status"
|
||||||
|
>
|
||||||
|
<a-tooltip>
|
||||||
|
<template #title>删除</template>
|
||||||
|
<a-button style="padding: 0" type="link">
|
||||||
|
<delete-outlined />
|
||||||
|
</a-button>
|
||||||
|
</a-tooltip>
|
||||||
|
</a-popconfirm>
|
||||||
|
</a-space>
|
||||||
|
</template>
|
||||||
|
</JTable>
|
||||||
|
|
||||||
|
<div class="dialog">
|
||||||
|
<ButtonAddDialog ref="dialogRef" @confirm="dialog.confirm" />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import {
|
||||||
|
EditOutlined,
|
||||||
|
DeleteOutlined,
|
||||||
|
PlusOutlined,
|
||||||
|
} from '@ant-design/icons-vue';
|
||||||
|
import ButtonAddDialog from '../components/ButtonAddDialog.vue';
|
||||||
|
|
||||||
|
import { getMenuInfo_api } from '@/api/system/menu';
|
||||||
|
|
||||||
|
// 路由
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const routeParams = {
|
const routeParams = {
|
||||||
id: route.params.id === ':id' ? '' : route.params.id,
|
id: route.params.id === ':id' ? '' : (route.params.id as string),
|
||||||
...route.query,
|
...route.query,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 弹窗相关
|
||||||
|
const dialogRef = ref<any>(null);
|
||||||
|
const dialog = {
|
||||||
|
// 打开弹窗
|
||||||
|
openDialog: (row?: object) => {
|
||||||
|
dialogRef.value && dialogRef.value.openDialog(row);
|
||||||
|
},
|
||||||
|
confirm: () => {},
|
||||||
|
};
|
||||||
|
// 表格相关
|
||||||
|
const table = reactive({
|
||||||
|
columns: [
|
||||||
|
{
|
||||||
|
title: '编码',
|
||||||
|
dataIndex: 'id',
|
||||||
|
key: 'id',
|
||||||
|
width: 220,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '名称',
|
||||||
|
dataIndex: 'name',
|
||||||
|
key: 'name',
|
||||||
|
width: 300,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '说明',
|
||||||
|
dataIndex: 'description',
|
||||||
|
key: 'description',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '操作',
|
||||||
|
dataIndex: 'action',
|
||||||
|
key: 'action',
|
||||||
|
scopedSlots: true,
|
||||||
|
width: 240,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
data: [] as tableDataItem[],
|
||||||
|
getList: () => {
|
||||||
|
routeParams.id &&
|
||||||
|
getMenuInfo_api(routeParams.id).then((resp: any) => {
|
||||||
|
table.data = resp.result.buttons as tableDataItem[];
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
table.getList();
|
||||||
|
type tableDataItem = {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
description?: string;
|
||||||
|
permissions: object[];
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped></style>
|
||||||
|
|
||||||
</style>
|
|
||||||
|
|
|
@ -0,0 +1,97 @@
|
||||||
|
<template>
|
||||||
|
<a-modal
|
||||||
|
v-model:visible="dialog.visible"
|
||||||
|
title="新增"
|
||||||
|
width="660px"
|
||||||
|
@ok="dialog.handleOk"
|
||||||
|
>
|
||||||
|
<a-form :model="form.data" class="basic-form">
|
||||||
|
<a-form-item
|
||||||
|
label="编码"
|
||||||
|
name="id"
|
||||||
|
:rules="[
|
||||||
|
{ required: true, message: '请输入编码' },
|
||||||
|
{ max: 64, message: '最多可输入64个字符' },
|
||||||
|
]"
|
||||||
|
>
|
||||||
|
<a-input v-model:value="form.data.id" />
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item
|
||||||
|
label="名称"
|
||||||
|
name="name"
|
||||||
|
:rules="[
|
||||||
|
{ required: true, message: '请输入名称' },
|
||||||
|
{ max: 64, message: '最多可输入64个字符' },
|
||||||
|
]"
|
||||||
|
>
|
||||||
|
<a-input v-model:value="form.data.name" />
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="权限">
|
||||||
|
<PermissChoose
|
||||||
|
:first-width="8"
|
||||||
|
max-height="350px"
|
||||||
|
v-model:value="form.data.permissions"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="说明" name="describe">
|
||||||
|
<a-textarea
|
||||||
|
v-model:value="form.data.describe"
|
||||||
|
:rows="4"
|
||||||
|
placeholder="请输入说明"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-form>
|
||||||
|
</a-modal>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import PermissChoose from '../components/PermissChoose.vue';
|
||||||
|
|
||||||
|
const emits = defineEmits(['confirm']);
|
||||||
|
const dialog = reactive({
|
||||||
|
visible: false,
|
||||||
|
handleOk: () => {
|
||||||
|
dialog.changeVisible();
|
||||||
|
},
|
||||||
|
changeVisible: (formValue?: formType, show?: boolean) => {
|
||||||
|
dialog.visible = show === undefined ? !dialog.visible : show;
|
||||||
|
form.data = formValue || { ...initForm };
|
||||||
|
console.log(1111111111, form.data);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const initForm = {
|
||||||
|
name: '',
|
||||||
|
id: '',
|
||||||
|
permissions: [],
|
||||||
|
describe: '',
|
||||||
|
} as formType;
|
||||||
|
const form = reactive({
|
||||||
|
data: { ...initForm },
|
||||||
|
});
|
||||||
|
|
||||||
|
// 将打开弹窗的操作暴露给父组件
|
||||||
|
defineExpose({
|
||||||
|
openDialog: dialog.changeVisible,
|
||||||
|
});
|
||||||
|
|
||||||
|
type formType = {
|
||||||
|
name: string;
|
||||||
|
id: string;
|
||||||
|
permissions: any[];
|
||||||
|
describe: string;
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.basic-form {
|
||||||
|
.ant-form-item {
|
||||||
|
display: block;
|
||||||
|
:deep(.ant-form-item-label) {
|
||||||
|
overflow: inherit;
|
||||||
|
label::after {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -5,43 +5,207 @@
|
||||||
style="width: 300px"
|
style="width: 300px"
|
||||||
allowClear
|
allowClear
|
||||||
placeholder="请输入权限名称"
|
placeholder="请输入权限名称"
|
||||||
|
@input="search.search"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<div class="permission-table">
|
||||||
|
<a-row :gutter="24" class="table-head">
|
||||||
|
<a-col :span="props.firstWidth">权限名称</a-col
|
||||||
|
><a-col :span="24 - props.firstWidth">权限操作</a-col>
|
||||||
|
</a-row>
|
||||||
|
<div class="table-body" :style="{ 'max-height': props.maxHeight }">
|
||||||
|
<a-row
|
||||||
|
:gutter="24"
|
||||||
|
class="row"
|
||||||
|
v-for="rowItem in permission.list"
|
||||||
|
>
|
||||||
|
<a-col :span="props.firstWidth" class="item-name">
|
||||||
|
<a-checkbox
|
||||||
|
v-model:checked="rowItem.checkAll"
|
||||||
|
:indeterminate="rowItem.indeterminate"
|
||||||
|
@change="() => permission.selectAllOpions(rowItem)"
|
||||||
|
>
|
||||||
|
{{ rowItem.name }}
|
||||||
|
</a-checkbox>
|
||||||
|
</a-col>
|
||||||
|
<a-col :span="24 - props.firstWidth">
|
||||||
|
<a-checkbox-group
|
||||||
|
v-model:value="rowItem.checkedList"
|
||||||
|
:options="rowItem.options"
|
||||||
|
@change="((checkValue:string[])=>permission.selectOption(rowItem, checkValue))"
|
||||||
|
/>
|
||||||
|
</a-col>
|
||||||
|
</a-row>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { exportPermission_api } from '@/api/system/permission';
|
import { exportPermission_api } from '@/api/system/permission';
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps<{
|
||||||
value: Array,
|
value: any[];
|
||||||
});
|
firstWidth: number;
|
||||||
|
maxHeight: string;
|
||||||
|
}>();
|
||||||
|
const emits = defineEmits(['update:value']);
|
||||||
const searchValue = ref<string>('');
|
const searchValue = ref<string>('');
|
||||||
|
|
||||||
|
const search = reactive({
|
||||||
|
value: '',
|
||||||
|
searchTimer: null as null | number,
|
||||||
|
search: () => {
|
||||||
|
if (search.searchTimer) {
|
||||||
|
clearTimeout(search.searchTimer);
|
||||||
|
}
|
||||||
|
search.searchTimer = setTimeout(() => {
|
||||||
|
nextTick(() => permission.getList());
|
||||||
|
search.searchTimer = null;
|
||||||
|
}, 1000);
|
||||||
|
},
|
||||||
|
});
|
||||||
const permission = reactive({
|
const permission = reactive({
|
||||||
list: [] as permissionType[],
|
list: [] as permissionType[],
|
||||||
// 获取权限列表
|
// 获取权限列表
|
||||||
getList: () => {
|
getList: () => {
|
||||||
|
const params: paramsType = {
|
||||||
exportPermission_api({ paging: false }).then((resp) => {
|
paging: false,
|
||||||
permission.list = resp.result as permissionType[]
|
};
|
||||||
|
if (search.value) {
|
||||||
|
params.terms = [
|
||||||
|
{ column: 'name$like', value: `%${search.value}%` },
|
||||||
|
];
|
||||||
|
}
|
||||||
|
exportPermission_api(params).then((resp) => {
|
||||||
|
permission.list = permission.makeList(
|
||||||
|
props.value,
|
||||||
|
resp.result as any[],
|
||||||
|
);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
// 全选/取消全选
|
||||||
|
selectAllOpions: (row: permissionType) => {
|
||||||
|
const newValue = props.value.filter(
|
||||||
|
(item) => item.permission !== row.id,
|
||||||
|
);
|
||||||
|
row = toRaw(row);
|
||||||
|
if (row.checkAll) {
|
||||||
|
row.checkedList = row.options.map((item) => item.value);
|
||||||
|
|
||||||
|
newValue.push({
|
||||||
|
permission: row.id,
|
||||||
|
actions: row.checkedList,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
row.checkedList = [];
|
||||||
|
}
|
||||||
|
emits('update:value', newValue);
|
||||||
|
},
|
||||||
|
// 单选
|
||||||
|
selectOption: (row: permissionType, newValue: string[]) => {
|
||||||
|
const newProp = props.value.filter(
|
||||||
|
(item) => item.permission !== row.id,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (newValue.length === row.options.length) {
|
||||||
|
row.checkAll = true;
|
||||||
|
row.indeterminate = false;
|
||||||
|
newProp.push({
|
||||||
|
permission: row.id,
|
||||||
|
actions: newValue,
|
||||||
|
});
|
||||||
|
} else if (newValue.length > 0) {
|
||||||
|
row.checkAll = false;
|
||||||
|
row.indeterminate = true;
|
||||||
|
newProp.push({
|
||||||
|
permission: row.id,
|
||||||
|
actions: newValue,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
emits('update:value', newProp);
|
||||||
|
},
|
||||||
|
makeList: (checkedValue: any[], sourceList: any[]): permissionType[] => {
|
||||||
|
console.log(checkedValue);
|
||||||
|
|
||||||
|
const result = sourceList.map((item) => {
|
||||||
|
const checked = checkedValue.find(
|
||||||
|
(checkedItem) => checkedItem.permission === item.id,
|
||||||
|
);
|
||||||
|
const options = item.actions.map((actionItem: any) => ({
|
||||||
|
label: actionItem.name,
|
||||||
|
value: actionItem.action,
|
||||||
|
}));
|
||||||
|
console.log(item, checked);
|
||||||
|
|
||||||
|
return {
|
||||||
|
id: item.id,
|
||||||
|
name: item.name,
|
||||||
|
checkedList: (checked && checked.actions) || [],
|
||||||
|
checkAll:
|
||||||
|
(checked &&
|
||||||
|
item.actions &&
|
||||||
|
checked?.actions.length === item.actions.length) ||
|
||||||
|
false,
|
||||||
|
indeterminate:
|
||||||
|
(checked &&
|
||||||
|
item.actions &&
|
||||||
|
checked.actions.length < item.actions.length) ||
|
||||||
|
false,
|
||||||
|
options,
|
||||||
|
};
|
||||||
|
}) as permissionType[];
|
||||||
|
|
||||||
|
return result;
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
permission.getList()
|
permission.getList();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
type permissionType = {
|
type permissionType = {
|
||||||
id: string;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
actions: object[]
|
checkedList: string[];
|
||||||
}
|
checkAll: boolean;
|
||||||
|
indeterminate: boolean;
|
||||||
|
options: any[];
|
||||||
|
};
|
||||||
|
type paramsType = {
|
||||||
|
paging: boolean;
|
||||||
|
terms?: object[];
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped></style>
|
<style lang="less" scoped>
|
||||||
|
.permission-choose-container {
|
||||||
|
.permission-table {
|
||||||
|
margin-top: 12px;
|
||||||
|
font-size: 14px;
|
||||||
|
border: 1px solid #d9d9d9;
|
||||||
|
color: rgba(0, 0, 0, 0.85);
|
||||||
|
.table-head {
|
||||||
|
padding: 12px;
|
||||||
|
background-color: #d9d9d9;
|
||||||
|
margin: 0 !important;
|
||||||
|
}
|
||||||
|
.table-body {
|
||||||
|
overflow: auto;
|
||||||
|
.row {
|
||||||
|
margin: 0 !important;
|
||||||
|
|
||||||
|
border-bottom: 1px solid #d9d9d9;
|
||||||
|
|
||||||
|
> div {
|
||||||
|
padding: 8px 12px;
|
||||||
|
}
|
||||||
|
.item-name {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
border-right: 1px solid #d9d9d9;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
<a-button>菜单实例</a-button>
|
<a-button>菜单实例</a-button>
|
||||||
</template>
|
</template>
|
||||||
<template #createTime="slotProps">
|
<template #createTime="slotProps">
|
||||||
{{ slotProps.createTime }}
|
{{ moment(slotProps.createTime).format('YYYY-MM-DD HH:mm:ss') }}
|
||||||
</template>
|
</template>
|
||||||
<template #action="slotProps">
|
<template #action="slotProps">
|
||||||
<a-space :size="16">
|
<a-space :size="16">
|
||||||
|
@ -30,7 +30,7 @@
|
||||||
type="link"
|
type="link"
|
||||||
@click="table.toDetails(slotProps)"
|
@click="table.toDetails(slotProps)"
|
||||||
>
|
>
|
||||||
<edit-outlined />
|
<search-outlined />
|
||||||
</a-button>
|
</a-button>
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
<a-tooltip>
|
<a-tooltip>
|
||||||
|
@ -40,7 +40,7 @@
|
||||||
type="link"
|
type="link"
|
||||||
@click="table.toDetails(slotProps)"
|
@click="table.toDetails(slotProps)"
|
||||||
>
|
>
|
||||||
<edit-outlined />
|
<plus-circle-outlined />
|
||||||
</a-button>
|
</a-button>
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
|
|
||||||
|
@ -66,6 +66,13 @@
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { getMenuTree_api } from '@/api/system/menu';
|
import { getMenuTree_api } from '@/api/system/menu';
|
||||||
|
import {
|
||||||
|
SearchOutlined,
|
||||||
|
DeleteOutlined,
|
||||||
|
PlusOutlined,
|
||||||
|
PlusCircleOutlined
|
||||||
|
} from '@ant-design/icons-vue';
|
||||||
|
import moment from 'moment';
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue