Commit 0b3b21b771f8f320e6c820183d6a7793a00446eb

Authored by loveumiko
2 parents 3da1f60b d336bc7a

Merge branch 'main_dev' of http://git.yunteng.com/yunteng/thingskit-front into f…

…eat/device-new-protocol
Showing 35 changed files with 424 additions and 133 deletions
@@ -33,6 +33,7 @@ @@ -33,6 +33,7 @@
33 import { openWindow } from '/@/utils'; 33 import { openWindow } from '/@/utils';
34 34
35 import { useOpenKeys } from './useOpenKeys'; 35 import { useOpenKeys } from './useOpenKeys';
  36 + import { useMenuActiveFix } from '/@/hooks/business/useMenuActiveFix';
36 export default defineComponent({ 37 export default defineComponent({
37 name: 'SimpleMenu', 38 name: 'SimpleMenu',
38 components: { 39 components: {
@@ -120,7 +121,9 @@ @@ -120,7 +121,9 @@
120 isClickGo.value = false; 121 isClickGo.value = false;
121 return; 122 return;
122 } 123 }
123 - const path = (route || unref(currentRoute)).path; 124 +
  125 + let { flag, path } = useMenuActiveFix(route || unref(currentRoute));
  126 + path = flag ? path : (route || unref(currentRoute)).path;
124 127
125 menuState.activeName = path; 128 menuState.activeName = path;
126 129
@@ -29,7 +29,6 @@ export function useOpenKeys( @@ -29,7 +29,6 @@ export function useOpenKeys(
29 return; 29 return;
30 } 30 }
31 const keys = getAllParentPath(menuList, path); 31 const keys = getAllParentPath(menuList, path);
32 -  
33 if (!unref(accordion)) { 32 if (!unref(accordion)) {
34 menuState.openNames = uniq([...menuState.openNames, ...keys]); 33 menuState.openNames = uniq([...menuState.openNames, ...keys]);
35 } else { 34 } else {
  1 +import { RouteLocationNormalizedLoaded } from 'vue-router';
  2 +
  3 +const menuMap = new Map();
  4 +
  5 +menuMap.set('/visual/board/detail/:boardId/:boardName?', '/visual/board');
  6 +
  7 +export const useMenuActiveFix = (route: RouteLocationNormalizedLoaded) => {
  8 + let flag = false;
  9 + let path;
  10 +
  11 + const matchPath = route.matched.map((item) => item.path);
  12 + const needFixMenus: string[] = Array.from(menuMap.keys());
  13 +
  14 + for (const item of matchPath) {
  15 + for (const menu of needFixMenus) {
  16 + if (menu === item) {
  17 + flag = true;
  18 + path = menuMap.get(menu);
  19 + break;
  20 + }
  21 + }
  22 + }
  23 +
  24 + return {
  25 + flag,
  26 + path,
  27 + };
  28 +};
@@ -19,6 +19,7 @@ @@ -19,6 +19,7 @@
19 import { useRootSetting } from '/@/hooks/setting/useRootSetting'; 19 import { useRootSetting } from '/@/hooks/setting/useRootSetting';
20 import { useAppInject } from '/@/hooks/web/useAppInject'; 20 import { useAppInject } from '/@/hooks/web/useAppInject';
21 import { useDesign } from '/@/hooks/web/useDesign'; 21 import { useDesign } from '/@/hooks/web/useDesign';
  22 + import { OUTSIDE_LINK_PREFIX } from '/@/router/helper/routeHelper';
22 23
23 export default defineComponent({ 24 export default defineComponent({
24 name: 'LayoutMenu', 25 name: 'LayoutMenu',
@@ -113,6 +114,11 @@ @@ -113,6 +114,11 @@
113 */ 114 */
114 115
115 function handleMenuClick(path: string) { 116 function handleMenuClick(path: string) {
  117 + if (path.startsWith(OUTSIDE_LINK_PREFIX)) {
  118 + path = path.replace(OUTSIDE_LINK_PREFIX, '');
  119 + window.open(path);
  120 + return;
  121 + }
116 go(path); 122 go(path);
117 } 123 }
118 124
@@ -6,6 +6,7 @@ import { cloneDeep, omit } from 'lodash-es'; @@ -6,6 +6,7 @@ import { cloneDeep, omit } from 'lodash-es';
6 import { warn } from '/@/utils/log'; 6 import { warn } from '/@/utils/log';
7 import { createRouter, createWebHashHistory } from 'vue-router'; 7 import { createRouter, createWebHashHistory } from 'vue-router';
8 8
  9 +export const OUTSIDE_LINK_PREFIX = '/outside/link';
9 export type LayoutMapKey = 'LAYOUT'; 10 export type LayoutMapKey = 'LAYOUT';
10 const IFRAME = () => import('/@/views/sys/iframe/FrameBlank.vue'); 11 const IFRAME = () => import('/@/views/sys/iframe/FrameBlank.vue');
11 12
@@ -81,6 +82,9 @@ export function transformObjToRoute<T = AppRouteModule>(routeList: AppRouteModul @@ -81,6 +82,9 @@ export function transformObjToRoute<T = AppRouteModule>(routeList: AppRouteModul
81 route.meta = meta; 82 route.meta = meta;
82 } 83 }
83 } 84 }
  85 + if (!route.path.startsWith('/') && route.meta.isLink) {
  86 + route.path = `${OUTSIDE_LINK_PREFIX}${route.path}`;
  87 + }
84 route.children && asyncImportRoute(route.children); 88 route.children && asyncImportRoute(route.children);
85 }); 89 });
86 return routeList as unknown as T[]; 90 return routeList as unknown as T[];
@@ -37,13 +37,21 @@ @@ -37,13 +37,21 @@
37 </a-button> 37 </a-button>
38 </template> 38 </template>
39 <template #status="{ record }"> 39 <template #status="{ record }">
40 - <Switch  
41 - :checked="record.status === 1"  
42 - :loading="record.pendingStatus"  
43 - checkedChildren="启用"  
44 - unCheckedChildren="禁用"  
45 - @change="(checked:boolean)=>statusChange(checked,record)"  
46 - /> 40 + <Authority value="api:yt:alarm:profile:status">
  41 + <Switch
  42 + :checked="record.status === 1"
  43 + :loading="record.pendingStatus"
  44 + checkedChildren="启用"
  45 + unCheckedChildren="禁用"
  46 + @change="(checked:boolean)=>statusChange(checked,record)"
  47 + />
  48 + </Authority>
  49 + <Tag
  50 + v-if="!hasPermission('api:yt:alarm:profile:status')"
  51 + :color="record.status ? 'green' : 'red'"
  52 + >
  53 + {{ record.status ? '启用' : '禁用' }}
  54 + </Tag>
47 </template> 55 </template>
48 <template #action="{ record }"> 56 <template #action="{ record }">
49 <TableAction 57 <TableAction
@@ -88,7 +96,7 @@ @@ -88,7 +96,7 @@
88 import { useResetOrganizationTree, OrganizationIdTree } from '/@/views/common/organizationIdTree'; 96 import { useResetOrganizationTree, OrganizationIdTree } from '/@/views/common/organizationIdTree';
89 import { deleteAlarmConfig, queryAlarmConfig } from '/@/api/alarm/config/alarmConfig'; 97 import { deleteAlarmConfig, queryAlarmConfig } from '/@/api/alarm/config/alarmConfig';
90 import { searchFormSchema, columns } from './config.data'; 98 import { searchFormSchema, columns } from './config.data';
91 - import { Modal, Popconfirm } from 'ant-design-vue'; 99 + import { Modal, Popconfirm, Tag } from 'ant-design-vue';
92 import { JsonPreview } from '/@/components/CodeEditor'; 100 import { JsonPreview } from '/@/components/CodeEditor';
93 import { findDictItemByCode } from '/@/api/system/dict'; 101 import { findDictItemByCode } from '/@/api/system/dict';
94 import { alarmContactGetPage } from '/@/api/device/deviceConfigApi'; 102 import { alarmContactGetPage } from '/@/api/device/deviceConfigApi';
@@ -97,6 +105,7 @@ @@ -97,6 +105,7 @@
97 import { putAlarmConfigStatus } from '/@/api/alarm/config/alarmConfig'; 105 import { putAlarmConfigStatus } from '/@/api/alarm/config/alarmConfig';
98 import { useMessage } from '/@/hooks/web/useMessage'; 106 import { useMessage } from '/@/hooks/web/useMessage';
99 import { Authority } from '/@/components/Authority'; 107 import { Authority } from '/@/components/Authority';
  108 + import { usePermission } from '/@/hooks/web/usePermission';
100 109
101 export default defineComponent({ 110 export default defineComponent({
102 components: { 111 components: {
@@ -108,8 +117,10 @@ @@ -108,8 +117,10 @@
108 Switch, 117 Switch,
109 Authority, 118 Authority,
110 Popconfirm, 119 Popconfirm,
  120 + Tag,
111 }, 121 },
112 setup() { 122 setup() {
  123 + const { hasPermission } = usePermission();
113 const searchInfo = reactive<Recordable>({}); 124 const searchInfo = reactive<Recordable>({});
114 const { organizationIdTreeRef, resetFn } = useResetOrganizationTree(searchInfo); 125 const { organizationIdTreeRef, resetFn } = useResetOrganizationTree(searchInfo);
115 // 刷新 126 // 刷新
@@ -250,6 +261,7 @@ @@ -250,6 +261,7 @@
250 showAlarmContact, 261 showAlarmContact,
251 showMessageMode, 262 showMessageMode,
252 statusChange, 263 statusChange,
  264 + hasPermission,
253 }; 265 };
254 }, 266 },
255 }); 267 });
@@ -17,7 +17,8 @@ export enum ConfigurationPermission { @@ -17,7 +17,8 @@ export enum ConfigurationPermission {
17 UPDATE = 'api:yt:dataview:center:update', 17 UPDATE = 'api:yt:dataview:center:update',
18 DELETE = 'api:yt:dataview:center:delete', 18 DELETE = 'api:yt:dataview:center:delete',
19 SHARE = 'api:yt:dataview:center:share', 19 SHARE = 'api:yt:dataview:center:share',
20 - DESIGN = 'api:yt:dataview:center:get_configuration_info:design', 20 + // DESIGN = 'api:yt:dataview:center:get_configuration_info:design',
  21 + DESIGN = 'api:yt:dataview:center:get_dataview_info:design',
21 PREVIEW = 'api:yt:dataview:center:get_configuration_info:preview', 22 PREVIEW = 'api:yt:dataview:center:get_configuration_info:preview',
22 PUBLISH = 'api:yt:dataview:center:publish', 23 PUBLISH = 'api:yt:dataview:center:publish',
23 // CANCEL_PUBLISH = 'api:yt:dataview:center:cancel_publish', 24 // CANCEL_PUBLISH = 'api:yt:dataview:center:cancel_publish',
@@ -280,6 +280,7 @@ @@ -280,6 +280,7 @@
280 </Tooltip> 280 </Tooltip>
281 <Tooltip v-if="!isCustomerUser" title="设计"> 281 <Tooltip v-if="!isCustomerUser" title="设计">
282 <AuthIcon 282 <AuthIcon
  283 + :auth="ConfigurationPermission.DESIGN"
283 :disabled="item.state === 1" 284 :disabled="item.state === 1"
284 icon="ant-design:edit-outlined" 285 icon="ant-design:edit-outlined"
285 @click="handleDesign(item)" 286 @click="handleDesign(item)"
@@ -169,12 +169,12 @@ export const alarmColumns: BasicColumn[] = [ @@ -169,12 +169,12 @@ export const alarmColumns: BasicColumn[] = [
169 { 169 {
170 title: '告警时间', 170 title: '告警时间',
171 dataIndex: 'createdTime', 171 dataIndex: 'createdTime',
172 - width: 120, 172 + width: 180,
173 }, 173 },
174 { 174 {
175 title: '告警设备', 175 title: '告警设备',
176 dataIndex: 'deviceName', 176 dataIndex: 'deviceName',
177 - width: 100, 177 + width: 120,
178 }, 178 },
179 { 179 {
180 title: '告警场景', 180 title: '告警场景',
@@ -184,14 +184,20 @@ export const alarmColumns: BasicColumn[] = [ @@ -184,14 +184,20 @@ export const alarmColumns: BasicColumn[] = [
184 { 184 {
185 title: '告警级别', 185 title: '告警级别',
186 dataIndex: 'severity', 186 dataIndex: 'severity',
187 - width: 160, 187 + width: 90,
188 format: (text) => alarmLevel(text), 188 format: (text) => alarmLevel(text),
189 }, 189 },
190 { 190 {
  191 + title: '告警详情',
  192 + dataIndex: 'details',
  193 + slots: { customRender: 'details' },
  194 + width: 160,
  195 + },
  196 + {
191 title: '状态', 197 title: '状态',
192 dataIndex: 'status', 198 dataIndex: 'status',
193 format: (text) => statusType(text), 199 format: (text) => statusType(text),
194 - width: 160, 200 + width: 100,
195 }, 201 },
196 ]; 202 ];
197 203
@@ -263,14 +269,6 @@ export const alarmSchemasForm: FormSchema[] = [ @@ -263,14 +269,6 @@ export const alarmSchemasForm: FormSchema[] = [
263 disabled: true, 269 disabled: true,
264 }, 270 },
265 }, 271 },
266 - {  
267 - field: 'details',  
268 - label: '详情',  
269 - component: 'InputTextArea',  
270 - componentProps: {  
271 - maxLength: 255,  
272 - },  
273 - },  
274 ]; 272 ];
275 // 子设备 273 // 子设备
276 export const childDeviceSchemas: FormSchema[] = [ 274 export const childDeviceSchemas: FormSchema[] = [
@@ -54,10 +54,6 @@ @@ -54,10 +54,6 @@
54 await resetFields(); 54 await resetFields();
55 await setFieldsValue({ 55 await setFieldsValue({
56 ...data, 56 ...data,
57 - details: JSON.stringify(data?.details?.data).slice(  
58 - 1,  
59 - JSON.stringify(data?.details?.data).length - 1  
60 - ),  
61 severity: alarmLevel(data.severity), 57 severity: alarmLevel(data.severity),
62 status: statusType(data.status), 58 status: statusType(data.status),
63 }); 59 });
@@ -145,6 +145,8 @@ @@ -145,6 +145,8 @@
145 // !!!此处需要删除地图的属性,否则会报堆栈溢出的错误 Uncaught RangeError: Maximum call stack size exceeded 145 // !!!此处需要删除地图的属性,否则会报堆栈溢出的错误 Uncaught RangeError: Maximum call stack size exceeded
146 Reflect.deleteProperty(DeviceStep1Ref.value.positionState, 'map'); 146 Reflect.deleteProperty(DeviceStep1Ref.value.positionState, 'map');
147 Reflect.deleteProperty(DeviceStep1Ref.value.positionState, 'marker'); 147 Reflect.deleteProperty(DeviceStep1Ref.value.positionState, 'marker');
  148 + Reflect.deleteProperty(DeviceStep1Ref.value.devicePositionState, 'map');
  149 + Reflect.deleteProperty(DeviceStep1Ref.value.devicePositionState, 'marker');
148 setModalProps({ 150 setModalProps({
149 confirmLoading: true, 151 confirmLoading: true,
150 }); 152 });
@@ -156,7 +158,7 @@ @@ -156,7 +158,7 @@
156 customerId: currentDeviceData.customerId, 158 customerId: currentDeviceData.customerId,
157 deviceInfo: { 159 deviceInfo: {
158 avatar: DeviceStep1Ref.value?.devicePic, 160 avatar: DeviceStep1Ref.value?.devicePic,
159 - ...DeviceStep1Ref.value?.positionState, 161 + ...DeviceStep1Ref.value?.devicePositionState,
160 }, 162 },
161 }; 163 };
162 validateNameLength(stepRecord.name); 164 validateNameLength(stepRecord.name);
@@ -168,7 +170,7 @@ @@ -168,7 +170,7 @@
168 sn: stepRecord.name, 170 sn: stepRecord.name,
169 deviceInfo: { 171 deviceInfo: {
170 avatar: DeviceStep1Ref.value?.devicePic, 172 avatar: DeviceStep1Ref.value?.devicePic,
171 - ...DeviceStep1Ref.value?.positionState, 173 + ...DeviceStep1Ref.value?.devicePositionState,
172 }, 174 },
173 deviceToken: 175 deviceToken:
174 unref(current) === 0 || !unref(stepState).addAgree 176 unref(current) === 0 || !unref(stepState).addAgree
@@ -46,7 +46,7 @@ @@ -46,7 +46,7 @@
46 </div> 46 </div>
47 </template> 47 </template>
48 <template #deviceAddress> 48 <template #deviceAddress>
49 - <Input disabled v-model:value="positionState.address"> 49 + <Input disabled v-model:value="devicePositionState.address">
50 <template #addonAfter> 50 <template #addonAfter>
51 <EnvironmentTwoTone @click="selectPosition" /> 51 <EnvironmentTwoTone @click="selectPosition" />
52 </template> 52 </template>
@@ -128,6 +128,7 @@ @@ -128,6 +128,7 @@
128 import { useDrawer } from '/@/components/Drawer'; 128 import { useDrawer } from '/@/components/Drawer';
129 import DeptDrawer from '/@/views/system/organization/OrganizationDrawer.vue'; 129 import DeptDrawer from '/@/views/system/organization/OrganizationDrawer.vue';
130 import { TaskTypeEnum } from '/@/views/task/center/config'; 130 import { TaskTypeEnum } from '/@/views/task/center/config';
  131 + import { toRaw } from 'vue';
131 132
132 export default defineComponent({ 133 export default defineComponent({
133 components: { 134 components: {
@@ -239,8 +240,14 @@ @@ -239,8 +240,14 @@
239 const selectPosition = () => { 240 const selectPosition = () => {
240 visible.value = true; 241 visible.value = true;
241 if (!positionState.longitude) { 242 if (!positionState.longitude) {
242 - positionState.longitude = '104.04666605565338';  
243 - positionState.latitude = '30.543516387560476'; 243 + positionState.longitude = '104.05326410962411';
  244 + positionState.latitude = '30.54855093076791';
  245 +
  246 + // 根据经纬度获取详细位置
  247 + if (positionState.longitude && positionState.latitude) {
  248 + var pt = new BMap.Point(positionState.longitude, positionState.latitude);
  249 + getAddrByPoint(pt);
  250 + }
244 initMap(positionState.longitude, positionState.latitude); 251 initMap(positionState.longitude, positionState.latitude);
245 } else { 252 } else {
246 initMap(positionState.longitude, positionState.latitude); 253 initMap(positionState.longitude, positionState.latitude);
@@ -261,6 +268,15 @@ @@ -261,6 +268,15 @@
261 map: null, 268 map: null,
262 marker: null, 269 marker: null,
263 }); 270 });
  271 +
  272 + const devicePositionState = ref({
  273 + longitude: '',
  274 + latitude: '',
  275 + address: '',
  276 + map: null,
  277 + marker: null,
  278 + });
  279 +
264 /** 280 /**
265 * 逆地址解析函数(根据坐标点获取详细地址) 281 * 逆地址解析函数(根据坐标点获取详细地址)
266 * @param {Object} point 百度地图坐标点,必传 282 * @param {Object} point 百度地图坐标点,必传
@@ -371,6 +387,7 @@ @@ -371,6 +387,7 @@
371 // 确定选择的位置 387 // 确定选择的位置
372 const handleOk = () => { 388 const handleOk = () => {
373 visible.value = false; 389 visible.value = false;
  390 + devicePositionState.value = { ...toRaw(positionState) };
374 }; 391 };
375 // 取消选择位置 392 // 取消选择位置
376 const handleCancel = () => { 393 const handleCancel = () => {
@@ -385,6 +402,7 @@ @@ -385,6 +402,7 @@
385 positionState.longitude = deviceInfo.longitude; 402 positionState.longitude = deviceInfo.longitude;
386 positionState.latitude = deviceInfo.latitude; 403 positionState.latitude = deviceInfo.latitude;
387 positionState.address = deviceInfo.address; 404 positionState.address = deviceInfo.address;
  405 + devicePositionState.value = { ...toRaw(positionState) };
388 devicePic.value = deviceInfo.avatar; 406 devicePic.value = deviceInfo.avatar;
389 setFieldsValue({ 407 setFieldsValue({
390 ...data, 408 ...data,
@@ -418,11 +436,13 @@ @@ -418,11 +436,13 @@
418 function parentResetDevicePic(deviceInfo) { 436 function parentResetDevicePic(deviceInfo) {
419 devicePic.value = deviceInfo.avatar; 437 devicePic.value = deviceInfo.avatar;
420 } 438 }
  439 +
421 // 父组件重置位置 440 // 父组件重置位置
422 function parentResetPositionState() { 441 function parentResetPositionState() {
423 for (let key in positionState) { 442 for (let key in positionState) {
424 positionState[key] = ''; 443 positionState[key] = '';
425 } 444 }
  445 + devicePositionState.value = { ...toRaw(positionState) };
426 } 446 }
427 // 禁用设备类型 447 // 禁用设备类型
428 function disabledDeviceType(disabled: boolean) { 448 function disabledDeviceType(disabled: boolean) {
@@ -474,6 +494,7 @@ @@ -474,6 +494,7 @@
474 handleOpenOrgDrawer, 494 handleOpenOrgDrawer,
475 handleSuccess, 495 handleSuccess,
476 handleTreeOrg, 496 handleTreeOrg,
  497 + devicePositionState,
477 }; 498 };
478 }, 499 },
479 }); 500 });
@@ -12,17 +12,31 @@ @@ -12,17 +12,31 @@
12 ]" 12 ]"
13 /> 13 />
14 </template> 14 </template>
  15 + <template #details="{ record }">
  16 + <a-button type="link" class="ml-2" @click="handleViewAlarmDetails(record)">
  17 + 查看告警详情
  18 + </a-button>
  19 + </template>
15 </BasicTable> 20 </BasicTable>
16 <AlarmDetailModal @register="registerDetailModal" @success="handleSuccess" /> 21 <AlarmDetailModal @register="registerDetailModal" @success="handleSuccess" />
17 </div> 22 </div>
18 </template> 23 </template>
19 <script lang="ts"> 24 <script lang="ts">
20 - import { defineComponent } from 'vue'; 25 + import { defineComponent, h, nextTick } from 'vue';
21 import { BasicTable, useTable, TableAction } from '/@/components/Table'; 26 import { BasicTable, useTable, TableAction } from '/@/components/Table';
22 import { alarmColumns, alarmSearchSchemas } from '../../config/detail.config'; 27 import { alarmColumns, alarmSearchSchemas } from '../../config/detail.config';
23 import { getDeviceAlarm } from '/@/api/device/deviceManager'; 28 import { getDeviceAlarm } from '/@/api/device/deviceManager';
24 import AlarmDetailModal from '../modal/AlarmDetailModal.vue'; 29 import AlarmDetailModal from '../modal/AlarmDetailModal.vue';
25 import { useModal } from '/@/components/Modal'; 30 import { useModal } from '/@/components/Modal';
  31 + import { Modal } from 'ant-design-vue';
  32 + import { JsonPreview } from '/@/components/CodeEditor';
  33 + import { getDeviceDetail } from '/@/api/device/deviceManager';
  34 + import { getAttribute } from '/@/api/ruleengine/ruleengineApi';
  35 + import {
  36 + operationNumber_OR_TIME,
  37 + operationString,
  38 + operationBoolean,
  39 + } from '/@/views/rule/linkedge/config/formatData';
26 export default defineComponent({ 40 export default defineComponent({
27 name: 'DeviceManagement', 41 name: 'DeviceManagement',
28 components: { 42 components: {
@@ -66,11 +80,85 @@ @@ -66,11 +80,85 @@
66 const handleSuccess = () => { 80 const handleSuccess = () => {
67 reload(); 81 reload();
68 }; 82 };
  83 + const handleViewAlarmDetails = async (record: Recordable) => {
  84 + await nextTick();
  85 + const { details } = record;
  86 + const deviceIdKeys = Object.keys(details);
  87 + const detailObject = deviceIdKeys.map((key) => ({ label: key, value: details[key] }));
  88 + const dataFormat = await handleAlarmDetailFormat(deviceIdKeys);
  89 + const dataFormats = detailObject.reduce((acc: any, curr: any) => {
  90 + dataFormat.forEach((item) => {
  91 + if (item.tbDeviceId === curr.label) {
  92 + const findName = item.attribute.find(
  93 + (item) => item.identifier === curr.value.key
  94 + )?.name;
  95 + const findLogin = [
  96 + ...operationNumber_OR_TIME,
  97 + ...operationString,
  98 + ...operationBoolean,
  99 + ].find((item) => item.value === curr.value.logic)?.symbol;
  100 + const findAttribute = item.attribute.find(
  101 + (findItem) => findItem.identifier === curr.value.key
  102 + );
  103 + const value = {
  104 + ['触发属性']: findName,
  105 + ['触发条件']: `${findLogin}${curr.value.logicValue}`,
  106 + ['触发值']: `${curr.value.realValue}${findAttribute.detail?.dataType?.specs?.unit?.key}`,
  107 + };
  108 + const data = {
  109 + [item.name]: value,
  110 + };
  111 + acc.push(data);
  112 + }
  113 + });
  114 + return [...acc];
  115 + }, []);
  116 + const objectFormat = dataFormats.reduce((acc: any, curr: any) => {
  117 + return {
  118 + ...acc,
  119 + ...curr,
  120 + };
  121 + }, {});
  122 + Modal.info({
  123 + title: '告警详情',
  124 + width: 600,
  125 + centered: true,
  126 + maskClosable: true,
  127 + content: h(JsonPreview, { data: JSON.parse(JSON.stringify(objectFormat)) }),
  128 + });
  129 + };
  130 + const handleAlarmDetailFormat = async (keys: string[]) => {
  131 + const temp: any = [];
  132 + for (let item of keys) {
  133 + if (item === 'key' || item === 'data') return; //旧数据则终止
  134 + const deviceDetailRes = await getDeviceDetail(item);
  135 + const { deviceProfileId } = deviceDetailRes;
  136 + if (!deviceProfileId) return;
  137 + const attributeRes = await getAttribute(deviceProfileId);
  138 + const dataFormat: any = handleDataFormat(deviceDetailRes, attributeRes);
  139 + temp.push(dataFormat);
  140 + }
  141 + return temp;
  142 + };
  143 + const handleDataFormat = (deviceDetail: any, attributes: any) => {
  144 + const { name, tbDeviceId } = deviceDetail;
  145 + const attribute = attributes.map((item) => ({
  146 + identifier: item.identifier,
  147 + name: item.name,
  148 + detail: item.detail,
  149 + }));
  150 + return {
  151 + name,
  152 + tbDeviceId,
  153 + attribute,
  154 + };
  155 + };
69 return { 156 return {
70 registerTable, 157 registerTable,
71 registerDetailModal, 158 registerDetailModal,
72 handleDetail, 159 handleDetail,
73 handleSuccess, 160 handleSuccess,
  161 + handleViewAlarmDetails,
74 }; 162 };
75 }, 163 },
76 }); 164 });
@@ -52,7 +52,9 @@ @@ -52,7 +52,9 @@
52 <div class="mt-4" v-if="!isCustomer"> 52 <div class="mt-4" v-if="!isCustomer">
53 <a-button type="primary" class="mr-4" @click="copyTbDeviceId">复制设备ID</a-button> 53 <a-button type="primary" class="mr-4" @click="copyTbDeviceId">复制设备ID</a-button>
54 <a-button type="primary" class="mr-4" @click="copyDeviceToken">复制访问令牌</a-button> 54 <a-button type="primary" class="mr-4" @click="copyDeviceToken">复制访问令牌</a-button>
55 - <a-button type="primary" class="mr-4" @click="manageDeviceToken">管理设备凭证</a-button> 55 + <Authority value="api:yt:device:equipment">
  56 + <a-button type="primary" class="mr-4" @click="manageDeviceToken">管理设备凭证</a-button>
  57 + </Authority>
56 <ManageDeviceTokenModal @register="registerModal" /> 58 <ManageDeviceTokenModal @register="registerModal" />
57 </div> 59 </div>
58 <div class="mt-4"> 60 <div class="mt-4">
@@ -84,10 +86,10 @@ @@ -84,10 +86,10 @@
84 import { DeviceTypeEnum } from '/@/api/device/model/deviceModel'; 86 import { DeviceTypeEnum } from '/@/api/device/model/deviceModel';
85 import { useAuthDeviceDetail } from '../../hook/useAuthDeviceDetail'; 87 import { useAuthDeviceDetail } from '../../hook/useAuthDeviceDetail';
86 import { useClipboard } from '@vueuse/core'; 88 import { useClipboard } from '@vueuse/core';
87 -  
88 import wz from '/@/assets/images/wz.png'; 89 import wz from '/@/assets/images/wz.png';
89 import { useAsyncQueue } from '../../../localtion/useAsyncQueue'; 90 import { useAsyncQueue } from '../../../localtion/useAsyncQueue';
90 import locationImage from '/@/assets/icons/location.svg'; 91 import locationImage from '/@/assets/icons/location.svg';
  92 + import { Authority } from '/@/components/Authority';
91 93
92 export default defineComponent({ 94 export default defineComponent({
93 components: { 95 components: {
@@ -98,6 +100,7 @@ @@ -98,6 +100,7 @@
98 BasicModal, 100 BasicModal,
99 Tooltip, 101 Tooltip,
100 Empty, 102 Empty,
  103 + Authority,
101 }, 104 },
102 props: { 105 props: {
103 deviceDetail: { 106 deviceDetail: {
@@ -5,7 +5,9 @@ @@ -5,7 +5,9 @@
5 > 5 >
6 <template #toolbar> 6 <template #toolbar>
7 <Space> 7 <Space>
8 - <Button type="primary" @click="openModal(true)">命令下发</Button> 8 + <Authority value="api:yt:device:rpc">
  9 + <Button type="primary" @click="openModal(true)">命令下发</Button>
  10 + </Authority>
9 </Space> 11 </Space>
10 </template> 12 </template>
11 <template #recordContent="{ record }"> 13 <template #recordContent="{ record }">
@@ -43,6 +45,7 @@ @@ -43,6 +45,7 @@
43 import { DeviceRecord } from '/@/api/device/model/deviceModel'; 45 import { DeviceRecord } from '/@/api/device/model/deviceModel';
44 import { BasicModal, useModal } from '/@/components/Modal'; 46 import { BasicModal, useModal } from '/@/components/Modal';
45 import CommandIssuance from '../CommandIssuance.vue'; 47 import CommandIssuance from '../CommandIssuance.vue';
  48 + import { Authority } from '/@/components/Authority';
46 49
47 const props = defineProps({ 50 const props = defineProps({
48 fromId: { 51 fromId: {
@@ -24,14 +24,16 @@ @@ -24,14 +24,16 @@
24 <Authority value="api:yt:device:import"> 24 <Authority value="api:yt:device:import">
25 <Button type="primary" @click="handleBatchImport">导入</Button> 25 <Button type="primary" @click="handleBatchImport">导入</Button>
26 </Authority> 26 </Authority>
27 - <a-button  
28 - v-if="authBtn(role)"  
29 - type="primary"  
30 - @click="handleBatchAssign"  
31 - :disabled="!isExistOption"  
32 - >  
33 - 批量分配  
34 - </a-button> 27 + <Authority value="api:yt:device:assign">
  28 + <a-button
  29 + v-if="authBtn(role)"
  30 + type="primary"
  31 + @click="handleBatchAssign"
  32 + :disabled="!isExistOption"
  33 + >
  34 + 批量分配
  35 + </a-button>
  36 + </Authority>
35 </template> 37 </template>
36 <template #img="{ record }"> 38 <template #img="{ record }">
37 <TableImg 39 <TableImg
@@ -134,6 +136,7 @@ @@ -134,6 +136,7 @@
134 label: '分配客户', 136 label: '分配客户',
135 icon: 'mdi:account-arrow-right', 137 icon: 'mdi:account-arrow-right',
136 ifShow: authBtn(role), 138 ifShow: authBtn(role),
  139 + auth: 'api:yt:device:assign',
137 onClick: handleDispatchCustomer.bind(null, record), 140 onClick: handleDispatchCustomer.bind(null, record),
138 }, 141 },
139 { 142 {
@@ -33,9 +33,15 @@ @@ -33,9 +33,15 @@
33 </Button> 33 </Button>
34 </Authority> 34 </Authority>
35 <Button type="primary" @click="handleOpenTsl"> 物模型TSL </Button> 35 <Button type="primary" @click="handleOpenTsl"> 物模型TSL </Button>
36 - <Upload v-if="isShowBtn" :show-upload-list="false" :customRequest="handleImportModel">  
37 - <Button type="primary" :loading="importLoading"> 导入物模型 </Button>  
38 - </Upload> 36 + <Authority value="api:yt:things_model:import">
  37 + <Upload
  38 + v-if="isShowBtn"
  39 + :show-upload-list="false"
  40 + :customRequest="handleImportModel"
  41 + >
  42 + <Button type="primary" :loading="importLoading"> 导入物模型 </Button>
  43 + </Upload>
  44 + </Authority>
39 </div> 45 </div>
40 <div class="flex gap-2"> 46 <div class="flex gap-2">
41 <Authority :value="ModelOfMatterPermission.RELEASE"> 47 <Authority :value="ModelOfMatterPermission.RELEASE">
@@ -19,6 +19,6 @@ @@ -19,6 +19,6 @@
19 </template> 19 </template>
20 <style scoped> 20 <style scoped>
21 :deep(.ant-table-body) { 21 :deep(.ant-table-body) {
22 - overflow: hidden !important; 22 + overflow: auto !important;
23 } 23 }
24 </style> 24 </style>
@@ -17,16 +17,26 @@ @@ -17,16 +17,26 @@
17 </Authority> 17 </Authority>
18 </template> 18 </template>
19 <template #config="{ record }"> 19 <template #config="{ record }">
20 - <a-button type="link" class="ml-2" @click="showData(record)"> 查看配置 </a-button> 20 + <Authority value="api:yt:message:get">
  21 + <a-button type="link" class="ml-2" @click="showData(record)"> 查看配置 </a-button>
  22 + </Authority>
21 </template> 23 </template>
22 <template #status="{ record }"> 24 <template #status="{ record }">
23 - <Switch  
24 - :checked="record.status === 1"  
25 - :loading="record.pendingStatus"  
26 - checkedChildren="启用"  
27 - unCheckedChildren="禁用"  
28 - @change="(checked:boolean)=>statusChange(checked,record)"  
29 - /> 25 + <Authority value="api:yt:message:status">
  26 + <Switch
  27 + :checked="record.status === 1"
  28 + :loading="record.pendingStatus"
  29 + checkedChildren="启用"
  30 + unCheckedChildren="禁用"
  31 + @change="(checked:boolean)=>statusChange(checked,record)"
  32 + />
  33 + </Authority>
  34 + <Tag
  35 + v-if="!hasPermission('api:yt:message:status')"
  36 + :color="record.status ? 'green' : 'red'"
  37 + >
  38 + {{ record.status ? '启用' : '禁用' }}
  39 + </Tag>
30 </template> 40 </template>
31 <template #action="{ record }"> 41 <template #action="{ record }">
32 <TableAction 42 <TableAction
@@ -62,18 +72,20 @@ @@ -62,18 +72,20 @@
62 import { useDrawer } from '/@/components/Drawer'; 72 import { useDrawer } from '/@/components/Drawer';
63 import ConfigDrawer from './ConfigDrawer.vue'; 73 import ConfigDrawer from './ConfigDrawer.vue';
64 import { columns, searchFormSchema } from './config.data'; 74 import { columns, searchFormSchema } from './config.data';
65 - import { Modal, Popconfirm } from 'ant-design-vue'; 75 + import { Modal, Popconfirm, Tag } from 'ant-design-vue';
66 import { JsonPreview } from '/@/components/CodeEditor'; 76 import { JsonPreview } from '/@/components/CodeEditor';
67 import { useMessage } from '/@/hooks/web/useMessage'; 77 import { useMessage } from '/@/hooks/web/useMessage';
68 import { useBatchDelete } from '/@/hooks/web/useBatchDelete'; 78 import { useBatchDelete } from '/@/hooks/web/useBatchDelete';
69 import { Switch } from 'ant-design-vue'; 79 import { Switch } from 'ant-design-vue';
70 import { setMessageConfigStatus } from '/@/api/message/config'; 80 import { setMessageConfigStatus } from '/@/api/message/config';
71 import { Authority } from '/@/components/Authority'; 81 import { Authority } from '/@/components/Authority';
  82 + import { usePermission } from '/@/hooks/web/usePermission';
72 83
73 export default defineComponent({ 84 export default defineComponent({
74 name: 'MessageConfigManagement', 85 name: 'MessageConfigManagement',
75 - components: { BasicTable, ConfigDrawer, TableAction, Switch, Authority, Popconfirm }, 86 + components: { BasicTable, ConfigDrawer, TableAction, Switch, Authority, Popconfirm, Tag },
76 setup() { 87 setup() {
  88 + const { hasPermission } = usePermission();
77 const [registerDrawer, { openDrawer }] = useDrawer(); 89 const [registerDrawer, { openDrawer }] = useDrawer();
78 function handleSuccess() { 90 function handleSuccess() {
79 reload(); 91 reload();
@@ -168,6 +180,7 @@ @@ -168,6 +180,7 @@
168 handleDeleteOrBatchDelete, 180 handleDeleteOrBatchDelete,
169 hasBatchDelete, 181 hasBatchDelete,
170 statusChange, 182 statusChange,
  183 + hasPermission,
171 }; 184 };
172 }, 185 },
173 }); 186 });
@@ -22,13 +22,21 @@ @@ -22,13 +22,21 @@
22 </a-button> 22 </a-button>
23 </template> 23 </template>
24 <template #status="{ record }"> 24 <template #status="{ record }">
25 - <Switch  
26 - :checked="record.status === 1"  
27 - :loading="record.pendingStatus"  
28 - checkedChildren="启用"  
29 - unCheckedChildren="禁用"  
30 - @change="(checked:boolean)=>statusChange(checked,record)"  
31 - /> 25 + <Authority value="api:yt:template:status">
  26 + <Switch
  27 + :checked="record.status === 1"
  28 + :loading="record.pendingStatus"
  29 + checkedChildren="启用"
  30 + unCheckedChildren="禁用"
  31 + @change="(checked:boolean)=>statusChange(checked,record)"
  32 + />
  33 + </Authority>
  34 + <Tag
  35 + v-if="!hasPermission('api:yt:template:status')"
  36 + :color="record.status ? 'green' : 'red'"
  37 + >
  38 + {{ record.status ? '启用' : '禁用' }}
  39 + </Tag>
32 </template> 40 </template>
33 <template #action="{ record }"> 41 <template #action="{ record }">
34 <TableAction 42 <TableAction
@@ -80,9 +88,10 @@ @@ -80,9 +88,10 @@
80 import SendEmail from '/@/views/message/template/SendEmail.vue'; 88 import SendEmail from '/@/views/message/template/SendEmail.vue';
81 import { useMessage } from '/@/hooks/web/useMessage'; 89 import { useMessage } from '/@/hooks/web/useMessage';
82 import { useBatchDelete } from '/@/hooks/web/useBatchDelete'; 90 import { useBatchDelete } from '/@/hooks/web/useBatchDelete';
83 - import { Switch, Popconfirm } from 'ant-design-vue'; 91 + import { Switch, Popconfirm, Tag } from 'ant-design-vue';
84 import { setMessageTemplateStatus } from '/@/api/message/template'; 92 import { setMessageTemplateStatus } from '/@/api/message/template';
85 import { Authority } from '/@/components/Authority'; 93 import { Authority } from '/@/components/Authority';
  94 + import { usePermission } from '/@/hooks/web/usePermission';
86 95
87 export default defineComponent({ 96 export default defineComponent({
88 name: 'MessageTemplateManagement', 97 name: 'MessageTemplateManagement',
@@ -95,8 +104,10 @@ @@ -95,8 +104,10 @@
95 Switch, 104 Switch,
96 Authority, 105 Authority,
97 Popconfirm, 106 Popconfirm,
  107 + Tag,
98 }, 108 },
99 setup() { 109 setup() {
  110 + const { hasPermission } = usePermission();
100 const [registerModal, { openModal: openModal }] = useModal(); 111 const [registerModal, { openModal: openModal }] = useModal();
101 const [registerMailModal, { openModal: openMailModal }] = useModal(); 112 const [registerMailModal, { openModal: openMailModal }] = useModal();
102 const go = useGo(); 113 const go = useGo();
@@ -218,6 +229,7 @@ @@ -218,6 +229,7 @@
218 handleDeleteOrBatchDelete, 229 handleDeleteOrBatchDelete,
219 statusChange, 230 statusChange,
220 hasBatchDelete, 231 hasBatchDelete,
  232 + hasPermission,
221 }; 233 };
222 }, 234 },
223 }); 235 });
@@ -135,10 +135,14 @@ @@ -135,10 +135,14 @@
135 <Tabs.TabPane tab="详情" key="detail"> 135 <Tabs.TabPane tab="详情" key="detail">
136 <Space> 136 <Space>
137 <!-- <Button type="primary" @click="openDetailPage">打开详情页</Button> --> 137 <!-- <Button type="primary" @click="openDetailPage">打开详情页</Button> -->
138 - <Button type="primary" @click="downloadPackage" :disabled="!!otaRecord.url">  
139 - 下载包  
140 - </Button>  
141 - <Button type="primary" @click="deletePackage" danger>删除包</Button> 138 + <Authority :value="OtaPermissionKey.DOWNLOAD">
  139 + <Button type="primary" @click="downloadPackage" :disabled="!!otaRecord.url">
  140 + 下载包
  141 + </Button>
  142 + </Authority>
  143 + <Authority :value="OtaPermissionKey.DELETE">
  144 + <Button type="primary" @click="deletePackage" danger>删除包</Button>
  145 + </Authority>
142 </Space> 146 </Space>
143 <div class="mt-3"> 147 <div class="mt-3">
144 <Space> 148 <Space>
@@ -9,6 +9,7 @@ export enum PermissionReportConfigEnum { @@ -9,6 +9,7 @@ export enum PermissionReportConfigEnum {
9 PERMISSION_GET = 'api:yt:report:get', 9 PERMISSION_GET = 'api:yt:report:get',
10 PERMISSION_DELETE = 'api:yt:report_form:config:delete', 10 PERMISSION_DELETE = 'api:yt:report_form:config:delete',
11 PERMISSION_UPDATE = 'api:yt:report_form:config:update', 11 PERMISSION_UPDATE = 'api:yt:report_form:config:update',
  12 + PERMISSION_STATUS = 'api:yt:report_form:config:status',
12 } 13 }
13 14
14 //业务文字描述配置枚举 15 //业务文字描述配置枚举
@@ -74,14 +74,22 @@ @@ -74,14 +74,22 @@
74 /> 74 />
75 </template> 75 </template>
76 <template #configStatus="{ record }"> 76 <template #configStatus="{ record }">
77 - <Switch  
78 - :disabled="disabledSwitch"  
79 - :checked="record.status === 1"  
80 - :loading="record.pendingStatus"  
81 - :checkedChildren="BusinessReportConfigTextEnum.BUSINESS_ENABLE_TEXT"  
82 - :unCheckedChildren="BusinessReportConfigTextEnum.BUSINESS_DISABLE_TEXT"  
83 - @change="(checked: boolean) => statusChange(checked, record)"  
84 - /> 77 + <Authority :value="PermissionReportConfigEnum.PERMISSION_STATUS">
  78 + <Switch
  79 + :disabled="disabledSwitch"
  80 + :checked="record.status === 1"
  81 + :loading="record.pendingStatus"
  82 + :checkedChildren="BusinessReportConfigTextEnum.BUSINESS_ENABLE_TEXT"
  83 + :unCheckedChildren="BusinessReportConfigTextEnum.BUSINESS_DISABLE_TEXT"
  84 + @change="(checked: boolean) => statusChange(checked, record)"
  85 + />
  86 + </Authority>
  87 + <Tag
  88 + v-if="!hasPermission(PermissionReportConfigEnum.PERMISSION_STATUS)"
  89 + :color="record.status ? 'green' : 'red'"
  90 + >
  91 + {{ record.status ? '启用' : '禁用' }}
  92 + </Tag>
85 </template> 93 </template>
86 </BasicTable> 94 </BasicTable>
87 <ReportConfigDrawer @register="registerDrawer" @success="handleSuccess" /> 95 <ReportConfigDrawer @register="registerDrawer" @success="handleSuccess" />
@@ -101,7 +109,7 @@ @@ -101,7 +109,7 @@
101 import { defaultTableAttribtes } from './config'; 109 import { defaultTableAttribtes } from './config';
102 import { Authority } from '/@/components/Authority'; 110 import { Authority } from '/@/components/Authority';
103 import { useBatchDelete } from '/@/hooks/web/useBatchDelete'; 111 import { useBatchDelete } from '/@/hooks/web/useBatchDelete';
104 - import { Popconfirm, Switch } from 'ant-design-vue'; 112 + import { Popconfirm, Switch, Tag } from 'ant-design-vue';
105 import { useModal } from '/@/components/Modal'; 113 import { useModal } from '/@/components/Modal';
106 import { useGo } from '/@/hooks/web/usePage'; 114 import { useGo } from '/@/hooks/web/usePage';
107 import { useMessage } from '/@/hooks/web/useMessage'; 115 import { useMessage } from '/@/hooks/web/useMessage';
@@ -111,6 +119,9 @@ @@ -111,6 +119,9 @@
111 BusinessReportConfigTextEnum, 119 BusinessReportConfigTextEnum,
112 BusinessReportConfigStatusEnum, 120 BusinessReportConfigStatusEnum,
113 } from './enum'; 121 } from './enum';
  122 + import { usePermission } from '/@/hooks/web/usePermission';
  123 +
  124 + const { hasPermission } = usePermission();
114 125
115 const disabledSwitch = ref(false); 126 const disabledSwitch = ref(false);
116 127
@@ -8,6 +8,7 @@ export enum PermissionDataFlowEnum { @@ -8,6 +8,7 @@ export enum PermissionDataFlowEnum {
8 PERMISSION_GET = 'api:yt:convert:config:get', 8 PERMISSION_GET = 'api:yt:convert:config:get',
9 PERMISSION_DELETE = 'api:yt:convert:config:delete', 9 PERMISSION_DELETE = 'api:yt:convert:config:delete',
10 PERMISSION_UPDATE = 'api:yt:convert:config:update', 10 PERMISSION_UPDATE = 'api:yt:convert:config:update',
  11 + PERMISSION_STATUS = 'api:yt:convert:config:status',
11 } 12 }
12 13
13 //业务文字描述配置枚举 14 //业务文字描述配置枚举
@@ -79,13 +79,21 @@ @@ -79,13 +79,21 @@
79 /> 79 />
80 </template> 80 </template>
81 <template #status="{ record }"> 81 <template #status="{ record }">
82 - <Switch  
83 - :checked="record.status === 1"  
84 - :loading="record.pendingStatus"  
85 - checkedChildren="启用"  
86 - unCheckedChildren="禁用"  
87 - @change="(checked:boolean)=>hanldeSwitch(checked,record)"  
88 - /> 82 + <Authority :value="PermissionDataFlowEnum.PERMISSION_STATUS">
  83 + <Switch
  84 + :checked="record.status === 1"
  85 + :loading="record.pendingStatus"
  86 + checkedChildren="启用"
  87 + unCheckedChildren="禁用"
  88 + @change="(checked:boolean)=>hanldeSwitch(checked,record)"
  89 + />
  90 + </Authority>
  91 + <Tag
  92 + v-if="!hasPermission(PermissionDataFlowEnum.PERMISSION_STATUS)"
  93 + :color="record.status ? 'green' : 'red'"
  94 + >
  95 + {{ record.status ? '启用' : '禁用' }}
  96 + </Tag>
89 </template> 97 </template>
90 </BasicTable> 98 </BasicTable>
91 <DataFlowModal @register="registerModal" @success="handleSuccess" /> 99 <DataFlowModal @register="registerModal" @success="handleSuccess" />
@@ -103,15 +111,18 @@ @@ -103,15 +111,18 @@
103 import { useMessage } from '/@/hooks/web/useMessage'; 111 import { useMessage } from '/@/hooks/web/useMessage';
104 import { Authority } from '/@/components/Authority'; 112 import { Authority } from '/@/components/Authority';
105 import { useBatchDelete } from '/@/hooks/web/useBatchDelete'; 113 import { useBatchDelete } from '/@/hooks/web/useBatchDelete';
106 - import { Switch, Popconfirm } from 'ant-design-vue'; 114 + import { Switch, Popconfirm, Tag } from 'ant-design-vue';
107 import { PermissionDataFlowEnum, BusinessDataFlowTextEnum } from './enum'; 115 import { PermissionDataFlowEnum, BusinessDataFlowTextEnum } from './enum';
108 import { DataFlowModal } from './components/dataflowmodal'; 116 import { DataFlowModal } from './components/dataflowmodal';
109 import { defaultTableAttribute } from './config'; 117 import { defaultTableAttribute } from './config';
  118 + import { usePermission } from '/@/hooks/web/usePermission';
110 119
111 const { createMessage } = useMessage(); 120 const { createMessage } = useMessage();
112 121
113 const loading = ref(true); 122 const loading = ref(true);
114 123
  124 + const { hasPermission } = usePermission();
  125 +
115 const handleSuccess = () => { 126 const handleSuccess = () => {
116 reload(); 127 reload();
117 }; 128 };
@@ -164,26 +164,26 @@ export const genActionData = (actionData) => { @@ -164,26 +164,26 @@ export const genActionData = (actionData) => {
164 }; 164 };
165 165
166 export const operationNumber_OR_TIME = [ 166 export const operationNumber_OR_TIME = [
167 - { label: '等于', value: Number_Operation.EQUAL },  
168 - { label: '不等于', value: Number_Operation.NOT_EQUAL },  
169 - { label: '小于', value: Number_Operation.LESS },  
170 - { label: '小于等于', value: Number_Operation.LESS_OR_EQUAL },  
171 - { label: '大于', value: Number_Operation.GREATER },  
172 - { label: '大于等于', value: Number_Operation.GREATER_OR_EQUAL }, 167 + { label: '等于', value: Number_Operation.EQUAL, symbol: '=' },
  168 + { label: '不等于', value: Number_Operation.NOT_EQUAL, symbol: '!=' },
  169 + { label: '小于', value: Number_Operation.LESS, symbol: '<' },
  170 + { label: '小于等于', value: Number_Operation.LESS_OR_EQUAL, symbol: '<=' },
  171 + { label: '大于', value: Number_Operation.GREATER, symbol: '>' },
  172 + { label: '大于等于', value: Number_Operation.GREATER_OR_EQUAL, symbol: '>=' },
173 ]; 173 ];
174 174
175 export const operationString = [ 175 export const operationString = [
176 - { label: '等于', value: String_Operation.EQUAL },  
177 - { label: '不等于', value: String_Operation.NOT_EQUAL },  
178 - { label: '开始于', value: String_Operation.BEGAN_IN },  
179 - { label: '结束于', value: String_Operation.END_IN },  
180 - { label: '包含', value: String_Operation.INCLUDE },  
181 - { label: '不包含', value: String_Operation.NOT_INCLUDE }, 176 + { label: '等于', value: String_Operation.EQUAL, symbol: '=' },
  177 + { label: '不等于', value: String_Operation.NOT_EQUAL, symbol: '!=' },
  178 + { label: '开始于', value: String_Operation.BEGAN_IN, symbol: '开始于' },
  179 + { label: '结束于', value: String_Operation.END_IN, symbol: '结束于' },
  180 + { label: '包含', value: String_Operation.INCLUDE, symbol: '包含' },
  181 + { label: '不包含', value: String_Operation.NOT_INCLUDE, symbol: '不包含' },
182 ]; 182 ];
183 183
184 export const operationBoolean = [ 184 export const operationBoolean = [
185 - { label: '等于', value: Boolean_Operation.EQUAL },  
186 - { label: '不等于', value: Boolean_Operation.NOT_EQUAL }, 185 + { label: '等于', value: Boolean_Operation.EQUAL, symbol: '=' },
  186 + { label: '不等于', value: Boolean_Operation.NOT_EQUAL, symbol: '!=' },
187 ]; 187 ];
188 188
189 export const scheduleOptions = [ 189 export const scheduleOptions = [
@@ -50,13 +50,21 @@ @@ -50,13 +50,21 @@
50 </template> 50 </template>
51 51
52 <template #status="{ record }"> 52 <template #status="{ record }">
53 - <Switch  
54 - :checked="record.status === 1"  
55 - :loading="record.pendingStatus"  
56 - checkedChildren="启用"  
57 - unCheckedChildren="禁用"  
58 - @change="(checked:boolean)=>statusChange(checked,record)"  
59 - /> 53 + <Authority value="api:yt:sceneLinkage:status">
  54 + <Switch
  55 + :checked="record.status === 1"
  56 + :loading="record.pendingStatus"
  57 + checkedChildren="启用"
  58 + unCheckedChildren="禁用"
  59 + @change="(checked:boolean)=>statusChange(checked,record)"
  60 + />
  61 + </Authority>
  62 + <Tag
  63 + v-if="!hasPermission('api:yt:sceneLinkage:status')"
  64 + :color="record.status ? 'green' : 'red'"
  65 + >
  66 + {{ record.status ? '启用' : '禁用' }}
  67 + </Tag>
60 </template> 68 </template>
61 </BasicTable> 69 </BasicTable>
62 <SceneLinkAgeDrawer @register="registerDrawer" @success="handleSuccess" /> 70 <SceneLinkAgeDrawer @register="registerDrawer" @success="handleSuccess" />
@@ -72,16 +80,18 @@ @@ -72,16 +80,18 @@
72 screenLinkPagePutApi, 80 screenLinkPagePutApi,
73 } from '/@/api/ruleengine/ruleengineApi'; 81 } from '/@/api/ruleengine/ruleengineApi';
74 import { useBatchDelete } from '/@/hooks/web/useBatchDelete'; 82 import { useBatchDelete } from '/@/hooks/web/useBatchDelete';
75 - import { Switch, Popconfirm } from 'ant-design-vue'; 83 + import { Switch, Popconfirm, Tag } from 'ant-design-vue';
76 import { columns, searchFormSchema } from './config/config.data'; 84 import { columns, searchFormSchema } from './config/config.data';
77 import { USER_INFO_KEY } from '/@/enums/cacheEnum'; 85 import { USER_INFO_KEY } from '/@/enums/cacheEnum';
78 import { getAuthCache } from '/@/utils/auth'; 86 import { getAuthCache } from '/@/utils/auth';
79 import SceneLinkAgeDrawer from './SceneLinkAgeDrawer.vue'; 87 import SceneLinkAgeDrawer from './SceneLinkAgeDrawer.vue';
80 import { useMessage } from '/@/hooks/web/useMessage'; 88 import { useMessage } from '/@/hooks/web/useMessage';
81 import { Authority } from '/@/components/Authority'; 89 import { Authority } from '/@/components/Authority';
  90 + import { usePermission } from '/@/hooks/web/usePermission';
82 91
83 const userInfo: any = getAuthCache(USER_INFO_KEY); 92 const userInfo: any = getAuthCache(USER_INFO_KEY);
84 const userId = userInfo.userId; 93 const userId = userInfo.userId;
  94 + const { hasPermission } = usePermission();
85 95
86 const [registerDrawer, { openDrawer }] = useDrawer(); 96 const [registerDrawer, { openDrawer }] = useDrawer();
87 const [registerTable, { reload, setProps, setSelectedRowKeys }] = useTable({ 97 const [registerTable, { reload, setProps, setSelectedRowKeys }] = useTable({
@@ -17,13 +17,21 @@ @@ -17,13 +17,21 @@
17 </Authority> 17 </Authority>
18 </template> 18 </template>
19 <template #status="{ record }"> 19 <template #status="{ record }">
20 - <Switch  
21 - :checked="record.status === 1"  
22 - :loading="record.pendingStatus"  
23 - checkedChildren="启用"  
24 - unCheckedChildren="禁用"  
25 - @change="(checked:boolean)=>statusChange(checked,record)"  
26 - /> 20 + <Authority value="api:yt:convert:js:status">
  21 + <Switch
  22 + :checked="record.status === 1"
  23 + :loading="record.pendingStatus"
  24 + checkedChildren="启用"
  25 + unCheckedChildren="禁用"
  26 + @change="(checked:boolean)=>statusChange(checked,record)"
  27 + />
  28 + </Authority>
  29 + <Tag
  30 + v-if="!hasPermission('api:yt:convert:js:status')"
  31 + :color="record.status ? 'green' : 'red'"
  32 + >
  33 + {{ record.status ? '启用' : '禁用' }}
  34 + </Tag>
27 </template> 35 </template>
28 <template #action="{ record }"> 36 <template #action="{ record }">
29 <TableAction 37 <TableAction
@@ -69,7 +77,7 @@ @@ -69,7 +77,7 @@
69 77
70 <script lang="ts" setup> 78 <script lang="ts" setup>
71 import { ref, nextTick } from 'vue'; 79 import { ref, nextTick } from 'vue';
72 - import { Switch, Popconfirm } from 'ant-design-vue'; 80 + import { Switch, Popconfirm, Tag } from 'ant-design-vue';
73 import { BasicTable, useTable, TableAction } from '/@/components/Table'; 81 import { BasicTable, useTable, TableAction } from '/@/components/Table';
74 import { columns } from '../config/config.data'; 82 import { columns } from '../config/config.data';
75 import { getConvertApi, deleteTransformApi } from '/@/api/device/TransformScriptApi'; 83 import { getConvertApi, deleteTransformApi } from '/@/api/device/TransformScriptApi';
@@ -81,11 +89,14 @@ @@ -81,11 +89,14 @@
81 import { useBatchDelete } from '/@/hooks/web/useBatchDelete'; 89 import { useBatchDelete } from '/@/hooks/web/useBatchDelete';
82 import { Authority } from '/@/components/Authority'; 90 import { Authority } from '/@/components/Authority';
83 import { computed, unref } from 'vue'; 91 import { computed, unref } from 'vue';
  92 + import { usePermission } from '/@/hooks/web/usePermission';
84 93
85 const props = defineProps<{ searchInfo: Recordable }>(); 94 const props = defineProps<{ searchInfo: Recordable }>();
86 95
87 const getSearchInfo = computed(() => props.searchInfo); 96 const getSearchInfo = computed(() => props.searchInfo);
88 97
  98 + const { hasPermission } = usePermission();
  99 +
89 const handleSuccess = () => { 100 const handleSuccess = () => {
90 reload(); 101 reload();
91 }; 102 };
@@ -24,8 +24,9 @@ @@ -24,8 +24,9 @@
24 :customRequest="customUploadIconPic" 24 :customRequest="customUploadIconPic"
25 :before-upload="beforeUploadIconPic" 25 :before-upload="beforeUploadIconPic"
26 > 26 >
27 - <div v-if="iconPic"> 27 + <div v-if="iconPic" class="relative">
28 <img :src="iconPic" class="m-auto fill-img" /> 28 <img :src="iconPic" class="m-auto fill-img" />
  29 + <CloseCircleOutlined class="absolute icon-delete" @click.stop="handleDelete" />
29 <div style="background-color: #ccc; margin-top: 20px">重新上传</div> 30 <div style="background-color: #ccc; margin-top: 20px">重新上传</div>
30 </div> 31 </div>
31 <div v-else> 32 <div v-else>
@@ -81,7 +82,7 @@ @@ -81,7 +82,7 @@
81 import { useMessage } from '/@/hooks/web/useMessage'; 82 import { useMessage } from '/@/hooks/web/useMessage';
82 import type { FileItem } from '/@/components/Upload/src/typing'; 83 import type { FileItem } from '/@/components/Upload/src/typing';
83 import { iconUpload, getPlatForm, updatePlatForm, resetPlateInfo } from '/@/api/oem/index'; 84 import { iconUpload, getPlatForm, updatePlatForm, resetPlateInfo } from '/@/api/oem/index';
84 - import { PlusOutlined } from '@ant-design/icons-vue'; 85 + import { PlusOutlined, CloseCircleOutlined } from '@ant-design/icons-vue';
85 import { useUserStore } from '/@/store/modules/user'; 86 import { useUserStore } from '/@/store/modules/user';
86 import { createLocalStorage } from '/@/utils/cache/index'; 87 import { createLocalStorage } from '/@/utils/cache/index';
87 import { Authority } from '/@/components/Authority'; 88 import { Authority } from '/@/components/Authority';
@@ -100,6 +101,7 @@ @@ -100,6 +101,7 @@
100 ContentUploadText, 101 ContentUploadText,
101 Spin, 102 Spin,
102 CustomUploadComp, 103 CustomUploadComp,
  104 + CloseCircleOutlined,
103 }, 105 },
104 setup() { 106 setup() {
105 const loading = ref(false); 107 const loading = ref(false);
@@ -188,6 +190,11 @@ @@ -188,6 +190,11 @@
188 storage.set('platformInfo', newFieldValue); 190 storage.set('platformInfo', newFieldValue);
189 } 191 }
190 192
  193 + // 删除浏览器ico图标
  194 + const handleDelete = () => {
  195 + iconPic.value = '';
  196 + };
  197 +
191 onMounted(async () => { 198 onMounted(async () => {
192 const res = await getPlatForm(); 199 const res = await getPlatForm();
193 setFieldsValue(res); 200 setFieldsValue(res);
@@ -227,6 +234,7 @@ @@ -227,6 +234,7 @@
227 handleResetInfo, 234 handleResetInfo,
228 handleSetBgImgUrl, 235 handleSetBgImgUrl,
229 handleSetLogoImgUrl, 236 handleSetLogoImgUrl,
  237 + handleDelete,
230 }; 238 };
231 }, 239 },
232 }); 240 });
@@ -251,4 +259,12 @@ @@ -251,4 +259,12 @@
251 width: 100%; 259 width: 100%;
252 height: 100%; 260 height: 100%;
253 } 261 }
  262 +
  263 + .icon-delete {
  264 + top: -13px;
  265 + right: -13px;
  266 + color: rgb(146, 145, 145);
  267 + font-size: 1rem;
  268 + z-index: 9999;
  269 + }
254 </style> 270 </style>
1 <script setup name="CustomUploadComp" lang="ts"> 1 <script setup name="CustomUploadComp" lang="ts">
2 - import { PlusOutlined } from '@ant-design/icons-vue'; 2 + import { PlusOutlined, CloseCircleOutlined } from '@ant-design/icons-vue';
3 import { Upload, Spin } from 'ant-design-vue'; 3 import { Upload, Spin } from 'ant-design-vue';
4 import { ref, watchEffect } from 'vue'; 4 import { ref, watchEffect } from 'vue';
5 import { useUpload } from './hooks/useUploadFile.hook'; 5 import { useUpload } from './hooks/useUploadFile.hook';
@@ -40,6 +40,12 @@ @@ -40,6 +40,12 @@
40 } 40 }
41 }; 41 };
42 42
  43 + // 删除图片
  44 + const handleDelete = () => {
  45 + uploadImgUrl.value = '';
  46 + emit('setImg', uploadImgUrl.value);
  47 + };
  48 +
43 watchEffect(() => { 49 watchEffect(() => {
44 init(); 50 init();
45 }); 51 });
@@ -59,7 +65,10 @@ @@ -59,7 +65,10 @@
59 :customRequest="customUpload" 65 :customRequest="customUpload"
60 :before-upload="beforeUploadVerify" 66 :before-upload="beforeUploadVerify"
61 > 67 >
62 - <img v-if="uploadImgUrl" class="fill-img" :src="uploadImgUrl" alt="avatar" /> 68 + <div v-if="uploadImgUrl" class="w-full h-full modal-div relative">
  69 + <img class="fill-img" :src="uploadImgUrl" alt="avatar" />
  70 + <CloseCircleOutlined class="absolute icon-delete" @click.stop="handleDelete" />
  71 + </div>
63 <div v-else> 72 <div v-else>
64 <Spin v-if="uploadLoading" tip="正在上传中..." /> 73 <Spin v-if="uploadLoading" tip="正在上传中..." />
65 <PlusOutlined v-else /> 74 <PlusOutlined v-else />
@@ -74,4 +83,12 @@ @@ -74,4 +83,12 @@
74 width: 100%; 83 width: 100%;
75 height: 100%; 84 height: 100%;
76 } 85 }
  86 +
  87 + .icon-delete {
  88 + top: -13px;
  89 + right: -13px;
  90 + color: rgb(146, 145, 145);
  91 + font-size: 1rem;
  92 + z-index: 9999;
  93 + }
77 </style> 94 </style>
@@ -21,13 +21,18 @@ @@ -21,13 +21,18 @@
21 </Authority> 21 </Authority>
22 </template> 22 </template>
23 <template #status="{ record }"> 23 <template #status="{ record }">
24 - <Switch  
25 - :checked="record.status === 1"  
26 - :loading="record.pendingStatus"  
27 - checkedChildren="启用"  
28 - unCheckedChildren="禁用"  
29 - @change="(checked:boolean)=>statusChange(checked,record)"  
30 - /> 24 + <Authority value="api:yt:role:status">
  25 + <Switch
  26 + :checked="record.status === 1"
  27 + :loading="record.pendingStatus"
  28 + checkedChildren="启用"
  29 + unCheckedChildren="禁用"
  30 + @change="(checked:boolean)=>statusChange(checked,record)"
  31 + />
  32 + </Authority>
  33 + <Tag v-if="!hasPermission('api:yt:role:status')" :color="record.status ? 'green' : 'red'">
  34 + {{ record.status ? '启用' : '禁用' }}
  35 + </Tag>
31 </template> 36 </template>
32 <template #action="{ record }"> 37 <template #action="{ record }">
33 <TableAction 38 <TableAction
@@ -67,12 +72,14 @@ @@ -67,12 +72,14 @@
67 import { Authority } from '/@/components/Authority'; 72 import { Authority } from '/@/components/Authority';
68 import { useBatchDelete } from '/@/hooks/web/useBatchDelete'; 73 import { useBatchDelete } from '/@/hooks/web/useBatchDelete';
69 import { useMessage } from '/@/hooks/web/useMessage'; 74 import { useMessage } from '/@/hooks/web/useMessage';
70 - import { Switch, Popconfirm } from 'ant-design-vue'; 75 + import { Switch, Popconfirm, Tag } from 'ant-design-vue';
  76 + import { usePermission } from '/@/hooks/web/usePermission';
71 77
72 export default defineComponent({ 78 export default defineComponent({
73 name: 'RoleManagement', 79 name: 'RoleManagement',
74 - components: { BasicTable, RoleDrawer, TableAction, Authority, Switch, Popconfirm }, 80 + components: { BasicTable, RoleDrawer, TableAction, Authority, Switch, Popconfirm, Tag },
75 setup() { 81 setup() {
  82 + const { hasPermission } = usePermission();
76 const [registerDrawer, { openDrawer }] = useDrawer(); 83 const [registerDrawer, { openDrawer }] = useDrawer();
77 function handleSuccess() { 84 function handleSuccess() {
78 reload(); 85 reload();
@@ -157,6 +164,7 @@ @@ -157,6 +164,7 @@
157 hasBatchDelete, 164 hasBatchDelete,
158 handleDeleteOrBatchDelete, 165 handleDeleteOrBatchDelete,
159 statusChange, 166 statusChange,
  167 + hasPermission,
160 }; 168 };
161 }, 169 },
162 }); 170 });
@@ -7,7 +7,7 @@ export const validateDevicePicker = () => { @@ -7,7 +7,7 @@ export const validateDevicePicker = () => {
7 validateTrigger: 'blur', 7 validateTrigger: 'blur',
8 validator(_rule: Recordable, value: Recordable, _callback: Fn) { 8 validator(_rule: Recordable, value: Recordable, _callback: Fn) {
9 const device = Reflect.get(value || {}, FormFieldsEnum.DEVICE); 9 const device = Reflect.get(value || {}, FormFieldsEnum.DEVICE);
10 - if (!device) return Promise.reject('请选择设备'); 10 + if (!device || !device.length) return Promise.reject('请选择设备');
11 return Promise.resolve(); 11 return Promise.resolve();
12 }, 12 },
13 } as Rule; 13 } as Rule;
@@ -133,6 +133,7 @@ @@ -133,6 +133,7 @@
133 text: '详情', 133 text: '详情',
134 event: DropMenuEvent.DETAIL, 134 event: DropMenuEvent.DETAIL,
135 icon: 'ant-design:eye-outlined', 135 icon: 'ant-design:eye-outlined',
  136 + auth: PermissionEnum.DETAIL,
136 onClick: emit.bind(null, 'detail', getRecord), 137 onClick: emit.bind(null, 'detail', getRecord),
137 }, 138 },
138 { 139 {
@@ -7,6 +7,7 @@ export enum PermissionEnum { @@ -7,6 +7,7 @@ export enum PermissionEnum {
7 DELETE = 'api:yt:task_center:delete', 7 DELETE = 'api:yt:task_center:delete',
8 ALLOW = 'api:yt:task_center:cancel:allow', 8 ALLOW = 'api:yt:task_center:cancel:allow',
9 EXECUTE = 'api:yt:task_center:immediate:execute', 9 EXECUTE = 'api:yt:task_center:immediate:execute',
  10 + DETAIL = 'api:yt:task_center:get',
10 } 11 }
11 12
12 export enum FormFieldsEnum { 13 export enum FormFieldsEnum {
@@ -54,7 +54,7 @@ @@ -54,7 +54,7 @@
54 }, 54 },
55 labelWidth: 120, 55 labelWidth: 120,
56 fieldMapToTime: [ 56 fieldMapToTime: [
57 - [SchemaFiled.DATE_RANGE, [SchemaFiled.START_TS, SchemaFiled.END_TS], 'YYYY-MM-DD HH:ss'], 57 + [SchemaFiled.DATE_RANGE, [SchemaFiled.START_TS, SchemaFiled.END_TS], 'YYYY-MM-DD HH:mm:ss'],
58 ], 58 ],
59 submitButtonOptions: { 59 submitButtonOptions: {
60 loading: loading as unknown as boolean, 60 loading: loading as unknown as boolean,
@@ -260,7 +260,7 @@ @@ -260,7 +260,7 @@
260 :show-ok-btn="false" 260 :show-ok-btn="false"
261 cancel-text="关闭" 261 cancel-text="关闭"
262 width="70%" 262 width="70%"
263 - title="历史趋势" 263 + title="选择时间"
264 > 264 >
265 <section 265 <section
266 class="flex flex-col p-4 h-full w-full min-w-7/10" 266 class="flex flex-col p-4 h-full w-full min-w-7/10"