16 changed files with 731 additions and 221 deletions
@ -0,0 +1,181 @@
@@ -0,0 +1,181 @@
|
||||
<template> |
||||
<div class="info-card"> |
||||
<div class="hd"> |
||||
<span class="title">{{ title }}</span> |
||||
<span class="detail-btn">查看详情</span> |
||||
</div> |
||||
|
||||
<!-- 键值对信息块 --> |
||||
<div v-if="kvColumns.length" class="kv"> |
||||
<div class="kv-row" v-for="(col, idx) in kvColumns" :key="idx"> |
||||
<div class="kv-label">{{ col.label }}:</div> |
||||
<div class="kv-value">{{ safeGet(kvData, col.key) }}</div> |
||||
</div> |
||||
</div> |
||||
|
||||
<!-- 状态行(可选) --> |
||||
<!-- <div v-if="status" class="status-row"> |
||||
<span class="status-label">设备状态:</span> |
||||
<span class="status-value" :style="{ color }">{{ status }}</span> |
||||
</div> --> |
||||
|
||||
<!-- 原生表格(报警信息记录等) --> |
||||
<div v-if="tableColumns.length && tableData.length" class="table-wrap"> |
||||
<div class="table-title">{{ tableTitle }}</div> |
||||
<table class="native-table"> |
||||
<thead> |
||||
<tr> |
||||
<th v-for="(c, i) in tableColumns" :key="i" :style="{ width: c.width ? c.width + 'px' : 'auto' }">{{ c.label }}</th> |
||||
</tr> |
||||
</thead> |
||||
<tbody> |
||||
<tr v-for="(row, r) in tableData" :key="r"> |
||||
<td v-for="(c, i) in tableColumns" :key="i">{{ safeGet(row, c.key) }}</td> |
||||
</tr> |
||||
</tbody> |
||||
</table> |
||||
</div> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
export default { |
||||
name: 'InfoCard', |
||||
props: { |
||||
title: { type: String, default: '设备信息' }, |
||||
color: { type: String, default: '#29a9fd' }, |
||||
status: { type: String, default: '' }, |
||||
// 键值对:columns + data |
||||
kvColumns: { type: Array, default: () => [] }, // [{ label, key }] |
||||
kvData: { type: Object, default: () => ({}) }, |
||||
// 表格:columns + data |
||||
tableTitle: { type: String, default: '报警信息记录' }, |
||||
tableColumns: { type: Array, default: () => [] }, // [{ label, key, width? }] |
||||
tableData: { type: Array, default: () => [] } |
||||
}, |
||||
methods: { |
||||
safeGet(obj, path) { |
||||
if (!obj || !path) return '-'; |
||||
const segs = path.split('.'); |
||||
let cur = obj; |
||||
for (let i = 0; i < segs.length; i++) { |
||||
if (cur == null) return '-'; |
||||
cur = cur[segs[i]]; |
||||
} |
||||
if (cur === undefined || cur === null || cur === '') return '-'; |
||||
return cur; |
||||
} |
||||
} |
||||
}; |
||||
</script> |
||||
|
||||
<style scoped> |
||||
.info-card { |
||||
display: inline-block; |
||||
min-width: 320px; |
||||
max-width: 480px; |
||||
border-radius: 8px; |
||||
background: rgba(245, 248, 253, 0.98); |
||||
border: 1px solid rgba(255, 255, 255, 1); |
||||
box-shadow: 0 6px 18px rgba(0, 0, 0, 0.25); |
||||
padding: 16px; |
||||
} |
||||
.hd { |
||||
display: flex; |
||||
align-items: center; |
||||
justify-content: space-between; |
||||
margin-bottom: 8px; |
||||
} |
||||
.title { |
||||
height: 20px; |
||||
font-family: PingFang SC, PingFang SC; |
||||
font-weight: 500; |
||||
font-size: 14px; |
||||
color: #000000; |
||||
text-align: left; |
||||
font-style: normal; |
||||
text-transform: none; |
||||
} |
||||
.detail-btn { |
||||
font-family: PingFang SC, PingFang SC; |
||||
font-weight: 400; |
||||
font-size: 14px; |
||||
color: #0d79e8; |
||||
text-align: left; |
||||
font-style: normal; |
||||
text-transform: none; |
||||
} |
||||
.kv { |
||||
margin-top: 6px; |
||||
} |
||||
.kv-row { |
||||
display: flex; |
||||
align-items: baseline; |
||||
padding: 6px 0; |
||||
justify-content: space-between; |
||||
} |
||||
.kv-label { |
||||
font-family: PingFang SC, PingFang SC; |
||||
font-weight: 400; |
||||
font-size: 14px; |
||||
color: #999999; |
||||
text-align: left; |
||||
font-style: normal; |
||||
text-transform: none; |
||||
} |
||||
.kv-value { |
||||
font-family: PingFang SC, PingFang SC; |
||||
font-weight: 400; |
||||
font-size: 14px; |
||||
color: #333333; |
||||
text-align: left; |
||||
font-style: normal; |
||||
text-transform: none; |
||||
} |
||||
|
||||
.status-row { |
||||
margin: 8px 0 4px; |
||||
font-size: 18px; |
||||
font-weight: 600; |
||||
} |
||||
.status-label { |
||||
color: #7a869a; |
||||
font-size: 14px; |
||||
font-weight: 400; |
||||
margin-right: 8px; |
||||
} |
||||
.status-value { |
||||
font-size: 18px; |
||||
} |
||||
|
||||
.table-wrap { |
||||
margin-top: 10px; |
||||
} |
||||
.table-title { |
||||
font-size: 14px; |
||||
color: #2b2f36; |
||||
font-weight: 600; |
||||
margin-bottom: 6px; |
||||
} |
||||
.native-table { |
||||
width: 100%; |
||||
border-collapse: collapse; |
||||
background: #fff; |
||||
} |
||||
.native-table th { |
||||
text-align: left; |
||||
background: #f4f6f8; |
||||
color: #6b778c; |
||||
font-weight: 600; |
||||
font-size: 13px; |
||||
padding: 8px 10px; |
||||
} |
||||
.native-table td { |
||||
color: #2b2f36; |
||||
font-size: 13px; |
||||
padding: 10px; |
||||
} |
||||
.native-table tr + tr td { |
||||
border-top: 1px solid #edf0f3; |
||||
} |
||||
</style> |
||||
@ -0,0 +1,45 @@
@@ -0,0 +1,45 @@
|
||||
// 设备列表表格列
|
||||
export const deviceTableColumns = [ |
||||
{ label: '设备ID', key: 'name', width: 60 }, |
||||
{ label: '当前区域', key: 'area', width: 60 }, |
||||
{ label: '工作人员', key: 'team', width: 60 }, |
||||
{ label: '今日工作量', key: 'dayWork', width: 60 }, |
||||
{ label: '今日运行时长(h)', key: 'runtime' } |
||||
]; |
||||
// 设备弹窗表格列
|
||||
export const devicePopupColumns = [ |
||||
{ label: '设备编号', key: 'name' }, |
||||
{ label: '设备类型', key: 'type' }, |
||||
{ label: '设备位置', key: 'position' }, |
||||
{ label: '操作人员', key: 'team' }, |
||||
{ label: '今日安装量', key: 'dayWork' }, |
||||
{ label: '设备状态', key: 'status' }, |
||||
{ label: '运行时长(h)', key: 'runtime' } |
||||
]; |
||||
export const areaPopupColumns = [ |
||||
{ label: '工区编号', key: 'name' }, |
||||
{ label: '工区状态', key: 'name' }, |
||||
{ label: '桩条安装数量', key: 'pileCount' }, |
||||
{ label: '组件安装数量', key: 'moduleCount' } |
||||
]; |
||||
|
||||
export const alarmTableColumns = [ |
||||
{ label: '预警类别', key: 'code' }, |
||||
{ label: '设备编码', key: 'device' }, |
||||
{ label: '报警内容', key: 'desc' }, |
||||
{ label: '报警时间', key: 'time' } |
||||
]; |
||||
export const STATUS_STYLE = { |
||||
施工中: { stroke: 'rgba(19, 126, 233, 1)', fill: 'rgba(19, 126, 233, 0.4)' }, |
||||
已施工: { stroke: 'rgba(26, 213, 154, 1)', fill: 'rgba(26, 213, 154, 0.4)' }, |
||||
未施工: { stroke: 'rgba(255, 188, 72, 1)', fill: 'rgba(255, 188, 72, 0.4)' }, |
||||
故障: { stroke: 'rgba(219,77,77,1)', fill: 'rgba(219,77,77,0.4)' }, |
||||
运行中: { stroke: 'rgba(19,194,194,1)', fill: 'rgba(19,194,194,0.4)' }, |
||||
停机: { stroke: 'rgba(243,180,71,1)', fill: 'rgba(243,180,71,0.4)' } |
||||
}; |
||||
export const isDevice = (item) => { |
||||
return ['故障', '运行中', '停机'].includes(item.status); |
||||
}; |
||||
export const isArea = (item) => { |
||||
return ['施工中', '已施工', '未施工'].includes(item.status); |
||||
}; |
||||
Loading…
Reference in new issue