| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305 |
- <template>
- <el-dialog
- v-model="visible"
- :title="
- (deviceTypeOptions?.find((v: DeviceTypeVO) => v.deviceType == device?.deviceType)
- ?.deviceTypeName || '-') + ' - 详细信息'
- "
- width="700px"
- append-to-body
- class="large-screen-dialog"
- >
- <div class="device-detail-content" v-if="device">
- <div class="device-detail-header">
- <div class="device-icon-xlarge">
- <Icon :icon="getDeviceInfo(device).icon" />
- </div>
- <div class="device-detail-info">
- <h3>
- {{
- deviceTypeOptions?.find((v: DeviceTypeVO) => v.deviceType == device?.deviceType)
- ?.deviceTypeName || '-'
- }}
- </h3>
- <p>设备类型: {{ device.deviceType }}</p>
- <p>安装位置: {{ device.installPosition }}</p>
- <p>
- 设备状态:
- <el-tag :type="textStatusMap[device.status]">
- {{ device.status }}
- </el-tag>
- </p>
- </div>
- </div>
- <div class="device-data-detail">
- <h4>设备数据</h4>
- <div class="data-grid" v-if="device.indicatorInfo && device.indicatorInfo?.length">
- <div class="data-item" v-for="(item, value) in device.indicatorInfo" :key="value">
- <span class="data-label">{{ item.name }}</span>
- <span class="data-value">{{ item.value }}</span>
- </div>
- </div>
- <el-empty v-else description="暂无设备数据" :image-size="40" />
- </div>
- <div class="device-history">
- <h4>历史记录</h4>
- <div class="history-list" v-if="device.historyInfo && device.historyInfo?.length">
- <div class="history-item" v-for="(record, index) in device.historyInfo" :key="index">
- <span class="history-time">{{
- record.happensAt ? formatToDateTime(record.happensAt) : ''
- }}</span>
- <span class="history-event">{{ record.content }}</span>
- </div>
- </div>
- <el-empty v-else description="暂无历史记录" :image-size="40" />
- </div>
- </div>
- <template #footer>
- <el-button @click="closeDialog" size="large">关闭</el-button>
- </template>
- </el-dialog>
- </template>
- <script lang="ts" setup>
- import { computed } from 'vue'
- import { formatToDateTime } from '@/utils/dateUtil'
- interface CommonVo {
- name: string
- value: string
- }
- interface HistoryInfoVo {
- happensAt: string
- content: string
- }
- interface Device {
- deviceType: string
- installPosition: string
- status: string
- indicatorInfo: CommonVo[]
- historyInfo: HistoryInfoVo[]
- }
- interface DeviceTypeVO {
- deviceType: string
- deviceTypeName: string
- displayOrder: number
- }
- interface Props {
- visible: boolean
- device: Device | null
- deviceTypeOptions?: DeviceTypeVO[]
- }
- const props = defineProps<Props>()
- const emit = defineEmits<{
- 'update:visible': [value: boolean]
- }>()
- const textStatusMap = {
- 在线: 'success',
- 离线: 'danger',
- 警告: 'warning'
- }
- const deviceTypeMap: Record<
- string,
- {
- name: string
- icon: string
- color: string
- }
- > = {
- ['health_band']: { name: '健康监测手环', icon: 'mdi:watch-variant', color: '#ff6b6b' },
- ['smart_mattress']: { name: '智能床垫', icon: 'mdi:bed-queen', color: '#4ecdc4' },
- ['security_camera']: { name: '安防摄像头', icon: 'mdi:cctv', color: '#45aaf2' },
- ['blood_pressure_monitor']: {
- name: '血压监测仪',
- icon: 'mdi:heart-pulse',
- color: '#a55eea'
- },
- ['emergency_button']: {
- name: '紧急呼叫按钮',
- icon: 'mdi:alarm-light',
- color: '#fd9644'
- },
- ['smoke_sensor']: { name: '烟雾传感器', icon: 'mdi:smoke-detector', color: '#26de81' },
- ['water_sensor']: { name: '水浸传感器', icon: 'mdi:water-alert', color: '#26de81' },
- ['infrared_sensor']: {
- name: '人体红外传感器',
- icon: 'mdi:motion-sensor',
- color: '#26de81'
- },
- ['door_sensor']: { name: '门磁传感器', icon: 'mdi:door-closed', color: '#26de81' },
- ['gas_sensor']: { name: '燃气传感器', icon: 'mdi:gas-cylinder', color: '#26de81' },
- ['temperature_sensor']: {
- name: '温度传感器',
- icon: 'mdi:thermometer',
- color: '#ff6b6b'
- },
- ['humidity_sensor']: {
- name: '湿度传感器',
- icon: 'mdi:water-percent',
- color: '#48dbfb'
- },
- ['fall_detection_sensor']: {
- name: '跌倒检测传感器',
- icon: 'mdi:human-falling',
- color: '#ff9ff3'
- },
- ['pill_box']: {
- name: '智能药盒',
- icon: 'mdi:pill',
- color: '#1dd1a1'
- },
- ['oxygen_saturation_monitor']: {
- name: '血氧监测仪',
- icon: 'mdi:heart-pulse',
- color: '#a55eea'
- },
- ['glucose_meter']: {
- name: '血糖仪',
- icon: 'mdi:needle',
- color: '#fed330'
- },
- ['sleep_radar']: {
- name: '睡眠雷达',
- icon: 'mdi:radar',
- color: '#26de81'
- },
- ['alarm_controller']: {
- name: '报警主机',
- icon: 'mdi:shield-home',
- color: '#fd9644'
- }
- }
- const visible = computed({
- get: () => props.visible,
- set: (value) => emit('update:visible', value)
- })
- const getDeviceInfo = (device: Device) => {
- return (
- deviceTypeMap[device.deviceType] || {
- name: '未知设备',
- icon: 'mdi:help-circle-outline',
- color: '#a5b1c2'
- }
- )
- }
- const closeDialog = () => {
- visible.value = false
- }
- </script>
- <style lang="scss" scoped>
- $text-light: #fff;
- $text-gray: #8a8f98;
- $primary-color: #1a73e8;
- .device-detail-content {
- .device-detail-header {
- display: flex;
- padding-bottom: 20px;
- margin-bottom: 25px;
- border-bottom: 1px solid rgb(255 255 255 / 10%);
- align-items: center;
- gap: 20px;
- }
- .device-icon-xlarge {
- display: flex;
- width: 80px;
- height: 80px;
- background: rgb(26 115 232 / 20%);
- border-radius: 16px;
- align-items: center;
- justify-content: center;
- flex-shrink: 0;
- :deep(svg),
- :deep(span) {
- width: 32px !important;
- height: 32px !important;
- }
- }
- .device-detail-info {
- flex: 1;
- h3 {
- margin-bottom: 10px;
- font-size: 24px;
- }
- p {
- margin-bottom: 5px;
- color: $text-gray;
- }
- }
- .device-data-detail {
- margin-bottom: 25px;
- h4 {
- margin-bottom: 15px;
- font-size: 18px;
- }
- .data-grid {
- display: grid;
- grid-template-columns: repeat(2, 1fr);
- gap: 15px;
- }
- .data-item {
- display: flex;
- justify-content: space-between;
- padding: 12px 15px;
- background: rgb(255 255 255 / 5%);
- border-radius: 8px;
- .data-label {
- color: $text-gray;
- }
- .data-value {
- font-weight: 600;
- }
- }
- }
- .device-history {
- h4 {
- margin-bottom: 15px;
- font-size: 18px;
- }
- .history-list {
- max-height: 200px;
- overflow-y: auto;
- }
- .history-item {
- display: flex;
- justify-content: space-between;
- padding: 10px 15px;
- border-bottom: 1px solid rgb(255 255 255 / 5%);
- .history-time {
- font-size: 14px;
- color: $text-gray;
- }
- }
- }
- }
- </style>
|