Commit 0109c9c52e6535cca35112013e83da468790635c
Merge branch 'perf/device-list' into 'main_dev'
perf: 设备列表新增告警状态提示 && 变更收藏样式 See merge request yunteng/thingskit-front!1160
Showing
6 changed files
with
85 additions
and
17 deletions
| ... | ... | @@ -4,12 +4,12 @@ |
| 4 | 4 | <Tooltip v-if="action.tooltip" v-bind="getTooltip(action.tooltip)"> |
| 5 | 5 | <PopConfirmButton v-bind="action"> |
| 6 | 6 | <Icon :icon="action.icon" :class="{ 'mr-1': !!action.label }" v-if="action.icon" /> |
| 7 | - <template v-if="action.label">{{ action.label }}</template> | |
| 7 | + <template v-if="action.label"><Label :label="action.label" /></template> | |
| 8 | 8 | </PopConfirmButton> |
| 9 | 9 | </Tooltip> |
| 10 | 10 | <PopConfirmButton v-else v-bind="action"> |
| 11 | 11 | <Icon :icon="action.icon" :class="{ 'mr-1': !!action.label }" v-if="action.icon" /> |
| 12 | - <template v-if="action.label">{{ action.label }}</template> | |
| 12 | + <template v-if="action.label"><Label :label="action.label" /> </template> | |
| 13 | 13 | </PopConfirmButton> |
| 14 | 14 | <Divider |
| 15 | 15 | type="vertical" |
| ... | ... | @@ -36,7 +36,7 @@ |
| 36 | 36 | </div> |
| 37 | 37 | </template> |
| 38 | 38 | <script lang="ts"> |
| 39 | - import { defineComponent, PropType, computed, toRaw, unref } from 'vue'; | |
| 39 | + import { defineComponent, PropType, computed, toRaw, unref, VNode } from 'vue'; | |
| 40 | 40 | // import { MoreOutlined } from '@ant-design/icons-vue'; |
| 41 | 41 | import { Divider, Tooltip, TooltipProps } from 'ant-design-vue'; |
| 42 | 42 | import Icon from '/@/components/Icon/index'; |
| ... | ... | @@ -52,7 +52,14 @@ |
| 52 | 52 | |
| 53 | 53 | export default defineComponent({ |
| 54 | 54 | name: 'TableAction', |
| 55 | - components: { Icon, PopConfirmButton, Divider, Dropdown, Tooltip }, | |
| 55 | + components: { | |
| 56 | + Icon, | |
| 57 | + PopConfirmButton, | |
| 58 | + Divider, | |
| 59 | + Dropdown, | |
| 60 | + Tooltip, | |
| 61 | + Label: (props: { label: VNode | string }) => props.label, | |
| 62 | + }, | |
| 56 | 63 | props: { |
| 57 | 64 | actions: { |
| 58 | 65 | type: Array as PropType<ActionItem[]>, | ... | ... |
| 1 | 1 | import { ButtonProps } from 'ant-design-vue/es/button/buttonTypes'; |
| 2 | 2 | import { TooltipProps } from 'ant-design-vue/es/tooltip/Tooltip'; |
| 3 | 3 | import { RoleEnum } from '/@/enums/roleEnum'; |
| 4 | +import { VNode } from 'vue'; | |
| 4 | 5 | export interface ActionItem extends ButtonProps { |
| 5 | 6 | onClick?: Fn; |
| 6 | - label?: string; | |
| 7 | + label?: string | VNode; | |
| 7 | 8 | color?: 'success' | 'error' | 'warning'; |
| 8 | 9 | icon?: string; |
| 9 | 10 | popConfirm?: PopConfirm; | ... | ... |
| ... | ... | @@ -19,7 +19,20 @@ |
| 19 | 19 | <Tabs.TabPane key="modelOfMatter" tab="物模型数据"> |
| 20 | 20 | <ModelOfMatter :deviceDetail="deviceDetail" /> |
| 21 | 21 | </Tabs.TabPane> |
| 22 | - <Tabs.TabPane key="3" tab="告警"> | |
| 22 | + <Tabs.TabPane key="3"> | |
| 23 | + <template #tab> | |
| 24 | + <Badge :offset="[2, -5]" style="color: inherit"> | |
| 25 | + <span>告警</span> | |
| 26 | + <template #count> | |
| 27 | + <div | |
| 28 | + :style="{ visibility: deviceDetail.alarmStatus ? 'visible' : 'hidden' }" | |
| 29 | + class="w-3.5 h-3.5 !flex justify-center items-center rounded-1 border-red-400 border" | |
| 30 | + > | |
| 31 | + <Icon icon="mdi:bell-warning" color="#f46161" :size="12" class="!mr-0" /> | |
| 32 | + </div> | |
| 33 | + </template> | |
| 34 | + </Badge> | |
| 35 | + </template> | |
| 23 | 36 | <AlarmLog :device-id="deviceDetail.id" class="bg-gray-100" /> |
| 24 | 37 | </Tabs.TabPane> |
| 25 | 38 | <Tabs.TabPane key="4" tab="子设备" v-if="deviceDetail?.deviceType === 'GATEWAY'"> |
| ... | ... | @@ -51,7 +64,7 @@ |
| 51 | 64 | <script lang="ts" setup> |
| 52 | 65 | import { ref, computed } from 'vue'; |
| 53 | 66 | import { BasicDrawer, useDrawerInner } from '/@/components/Drawer'; |
| 54 | - import { Tabs } from 'ant-design-vue'; | |
| 67 | + import { Tabs, Badge } from 'ant-design-vue'; | |
| 55 | 68 | import Detail from '../tabs/Detail.vue'; |
| 56 | 69 | import ChildDevice from '../tabs/ChildDevice.vue'; |
| 57 | 70 | import TBoxDetail from '../tabs/TBoxDetail.vue'; |
| ... | ... | @@ -62,6 +75,7 @@ |
| 62 | 75 | import { DeviceRecord } from '/@/api/device/model/deviceModel'; |
| 63 | 76 | import Task from '../tabs/Task.vue'; |
| 64 | 77 | import AlarmLog from '/@/views/alarm/log/index.vue'; |
| 78 | + import { Icon } from '/@/components/Icon'; | |
| 65 | 79 | |
| 66 | 80 | const emit = defineEmits(['reload', 'register', 'openTbDeviceDetail', 'openGatewayDeviceDetail']); |
| 67 | 81 | ... | ... |
| ... | ... | @@ -106,13 +106,17 @@ |
| 106 | 106 | </Tag> |
| 107 | 107 | </template> |
| 108 | 108 | <template #deviceState="{ record }"> |
| 109 | - <!-- <HeartOutlined v-if="!record.isCollect" class="mr-1" style="color: red" /> --> | |
| 110 | - <Tooltip> | |
| 111 | - <template #title> 我的收藏</template> | |
| 112 | - <HeartTwoTone v-if="record.isCollect" class="mr-1" twoToneColor="#3B82F6" /> | |
| 113 | - </Tooltip> | |
| 109 | + <div v-if="record.isCollect"> | |
| 110 | + <div class="absolute top-0 left-0 device-collect"> </div> | |
| 111 | + <Icon | |
| 112 | + icon="ph:star-fill" | |
| 113 | + class="fill-light-50 absolute top-0.5 left-0.5" | |
| 114 | + color="#fff" | |
| 115 | + :size="12" | |
| 116 | + /> | |
| 117 | + </div> | |
| 118 | + | |
| 114 | 119 | <Tag |
| 115 | - :style="{ marginLeft: !record.isCollect ? '17px' : '' }" | |
| 116 | 120 | :color=" |
| 117 | 121 | record.deviceState == DeviceState.INACTIVE |
| 118 | 122 | ? 'warning' |
| ... | ... | @@ -135,7 +139,7 @@ |
| 135 | 139 | <TableAction |
| 136 | 140 | :actions="[ |
| 137 | 141 | { |
| 138 | - label: '详情', | |
| 142 | + label: AlarmDetailActionButton({ hasAlarm: !!record.alarmStatus }), | |
| 139 | 143 | icon: 'ant-design:eye-outlined', |
| 140 | 144 | auth: DeviceListAuthEnum.DETAIL, |
| 141 | 145 | onClick: handleDetail.bind(null, record), |
| ... | ... | @@ -232,7 +236,7 @@ |
| 232 | 236 | </div> |
| 233 | 237 | </template> |
| 234 | 238 | <script lang="ts" setup> |
| 235 | - import { reactive, onMounted, ref } from 'vue'; | |
| 239 | + import { reactive, onMounted, ref, h, CSSProperties } from 'vue'; | |
| 236 | 240 | import { |
| 237 | 241 | DeviceModel, |
| 238 | 242 | DeviceRecord, |
| ... | ... | @@ -241,8 +245,7 @@ |
| 241 | 245 | } from '/@/api/device/model/deviceModel'; |
| 242 | 246 | import { BasicTable, useTable, TableAction, TableImg } from '/@/components/Table'; |
| 243 | 247 | import { columns, DeviceListAuthEnum, searchFormSchema } from './config/device.data'; |
| 244 | - import { Tag, Popover, Button, Tooltip } from 'ant-design-vue'; | |
| 245 | - import { HeartTwoTone } from '@ant-design/icons-vue'; | |
| 248 | + import { Tag, Popover, Button, Badge } from 'ant-design-vue'; | |
| 246 | 249 | import { |
| 247 | 250 | deleteDevice, |
| 248 | 251 | devicePage, |
| ... | ... | @@ -278,6 +281,7 @@ |
| 278 | 281 | } from './cpns/modal/BatchUpdateProductModal'; |
| 279 | 282 | import { DataActionModeEnum } from '/@/enums/toolEnum'; |
| 280 | 283 | import { AuthDropDown } from '/@/components/Widget'; |
| 284 | + import Icon from '/@/components/Icon'; | |
| 281 | 285 | |
| 282 | 286 | const { isCustomer } = useAuthDeviceDetail(); |
| 283 | 287 | const { createMessage } = useMessage(); |
| ... | ... | @@ -294,6 +298,32 @@ |
| 294 | 298 | const [registerImportModal, { openModal: openImportModal }] = useModal(); |
| 295 | 299 | const [registerBatchUpdateProductModal, { openModal: openBatchUpdateProductModal }] = useModal(); |
| 296 | 300 | |
| 301 | + const AlarmDetailActionButton = ({ hasAlarm }: { hasAlarm?: boolean }) => | |
| 302 | + h( | |
| 303 | + Badge, | |
| 304 | + { offset: [0, -5] }, | |
| 305 | + { | |
| 306 | + default: () => h('span', { style: { color: '#377dff' } }, '详情'), | |
| 307 | + count: () => | |
| 308 | + h( | |
| 309 | + 'div', | |
| 310 | + { | |
| 311 | + style: { | |
| 312 | + visibility: hasAlarm ? 'visible' : 'hidden', | |
| 313 | + width: '14px', | |
| 314 | + height: '14px', | |
| 315 | + display: 'flex', | |
| 316 | + justifyContent: 'center', | |
| 317 | + alignItems: 'center', | |
| 318 | + border: '1px solid #f46161', | |
| 319 | + borderRadius: '50%', | |
| 320 | + } as CSSProperties, | |
| 321 | + }, | |
| 322 | + h(Icon, { icon: 'mdi:bell-warning', color: '#f46161', size: 12 }) | |
| 323 | + ), | |
| 324 | + } | |
| 325 | + ); | |
| 326 | + | |
| 297 | 327 | const batchUpdateProductFlag = ref(true); |
| 298 | 328 | |
| 299 | 329 | const [ |
| ... | ... | @@ -336,6 +366,7 @@ |
| 336 | 366 | rowKey: 'id', |
| 337 | 367 | searchInfo: searchInfo, |
| 338 | 368 | clickToRowSelect: false, |
| 369 | + rowClassName: (record) => ((record as DeviceRecord).alarmStatus ? 'device-alarm-badge' : ''), | |
| 339 | 370 | actionColumn: { |
| 340 | 371 | width: 200, |
| 341 | 372 | title: '操作', |
| ... | ... | @@ -566,3 +597,16 @@ |
| 566 | 597 | } |
| 567 | 598 | } |
| 568 | 599 | </style> |
| 600 | + | |
| 601 | +<style lang="less"> | |
| 602 | + .device-status { | |
| 603 | + position: relative; | |
| 604 | + | |
| 605 | + .device-collect { | |
| 606 | + width: 0; | |
| 607 | + height: 0; | |
| 608 | + border-top: 30px solid #377dff; | |
| 609 | + border-right: 30px solid transparent; | |
| 610 | + } | |
| 611 | + } | |
| 612 | +</style> | ... | ... |