Commit 1b471b784586e802a1a8f662567e6544699f0cdf
Merge branch 'main_dev' of http://git.yunteng.com/yunteng/thingskit-front into f…
…ix/board-style-issues
Showing
39 changed files
with
263 additions
and
106 deletions
| @@ -8,6 +8,7 @@ export interface BigScreenCenterItemsModel { | @@ -8,6 +8,7 @@ export interface BigScreenCenterItemsModel { | ||
| 8 | remark: string; | 8 | remark: string; |
| 9 | state: number; | 9 | state: number; |
| 10 | publicId: string; | 10 | publicId: string; |
| 11 | + organizationId?: string; | ||
| 11 | } | 12 | } |
| 12 | export type queryPageParams = BasicPageParams & { | 13 | export type queryPageParams = BasicPageParams & { |
| 13 | name?: Nullable<string>; | 14 | name?: Nullable<string>; |
| @@ -7,6 +7,7 @@ export interface ConfigurationCenterItemsModal { | @@ -7,6 +7,7 @@ export interface ConfigurationCenterItemsModal { | ||
| 7 | creator: string; | 7 | creator: string; |
| 8 | remark: string; | 8 | remark: string; |
| 9 | publicId?: string; | 9 | publicId?: string; |
| 10 | + organizationId?: string; | ||
| 10 | } | 11 | } |
| 11 | export type queryPageParams = BasicPageParams & { | 12 | export type queryPageParams = BasicPageParams & { |
| 12 | name?: Nullable<string>; | 13 | name?: Nullable<string>; |
| @@ -85,7 +85,7 @@ interface TrendParamsType { | @@ -85,7 +85,7 @@ interface TrendParamsType { | ||
| 85 | } | 85 | } |
| 86 | // 获取租户趋势或者客户趋势数据 | 86 | // 获取租户趋势或者客户趋势数据 |
| 87 | export const getTrendData = (params: TrendParamsType) => { | 87 | export const getTrendData = (params: TrendParamsType) => { |
| 88 | - return defHttp.get({ | 88 | + return defHttp.get<Record<'date' | 'value', string>[]>({ |
| 89 | url: HomeEnum.TrendAPI, | 89 | url: HomeEnum.TrendAPI, |
| 90 | params, | 90 | params, |
| 91 | }); | 91 | }); |
| @@ -30,6 +30,8 @@ enum DeviceManagerApi { | @@ -30,6 +30,8 @@ enum DeviceManagerApi { | ||
| 30 | 30 | ||
| 31 | ALARM_BATCH_ACK = '/alarm/batch/ack', | 31 | ALARM_BATCH_ACK = '/alarm/batch/ack', |
| 32 | 32 | ||
| 33 | + ALARM_BATCH_CLEAR = '/alarm/batch/clear', | ||
| 34 | + | ||
| 33 | DEVICE_CREDENTIALS = '/device/credentials', | 35 | DEVICE_CREDENTIALS = '/device/credentials', |
| 34 | 36 | ||
| 35 | COMMAND_ISSUANCE = '/rpc', | 37 | COMMAND_ISSUANCE = '/rpc', |
| @@ -358,3 +360,13 @@ export const doBatchAckAlarm = (ids: string[]) => { | @@ -358,3 +360,13 @@ export const doBatchAckAlarm = (ids: string[]) => { | ||
| 358 | { joinPrefix: false } | 360 | { joinPrefix: false } |
| 359 | ); | 361 | ); |
| 360 | }; | 362 | }; |
| 363 | + | ||
| 364 | +export const doBatchClearAlarm = (ids: string[]) => { | ||
| 365 | + return defHttp.post( | ||
| 366 | + { | ||
| 367 | + url: DeviceManagerApi.ALARM_BATCH_CLEAR, | ||
| 368 | + data: { alarmIds: ids }, | ||
| 369 | + }, | ||
| 370 | + { joinPrefix: false } | ||
| 371 | + ); | ||
| 372 | +}; |
| @@ -9,7 +9,7 @@ | @@ -9,7 +9,7 @@ | ||
| 9 | import { useMessage } from '/@/hooks/web/useMessage'; | 9 | import { useMessage } from '/@/hooks/web/useMessage'; |
| 10 | import { computed, ref, unref } from 'vue'; | 10 | import { computed, ref, unref } from 'vue'; |
| 11 | import { cloneDeep } from 'lodash-es'; | 11 | import { cloneDeep } from 'lodash-es'; |
| 12 | - import { isFunction, isNumber, isObject } from '/@/utils/is'; | 12 | + import { isFunction, isNumber, isObject, isString } from '/@/utils/is'; |
| 13 | import { useDesign } from '/@/hooks/web/useDesign'; | 13 | import { useDesign } from '/@/hooks/web/useDesign'; |
| 14 | 14 | ||
| 15 | export interface FileItem { | 15 | export interface FileItem { |
| @@ -59,10 +59,19 @@ | @@ -59,10 +59,19 @@ | ||
| 59 | ); | 59 | ); |
| 60 | 60 | ||
| 61 | const handleBeforeUpload = (file: File, fileList: File[]) => { | 61 | const handleBeforeUpload = (file: File, fileList: File[]) => { |
| 62 | - const { beforeUpload } = props; | 62 | + const { beforeUpload, accept } = props; |
| 63 | 63 | ||
| 64 | if (beforeUpload && isFunction(beforeUpload)) return beforeUpload?.(file, fileList); | 64 | if (beforeUpload && isFunction(beforeUpload)) return beforeUpload?.(file, fileList); |
| 65 | 65 | ||
| 66 | + if (accept && isString(accept)) { | ||
| 67 | + const limitFileSuffix = accept.split(','); | ||
| 68 | + | ||
| 69 | + if (limitFileSuffix.length && !limitFileSuffix.some((suffix) => file.name.includes(suffix))) { | ||
| 70 | + createMessage.warning(`允许上传的文件类型包括${accept}`); | ||
| 71 | + return false; | ||
| 72 | + } | ||
| 73 | + } | ||
| 74 | + | ||
| 66 | if (file.size > props.maxSize) { | 75 | if (file.size > props.maxSize) { |
| 67 | createMessage.warning(`文件大小超过${Math.floor(props.maxSize / 1024 / 1024)}mb`); | 76 | createMessage.warning(`文件大小超过${Math.floor(props.maxSize / 1024 / 1024)}mb`); |
| 68 | return false; | 77 | return false; |
| @@ -2,7 +2,7 @@ import { RouteLocationNormalizedLoaded } from 'vue-router'; | @@ -2,7 +2,7 @@ import { RouteLocationNormalizedLoaded } from 'vue-router'; | ||
| 2 | 2 | ||
| 3 | const menuMap = new Map(); | 3 | const menuMap = new Map(); |
| 4 | 4 | ||
| 5 | -menuMap.set('/visual/board/detail/:boardId/:boardName?', '/visual/board'); | 5 | +menuMap.set('/visual/board/detail/:boardId/:boardName/:organizationId?', '/visual/board'); |
| 6 | menuMap.set('/rule/chain/:id', '/rule/chain'); | 6 | menuMap.set('/rule/chain/:id', '/rule/chain'); |
| 7 | 7 | ||
| 8 | export const useMenuActiveFix = (route: RouteLocationNormalizedLoaded) => { | 8 | export const useMenuActiveFix = (route: RouteLocationNormalizedLoaded) => { |
| @@ -37,7 +37,7 @@ | @@ -37,7 +37,7 @@ | ||
| 37 | </a-button> | 37 | </a-button> |
| 38 | </template> | 38 | </template> |
| 39 | <template #status="{ record }"> | 39 | <template #status="{ record }"> |
| 40 | - <Authority value="api:yt:alarm:profile:status"> | 40 | + <Authority value="api:yt:alarm:profile:update"> |
| 41 | <Switch | 41 | <Switch |
| 42 | :checked="record.status === 1" | 42 | :checked="record.status === 1" |
| 43 | :loading="record.pendingStatus" | 43 | :loading="record.pendingStatus" |
| @@ -47,7 +47,7 @@ | @@ -47,7 +47,7 @@ | ||
| 47 | /> | 47 | /> |
| 48 | </Authority> | 48 | </Authority> |
| 49 | <Tag | 49 | <Tag |
| 50 | - v-if="!hasPermission('api:yt:alarm:profile:status')" | 50 | + v-if="!hasPermission('api:yt:alarm:profile:update')" |
| 51 | :color="record.status ? 'green' : 'red'" | 51 | :color="record.status ? 'green' : 'red'" |
| 52 | > | 52 | > |
| 53 | {{ record.status ? '启用' : '禁用' }} | 53 | {{ record.status ? '启用' : '禁用' }} |
| @@ -19,7 +19,30 @@ | @@ -19,7 +19,30 @@ | ||
| 19 | </a-button> | 19 | </a-button> |
| 20 | </template> | 20 | </template> |
| 21 | <template #toolbar> | 21 | <template #toolbar> |
| 22 | - <Button @click="handleBatchAck" type="primary" :disabled="getCanBatchAck">批量处理</Button> | 22 | + <Tooltip> |
| 23 | + <template #title> | ||
| 24 | + <div>激活未确认: 可以处理,清除</div> | ||
| 25 | + <div>激活已确认: 只可清除,已经处理</div> | ||
| 26 | + <div>清除未确认: 只可处理,已经清除</div> | ||
| 27 | + <div>清除已确认: 不需要做处理和清除</div> | ||
| 28 | + </template> | ||
| 29 | + <Button @click="handleBatchClear" type="primary" :disabled="getCanBatchClear"> | ||
| 30 | + <QuestionCircleOutlined class="cursor-pointer" /> | ||
| 31 | + <span>批量清除</span> | ||
| 32 | + </Button> | ||
| 33 | + </Tooltip> | ||
| 34 | + <Tooltip> | ||
| 35 | + <template #title> | ||
| 36 | + <div>激活未确认: 可以处理,清除</div> | ||
| 37 | + <div>激活已确认: 只可清除,已经处理</div> | ||
| 38 | + <div>清除未确认: 只可处理,已经清除</div> | ||
| 39 | + <div>清除已确认: 不需要做处理和清除</div> | ||
| 40 | + </template> | ||
| 41 | + <Button @click="handleBatchAck" type="primary" :disabled="getCanBatchAck"> | ||
| 42 | + <QuestionCircleOutlined class="cursor-pointer" /> | ||
| 43 | + <span>批量处理</span> | ||
| 44 | + </Button> | ||
| 45 | + </Tooltip> | ||
| 23 | </template> | 46 | </template> |
| 24 | </BasicTable> | 47 | </BasicTable> |
| 25 | <AlarmDetailDrawer @register="registerDetailDrawer" @success="handleSuccess" /> | 48 | <AlarmDetailDrawer @register="registerDetailDrawer" @success="handleSuccess" /> |
| @@ -29,10 +52,10 @@ | @@ -29,10 +52,10 @@ | ||
| 29 | import { defineComponent, nextTick, h, computed } from 'vue'; | 52 | import { defineComponent, nextTick, h, computed } from 'vue'; |
| 30 | import { BasicTable, useTable, TableAction } from '/@/components/Table'; | 53 | import { BasicTable, useTable, TableAction } from '/@/components/Table'; |
| 31 | import { alarmColumns, alarmSearchSchemas } from './config/detail.config'; | 54 | import { alarmColumns, alarmSearchSchemas } from './config/detail.config'; |
| 32 | - import { doBatchAckAlarm, getDeviceAlarm } from '/@/api/device/deviceManager'; | 55 | + import { doBatchAckAlarm, doBatchClearAlarm, getDeviceAlarm } from '/@/api/device/deviceManager'; |
| 33 | import { useDrawer } from '/@/components/Drawer'; | 56 | import { useDrawer } from '/@/components/Drawer'; |
| 34 | import AlarmDetailDrawer from './cpns/AlarmDetailDrawer.vue'; | 57 | import AlarmDetailDrawer from './cpns/AlarmDetailDrawer.vue'; |
| 35 | - import { Modal, Button } from 'ant-design-vue'; | 58 | + import { Modal, Button, Tooltip } from 'ant-design-vue'; |
| 36 | import { JsonPreview } from '/@/components/CodeEditor'; | 59 | import { JsonPreview } from '/@/components/CodeEditor'; |
| 37 | import { getDeviceDetail } from '/@/api/device/deviceManager'; | 60 | import { getDeviceDetail } from '/@/api/device/deviceManager'; |
| 38 | import { getAttribute } from '/@/api/ruleengine/ruleengineApi'; | 61 | import { getAttribute } from '/@/api/ruleengine/ruleengineApi'; |
| @@ -44,6 +67,7 @@ | @@ -44,6 +67,7 @@ | ||
| 44 | import { AlarmLogItem } from '/@/api/device/model/deviceConfigModel'; | 67 | import { AlarmLogItem } from '/@/api/device/model/deviceConfigModel'; |
| 45 | import { AlarmStatus } from '/@/enums/alarmEnum'; | 68 | import { AlarmStatus } from '/@/enums/alarmEnum'; |
| 46 | import { useMessage } from '/@/hooks/web/useMessage'; | 69 | import { useMessage } from '/@/hooks/web/useMessage'; |
| 70 | + import { QuestionCircleOutlined } from '@ant-design/icons-vue'; | ||
| 47 | 71 | ||
| 48 | export default defineComponent({ | 72 | export default defineComponent({ |
| 49 | name: 'AlarmCenter', | 73 | name: 'AlarmCenter', |
| @@ -52,6 +76,8 @@ | @@ -52,6 +76,8 @@ | ||
| 52 | BasicTable, | 76 | BasicTable, |
| 53 | TableAction, | 77 | TableAction, |
| 54 | AlarmDetailDrawer, | 78 | AlarmDetailDrawer, |
| 79 | + QuestionCircleOutlined, | ||
| 80 | + Tooltip, | ||
| 55 | }, | 81 | }, |
| 56 | 82 | ||
| 57 | setup() { | 83 | setup() { |
| @@ -60,6 +86,7 @@ | @@ -60,6 +86,7 @@ | ||
| 60 | title: '告警记录列表', | 86 | title: '告警记录列表', |
| 61 | api: getDeviceAlarm, | 87 | api: getDeviceAlarm, |
| 62 | columns: alarmColumns, | 88 | columns: alarmColumns, |
| 89 | + rowKey: 'id', | ||
| 63 | useSearchForm: true, | 90 | useSearchForm: true, |
| 64 | formConfig: { | 91 | formConfig: { |
| 65 | labelWidth: 120, | 92 | labelWidth: 120, |
| @@ -168,9 +195,30 @@ | @@ -168,9 +195,30 @@ | ||
| 168 | }; | 195 | }; |
| 169 | }; | 196 | }; |
| 170 | 197 | ||
| 198 | + const getCanBatchClear = computed(() => { | ||
| 199 | + const rowSelection = getRowSelection(); | ||
| 200 | + const getRows: AlarmLogItem[] = getSelectRows(); | ||
| 201 | + | ||
| 202 | + return ( | ||
| 203 | + !rowSelection.selectedRowKeys?.length || | ||
| 204 | + getRows.some( | ||
| 205 | + (item) => | ||
| 206 | + item.status === AlarmStatus.CLEARED_ACK || item.status === AlarmStatus.CLEARED_UN_ACK | ||
| 207 | + ) | ||
| 208 | + ); | ||
| 209 | + }); | ||
| 210 | + | ||
| 171 | const getCanBatchAck = computed(() => { | 211 | const getCanBatchAck = computed(() => { |
| 172 | const rowSelection = getRowSelection(); | 212 | const rowSelection = getRowSelection(); |
| 173 | - return !rowSelection.selectedRowKeys?.length; | 213 | + const getRows: AlarmLogItem[] = getSelectRows(); |
| 214 | + | ||
| 215 | + return ( | ||
| 216 | + !rowSelection.selectedRowKeys?.length || | ||
| 217 | + getRows.some( | ||
| 218 | + (item) => | ||
| 219 | + item.status === AlarmStatus.CLEARED_ACK || item.status === AlarmStatus.ACTIVE_ACK | ||
| 220 | + ) | ||
| 221 | + ); | ||
| 174 | }); | 222 | }); |
| 175 | 223 | ||
| 176 | const { createMessage } = useMessage(); | 224 | const { createMessage } = useMessage(); |
| @@ -183,6 +231,15 @@ | @@ -183,6 +231,15 @@ | ||
| 183 | reload(); | 231 | reload(); |
| 184 | }; | 232 | }; |
| 185 | 233 | ||
| 234 | + const handleBatchClear = async () => { | ||
| 235 | + const ids = getSelectRows<AlarmLogItem>().map((item) => item.id); | ||
| 236 | + if (!ids.length) return; | ||
| 237 | + await doBatchClearAlarm(ids); | ||
| 238 | + createMessage.success('操作成功'); | ||
| 239 | + clearSelectedRowKeys(); | ||
| 240 | + reload(); | ||
| 241 | + }; | ||
| 242 | + | ||
| 186 | return { | 243 | return { |
| 187 | registerTable, | 244 | registerTable, |
| 188 | registerDetailDrawer, | 245 | registerDetailDrawer, |
| @@ -190,7 +247,9 @@ | @@ -190,7 +247,9 @@ | ||
| 190 | handleSuccess, | 247 | handleSuccess, |
| 191 | handleViewAlarmDetails, | 248 | handleViewAlarmDetails, |
| 192 | handleBatchAck, | 249 | handleBatchAck, |
| 250 | + handleBatchClear, | ||
| 193 | getCanBatchAck, | 251 | getCanBatchAck, |
| 252 | + getCanBatchClear, | ||
| 194 | }; | 253 | }; |
| 195 | }, | 254 | }, |
| 196 | }); | 255 | }); |
| @@ -56,7 +56,10 @@ | @@ -56,7 +56,10 @@ | ||
| 56 | return unref(orgList); | 56 | return unref(orgList); |
| 57 | } | 57 | } |
| 58 | }, | 58 | }, |
| 59 | - params: { ...params, _t: unref(timespan) }, | 59 | + params: { |
| 60 | + ...params, | ||
| 61 | + _t: unref(timespan), | ||
| 62 | + }, | ||
| 60 | onChange: (...args: any[]) => { | 63 | onChange: (...args: any[]) => { |
| 61 | emit('change', ...args); | 64 | emit('change', ...args); |
| 62 | }, | 65 | }, |
| @@ -136,13 +136,19 @@ | @@ -136,13 +136,19 @@ | ||
| 136 | const handlePreview = (record: ConfigurationCenterItemsModal) => { | 136 | const handlePreview = (record: ConfigurationCenterItemsModal) => { |
| 137 | if (!unref(getPreviewFlag)) return; | 137 | if (!unref(getPreviewFlag)) return; |
| 138 | window.open( | 138 | window.open( |
| 139 | - `${configurationPrefix}/${isDev ? '?dev=1&' : '?'}configurationId=${record!.id}&lightbox=1` | 139 | + `${configurationPrefix}/${isDev ? '?dev=1&' : '?'}configurationId=${ |
| 140 | + record!.id | ||
| 141 | + }&lightbox=1&organizationId=${record.organizationId}` | ||
| 140 | ); | 142 | ); |
| 141 | }; | 143 | }; |
| 142 | 144 | ||
| 143 | const handleDesign = (record: ConfigurationCenterItemsModal) => { | 145 | const handleDesign = (record: ConfigurationCenterItemsModal) => { |
| 144 | if (!unref(getDesignFlag)) return; | 146 | if (!unref(getDesignFlag)) return; |
| 145 | - window.open(`${configurationPrefix}/${isDev ? '?dev=1&' : '?'}configurationId=${record!.id}`); | 147 | + window.open( |
| 148 | + `${configurationPrefix}/${isDev ? '?dev=1&' : '?'}configurationId=${ | ||
| 149 | + record!.id | ||
| 150 | + }&organizationId=${record.organizationId}` | ||
| 151 | + ); | ||
| 146 | }; | 152 | }; |
| 147 | 153 | ||
| 148 | const handleDelete = async (record: ConfigurationCenterItemsModal) => { | 154 | const handleDelete = async (record: ConfigurationCenterItemsModal) => { |
| @@ -165,6 +171,7 @@ | @@ -165,6 +171,7 @@ | ||
| 165 | searchParams.set('configurationId', record.id); | 171 | searchParams.set('configurationId', record.id); |
| 166 | searchParams.set('publicId', record.publicId || ''); | 172 | searchParams.set('publicId', record.publicId || ''); |
| 167 | searchParams.set('lightbox', '1'); | 173 | searchParams.set('lightbox', '1'); |
| 174 | + searchParams.set('organizationId', record!.organizationId || ''); | ||
| 168 | return `${origin}${configurationPrefix}/?${searchParams.toString()}`; | 175 | return `${origin}${configurationPrefix}/?${searchParams.toString()}`; |
| 169 | }; | 176 | }; |
| 170 | 177 |
| @@ -132,6 +132,9 @@ | @@ -132,6 +132,9 @@ | ||
| 132 | @calendarChange="handleCalendarChange" | 132 | @calendarChange="handleCalendarChange" |
| 133 | size="small" | 133 | size="small" |
| 134 | v-model:value="customerDateValue" | 134 | v-model:value="customerDateValue" |
| 135 | + :showTime="{ | ||
| 136 | + defaultValue: [dateUtil('00:00:00', 'HH:mm:ss'), dateUtil('23:59:59', 'HH:mm:ss')], | ||
| 137 | + }" | ||
| 135 | > | 138 | > |
| 136 | <Button | 139 | <Button |
| 137 | type="link" | 140 | type="link" |
| @@ -165,7 +168,7 @@ | @@ -165,7 +168,7 @@ | ||
| 165 | import { useWebSocket } from '@vueuse/core'; | 168 | import { useWebSocket } from '@vueuse/core'; |
| 166 | import { getAuthCache } from '/@/utils/auth'; | 169 | import { getAuthCache } from '/@/utils/auth'; |
| 167 | import { JWT_TOKEN_KEY } from '/@/enums/cacheEnum'; | 170 | import { JWT_TOKEN_KEY } from '/@/enums/cacheEnum'; |
| 168 | - import { formatToDateTime } from '/@/utils/dateUtil'; | 171 | + import { dateUtil, formatToDateTime } from '/@/utils/dateUtil'; |
| 169 | import CustomerTrend from './CustomerTrend.vue'; | 172 | import CustomerTrend from './CustomerTrend.vue'; |
| 170 | // import TenantTrend from './TenantTrend.vue'; | 173 | // import TenantTrend from './TenantTrend.vue'; |
| 171 | import CustomerAlarmMessage from './CustomerAlarmMessage.vue'; | 174 | import CustomerAlarmMessage from './CustomerAlarmMessage.vue'; |
| @@ -530,6 +533,7 @@ | @@ -530,6 +533,7 @@ | ||
| 530 | }; | 533 | }; |
| 531 | 534 | ||
| 532 | const handleDisableDate = (current: moment.Moment) => { | 535 | const handleDisableDate = (current: moment.Moment) => { |
| 536 | + if (!current) return true; | ||
| 533 | if (!unref(customerDateValue) || unref(customerDateValue).length === 0) { | 537 | if (!unref(customerDateValue) || unref(customerDateValue).length === 0) { |
| 534 | return false; | 538 | return false; |
| 535 | } | 539 | } |
| @@ -117,6 +117,9 @@ | @@ -117,6 +117,9 @@ | ||
| 117 | @calendarChange="handleCalendarChange" | 117 | @calendarChange="handleCalendarChange" |
| 118 | :disabledDate="handleDisableDate" | 118 | :disabledDate="handleDisableDate" |
| 119 | v-model:value="tenantDateValue" | 119 | v-model:value="tenantDateValue" |
| 120 | + :showTime="{ | ||
| 121 | + defaultValue: [dateUtil('00:00:00', 'HH:mm:ss'), dateUtil('23:59:59', 'HH:mm:ss')], | ||
| 122 | + }" | ||
| 120 | > | 123 | > |
| 121 | <Button | 124 | <Button |
| 122 | type="link" | 125 | type="link" |
| @@ -175,7 +178,7 @@ | @@ -175,7 +178,7 @@ | ||
| 175 | import { useWebSocket } from '@vueuse/core'; | 178 | import { useWebSocket } from '@vueuse/core'; |
| 176 | import { getAuthCache } from '/@/utils/auth'; | 179 | import { getAuthCache } from '/@/utils/auth'; |
| 177 | import { JWT_TOKEN_KEY } from '/@/enums/cacheEnum'; | 180 | import { JWT_TOKEN_KEY } from '/@/enums/cacheEnum'; |
| 178 | - import { formatToDateTime } from '/@/utils/dateUtil'; | 181 | + import { dateUtil, formatToDateTime } from '/@/utils/dateUtil'; |
| 179 | // import CustomerTrend from './CustomerTrend.vue'; | 182 | // import CustomerTrend from './CustomerTrend.vue'; |
| 180 | import TenantTrend from './TenantTrend.vue'; | 183 | import TenantTrend from './TenantTrend.vue'; |
| 181 | import CustomerAlarmMessage from './CustomerAlarmMessage.vue'; | 184 | import CustomerAlarmMessage from './CustomerAlarmMessage.vue'; |
| @@ -548,6 +551,7 @@ | @@ -548,6 +551,7 @@ | ||
| 548 | }; | 551 | }; |
| 549 | 552 | ||
| 550 | const handleDisableDate = (current: moment.Moment) => { | 553 | const handleDisableDate = (current: moment.Moment) => { |
| 554 | + if (!current) return true; | ||
| 551 | if (!unref(tenantDateValue) || unref(tenantDateValue).length === 0) { | 555 | if (!unref(tenantDateValue) || unref(tenantDateValue).length === 0) { |
| 552 | return false; | 556 | return false; |
| 553 | } | 557 | } |
| 1 | -import { dateUtil, formatToDateTime } from '/@/utils/dateUtil'; | ||
| 2 | -import { ref } from 'vue'; | 1 | +import { dateUtil } from '/@/utils/dateUtil'; |
| 2 | +import { Ref, ref } from 'vue'; | ||
| 3 | import { getTrendData } from '/@/api/dashboard'; | 3 | import { getTrendData } from '/@/api/dashboard'; |
| 4 | import { RangePickerValue } from 'ant-design-vue/lib/date-picker/interface'; | 4 | import { RangePickerValue } from 'ant-design-vue/lib/date-picker/interface'; |
| 5 | +import moment from 'moment'; | ||
| 5 | 6 | ||
| 6 | export enum ShortcutQueryKeyEnum { | 7 | export enum ShortcutQueryKeyEnum { |
| 7 | LATEST_1_MONTH = 'LATEST_1_MONTH', | 8 | LATEST_1_MONTH = 'LATEST_1_MONTH', |
| @@ -42,8 +43,8 @@ export function getDateByShortcutQueryKey(value: ShortcutQueryKeyEnum) { | @@ -42,8 +43,8 @@ export function getDateByShortcutQueryKey(value: ShortcutQueryKeyEnum) { | ||
| 42 | export function useDate() { | 43 | export function useDate() { |
| 43 | const tenantDateValue = ref([]); | 44 | const tenantDateValue = ref([]); |
| 44 | const customerDateValue = ref<RangePickerValue>([]); | 45 | const customerDateValue = ref<RangePickerValue>([]); |
| 45 | - const tenantTrendList = ref([]); | ||
| 46 | - const customerTrendList = ref([]); | 46 | + const tenantTrendList = ref<[string, string][]>([]); |
| 47 | + const customerTrendList = ref<[string, string][]>([]); | ||
| 47 | const activeTenantIndex = ref(0); | 48 | const activeTenantIndex = ref(0); |
| 48 | const activeCustomerIndex = ref(0); | 49 | const activeCustomerIndex = ref(0); |
| 49 | const TenantOrCustomerDateList = ref([ | 50 | const TenantOrCustomerDateList = ref([ |
| @@ -80,52 +81,39 @@ export function useDate() { | @@ -80,52 +81,39 @@ export function useDate() { | ||
| 80 | } | 81 | } |
| 81 | 82 | ||
| 82 | // 获取选中的时间范围内的数据 | 83 | // 获取选中的时间范围内的数据 |
| 83 | - async function getDateData(startTs, endTs, trend: 'CUSTOMER_TREND' | 'TENANT_TREND', list) { | ||
| 84 | - // 计算时间间隔 | ||
| 85 | - function computedInterval(startTs: number, endTs: number) { | ||
| 86 | - /** | ||
| 87 | - * 选择的时间间隔 | ||
| 88 | - * <=1 2h | ||
| 89 | - * <=30 1day | ||
| 90 | - * >30<90 2day | ||
| 91 | - * >90 1month | ||
| 92 | - */ | ||
| 93 | - let interval = 86400000; | ||
| 94 | - if (endTs - startTs <= 86400000) { | ||
| 95 | - interval = 7200000; | ||
| 96 | - } else if (endTs - startTs <= 2592000000) { | ||
| 97 | - interval = 86400000; | ||
| 98 | - } else if (endTs - startTs > 2592000000 && endTs - startTs < 7776000000) { | ||
| 99 | - interval = 172800000; | ||
| 100 | - } else if (endTs - startTs > 7776000000) { | ||
| 101 | - interval = 2592000000; | ||
| 102 | - } | ||
| 103 | - return interval; | ||
| 104 | - } | ||
| 105 | - startTs = parseInt(formatToDateTime(startTs, 'x')) - 86400000; | ||
| 106 | - endTs = parseInt(formatToDateTime(endTs, 'x')); | 84 | + async function getDateData( |
| 85 | + startTs: moment.Moment, | ||
| 86 | + endTs: moment.Moment, | ||
| 87 | + trend: 'CUSTOMER_TREND' | 'TENANT_TREND', | ||
| 88 | + list: Ref<[string, string][]> | ||
| 89 | + ) { | ||
| 107 | const res = await getTrendData({ | 90 | const res = await getTrendData({ |
| 108 | - startTs, | ||
| 109 | - endTs, | ||
| 110 | - interval: computedInterval(startTs, endTs), | 91 | + startTs: startTs.valueOf(), |
| 92 | + endTs: endTs.valueOf(), | ||
| 93 | + interval: 24 * 60 * 60 * 1000, | ||
| 111 | trend, | 94 | trend, |
| 112 | }); | 95 | }); |
| 113 | - list.value = res.map((item) => [item.ts, item.value]); | 96 | + list.value = res.map((item) => [item.date, item.value]); |
| 114 | } | 97 | } |
| 115 | 98 | ||
| 116 | // 租户选择日期 | 99 | // 租户选择日期 |
| 117 | - function onDateTenantChange(_, dateString) { | ||
| 118 | - if (!_.length) return; | ||
| 119 | - const [startTs, endTs] = dateString; | 100 | + function onDateTenantChange(range: RangePickerValue) { |
| 101 | + if (!range.length) return; | ||
| 102 | + const [startTs, endTs] = range; | ||
| 120 | activeTenantIndex.value = -1; | 103 | activeTenantIndex.value = -1; |
| 121 | - getDateData(startTs, endTs, 'TENANT_TREND', tenantTrendList); | 104 | + getDateData(startTs as moment.Moment, endTs as moment.Moment, 'TENANT_TREND', tenantTrendList); |
| 122 | } | 105 | } |
| 123 | // 客户趋势选择日期 | 106 | // 客户趋势选择日期 |
| 124 | - function onDateCustomerChange(_, dateString) { | ||
| 125 | - if (!_.length) return; | ||
| 126 | - const [startTs, endTs] = dateString; | 107 | + function onDateCustomerChange(range: RangePickerValue) { |
| 108 | + if (!range.length) return; | ||
| 109 | + const [startTs, endTs] = range; | ||
| 127 | activeCustomerIndex.value = -1; | 110 | activeCustomerIndex.value = -1; |
| 128 | - getDateData(startTs, endTs, 'CUSTOMER_TREND', customerTrendList); | 111 | + getDateData( |
| 112 | + startTs as moment.Moment, | ||
| 113 | + endTs as moment.Moment, | ||
| 114 | + 'CUSTOMER_TREND', | ||
| 115 | + customerTrendList | ||
| 116 | + ); | ||
| 129 | } | 117 | } |
| 130 | return { | 118 | return { |
| 131 | tenantDateValue, | 119 | tenantDateValue, |
| @@ -124,12 +124,16 @@ | @@ -124,12 +124,16 @@ | ||
| 124 | const { largeDesignerPrefix } = useGlobSetting(); | 124 | const { largeDesignerPrefix } = useGlobSetting(); |
| 125 | 125 | ||
| 126 | const handlePreview = (record: BigScreenCenterItemsModel) => { | 126 | const handlePreview = (record: BigScreenCenterItemsModel) => { |
| 127 | - window.open(`${largeDesignerPrefix}/#/chart/preview/${record.id}`); | 127 | + window.open( |
| 128 | + `${largeDesignerPrefix}/#/chart/preview/${record.id}?organizationId=${record.organizationId}` | ||
| 129 | + ); | ||
| 128 | }; | 130 | }; |
| 129 | 131 | ||
| 130 | const handleDesign = (record: BigScreenCenterItemsModel) => { | 132 | const handleDesign = (record: BigScreenCenterItemsModel) => { |
| 131 | if (record.state === 1) return; | 133 | if (record.state === 1) return; |
| 132 | - window.open(`${largeDesignerPrefix}/#/chart/home/${record.id}`); | 134 | + window.open( |
| 135 | + `${largeDesignerPrefix}/#/chart/home/${record.id}?organizationId=${record.organizationId}` | ||
| 136 | + ); | ||
| 133 | }; | 137 | }; |
| 134 | 138 | ||
| 135 | const handleDelete = async (record: BigScreenCenterItemsModel) => { | 139 | const handleDelete = async (record: BigScreenCenterItemsModel) => { |
| @@ -10,7 +10,7 @@ | @@ -10,7 +10,7 @@ | ||
| 10 | </div> | 10 | </div> |
| 11 | </template> | 11 | </template> |
| 12 | <script lang="ts"> | 12 | <script lang="ts"> |
| 13 | - import { defineComponent, ref } from 'vue'; | 13 | + import { defineComponent, nextTick, ref } from 'vue'; |
| 14 | import { BasicForm, useForm } from '/@/components/Form'; | 14 | import { BasicForm, useForm } from '/@/components/Form'; |
| 15 | import { CommandFieldsEnum, CommandSchemas, CommandType, ValueType } from '../../config/data'; | 15 | import { CommandFieldsEnum, CommandSchemas, CommandType, ValueType } from '../../config/data'; |
| 16 | import { commandIssuanceApi } from '/@/api/device/deviceManager'; | 16 | import { commandIssuanceApi } from '/@/api/device/deviceManager'; |
| @@ -35,7 +35,7 @@ | @@ -35,7 +35,7 @@ | ||
| 35 | const { createMessage } = useMessage(); | 35 | const { createMessage } = useMessage(); |
| 36 | const loading = ref(false); | 36 | const loading = ref(false); |
| 37 | 37 | ||
| 38 | - const [registerForm, { getFieldsValue, validate, resetFields }] = useForm({ | 38 | + const [registerForm, { getFieldsValue, validate, resetFields, clearValidate }] = useForm({ |
| 39 | labelWidth: 120, | 39 | labelWidth: 120, |
| 40 | schemas: CommandSchemas( | 40 | schemas: CommandSchemas( |
| 41 | props.deviceDetail.deviceProfile.transportType as TransportTypeEnum, | 41 | props.deviceDetail.deviceProfile.transportType as TransportTypeEnum, |
| @@ -47,8 +47,10 @@ | @@ -47,8 +47,10 @@ | ||
| 47 | showResetButton: false, | 47 | showResetButton: false, |
| 48 | }); | 48 | }); |
| 49 | 49 | ||
| 50 | - const handleCancel = () => { | ||
| 51 | - resetFields(); | 50 | + const handleCancel = async () => { |
| 51 | + await resetFields(); | ||
| 52 | + await nextTick(); | ||
| 53 | + await clearValidate(); | ||
| 52 | }; | 54 | }; |
| 53 | 55 | ||
| 54 | const handleOk = async () => { | 56 | const handleOk = async () => { |
| @@ -36,6 +36,7 @@ | @@ -36,6 +36,7 @@ | ||
| 36 | <Authority value="api:yt:things_model:import"> | 36 | <Authority value="api:yt:things_model:import"> |
| 37 | <Upload | 37 | <Upload |
| 38 | v-if="isShowBtn" | 38 | v-if="isShowBtn" |
| 39 | + accept=".json," | ||
| 39 | :show-upload-list="false" | 40 | :show-upload-list="false" |
| 40 | :customRequest="handleImportModel" | 41 | :customRequest="handleImportModel" |
| 41 | > | 42 | > |
| @@ -22,7 +22,7 @@ | @@ -22,7 +22,7 @@ | ||
| 22 | </Authority> | 22 | </Authority> |
| 23 | </template> | 23 | </template> |
| 24 | <template #status="{ record }"> | 24 | <template #status="{ record }"> |
| 25 | - <Authority value="api:yt:message:status"> | 25 | + <Authority value="api:yt:message:update"> |
| 26 | <Switch | 26 | <Switch |
| 27 | :checked="record.status === 1" | 27 | :checked="record.status === 1" |
| 28 | :loading="record.pendingStatus" | 28 | :loading="record.pendingStatus" |
| @@ -32,7 +32,7 @@ | @@ -32,7 +32,7 @@ | ||
| 32 | /> | 32 | /> |
| 33 | </Authority> | 33 | </Authority> |
| 34 | <Tag | 34 | <Tag |
| 35 | - v-if="!hasPermission('api:yt:message:status')" | 35 | + v-if="!hasPermission('api:yt:message:update')" |
| 36 | :color="record.status ? 'green' : 'red'" | 36 | :color="record.status ? 'green' : 'red'" |
| 37 | > | 37 | > |
| 38 | {{ record.status ? '启用' : '禁用' }} | 38 | {{ record.status ? '启用' : '禁用' }} |
| @@ -22,7 +22,7 @@ | @@ -22,7 +22,7 @@ | ||
| 22 | </a-button> | 22 | </a-button> |
| 23 | </template> | 23 | </template> |
| 24 | <template #status="{ record }"> | 24 | <template #status="{ record }"> |
| 25 | - <Authority value="api:yt:template:status"> | 25 | + <Authority value="api:yt:template:update"> |
| 26 | <Switch | 26 | <Switch |
| 27 | :checked="record.status === 1" | 27 | :checked="record.status === 1" |
| 28 | :loading="record.pendingStatus" | 28 | :loading="record.pendingStatus" |
| @@ -32,7 +32,7 @@ | @@ -32,7 +32,7 @@ | ||
| 32 | /> | 32 | /> |
| 33 | </Authority> | 33 | </Authority> |
| 34 | <Tag | 34 | <Tag |
| 35 | - v-if="!hasPermission('api:yt:template:status')" | 35 | + v-if="!hasPermission('api:yt:template:update')" |
| 36 | :color="record.status ? 'green' : 'red'" | 36 | :color="record.status ? 'green' : 'red'" |
| 37 | > | 37 | > |
| 38 | {{ record.status ? '启用' : '禁用' }} | 38 | {{ record.status ? '启用' : '禁用' }} |
| @@ -4,12 +4,12 @@ | @@ -4,12 +4,12 @@ | ||
| 4 | <div style="height: 30px"></div> | 4 | <div style="height: 30px"></div> |
| 5 | <BasicForm @register="registerForm" /> | 5 | <BasicForm @register="registerForm" /> |
| 6 | <div class="flex flex-end" style="float: right"> | 6 | <div class="flex flex-end" style="float: right"> |
| 7 | - <a-button type="primary" @click="handleDeviceState">处理</a-button> | 7 | + <a-button v-if="!isHandler" type="primary" @click="handleDeviceState">处理</a-button> |
| 8 | </div> | 8 | </div> |
| 9 | </BasicDrawer> | 9 | </BasicDrawer> |
| 10 | </template> | 10 | </template> |
| 11 | <script lang="ts" setup> | 11 | <script lang="ts" setup> |
| 12 | - import { reactive } from 'vue'; | 12 | + import { reactive, ref } from 'vue'; |
| 13 | import { BasicForm, useForm } from '/@/components/Form'; | 13 | import { BasicForm, useForm } from '/@/components/Form'; |
| 14 | import { formHandleSchema, formDetailSchema } from './config.data'; | 14 | import { formHandleSchema, formDetailSchema } from './config.data'; |
| 15 | import { BasicDrawer, useDrawerInner } from '/@/components/Drawer'; | 15 | import { BasicDrawer, useDrawerInner } from '/@/components/Drawer'; |
| @@ -26,7 +26,7 @@ | @@ -26,7 +26,7 @@ | ||
| 26 | obj: {}, | 26 | obj: {}, |
| 27 | }); | 27 | }); |
| 28 | 28 | ||
| 29 | - const [registerForm, { resetFields, getFieldsValue }] = useForm({ | 29 | + const [registerForm, { resetFields, getFieldsValue, setFieldsValue }] = useForm({ |
| 30 | schemas: formHandleSchema, | 30 | schemas: formHandleSchema, |
| 31 | showActionButtonGroup: false, | 31 | showActionButtonGroup: false, |
| 32 | }); | 32 | }); |
| @@ -37,11 +37,15 @@ | @@ -37,11 +37,15 @@ | ||
| 37 | layout: 'vertical', | 37 | layout: 'vertical', |
| 38 | }); | 38 | }); |
| 39 | 39 | ||
| 40 | + const isHandler = ref(false); | ||
| 41 | + | ||
| 40 | const [registerDrawer, { setDrawerProps, closeDrawer }] = useDrawerInner(async (data) => { | 42 | const [registerDrawer, { setDrawerProps, closeDrawer }] = useDrawerInner(async (data) => { |
| 41 | await resetFields(); | 43 | await resetFields(); |
| 42 | setDrawerProps({ confirmLoading: false }); | 44 | setDrawerProps({ confirmLoading: false }); |
| 43 | record.obj = data.record; | 45 | record.obj = data.record; |
| 44 | setDescProps({ data: data.record }); | 46 | setDescProps({ data: data.record }); |
| 47 | + isHandler.value = data?.record?.remark; | ||
| 48 | + setFieldsValue(data.record); | ||
| 45 | }); | 49 | }); |
| 46 | 50 | ||
| 47 | const handleDeviceState = async () => { | 51 | const handleDeviceState = async () => { |
| @@ -194,6 +194,10 @@ export const formSchema: DescItem[] = [ | @@ -194,6 +194,10 @@ export const formSchema: DescItem[] = [ | ||
| 194 | field: 'createTime', | 194 | field: 'createTime', |
| 195 | label: '时间', | 195 | label: '时间', |
| 196 | }, | 196 | }, |
| 197 | + { | ||
| 198 | + field: 'remark', | ||
| 199 | + label: '备注', | ||
| 200 | + }, | ||
| 197 | ]; | 201 | ]; |
| 198 | 202 | ||
| 199 | export const formDetailSchema: DescItem[] = [ | 203 | export const formDetailSchema: DescItem[] = [ |
| @@ -221,7 +225,7 @@ export const formDetailSchema: DescItem[] = [ | @@ -221,7 +225,7 @@ export const formDetailSchema: DescItem[] = [ | ||
| 221 | //处理表单 | 225 | //处理表单 |
| 222 | export const formHandleSchema: FormSchema[] = [ | 226 | export const formHandleSchema: FormSchema[] = [ |
| 223 | { | 227 | { |
| 224 | - field: 'description', | 228 | + field: 'remark', |
| 225 | label: '备注', | 229 | label: '备注', |
| 226 | colProps: { span: 24 }, | 230 | colProps: { span: 24 }, |
| 227 | component: 'InputTextArea', | 231 | component: 'InputTextArea', |
| @@ -20,6 +20,7 @@ | @@ -20,6 +20,7 @@ | ||
| 20 | label: '处理', | 20 | label: '处理', |
| 21 | auth: 'api:yt:device:state:log::post', | 21 | auth: 'api:yt:device:state:log::post', |
| 22 | icon: 'clarity:note-edit-line', | 22 | icon: 'clarity:note-edit-line', |
| 23 | + ifShow: () => !record?.remark, | ||
| 23 | onClick: handleView.bind(null, record), | 24 | onClick: handleView.bind(null, record), |
| 24 | }, | 25 | }, |
| 25 | { | 26 | { |
| @@ -74,7 +74,7 @@ | @@ -74,7 +74,7 @@ | ||
| 74 | /> | 74 | /> |
| 75 | </template> | 75 | </template> |
| 76 | <template #configStatus="{ record }"> | 76 | <template #configStatus="{ record }"> |
| 77 | - <Authority :value="PermissionReportConfigEnum.PERMISSION_STATUS"> | 77 | + <Authority :value="PermissionReportConfigEnum.PERMISSION_UPDATE"> |
| 78 | <Switch | 78 | <Switch |
| 79 | :disabled="disabledSwitch" | 79 | :disabled="disabledSwitch" |
| 80 | :checked="record.status === 1" | 80 | :checked="record.status === 1" |
| @@ -85,7 +85,7 @@ | @@ -85,7 +85,7 @@ | ||
| 85 | /> | 85 | /> |
| 86 | </Authority> | 86 | </Authority> |
| 87 | <Tag | 87 | <Tag |
| 88 | - v-if="!hasPermission(PermissionReportConfigEnum.PERMISSION_STATUS)" | 88 | + v-if="!hasPermission(PermissionReportConfigEnum.PERMISSION_UPDATE)" |
| 89 | :color="record.status ? 'green' : 'red'" | 89 | :color="record.status ? 'green' : 'red'" |
| 90 | > | 90 | > |
| 91 | {{ record.status ? '启用' : '禁用' }} | 91 | {{ record.status ? '启用' : '禁用' }} |
| @@ -31,9 +31,9 @@ | @@ -31,9 +31,9 @@ | ||
| 31 | import { CredentialsEnum } from '../mqtt/enum'; | 31 | import { CredentialsEnum } from '../mqtt/enum'; |
| 32 | 32 | ||
| 33 | const credentialsFile = reactive({ | 33 | const credentialsFile = reactive({ |
| 34 | - caCertFileName: '', | ||
| 35 | - certFileName: '', | ||
| 36 | - privateKeyFileName: '', | 34 | + caCertFileName: undefined, |
| 35 | + certFileName: undefined, | ||
| 36 | + privateKeyFileName: undefined, | ||
| 37 | }); | 37 | }); |
| 38 | 38 | ||
| 39 | const [register, { validateFields, setFieldsValue, resetFields }] = useForm({ | 39 | const [register, { validateFields, setFieldsValue, resetFields }] = useForm({ |
| @@ -50,6 +50,11 @@ | @@ -50,6 +50,11 @@ | ||
| 50 | const getValue = async () => { | 50 | const getValue = async () => { |
| 51 | const values = await validateFields(); | 51 | const values = await validateFields(); |
| 52 | if (!values) return; | 52 | if (!values) return; |
| 53 | + // if (values.type == 'anonymous' || values.type == 'basic') { | ||
| 54 | + // credentialsFile.caCertFileName = undefined; | ||
| 55 | + // credentialsFile.certFileName = undefined; | ||
| 56 | + // credentialsFile.privateKeyFileName = undefined; | ||
| 57 | + // } | ||
| 53 | const credentials = { | 58 | const credentials = { |
| 54 | type: values['type'], | 59 | type: values['type'], |
| 55 | ...credentialsFile, | 60 | ...credentialsFile, |
| @@ -51,10 +51,16 @@ | @@ -51,10 +51,16 @@ | ||
| 51 | const getValue = async () => { | 51 | const getValue = async () => { |
| 52 | const values = await validateFields(); | 52 | const values = await validateFields(); |
| 53 | if (!values) return; | 53 | if (!values) return; |
| 54 | + if (values.type == 'anonymous' || values.type == 'basic') { | ||
| 55 | + credentialsFile.caCertFileName = undefined; | ||
| 56 | + credentialsFile.certFileName = undefined; | ||
| 57 | + credentialsFile.privateKeyFileName = undefined; | ||
| 58 | + } | ||
| 54 | const credentials = { | 59 | const credentials = { |
| 55 | type: values['type'], | 60 | type: values['type'], |
| 56 | ...credentialsFile, | 61 | ...credentialsFile, |
| 57 | }; | 62 | }; |
| 63 | + | ||
| 58 | const mergeValues = { | 64 | const mergeValues = { |
| 59 | ...values, | 65 | ...values, |
| 60 | ...{ credentials }, | 66 | ...{ credentials }, |
| @@ -67,7 +73,12 @@ | @@ -67,7 +73,12 @@ | ||
| 67 | if (credentials) { | 73 | if (credentials) { |
| 68 | for (let i in credentials) Reflect.set(credentialsFile, i, credentials[i]); | 74 | for (let i in credentials) Reflect.set(credentialsFile, i, credentials[i]); |
| 69 | } | 75 | } |
| 70 | - setFieldsValue({ ...value, type: credentials.type }); | 76 | + setFieldsValue({ |
| 77 | + ...value, | ||
| 78 | + type: credentials.type, | ||
| 79 | + username: credentials.username, | ||
| 80 | + password: credentials.password, | ||
| 81 | + }); | ||
| 71 | }; | 82 | }; |
| 72 | 83 | ||
| 73 | const resetValue = () => resetFields(); | 84 | const resetValue = () => resetFields(); |
| @@ -18,7 +18,7 @@ class MqttFormPartialConfig { | @@ -18,7 +18,7 @@ class MqttFormPartialConfig { | ||
| 18 | return [ | 18 | return [ |
| 19 | { label: 'Anonymous', value: 'anonymous' }, | 19 | { label: 'Anonymous', value: 'anonymous' }, |
| 20 | { label: 'Basic', value: 'basic' }, | 20 | { label: 'Basic', value: 'basic' }, |
| 21 | - { label: 'PEM', value: 'pem' }, | 21 | + { label: 'PEM', value: 'cert.PEM' }, |
| 22 | ]; | 22 | ]; |
| 23 | } | 23 | } |
| 24 | } | 24 | } |
| @@ -138,9 +138,21 @@ export const modeMqttForm: FormSchema[] = [ | @@ -138,9 +138,21 @@ export const modeMqttForm: FormSchema[] = [ | ||
| 138 | label: '凭据类型', | 138 | label: '凭据类型', |
| 139 | colProps: { span: 12 }, | 139 | colProps: { span: 12 }, |
| 140 | defaultValue: MqttFormPartialConfig.type, | 140 | defaultValue: MqttFormPartialConfig.type, |
| 141 | - componentProps: { | ||
| 142 | - placeholder: '请选择Credentials', | ||
| 143 | - options: MqttFormPartialConfig.getType(), | 141 | + componentProps: ({ formActionType }) => { |
| 142 | + const { setFieldsValue } = formActionType; | ||
| 143 | + return { | ||
| 144 | + placeholder: '请选择Credentials', | ||
| 145 | + options: MqttFormPartialConfig.getType(), | ||
| 146 | + onChange(e) { | ||
| 147 | + if (e) { | ||
| 148 | + console.log('执行'); | ||
| 149 | + setFieldsValue({ | ||
| 150 | + password: undefined, | ||
| 151 | + username: undefined, | ||
| 152 | + }); | ||
| 153 | + } | ||
| 154 | + }, | ||
| 155 | + }; | ||
| 144 | }, | 156 | }, |
| 145 | }, | 157 | }, |
| 146 | { | 158 | { |
| @@ -6,7 +6,7 @@ | @@ -6,7 +6,7 @@ | ||
| 6 | export enum CredentialsEnum { | 6 | export enum CredentialsEnum { |
| 7 | IS_ANONYMOUS = 'anonymous', | 7 | IS_ANONYMOUS = 'anonymous', |
| 8 | IS_BASIC = 'basic', | 8 | IS_BASIC = 'basic', |
| 9 | - IS_PEM = 'pem', | 9 | + IS_PEM = 'cert.PEM', |
| 10 | } | 10 | } |
| 11 | 11 | ||
| 12 | export const isBasic = (type: string) => { | 12 | export const isBasic = (type: string) => { |
| @@ -128,8 +128,9 @@ | @@ -128,8 +128,9 @@ | ||
| 128 | : undefined, | 128 | : undefined, |
| 129 | appendClientIdSuffix: getDataFlowParams.appendClientIdSuffix || undefined, | 129 | appendClientIdSuffix: getDataFlowParams.appendClientIdSuffix || undefined, |
| 130 | type: undefined, | 130 | type: undefined, |
| 131 | + username: undefined, | ||
| 132 | + password: undefined, | ||
| 131 | }; | 133 | }; |
| 132 | - | ||
| 133 | const rest = isRabbitmq(getDataFlowMethod?.type) | 134 | const rest = isRabbitmq(getDataFlowMethod?.type) |
| 134 | ? await postAddConvertApi({ ...restData.data, ...data }) | 135 | ? await postAddConvertApi({ ...restData.data, ...data }) |
| 135 | : await postAddConvertApi({ ...restData.data, ...data, configuration }); | 136 | : await postAddConvertApi({ ...restData.data, ...data, configuration }); |
| @@ -79,7 +79,7 @@ | @@ -79,7 +79,7 @@ | ||
| 79 | /> | 79 | /> |
| 80 | </template> | 80 | </template> |
| 81 | <template #status="{ record }"> | 81 | <template #status="{ record }"> |
| 82 | - <Authority :value="PermissionDataFlowEnum.PERMISSION_STATUS"> | 82 | + <Authority :value="PermissionDataFlowEnum.PERMISSION_UPDATE"> |
| 83 | <Switch | 83 | <Switch |
| 84 | :checked="record.status === 1" | 84 | :checked="record.status === 1" |
| 85 | :loading="record.pendingStatus" | 85 | :loading="record.pendingStatus" |
| @@ -89,7 +89,7 @@ | @@ -89,7 +89,7 @@ | ||
| 89 | /> | 89 | /> |
| 90 | </Authority> | 90 | </Authority> |
| 91 | <Tag | 91 | <Tag |
| 92 | - v-if="!hasPermission(PermissionDataFlowEnum.PERMISSION_STATUS)" | 92 | + v-if="!hasPermission(PermissionDataFlowEnum.PERMISSION_UPDATE)" |
| 93 | :color="record.status ? 'green' : 'red'" | 93 | :color="record.status ? 'green' : 'red'" |
| 94 | > | 94 | > |
| 95 | {{ record.status ? '启用' : '禁用' }} | 95 | {{ record.status ? '启用' : '禁用' }} |
| @@ -755,6 +755,18 @@ export const actionSchema: FormSchema[] = [ | @@ -755,6 +755,18 @@ export const actionSchema: FormSchema[] = [ | ||
| 755 | component: 'Select', | 755 | component: 'Select', |
| 756 | label: '', | 756 | label: '', |
| 757 | show: ({ values }) => isAlarmOut(values.outTarget), | 757 | show: ({ values }) => isAlarmOut(values.outTarget), |
| 758 | + // dynamicRules: (params) => { | ||
| 759 | + // const { outTarget } = params.values; | ||
| 760 | + // return [ | ||
| 761 | + // { | ||
| 762 | + // required: outTarget == 'MSG_NOTIFY' ? true : false, | ||
| 763 | + // validator: (_, value) => { | ||
| 764 | + // if (!value) return Promise.reject('请选择告警配置'); | ||
| 765 | + // Promise.resolve(); | ||
| 766 | + // }, | ||
| 767 | + // }, | ||
| 768 | + // ]; | ||
| 769 | + // }, | ||
| 758 | componentProps: { | 770 | componentProps: { |
| 759 | placeholder: '请选择告警等级', | 771 | placeholder: '请选择告警等级', |
| 760 | options: [ | 772 | options: [ |
| @@ -273,6 +273,10 @@ | @@ -273,6 +273,10 @@ | ||
| 273 | if (validate.device == 'PART' && validate.deviceId == undefined) | 273 | if (validate.device == 'PART' && validate.deviceId == undefined) |
| 274 | return createMessage.error('请选择设备'); | 274 | return createMessage.error('请选择设备'); |
| 275 | } | 275 | } |
| 276 | + if (type === 'MSG_NOTIFY') { | ||
| 277 | + if (!validate.alarm_config) return createMessage.error('请选择告警配置'); | ||
| 278 | + if (!validate.alarm_level) return createMessage.error('请选择告警等级'); | ||
| 279 | + } | ||
| 276 | //ft-add-2022-11-22 | 280 | //ft-add-2022-11-22 |
| 277 | //TODO-fengtao-设备验证 | 281 | //TODO-fengtao-设备验证 |
| 278 | const value = getFieldsValue(); | 282 | const value = getFieldsValue(); |
| @@ -50,7 +50,7 @@ | @@ -50,7 +50,7 @@ | ||
| 50 | </template> | 50 | </template> |
| 51 | 51 | ||
| 52 | <template #status="{ record }"> | 52 | <template #status="{ record }"> |
| 53 | - <Authority value="api:yt:sceneLinkage:status"> | 53 | + <Authority value="api:yt:sceneLinkage:update"> |
| 54 | <Switch | 54 | <Switch |
| 55 | :checked="record.status === 1" | 55 | :checked="record.status === 1" |
| 56 | :loading="record.pendingStatus" | 56 | :loading="record.pendingStatus" |
| @@ -60,7 +60,7 @@ | @@ -60,7 +60,7 @@ | ||
| 60 | /> | 60 | /> |
| 61 | </Authority> | 61 | </Authority> |
| 62 | <Tag | 62 | <Tag |
| 63 | - v-if="!hasPermission('api:yt:sceneLinkage:status')" | 63 | + v-if="!hasPermission('api:yt:sceneLinkage:update')" |
| 64 | :color="record.status ? 'green' : 'red'" | 64 | :color="record.status ? 'green' : 'red'" |
| 65 | > | 65 | > |
| 66 | {{ record.status ? '启用' : '禁用' }} | 66 | {{ record.status ? '启用' : '禁用' }} |
| @@ -17,7 +17,7 @@ | @@ -17,7 +17,7 @@ | ||
| 17 | </Authority> | 17 | </Authority> |
| 18 | </template> | 18 | </template> |
| 19 | <template #status="{ record }"> | 19 | <template #status="{ record }"> |
| 20 | - <Authority value="api:yt:convert:js:status"> | 20 | + <Authority value="api:yt:convert:js:update"> |
| 21 | <Switch | 21 | <Switch |
| 22 | :checked="record.status === 1" | 22 | :checked="record.status === 1" |
| 23 | :loading="record.pendingStatus" | 23 | :loading="record.pendingStatus" |
| @@ -27,7 +27,7 @@ | @@ -27,7 +27,7 @@ | ||
| 27 | /> | 27 | /> |
| 28 | </Authority> | 28 | </Authority> |
| 29 | <Tag | 29 | <Tag |
| 30 | - v-if="!hasPermission('api:yt:convert:js:status')" | 30 | + v-if="!hasPermission('api:yt:convert:js:update')" |
| 31 | :color="record.status ? 'green' : 'red'" | 31 | :color="record.status ? 'green' : 'red'" |
| 32 | > | 32 | > |
| 33 | {{ record.status ? '启用' : '禁用' }} | 33 | {{ record.status ? '启用' : '禁用' }} |
| @@ -71,7 +71,7 @@ | @@ -71,7 +71,7 @@ | ||
| 71 | /> | 71 | /> |
| 72 | </template> | 72 | </template> |
| 73 | <template #status="{ record }"> | 73 | <template #status="{ record }"> |
| 74 | - <Authority :value="PermissionConvertScriptEnum.PERMISSION_UPDATE_STATUS"> | 74 | + <Authority :value="PermissionConvertScriptEnum.PERMISSION_UPDATE"> |
| 75 | <Switch | 75 | <Switch |
| 76 | :checked="record.status === 1" | 76 | :checked="record.status === 1" |
| 77 | :loading="record.pendingStatus" | 77 | :loading="record.pendingStatus" |
| @@ -81,7 +81,7 @@ | @@ -81,7 +81,7 @@ | ||
| 81 | /> | 81 | /> |
| 82 | </Authority> | 82 | </Authority> |
| 83 | <Tag | 83 | <Tag |
| 84 | - v-if="!hasPermission(PermissionConvertScriptEnum.PERMISSION_UPDATE_STATUS)" | 84 | + v-if="!hasPermission(PermissionConvertScriptEnum.PERMISSION_UPDATE)" |
| 85 | :color="record.status ? 'green' : 'red'" | 85 | :color="record.status ? 'green' : 'red'" |
| 86 | > | 86 | > |
| 87 | {{ record.status ? '启用' : '禁用' }} | 87 | {{ record.status ? '启用' : '禁用' }} |
| @@ -21,7 +21,7 @@ | @@ -21,7 +21,7 @@ | ||
| 21 | </Authority> | 21 | </Authority> |
| 22 | </template> | 22 | </template> |
| 23 | <template #status="{ record }"> | 23 | <template #status="{ record }"> |
| 24 | - <Authority value="api:yt:role:status"> | 24 | + <Authority value="api:yt:role:saveOrUpdateRoleInfoWithMenu:update"> |
| 25 | <Switch | 25 | <Switch |
| 26 | :checked="record.status === 1" | 26 | :checked="record.status === 1" |
| 27 | :loading="record.pendingStatus" | 27 | :loading="record.pendingStatus" |
| @@ -30,7 +30,10 @@ | @@ -30,7 +30,10 @@ | ||
| 30 | @change="(checked:boolean)=>statusChange(checked,record)" | 30 | @change="(checked:boolean)=>statusChange(checked,record)" |
| 31 | /> | 31 | /> |
| 32 | </Authority> | 32 | </Authority> |
| 33 | - <Tag v-if="!hasPermission('api:yt:role:status')" :color="record.status ? 'green' : 'red'"> | 33 | + <Tag |
| 34 | + v-if="!hasPermission('api:yt:role:saveOrUpdateRoleInfoWithMenu:update')" | ||
| 35 | + :color="record.status ? 'green' : 'red'" | ||
| 36 | + > | ||
| 34 | {{ record.status ? '启用' : '禁用' }} | 37 | {{ record.status ? '启用' : '禁用' }} |
| 35 | </Tag> | 38 | </Tag> |
| 36 | </template> | 39 | </template> |
| @@ -2,7 +2,7 @@ | @@ -2,7 +2,7 @@ | ||
| 2 | import { BasicForm, useForm } from '/@/components/Form'; | 2 | import { BasicForm, useForm } from '/@/components/Form'; |
| 3 | import { BasicModal, useModalInner } from '/@/components/Modal'; | 3 | import { BasicModal, useModalInner } from '/@/components/Modal'; |
| 4 | import { formSchemas } from './config'; | 4 | import { formSchemas } from './config'; |
| 5 | - import { ref } from 'vue'; | 5 | + import { nextTick, ref } from 'vue'; |
| 6 | import { composeData, parseData } from './util'; | 6 | import { composeData, parseData } from './util'; |
| 7 | import { createTask, updateTask } from '/@/api/task'; | 7 | import { createTask, updateTask } from '/@/api/task'; |
| 8 | import { ModalParamsType } from '/#/utils'; | 8 | import { ModalParamsType } from '/#/utils'; |
| @@ -33,7 +33,10 @@ | @@ -33,7 +33,10 @@ | ||
| 33 | modalMode.value = mode; | 33 | modalMode.value = mode; |
| 34 | dataSource.value = record; | 34 | dataSource.value = record; |
| 35 | formMode.value = mode; | 35 | formMode.value = mode; |
| 36 | - resetFields(); | 36 | + resetFields().then(async () => { |
| 37 | + await nextTick(); | ||
| 38 | + clearValidate(); | ||
| 39 | + }); | ||
| 37 | if (record && mode === DataActionModeEnum.UPDATE) { | 40 | if (record && mode === DataActionModeEnum.UPDATE) { |
| 38 | const res = parseData(record); | 41 | const res = parseData(record); |
| 39 | setFieldsValue({ ...res }); | 42 | setFieldsValue({ ...res }); |
| @@ -41,13 +44,14 @@ | @@ -41,13 +44,14 @@ | ||
| 41 | } | 44 | } |
| 42 | ); | 45 | ); |
| 43 | 46 | ||
| 44 | - const [registerForm, { getFieldsValue, validate, setFieldsValue, resetFields }] = useForm({ | ||
| 45 | - schemas: formSchemas, | ||
| 46 | - showActionButtonGroup: false, | ||
| 47 | - layout: 'inline', | ||
| 48 | - baseColProps: { span: 24 }, | ||
| 49 | - labelWidth: 140, | ||
| 50 | - }); | 47 | + const [registerForm, { getFieldsValue, validate, setFieldsValue, resetFields, clearValidate }] = |
| 48 | + useForm({ | ||
| 49 | + schemas: formSchemas, | ||
| 50 | + showActionButtonGroup: false, | ||
| 51 | + layout: 'inline', | ||
| 52 | + baseColProps: { span: 24 }, | ||
| 53 | + labelWidth: 140, | ||
| 54 | + }); | ||
| 51 | 55 | ||
| 52 | const loading = ref(false); | 56 | const loading = ref(false); |
| 53 | const { createMessage } = useMessage(); | 57 | const { createMessage } = useMessage(); |
| @@ -124,7 +124,6 @@ export const parseData = (result: TaskRecordType): Required<FormValueType> => { | @@ -124,7 +124,6 @@ export const parseData = (result: TaskRecordType): Required<FormValueType> => { | ||
| 124 | TaskRecordType['executeTarget'] | 124 | TaskRecordType['executeTarget'] |
| 125 | >; | 125 | >; |
| 126 | const { type: executeTimeType, period, periodType, time, pollUnit } = executeTime; | 126 | const { type: executeTimeType, period, periodType, time, pollUnit } = executeTime; |
| 127 | - console.log(pushWay === PushWayEnum.MQTT ? JSON.stringify(rpcCommand, null, 2) : rpcCommand); | ||
| 128 | return { | 127 | return { |
| 129 | name, | 128 | name, |
| 130 | targetType, | 129 | targetType, |
| @@ -188,7 +188,9 @@ | @@ -188,7 +188,9 @@ | ||
| 188 | if (hasDetailPermission) { | 188 | if (hasDetailPermission) { |
| 189 | const boardId = encode(record.id); | 189 | const boardId = encode(record.id); |
| 190 | const boardName = encode(record.name); | 190 | const boardName = encode(record.name); |
| 191 | - router.push(`/visual/board/detail/${boardId}/${boardName}`); | 191 | + const organizationId = encode(record?.organizationId); |
| 192 | + | ||
| 193 | + router.push(`/visual/board/detail/${boardId}/${boardName}/${organizationId}`); | ||
| 192 | } else createMessage.warning('没有权限'); | 194 | } else createMessage.warning('没有权限'); |
| 193 | }; | 195 | }; |
| 194 | 196 |
| @@ -12,10 +12,6 @@ | @@ -12,10 +12,6 @@ | ||
| 12 | [PackagesCategoryEnum.MAP]: [ | 12 | [PackagesCategoryEnum.MAP]: [ |
| 13 | '地图组件,需绑定两个数据源,且数据源为同一设备。第一数据源为经度,第二数据源为纬度,否则地图组件不能正常显示。', | 13 | '地图组件,需绑定两个数据源,且数据源为同一设备。第一数据源为经度,第二数据源为纬度,否则地图组件不能正常显示。', |
| 14 | ], | 14 | ], |
| 15 | - [PackagesCategoryEnum.CONTROL]: [ | ||
| 16 | - '控制组件数据源为TCP产品,则其控制命令下发为TCP产品 物模型=>服务,且不具备状态显示功能.', | ||
| 17 | - '控制组件数据源为非TCP产品,则其控制命令下发为产品 物模型=>属性,且具备状态显示功能.', | ||
| 18 | - ], | ||
| 19 | }; | 15 | }; |
| 20 | 16 | ||
| 21 | const getMessage = computed(() => { | 17 | const getMessage = computed(() => { |
| @@ -90,6 +90,7 @@ export const commonDataSourceSchemas = (): FormSchema[] => { | @@ -90,6 +90,7 @@ export const commonDataSourceSchemas = (): FormSchema[] => { | ||
| 90 | const isUpdate = unref(mode) === DataActionModeEnum.UPDATE; | 90 | const isUpdate = unref(mode) === DataActionModeEnum.UPDATE; |
| 91 | const selectWidgetKeys = useSelectWidgetKeys(); | 91 | const selectWidgetKeys = useSelectWidgetKeys(); |
| 92 | const category = unref(selectWidgetKeys).categoryKey; | 92 | const category = unref(selectWidgetKeys).categoryKey; |
| 93 | + | ||
| 93 | return [ | 94 | return [ |
| 94 | { | 95 | { |
| 95 | field: DataSourceField.IS_GATEWAY_DEVICE, | 96 | field: DataSourceField.IS_GATEWAY_DEVICE, |
| @@ -191,6 +192,9 @@ export const commonDataSourceSchemas = (): FormSchema[] => { | @@ -191,6 +192,9 @@ export const commonDataSourceSchemas = (): FormSchema[] => { | ||
| 191 | }); | 192 | }); |
| 192 | }, | 193 | }, |
| 193 | showCreate: false, | 194 | showCreate: false, |
| 195 | + apiTreeSelectProps: { | ||
| 196 | + params: { organizationId: location?.pathname?.split('/')?.pop() || '' }, | ||
| 197 | + }, | ||
| 194 | getPopupContainer: () => document.body, | 198 | getPopupContainer: () => document.body, |
| 195 | }; | 199 | }; |
| 196 | }, | 200 | }, |