Commit c64231b090575f5df3eb63005cdc7720b635d358
Merge branch 'main_dev' of http://git.yunteng.com/yunteng/thingskit-front into f…
…ix/board-style-issues
Showing
16 changed files
with
91 additions
and
49 deletions
| @@ -47,7 +47,7 @@ | @@ -47,7 +47,7 @@ | ||
| 47 | transformFile?: (file: File) => string | Blob | Promise<string | Blob | File>; | 47 | transformFile?: (file: File) => string | Blob | Promise<string | Blob | File>; |
| 48 | api: (file: string | Blob | Promise<string | Blob | File>) => Promise<FileItem>; | 48 | api: (file: string | Blob | Promise<string | Blob | File>) => Promise<FileItem>; |
| 49 | overFileLimitHiddenUploadEntry?: boolean; | 49 | overFileLimitHiddenUploadEntry?: boolean; |
| 50 | - beforeUpload: (file: File, fileList: File[]) => boolean; | 50 | + beforeUpload?: (file: File, fileList: File[]) => boolean; |
| 51 | }>(), | 51 | }>(), |
| 52 | { | 52 | { |
| 53 | fileList: () => [], | 53 | fileList: () => [], |
| @@ -146,7 +146,7 @@ | @@ -146,7 +146,7 @@ | ||
| 146 | :remove="handleRemove" | 146 | :remove="handleRemove" |
| 147 | > | 147 | > |
| 148 | <Spin | 148 | <Spin |
| 149 | - v-if="!(fileList.length >= getMaxFileLimit) || overFileLimitHiddenUploadEntry" | 149 | + v-if="!(fileList.length >= getMaxFileLimit && overFileLimitHiddenUploadEntry)" |
| 150 | :spinning="loading" | 150 | :spinning="loading" |
| 151 | > | 151 | > |
| 152 | <div class="w-full h-full flex flex-col justify-center content-center"> | 152 | <div class="w-full h-full flex flex-col justify-center content-center"> |
| @@ -113,6 +113,10 @@ export const alarmColumns: BasicColumn[] = [ | @@ -113,6 +113,10 @@ export const alarmColumns: BasicColumn[] = [ | ||
| 113 | title: '告警设备', | 113 | title: '告警设备', |
| 114 | dataIndex: 'deviceName', | 114 | dataIndex: 'deviceName', |
| 115 | width: 100, | 115 | width: 100, |
| 116 | + customRender: ({ record }) => { | ||
| 117 | + const { deviceAlias, deviceName } = record || {}; | ||
| 118 | + return deviceAlias || deviceName; | ||
| 119 | + }, | ||
| 116 | }, | 120 | }, |
| 117 | { | 121 | { |
| 118 | title: '告警场景', | 122 | title: '告警场景', |
| @@ -46,14 +46,16 @@ | @@ -46,14 +46,16 @@ | ||
| 46 | const alarmStatus = ref(''); | 46 | const alarmStatus = ref(''); |
| 47 | const [registerDrawer, { closeDrawer }] = useDrawerInner(async (data) => { | 47 | const [registerDrawer, { closeDrawer }] = useDrawerInner(async (data) => { |
| 48 | await resetFields(); | 48 | await resetFields(); |
| 49 | + const { deviceAlias, deviceName, severity, status, details, id } = data || {}; | ||
| 49 | await setFieldsValue({ | 50 | await setFieldsValue({ |
| 50 | ...data, | 51 | ...data, |
| 51 | - severity: alarmLevel(data.severity), | ||
| 52 | - status: statusType(data.status), | ||
| 53 | - details: JSON.stringify(data.details), | 52 | + deviceName: deviceAlias || deviceName, |
| 53 | + severity: alarmLevel(severity), | ||
| 54 | + status: statusType(status), | ||
| 55 | + details: JSON.stringify(details), | ||
| 54 | }); | 56 | }); |
| 55 | - alarmStatus.value = data.status; | ||
| 56 | - alarmId.value = data.id; | 57 | + alarmStatus.value = status; |
| 58 | + alarmId.value = id; | ||
| 57 | }); | 59 | }); |
| 58 | // 处理报警 | 60 | // 处理报警 |
| 59 | const handleAlarm = async () => { | 61 | const handleAlarm = async () => { |
| @@ -19,14 +19,14 @@ | @@ -19,14 +19,14 @@ | ||
| 19 | </a-button> | 19 | </a-button> |
| 20 | </template> | 20 | </template> |
| 21 | <template #toolbar> | 21 | <template #toolbar> |
| 22 | - <Button @click="handleBatchAck" type="primary">批量处理</Button> | 22 | + <Button @click="handleBatchAck" type="primary" :disabled="getCanBatchAck">批量处理</Button> |
| 23 | </template> | 23 | </template> |
| 24 | </BasicTable> | 24 | </BasicTable> |
| 25 | <AlarmDetailDrawer @register="registerDetailDrawer" @success="handleSuccess" /> | 25 | <AlarmDetailDrawer @register="registerDetailDrawer" @success="handleSuccess" /> |
| 26 | </div> | 26 | </div> |
| 27 | </template> | 27 | </template> |
| 28 | <script lang="ts"> | 28 | <script lang="ts"> |
| 29 | - import { defineComponent, nextTick, h } from 'vue'; | 29 | + import { defineComponent, nextTick, h, computed } from 'vue'; |
| 30 | import { BasicTable, useTable, TableAction } from '/@/components/Table'; | 30 | import { BasicTable, useTable, TableAction } from '/@/components/Table'; |
| 31 | import { alarmColumns, alarmSearchSchemas } from './config/detail.config'; | 31 | import { alarmColumns, alarmSearchSchemas } from './config/detail.config'; |
| 32 | import { doBatchAckAlarm, getDeviceAlarm } from '/@/api/device/deviceManager'; | 32 | import { doBatchAckAlarm, getDeviceAlarm } from '/@/api/device/deviceManager'; |
| @@ -55,34 +55,36 @@ | @@ -55,34 +55,36 @@ | ||
| 55 | }, | 55 | }, |
| 56 | 56 | ||
| 57 | setup() { | 57 | setup() { |
| 58 | - const [registerTable, { reload, getSelectRows, clearSelectedRowKeys }] = useTable({ | ||
| 59 | - title: '告警记录列表', | ||
| 60 | - api: getDeviceAlarm, | ||
| 61 | - columns: alarmColumns, | ||
| 62 | - useSearchForm: true, | ||
| 63 | - formConfig: { | ||
| 64 | - labelWidth: 120, | ||
| 65 | - schemas: alarmSearchSchemas, | ||
| 66 | - fieldMapToTime: [['alarmTime', ['startTime', 'endTime'], 'x']], | ||
| 67 | - }, | ||
| 68 | - bordered: true, | ||
| 69 | - showIndexColumn: false, | ||
| 70 | - showTableSetting: true, | ||
| 71 | - rowSelection: { | ||
| 72 | - type: 'checkbox', | ||
| 73 | - getCheckboxProps: (record: AlarmLogItem) => { | ||
| 74 | - return { | ||
| 75 | - disabled: record.status === AlarmStatus.CLEARED_ACK, | ||
| 76 | - }; | 58 | + const [registerTable, { reload, getSelectRows, clearSelectedRowKeys, getRowSelection }] = |
| 59 | + useTable({ | ||
| 60 | + title: '告警记录列表', | ||
| 61 | + api: getDeviceAlarm, | ||
| 62 | + columns: alarmColumns, | ||
| 63 | + useSearchForm: true, | ||
| 64 | + formConfig: { | ||
| 65 | + labelWidth: 120, | ||
| 66 | + schemas: alarmSearchSchemas, | ||
| 67 | + fieldMapToTime: [['alarmTime', ['startTime', 'endTime'], 'x']], | ||
| 77 | }, | 68 | }, |
| 78 | - }, | ||
| 79 | - actionColumn: { | ||
| 80 | - width: 200, | ||
| 81 | - title: '操作', | ||
| 82 | - slots: { customRender: 'action' }, | ||
| 83 | - fixed: 'right', | ||
| 84 | - }, | ||
| 85 | - }); | 69 | + bordered: true, |
| 70 | + showIndexColumn: false, | ||
| 71 | + showTableSetting: true, | ||
| 72 | + clickToRowSelect: false, | ||
| 73 | + rowSelection: { | ||
| 74 | + type: 'checkbox', | ||
| 75 | + getCheckboxProps: (record: AlarmLogItem) => { | ||
| 76 | + return { | ||
| 77 | + disabled: record.status === AlarmStatus.CLEARED_ACK, | ||
| 78 | + }; | ||
| 79 | + }, | ||
| 80 | + }, | ||
| 81 | + actionColumn: { | ||
| 82 | + width: 200, | ||
| 83 | + title: '操作', | ||
| 84 | + slots: { customRender: 'action' }, | ||
| 85 | + fixed: 'right', | ||
| 86 | + }, | ||
| 87 | + }); | ||
| 86 | const [registerDetailDrawer, { openDrawer }] = useDrawer(); | 88 | const [registerDetailDrawer, { openDrawer }] = useDrawer(); |
| 87 | const handleDetail = (record: Recordable) => { | 89 | const handleDetail = (record: Recordable) => { |
| 88 | openDrawer(true, record); | 90 | openDrawer(true, record); |
| @@ -113,7 +115,9 @@ | @@ -113,7 +115,9 @@ | ||
| 113 | const value = { | 115 | const value = { |
| 114 | ['触发属性']: findName, | 116 | ['触发属性']: findName, |
| 115 | ['触发条件']: `${findLogin}${curr.value.logicValue}`, | 117 | ['触发条件']: `${findLogin}${curr.value.logicValue}`, |
| 116 | - ['触发值']: `${curr.value.realValue}${findAttribute.detail?.dataType?.specs?.unit?.key}`, | 118 | + ['触发值']: `${curr.value.realValue}${ |
| 119 | + findAttribute.detail?.dataType?.specs?.unit?.key ?? '' | ||
| 120 | + }`, | ||
| 117 | }; | 121 | }; |
| 118 | const data = { | 122 | const data = { |
| 119 | [item.name]: value, | 123 | [item.name]: value, |
| @@ -151,23 +155,28 @@ | @@ -151,23 +155,28 @@ | ||
| 151 | return temp; | 155 | return temp; |
| 152 | }; | 156 | }; |
| 153 | const handleDataFormat = (deviceDetail: any, attributes: any) => { | 157 | const handleDataFormat = (deviceDetail: any, attributes: any) => { |
| 154 | - const { name, tbDeviceId } = deviceDetail; | 158 | + const { name, tbDeviceId, alias } = deviceDetail; |
| 155 | const attribute = attributes.map((item) => ({ | 159 | const attribute = attributes.map((item) => ({ |
| 156 | identifier: item.identifier, | 160 | identifier: item.identifier, |
| 157 | name: item.name, | 161 | name: item.name, |
| 158 | detail: item.detail, | 162 | detail: item.detail, |
| 159 | })); | 163 | })); |
| 160 | return { | 164 | return { |
| 161 | - name, | 165 | + name: alias || name, |
| 162 | tbDeviceId, | 166 | tbDeviceId, |
| 163 | attribute, | 167 | attribute, |
| 164 | }; | 168 | }; |
| 165 | }; | 169 | }; |
| 166 | 170 | ||
| 171 | + const getCanBatchAck = computed(() => { | ||
| 172 | + const rowSelection = getRowSelection(); | ||
| 173 | + return !rowSelection.selectedRowKeys?.length; | ||
| 174 | + }); | ||
| 175 | + | ||
| 167 | const { createMessage } = useMessage(); | 176 | const { createMessage } = useMessage(); |
| 168 | const handleBatchAck = async () => { | 177 | const handleBatchAck = async () => { |
| 169 | const ids = getSelectRows<AlarmLogItem>().map((item) => item.id); | 178 | const ids = getSelectRows<AlarmLogItem>().map((item) => item.id); |
| 170 | - | 179 | + if (!ids.length) return; |
| 171 | await doBatchAckAlarm(ids); | 180 | await doBatchAckAlarm(ids); |
| 172 | createMessage.success('操作成功'); | 181 | createMessage.success('操作成功'); |
| 173 | clearSelectedRowKeys(); | 182 | clearSelectedRowKeys(); |
| @@ -181,6 +190,7 @@ | @@ -181,6 +190,7 @@ | ||
| 181 | handleSuccess, | 190 | handleSuccess, |
| 182 | handleViewAlarmDetails, | 191 | handleViewAlarmDetails, |
| 183 | handleBatchAck, | 192 | handleBatchAck, |
| 193 | + getCanBatchAck, | ||
| 184 | }; | 194 | }; |
| 185 | }, | 195 | }, |
| 186 | }); | 196 | }); |
| @@ -11,6 +11,7 @@ | @@ -11,6 +11,7 @@ | ||
| 11 | <template #iconSelect> | 11 | <template #iconSelect> |
| 12 | <Upload | 12 | <Upload |
| 13 | name="avatar" | 13 | name="avatar" |
| 14 | + accept=".png,.jpg,.jpeg,.gif" | ||
| 14 | list-type="picture-card" | 15 | list-type="picture-card" |
| 15 | class="avatar-uploader" | 16 | class="avatar-uploader" |
| 16 | :show-upload-list="false" | 17 | :show-upload-list="false" |
| @@ -93,6 +93,7 @@ export const formSchema: FormSchema[] = [ | @@ -93,6 +93,7 @@ export const formSchema: FormSchema[] = [ | ||
| 93 | return { | 93 | return { |
| 94 | listType: 'picture-card', | 94 | listType: 'picture-card', |
| 95 | maxFileLimit: 1, | 95 | maxFileLimit: 1, |
| 96 | + accept: '.png,.jpg,.jpeg,.gif', | ||
| 96 | api: async (file: File) => { | 97 | api: async (file: File) => { |
| 97 | try { | 98 | try { |
| 98 | const formData = new FormData(); | 99 | const formData = new FormData(); |
| @@ -11,7 +11,7 @@ | @@ -11,7 +11,7 @@ | ||
| 11 | import { ConfigurationCenterItemsModal } from '/@/api/configuration/center/model/configurationCenterModal'; | 11 | import { ConfigurationCenterItemsModal } from '/@/api/configuration/center/model/configurationCenterModal'; |
| 12 | import { PageWrapper } from '/@/components/Page'; | 12 | import { PageWrapper } from '/@/components/Page'; |
| 13 | import { BasicForm, useForm } from '/@/components/Form'; | 13 | import { BasicForm, useForm } from '/@/components/Form'; |
| 14 | - import { ConfigurationPermission, searchFormSchema } from './center.data'; | 14 | + import { ConfigurationPermission, Platform, searchFormSchema } from './center.data'; |
| 15 | import { useMessage } from '/@/hooks/web/useMessage'; | 15 | import { useMessage } from '/@/hooks/web/useMessage'; |
| 16 | import { Authority } from '/@/components/Authority'; | 16 | import { Authority } from '/@/components/Authority'; |
| 17 | import { isDevMode } from '/@/utils/env'; | 17 | import { isDevMode } from '/@/utils/env'; |
| @@ -30,6 +30,7 @@ | @@ -30,6 +30,7 @@ | ||
| 30 | import { ViewType } from '../../visual/board/config/panelDetail'; | 30 | import { ViewType } from '../../visual/board/config/panelDetail'; |
| 31 | import { useRole } from '/@/hooks/business/useRole'; | 31 | import { useRole } from '/@/hooks/business/useRole'; |
| 32 | import { useClipboard } from '@vueuse/core'; | 32 | import { useClipboard } from '@vueuse/core'; |
| 33 | + import { Icon } from '/@/components/Icon'; | ||
| 33 | 34 | ||
| 34 | const listColumn = ref(5); | 35 | const listColumn = ref(5); |
| 35 | 36 | ||
| @@ -187,7 +188,7 @@ | @@ -187,7 +188,7 @@ | ||
| 187 | 188 | ||
| 188 | onMounted(() => { | 189 | onMounted(() => { |
| 189 | const clientHeight = document.documentElement.clientHeight; | 190 | const clientHeight = document.documentElement.clientHeight; |
| 190 | - const rect = getBoundingClientRect(unref(listEl)!.$el!) as DOMRect; | 191 | + const rect = getBoundingClientRect(unref(listEl)!.$el! as HTMLElement) as DOMRect; |
| 191 | // margin-top 24 height 24 | 192 | // margin-top 24 height 24 |
| 192 | const paginationHeight = 24 + 24 + 8; | 193 | const paginationHeight = 24 + 24 + 8; |
| 193 | // list pading top 8 maring-top 8 extra slot 56 | 194 | // list pading top 8 maring-top 8 extra slot 56 |
| @@ -322,7 +323,16 @@ | @@ -322,7 +323,16 @@ | ||
| 322 | </template> | 323 | </template> |
| 323 | <template #description> | 324 | <template #description> |
| 324 | <div class="truncate h-11"> | 325 | <div class="truncate h-11"> |
| 325 | - <div class="truncate">{{ item.organizationDTO.name }}</div> | 326 | + <div class="truncate flex justify-between items-center"> |
| 327 | + <div>{{ item.organizationDTO.name }}</div> | ||
| 328 | + <Icon | ||
| 329 | + :icon=" | ||
| 330 | + item.platform === Platform.PC | ||
| 331 | + ? 'ri:computer-line' | ||
| 332 | + : 'clarity:mobile-phone-solid' | ||
| 333 | + " | ||
| 334 | + /> | ||
| 335 | + </div> | ||
| 326 | <div class="truncate">{{ item.remark || '' }} </div> | 336 | <div class="truncate">{{ item.remark || '' }} </div> |
| 327 | </div> | 337 | </div> |
| 328 | </template> | 338 | </template> |
| @@ -59,6 +59,7 @@ export const formSchema: FormSchema[] = [ | @@ -59,6 +59,7 @@ export const formSchema: FormSchema[] = [ | ||
| 59 | return { | 59 | return { |
| 60 | listType: 'picture-card', | 60 | listType: 'picture-card', |
| 61 | maxFileLimit: 1, | 61 | maxFileLimit: 1, |
| 62 | + accept: '.png,.jpg,.jpeg,.gif', | ||
| 62 | api: async (file: File) => { | 63 | api: async (file: File) => { |
| 63 | try { | 64 | try { |
| 64 | const formData = new FormData(); | 65 | const formData = new FormData(); |
| @@ -175,6 +175,10 @@ export const alarmColumns: BasicColumn[] = [ | @@ -175,6 +175,10 @@ export const alarmColumns: BasicColumn[] = [ | ||
| 175 | title: '告警设备', | 175 | title: '告警设备', |
| 176 | dataIndex: 'deviceName', | 176 | dataIndex: 'deviceName', |
| 177 | width: 120, | 177 | width: 120, |
| 178 | + customRender: ({ record }) => { | ||
| 179 | + const { deviceAlias, deviceName } = record || {}; | ||
| 180 | + return deviceAlias || deviceName; | ||
| 181 | + }, | ||
| 178 | }, | 182 | }, |
| 179 | { | 183 | { |
| 180 | title: '告警场景', | 184 | title: '告警场景', |
| @@ -52,13 +52,15 @@ | @@ -52,13 +52,15 @@ | ||
| 52 | const alarmStatus = ref(''); | 52 | const alarmStatus = ref(''); |
| 53 | const [registerModal, { closeModal }] = useModalInner(async (data) => { | 53 | const [registerModal, { closeModal }] = useModalInner(async (data) => { |
| 54 | await resetFields(); | 54 | await resetFields(); |
| 55 | + const { deviceAlias, deviceName, severity, status, id } = data || {}; | ||
| 55 | await setFieldsValue({ | 56 | await setFieldsValue({ |
| 56 | ...data, | 57 | ...data, |
| 57 | - severity: alarmLevel(data.severity), | ||
| 58 | - status: statusType(data.status), | 58 | + deviceName: deviceAlias || deviceName, |
| 59 | + severity: alarmLevel(severity), | ||
| 60 | + status: statusType(status), | ||
| 59 | }); | 61 | }); |
| 60 | - alarmId.value = data.id; | ||
| 61 | - alarmStatus.value = data.status; | 62 | + alarmId.value = id; |
| 63 | + alarmStatus.value = status; | ||
| 62 | }); | 64 | }); |
| 63 | // 处理报警 | 65 | // 处理报警 |
| 64 | const handleAlarm = async () => { | 66 | const handleAlarm = async () => { |
| @@ -25,6 +25,7 @@ | @@ -25,6 +25,7 @@ | ||
| 25 | <template #iconSelect> | 25 | <template #iconSelect> |
| 26 | <Upload | 26 | <Upload |
| 27 | name="avatar" | 27 | name="avatar" |
| 28 | + accept=".png,.jpg,.jpeg,.gif" | ||
| 28 | :show-upload-list="false" | 29 | :show-upload-list="false" |
| 29 | list-type="picture-card" | 30 | list-type="picture-card" |
| 30 | class="avatar-uploader" | 31 | class="avatar-uploader" |
| @@ -143,14 +143,14 @@ | @@ -143,14 +143,14 @@ | ||
| 143 | return temp; | 143 | return temp; |
| 144 | }; | 144 | }; |
| 145 | const handleDataFormat = (deviceDetail: any, attributes: any) => { | 145 | const handleDataFormat = (deviceDetail: any, attributes: any) => { |
| 146 | - const { name, tbDeviceId } = deviceDetail; | 146 | + const { name, alias, tbDeviceId } = deviceDetail; |
| 147 | const attribute = attributes.map((item) => ({ | 147 | const attribute = attributes.map((item) => ({ |
| 148 | identifier: item.identifier, | 148 | identifier: item.identifier, |
| 149 | name: item.name, | 149 | name: item.name, |
| 150 | detail: item.detail, | 150 | detail: item.detail, |
| 151 | })); | 151 | })); |
| 152 | return { | 152 | return { |
| 153 | - name, | 153 | + name: alias || name, |
| 154 | tbDeviceId, | 154 | tbDeviceId, |
| 155 | attribute, | 155 | attribute, |
| 156 | }; | 156 | }; |
| @@ -5,6 +5,7 @@ | @@ -5,6 +5,7 @@ | ||
| 5 | <Upload | 5 | <Upload |
| 6 | style="width: 20vw" | 6 | style="width: 20vw" |
| 7 | name="avatar" | 7 | name="avatar" |
| 8 | + accept=".png,.jpg,.jpeg,.gif" | ||
| 8 | list-type="picture-card" | 9 | list-type="picture-card" |
| 9 | class="avatar-uploader" | 10 | class="avatar-uploader" |
| 10 | :show-upload-list="false" | 11 | :show-upload-list="false" |
| @@ -67,6 +67,9 @@ | @@ -67,6 +67,9 @@ | ||
| 67 | for (let i in credentials) Reflect.set(credentialsFile, i, credentials[i]); | 67 | for (let i in credentials) Reflect.set(credentialsFile, i, credentials[i]); |
| 68 | } | 68 | } |
| 69 | setFieldsValue(value); | 69 | setFieldsValue(value); |
| 70 | + setFieldsValue({ | ||
| 71 | + type: credentials.type, | ||
| 72 | + }); | ||
| 70 | }; | 73 | }; |
| 71 | 74 | ||
| 72 | const resetValue = () => resetFields(); | 75 | const resetValue = () => resetFields(); |
| @@ -268,6 +268,7 @@ | @@ -268,6 +268,7 @@ | ||
| 268 | //ft-add-2022-11-22 | 268 | //ft-add-2022-11-22 |
| 269 | const type = validate?.outTarget; | 269 | const type = validate?.outTarget; |
| 270 | if (type === 'DEVICE_OUT') { | 270 | if (type === 'DEVICE_OUT') { |
| 271 | + if (!validate.deviceType) return createMessage.error('请选择类型'); | ||
| 271 | if (!validate.deviceProfileId) return createMessage.error('请选择产品'); | 272 | if (!validate.deviceProfileId) return createMessage.error('请选择产品'); |
| 272 | if (validate.device == 'PART' && validate.deviceId == undefined) | 273 | if (validate.device == 'PART' && validate.deviceId == undefined) |
| 273 | return createMessage.error('请选择设备'); | 274 | return createMessage.error('请选择设备'); |
| @@ -11,6 +11,7 @@ | @@ -11,6 +11,7 @@ | ||
| 11 | <template #iconSelect> | 11 | <template #iconSelect> |
| 12 | <Upload | 12 | <Upload |
| 13 | name="avatar" | 13 | name="avatar" |
| 14 | + accept=".png,.jpg,.jpeg,.gif" | ||
| 14 | list-type="picture-card" | 15 | list-type="picture-card" |
| 15 | class="avatar-uploader" | 16 | class="avatar-uploader" |
| 16 | :show-upload-list="false" | 17 | :show-upload-list="false" |