Commit 0b3b21b771f8f320e6c820183d6a7793a00446eb
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 { |
src/hooks/business/useMenuActiveFix.ts
0 → 100644
| 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"> |
| @@ -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" |