From dc6ad3b0815f7e410dc9af33493b93a499c94350 Mon Sep 17 00:00:00 2001 From: easy <1358086367@qq.com> Date: Sun, 29 Jan 2023 13:58:18 +0800 Subject: [PATCH 1/4] =?UTF-8?q?update:=20=E6=9D=83=E9=99=90=E7=AE=A1?= =?UTF-8?q?=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/system/permission.ts | 10 +- .../Permission/components/EditDialog.vue | 105 ++++++++++++++++-- src/views/system/Permission/index.vue | 21 ++-- 3 files changed, 116 insertions(+), 20 deletions(-) diff --git a/src/api/system/permission.ts b/src/api/system/permission.ts index 978e4b26..13a7e037 100644 --- a/src/api/system/permission.ts +++ b/src/api/system/permission.ts @@ -2,5 +2,11 @@ import server from '@/utils/request'; // 获取权限列表 export const getPermission_api = (data:object) => server.post(`/permission/_query/`,data); -// 修改权限信息 -export const editPermission_api = (data:object) => server.patch(`/permission`,data); \ No newline at end of file +// 新增时校验标识id是否可用 +export const checkId_api = (data:object) => server.get(`/permission/id/_validate`,data); +// 修改权限 +export const editPermission_api = (data:object) => server.patch(`/permission`,data); +// 添加权限 +export const addPermission_api = (data:object) => server.post(`/permission`,data); +// 删除权限 +export const delPermission_api = (id:string) => server.remove(`/permission/${id}`); \ No newline at end of file diff --git a/src/views/system/Permission/components/EditDialog.vue b/src/views/system/Permission/components/EditDialog.vue index d78ac2bb..953a084d 100644 --- a/src/views/system/Permission/components/EditDialog.vue +++ b/src/views/system/Permission/components/EditDialog.vue @@ -9,7 +9,10 @@ -
+
+ + {{ + i + 1 + }} + - - {{ - i + 1 - }} -
@@ -105,27 +109,40 @@ import { FormInstance, message } from 'ant-design-vue'; import { DeleteOutlined, PlusOutlined } from '@ant-design/icons-vue'; import { QuestionCircleOutlined } from '@ant-design/icons-vue'; +import { Rule } from 'ant-design-vue/es/form'; + +import { + checkId_api, + editPermission_api, + addPermission_api, +} from '@/api/system/permission'; const defaultAction = [ { action: 'query', name: '查询', describe: '查询' }, { action: 'save', name: '保存', describe: '保存' }, { action: 'delete', name: '删除', describe: '删除' }, ]; +const emits = defineEmits(['refresh']); // 弹窗相关 const dialog = reactive({ title: '', visible: false, handleOk: () => { - formRef.value?.validate().then(() => console.log('success')); + formRef.value?.validate().then(() => { + form.submit(); + }); }, // 控制弹窗的打开与关闭 changeVisible: (status: boolean, defaultForm: any = {}) => { - form.data = { name: '', description: '', ...defaultForm }; dialog.title = defaultForm.id ? '编辑' : '新增'; + form.data = { name: '', ...defaultForm }; table.data = defaultForm.id ? defaultForm.actions : [...defaultAction]; pager.total = table.data.length; pager.current = 1; dialog.visible = status; + nextTick(() => { + formRef.value?.clearValidate(); + }); }, }); // 表单相关 @@ -136,6 +153,46 @@ const form = reactive({ name: '', id: '', }, + rules: { + // 校验标识是否可用 + idCheck: (_rule: Rule, id: string, cb: Function) => { + if (!id) return cb('请输入标识(ID)'); + if (dialog.title === '编辑') return cb(); + checkId_api({ id }) + .then((resp: any) => { + if (resp.status === 200 && !resp.result.passed) + cb(resp.result.reason); + else cb(); + }) + .catch(() => cb('验证失败')); + + // return new Promise((resolve) => { + // checkId_api({ id }) + // .then((resp: any) => { + // if (resp.status === 200 && !resp.result.passed) + // resolve(resp.result.reason); + // else resolve(''); + // }) + // .catch(() => resolve('验证失败')); + // }); + }, + }, + submit: () => { + const params = { + ...form.data, + actions: table.data.filter((item: any) => item.action && item.name), + }; + const api = + dialog.title === '编辑' ? editPermission_api : addPermission_api; + + api(params).then((resp) => { + if (resp.status === 200) { + message.error('操作成功'); + emits('refresh'); + dialog.visible = false; + } + }); + }, }); const table = reactive({ @@ -144,21 +201,26 @@ const table = reactive({ title: '-', dataIndex: 'index', key: 'index', + width:80, + align:'center' }, { title: '操作类型', dataIndex: 'action', key: 'action', + width: 220 }, { title: '名称', dataIndex: 'name', key: 'name', + width: 220 }, { title: '说明', dataIndex: 'describe', key: 'describe', + width: 220 }, { title: '操作', @@ -230,5 +292,30 @@ defineExpose({ } } } + + .ant-table { + color: #ff4d4f; + + .ant-table-tbody { + color: #ff4d4f; + } + } + .delete-btn { + color: #000000d9; + &:hover{ + color: #415ed1; + } + } + .pager { + display: flex; + justify-content: center; + margin-bottom: 12px; + .ant-pagination { + margin-left: 8px; + :deep(.ant-pagination-item) { + display: none; + } + } + } } diff --git a/src/views/system/Permission/index.vue b/src/views/system/Permission/index.vue index ec763acd..baa12918 100644 --- a/src/views/system/Permission/index.vue +++ b/src/views/system/Permission/index.vue @@ -1,6 +1,6 @@ @@ -89,7 +89,7 @@ import { StopOutlined, PlayCircleOutlined, } from '@ant-design/icons-vue'; -import { getPermission_api, editPermission_api } from '@/api/system/permission'; +import { getPermission_api, editPermission_api, delPermission_api } from '@/api/system/permission'; const editDialogRef = ref(); // 新增弹窗实例 const tableRef = ref>({}); // 表格实例 @@ -138,6 +138,9 @@ const query = reactive({ }, ], params: {}, + search: (params:object)=>{ + query.params = params + } }); // 表格 @@ -181,12 +184,12 @@ const table = reactive({ }); }, clickDel: (row: any) => { - // delRole_api(row.id).then((resp: any) => { - // if (resp.status === 200) { - // tableRef.value?.reload(); - // message.success('操作成功!'); - // } - // }); + delPermission_api(row.id).then((resp: any) => { + if (resp.status === 200) { + tableRef.value?.reload(); + message.success('操作成功!'); + } + }); }, refresh: () => { tableRef.value.reload(); From 4badeb8d2a33a144785b420ebe34ad7bc2fcb6c1 Mon Sep 17 00:00:00 2001 From: easy <1358086367@qq.com> Date: Sun, 29 Jan 2023 16:08:40 +0800 Subject: [PATCH 2/4] =?UTF-8?q?update:=20=E9=A6=96=E9=A1=B5=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E5=8F=8A=E5=AE=8C=E5=96=84=E6=9D=83=E9=99=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/home.ts | 4 +- src/utils/comm.ts | 29 ++- src/views/home/components/StatusLabel.vue | 38 ++++ src/views/home/components/StepCard.vue | 13 +- .../components/dialogs/DeviceChooseDialog.vue | 181 ++++++++++++++++++ .../components/dialogs/FuncTestDialog.vue | 98 ---------- ...thodDialog.vue => ProductChooseDialog.vue} | 4 +- src/views/home/index.d.ts | 6 +- src/views/home/modules/config.ts | 64 +++---- 9 files changed, 294 insertions(+), 143 deletions(-) create mode 100644 src/views/home/components/StatusLabel.vue create mode 100644 src/views/home/components/dialogs/DeviceChooseDialog.vue delete mode 100644 src/views/home/components/dialogs/FuncTestDialog.vue rename src/views/home/components/dialogs/{AccessMethodDialog.vue => ProductChooseDialog.vue} (96%) diff --git a/src/api/home.ts b/src/api/home.ts index 2164e2f5..a37c0f3d 100644 --- a/src/api/home.ts +++ b/src/api/home.ts @@ -12,4 +12,6 @@ export const getDeviceCount_api = () => server.get(`/device/instance/_count`); // 产品数量 export const getProductCount_api = (data:object) => server.post(`/device-product/_count`, data); // 查询产品列表 -export const getProductList_api = (data:object) => server.get(`/device/product/_query/no-paging?paging=false`, data); +export const getProductList_api = (data:object={}) => server.get(`/device/product/_query/no-paging?paging=false`, data); +// 查询设备列表 +export const getDeviceList_api = (data:object) => server.post(`/device-instance/_query/`, data); diff --git a/src/utils/comm.ts b/src/utils/comm.ts index a2bb3385..d78696d8 100644 --- a/src/utils/comm.ts +++ b/src/utils/comm.ts @@ -6,7 +6,7 @@ import { Terms } from 'components/Search/types' * @param path {String} 路径 */ export const getImage = (path: string) => { - return new URL('/images'+path, import.meta.url).href + return new URL('/images' + path, import.meta.url).href } export const LocalStore = { @@ -57,3 +57,30 @@ export const filterTreeSelectNode = (value: string, treeNode: any, key: string = export const filterSelectNode = (value: string, option: any, key: string = 'label'): boolean => { return option[key]?.includes(value) } + +/** + * 时间转换为'2022-01-02 14:03:05' + * @param date 时间对象 + * @returns + */ +export const dateFormat = (dateSouce:any):string|Error => { + let date = null + try { + date = new Date(dateSouce) + } catch (error) { + return new Error('请传入日期格式数据') + } + let year = date.getFullYear(); + let month: number | string = date.getMonth() + 1; + let day: number | string = date.getDate(); + let hour: number | string = date.getHours(); + let minutes: number | string = date.getMinutes(); + let seconds: number | string = date.getSeconds(); + month = (month < 10) ? '0' + month : month; + day = (day < 10) ? '0' + day : day; + hour = (hour < 10) ? '0' + hour : hour; + minutes = (minutes < 10) ? '0' + minutes : minutes; + seconds = (seconds < 10) ? '0' + seconds : seconds; + return year + "-" + month + "-" + day + + " " + hour + ":" + minutes + ":" + seconds; +} \ No newline at end of file diff --git a/src/views/home/components/StatusLabel.vue b/src/views/home/components/StatusLabel.vue new file mode 100644 index 00000000..59a720f6 --- /dev/null +++ b/src/views/home/components/StatusLabel.vue @@ -0,0 +1,38 @@ + + + + + diff --git a/src/views/home/components/StepCard.vue b/src/views/home/components/StepCard.vue index ccc87a5d..661de226 100644 --- a/src/views/home/components/StepCard.vue +++ b/src/views/home/components/StepCard.vue @@ -21,11 +21,11 @@
- - @@ -38,8 +38,8 @@ import { PropType } from 'vue'; import { QuestionCircleOutlined } from '@ant-design/icons-vue'; import { message } from 'ant-design-vue'; -import AccessMethodDialog from './dialogs/AccessMethodDialog.vue'; -import FuncTestDialog from './dialogs/FuncTestDialog.vue'; +import ProductChooseDialog from './dialogs/ProductChooseDialog.vue'; +import DeviceChooseDialog from './dialogs/DeviceChooseDialog.vue'; import { recommendList } from '../index'; @@ -73,9 +73,8 @@ const jumpPage = (row: recommendList) => { } }; // 弹窗返回后的二次跳转 -const againJumpPage = (paramsSource: object) => { - const params = { ...(selectRow.params || {}), ...paramsSource }; - router.push(`${selectRow.linkUrl}${objToParams(params || {})}`); +const againJumpPage = (params: string) => { + router.push(`${selectRow.linkUrl}/${params}`); }; const objToParams = (source: object): string => { diff --git a/src/views/home/components/dialogs/DeviceChooseDialog.vue b/src/views/home/components/dialogs/DeviceChooseDialog.vue new file mode 100644 index 00000000..18a03947 --- /dev/null +++ b/src/views/home/components/dialogs/DeviceChooseDialog.vue @@ -0,0 +1,181 @@ + + + + + diff --git a/src/views/home/components/dialogs/FuncTestDialog.vue b/src/views/home/components/dialogs/FuncTestDialog.vue deleted file mode 100644 index f04db868..00000000 --- a/src/views/home/components/dialogs/FuncTestDialog.vue +++ /dev/null @@ -1,98 +0,0 @@ - - - - - diff --git a/src/views/home/components/dialogs/AccessMethodDialog.vue b/src/views/home/components/dialogs/ProductChooseDialog.vue similarity index 96% rename from src/views/home/components/dialogs/AccessMethodDialog.vue rename to src/views/home/components/dialogs/ProductChooseDialog.vue index 6bf83d48..07cb6e95 100644 --- a/src/views/home/components/dialogs/AccessMethodDialog.vue +++ b/src/views/home/components/dialogs/ProductChooseDialog.vue @@ -53,7 +53,7 @@ const productList = ref<[productItem] | []>([]); const getContainer = () => proxy?.$refs.modal as HTMLElement; const getOptions = () => { - getProductList_api().then((resp) => { + getProductList_api().then((resp:any) => { productList.value = resp.result .filter((i: any) => !i?.accessId) .map((item: { name: any; id: any }) => ({ @@ -63,7 +63,7 @@ const getOptions = () => { }); }; const handleOk = () => { - emits('confirm', form.value); + emits('confirm', form.value.productId); visible.value = false; }; const filterOption = (input: string, option: any) => { diff --git a/src/views/home/index.d.ts b/src/views/home/index.d.ts index 6b8a22bb..19b3c366 100644 --- a/src/views/home/index.d.ts +++ b/src/views/home/index.d.ts @@ -8,7 +8,11 @@ export interface recommendList { auth: boolean; dialogTag?: 'accessMethod' | 'funcTest'; } - +// 产品列表里的每项 +export interface productItem { + label: string; + value: string +} export interface deviceInfo { deviceId: string, deviceName: string, diff --git a/src/views/home/modules/config.ts b/src/views/home/modules/config.ts index 5857b8d0..49b1d104 100644 --- a/src/views/home/modules/config.ts +++ b/src/views/home/modules/config.ts @@ -1,9 +1,10 @@ // import {getImage} from '@/utils/comm' +import { useMenuStore } from "@/store/menu"; import { usePermissionStore } from "@/store/permission"; import { recommendList, bootConfig } from "../index"; -// 权限控制 +// 按钮权限控制 const hasPermission = usePermissionStore().hasPermission; const productPermission = (action: string) => hasPermission(`device/Product:${action}`); @@ -11,6 +12,8 @@ const devicePermission = (action: string) => hasPermission(`device/Instance:${action}`); const rulePermission = (action: string) => hasPermission(`rule-engine/Instance:${action}`); +// 页面权限控制 +const menuPermission = useMenuStore().hasPermission // 物联网引导-数据 @@ -18,7 +21,7 @@ export const deviceBootConfig: bootConfig[] = [ { english: 'STEP1', label: '创建产品', - link: '/a', + link: '/iot/device/Product', auth: productPermission('add'), params: { save: true, @@ -27,7 +30,7 @@ export const deviceBootConfig: bootConfig[] = [ { english: 'STEP2', label: '创建设备', - link: '/b', + link: '/iot/device/Instance', auth: devicePermission('add'), params: { save: true, @@ -36,7 +39,7 @@ export const deviceBootConfig: bootConfig[] = [ { english: 'STEP3', label: '规则引擎', - link: '/c', + link: '/iot/rule-engine/Instance', auth: rulePermission('add'), params: { save: true, @@ -50,7 +53,7 @@ export const deviceStepDetails: recommendList[] = [ details: '产品是设备的集合,通常指一组具有相同功能的设备。物联设备必须通过产品进行接入方式配置。', iconUrl: '/images/home/bottom-4.png', - linkUrl: '/a', + linkUrl: '/iot/device/Product', auth: productPermission('add'), params: { save: true, @@ -61,7 +64,7 @@ export const deviceStepDetails: recommendList[] = [ details: '通过产品对同一类型的设备进行统一的接入方式配置。请参照设备铭牌说明选择匹配的接入方式。', iconUrl: '/images/home/bottom-1.png', - linkUrl: '/a', + linkUrl: '/iot/device/Product/detail', auth: productPermission('update'), dialogTag: 'accessMethod', }, @@ -69,7 +72,7 @@ export const deviceStepDetails: recommendList[] = [ title: '添加测试设备', details: '添加单个设备,用于验证产品模型是否配置正确。', iconUrl: '/images/home/bottom-5.png', - linkUrl: '/a', + linkUrl: '/iot/device/Instance', auth: devicePermission('add'), params: { save: true, @@ -80,15 +83,16 @@ export const deviceStepDetails: recommendList[] = [ details: '对添加的测试设备进行功能调试,验证能否连接到平台,设备功能是否配置正确。', iconUrl: '/images/home/bottom-2.png', - linkUrl: '/a', + linkUrl: '/iot/device/Instance/detail', auth: devicePermission('update'), + // auth: true, dialogTag: 'funcTest', }, { title: '批量添加设备', details: '批量添加同一产品下的设备', iconUrl: '/images/home/bottom-3.png', - linkUrl: '/a', + linkUrl: '/iot/device/Instance', auth: devicePermission('import'), params: { import: true, @@ -102,14 +106,14 @@ export const opsBootConfig: bootConfig[] = [ { english: 'STEP1', label: '设备接入配置', - link: '/a', - auth: true, + link: '/iot/link/accessConfig', + auth: menuPermission('link/accessConfig'), }, { english: 'STEP2', label: '日志排查', - link: '/b', - auth: true, + link: '/iot/link/Log', + auth: menuPermission('link/Log'), params: { key: 'system', }, @@ -117,8 +121,8 @@ export const opsBootConfig: bootConfig[] = [ { english: 'STEP3', label: '实时监控', - link: '/c', - auth: false, + link: '/iot/link/dashboard', + auth: menuPermission('link/dashboard'), params: { save: true, }, @@ -131,44 +135,38 @@ export const opsStepDetails: recommendList[] = [ details: '根据业务需求自定义开发对应的产品(设备模型)接入协议,并上传到平台。', iconUrl: '/images/home/bottom-1.png', - linkUrl: '/a', - auth: true, - params: { - a: 1, - save: true, - }, + linkUrl: '/iot/link/protocol', + auth: menuPermission('link/Protocol'), + }, { title: '证书管理', details: '统一维护平台内的证书,用于数据通信加密。', iconUrl: '/images/home/bottom-6.png', - linkUrl: '/a', - auth: true, - params: { - a: 1, - save: false, - }, + linkUrl: '/iot/link/Certificate', + auth: menuPermission('link/Certificate'), + }, { title: '网络组件', details: '根据不同的传输类型配置平台底层网络组件相关参数。', iconUrl: '/images/home/bottom-3.png', - linkUrl: '/a', - auth: true, + linkUrl: '/iot/link/type', + auth: menuPermission('link/Type'), }, { title: '设备接入网关', details: '根据不同的传输类型,关联消息协议,配置设备接入网关相关参数。', iconUrl: '/images/home/bottom-4.png', - linkUrl: '/a', - auth: true, + linkUrl: '/iot/link/accessConfig', + auth: menuPermission('link/AccessConfig'), }, { title: '日志管理', details: '监控系统日志,及时处理系统异常。', iconUrl: '/images/home/bottom-5.png', - linkUrl: '/a', - auth: false, + linkUrl: '/iot/link/Log', + auth: menuPermission('Log'), params: { key: 'system', } From 8bdc44495701d1ebf4a5fb75991186fd89d0ed3c Mon Sep 17 00:00:00 2001 From: easy <1358086367@qq.com> Date: Sun, 29 Jan 2023 18:24:44 +0800 Subject: [PATCH 3/4] =?UTF-8?q?update:=20=E6=9D=83=E9=99=90=E7=AE=A1?= =?UTF-8?q?=E7=90=86=E6=B7=BB=E5=8A=A0=E6=9D=83=E9=99=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/system/permission.ts | 15 ++-- src/utils/comm.ts | 2 +- src/views/home/modules/config.ts | 4 +- src/views/system/Permission/index.vue | 116 ++++++++++++++++++++++++-- 4 files changed, 119 insertions(+), 18 deletions(-) diff --git a/src/api/system/permission.ts b/src/api/system/permission.ts index 13a7e037..659abbed 100644 --- a/src/api/system/permission.ts +++ b/src/api/system/permission.ts @@ -1,12 +1,15 @@ import server from '@/utils/request'; // 获取权限列表 -export const getPermission_api = (data:object) => server.post(`/permission/_query/`,data); +export const getPermission_api = (data: object) => server.post(`/permission/_query/`, data); // 新增时校验标识id是否可用 -export const checkId_api = (data:object) => server.get(`/permission/id/_validate`,data); -// 修改权限 -export const editPermission_api = (data:object) => server.patch(`/permission`,data); +export const checkId_api = (data: object) => server.get(`/permission/id/_validate`, data); +// 修改权限 | 导入文件内容 +export const editPermission_api = (data: object) => server.patch(`/permission`, data); // 添加权限 -export const addPermission_api = (data:object) => server.post(`/permission`,data); +export const addPermission_api = (data: object) => server.post(`/permission`, data); // 删除权限 -export const delPermission_api = (id:string) => server.remove(`/permission/${id}`); \ No newline at end of file +export const delPermission_api = (id: string) => server.remove(`/permission/${id}`); + +// 导出权限数据 +export const exportPermission_api = (data: object) => server.post(`/permission/_query/no-paging`, data); diff --git a/src/utils/comm.ts b/src/utils/comm.ts index d78696d8..3c032a79 100644 --- a/src/utils/comm.ts +++ b/src/utils/comm.ts @@ -83,4 +83,4 @@ export const dateFormat = (dateSouce:any):string|Error => { seconds = (seconds < 10) ? '0' + seconds : seconds; return year + "-" + month + "-" + day + " " + hour + ":" + minutes + ":" + seconds; -} \ No newline at end of file +} diff --git a/src/views/home/modules/config.ts b/src/views/home/modules/config.ts index 49b1d104..377db512 100644 --- a/src/views/home/modules/config.ts +++ b/src/views/home/modules/config.ts @@ -84,8 +84,8 @@ export const deviceStepDetails: recommendList[] = [ '对添加的测试设备进行功能调试,验证能否连接到平台,设备功能是否配置正确。', iconUrl: '/images/home/bottom-2.png', linkUrl: '/iot/device/Instance/detail', - auth: devicePermission('update'), - // auth: true, + // auth: devicePermission('update'), + auth: true, dialogTag: 'funcTest', }, { diff --git a/src/views/system/Permission/index.vue b/src/views/system/Permission/index.vue index baa12918..d221cc98 100644 --- a/src/views/system/Permission/index.vue +++ b/src/views/system/Permission/index.vue @@ -11,9 +11,40 @@ :defaultParams="{ sorts: [{ name: 'id', order: 'asc' }] }" >