|
|
@@ -1,5 +1,5 @@
|
|
|
<template>
|
|
|
- <div style="padding: 10px 0; overflow: hidden;">
|
|
|
+ <div style="padding: 10px 0; overflow: hidden">
|
|
|
<div class="board-table-container">
|
|
|
<!-- Table 区域 -->
|
|
|
<div class="table-section" v-if="tableConfig && tableData.length > 0">
|
|
|
@@ -7,50 +7,32 @@
|
|
|
<!-- 表头 -->
|
|
|
<div class="table__content_label" :class="`table__content_label_${tableConfig.type}`">
|
|
|
<!-- 单选框列占位(固定宽度) -->
|
|
|
- <div
|
|
|
- v-if="showRadio"
|
|
|
- :style="{ width: radioColumnWidth }"
|
|
|
- class="label-t table__content__list_item_radio"
|
|
|
- >
|
|
|
+ <div v-if="showRadio" :style="{ width: radioColumnWidth }" class="label-t table__content__list_item_radio">
|
|
|
<!-- 表头单选框位置留空 -->
|
|
|
</div>
|
|
|
<!-- 数据列头 -->
|
|
|
- <div
|
|
|
- class="label-t"
|
|
|
- v-for="(item, index) in tableColumns"
|
|
|
- :key="`header-${index}`"
|
|
|
- :style="{ flexBasis: dataColumnFlexBasis }"
|
|
|
- >
|
|
|
+ <div class="label-t" v-for="(item, index) in tableColumns" :key="`header-${index}`" :style="{ flexBasis: dataColumnFlexBasis }">
|
|
|
{{ item.name }}
|
|
|
</div>
|
|
|
</div>
|
|
|
<!-- 表格内容 -->
|
|
|
<div class="table__content_list" :class="`table__content_list_${tableConfig.type}`">
|
|
|
- <div
|
|
|
- class="table__content_list_row"
|
|
|
- v-for="(row, rowIndex) in tableData"
|
|
|
+ <div
|
|
|
+ class="table__content_list_row"
|
|
|
+ v-for="(row, rowIndex) in tableData"
|
|
|
:key="`row-${rowIndex}`"
|
|
|
:class="{ 'active-row': selectedRowIndex === rowIndex }"
|
|
|
@click="handleRowClick(rowIndex)"
|
|
|
>
|
|
|
<!-- 第一列:单选框(固定宽度) -->
|
|
|
- <div
|
|
|
- v-if="showRadio"
|
|
|
- :style="{ width: radioColumnWidth }"
|
|
|
- class="table__content__list_item_radio"
|
|
|
- >
|
|
|
- <input
|
|
|
- type="radio"
|
|
|
- :name="radioGroupName"
|
|
|
- :checked="selectedRowIndex === rowIndex"
|
|
|
- @click.stop="handleRowClick(rowIndex)"
|
|
|
- />
|
|
|
+ <div v-if="showRadio" :style="{ width: radioColumnWidth }" class="table__content__list_item_radio">
|
|
|
+ <input type="radio" :name="radioGroupName" :checked="selectedRowIndex === rowIndex" @click.stop="handleRowClick(rowIndex)" />
|
|
|
</div>
|
|
|
<!-- 其他列(平分剩余空间) -->
|
|
|
- <div
|
|
|
- v-for="(col, colIndex) in tableColumns"
|
|
|
- :key="`cell-${rowIndex}-${colIndex}`"
|
|
|
- :style="{ flexBasis: dataColumnFlexBasis }"
|
|
|
+ <div
|
|
|
+ v-for="(col, colIndex) in tableColumns"
|
|
|
+ :key="`cell-${rowIndex}-${colIndex}`"
|
|
|
+ :style="{ flexBasis: dataColumnFlexBasis }"
|
|
|
:class="`table__content__list_item_${tableConfig.type}`"
|
|
|
>
|
|
|
<!-- <slot :name="col.prop" :scope="row">
|
|
|
@@ -69,29 +51,29 @@
|
|
|
<div class="board-section">
|
|
|
<!-- 1. Board 标题单选框组 -->
|
|
|
<div class="board-tab-container" v-if="boardConfigList.length > 1">
|
|
|
- <div
|
|
|
+ <div
|
|
|
class="board-tab-item"
|
|
|
v-for="(cfg, index) in boardConfigList"
|
|
|
:key="`tab-${index}`"
|
|
|
- :class="{ 'active': selectedBoardIndex === index }"
|
|
|
+ :class="{ active: selectedBoardIndex === index }"
|
|
|
@click="selectedBoardIndex = index"
|
|
|
>
|
|
|
{{ cfg.title || `Board ${index + 1}` }}
|
|
|
</div>
|
|
|
</div>
|
|
|
-
|
|
|
+
|
|
|
<!-- 如果只有一个 board,直接显示标题(可选,或者隐藏标题) -->
|
|
|
<div class="board-title" v-else-if="boardConfigList.length === 1 && boardConfigList[0].title">
|
|
|
<div class="board-title-text">{{ boardConfigList[0].title }}</div>
|
|
|
</div>
|
|
|
|
|
|
<!-- 2. 单个 Board 内容展示区 -->
|
|
|
- <div class="board-list" v-if="currentBoardConfig">
|
|
|
+ <div class="board-list" :class="{ 'overflow-y-auto': boardOverflow }" v-if="currentBoardConfig">
|
|
|
<MiniBoard
|
|
|
v-for="(item, itemIndex) in getCurrentBoardItems()"
|
|
|
:key="`board-item-${itemIndex}`"
|
|
|
:label="item.label"
|
|
|
- :value="item.value"
|
|
|
+ :value="item.value as string"
|
|
|
:layout="currentBoardConfig.layout || 'val-top'"
|
|
|
:type="currentBoardConfig.type || 'D'"
|
|
|
/>
|
|
|
@@ -99,7 +81,6 @@
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
-
|
|
|
</template>
|
|
|
|
|
|
<script lang="ts" setup>
|
|
|
@@ -141,6 +122,7 @@
|
|
|
showRadio?: boolean;
|
|
|
defaultValue?: string;
|
|
|
radioWidth?: number; // 单选框列宽度
|
|
|
+ boardOverflow?: boolean;
|
|
|
}>(),
|
|
|
{
|
|
|
showRadio: false,
|
|
|
@@ -157,7 +139,7 @@
|
|
|
const selectedRowIndex = ref<number>(0);
|
|
|
// 当前选中的 Board 索引
|
|
|
const selectedBoardIndex = ref<number>(0);
|
|
|
-
|
|
|
+
|
|
|
const uniqueId = ref(`bt-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`);
|
|
|
const radioGroupName = computed(() => `board-table-radio-${uniqueId.value}`);
|
|
|
|
|
|
@@ -212,19 +194,19 @@
|
|
|
if (!rowData) return;
|
|
|
|
|
|
// 重新计算所有 board 的数据,确保切换时数据是最新的
|
|
|
- boardItemsList.value = boardConfigList.value.map(boardCfg => {
|
|
|
+ boardItemsList.value = boardConfigList.value.map((boardCfg) => {
|
|
|
if (!boardCfg?.items) return [];
|
|
|
|
|
|
- return boardCfg.items.map(item => {
|
|
|
+ return boardCfg.items.map((item) => {
|
|
|
const valueStr = String(item.value || '');
|
|
|
// 匹配 ${...} 格式
|
|
|
const match = valueStr.match(/\$\{(.+?)\}/);
|
|
|
-
|
|
|
+
|
|
|
let newValue = item.value;
|
|
|
if (match && match[1]) {
|
|
|
const fieldKey = match[1]; // 例如: "fireAlarm.alarmName"
|
|
|
const resolvedValue = get(rowData, fieldKey);
|
|
|
-
|
|
|
+
|
|
|
// 如果为 null/undefined,则使用默认值
|
|
|
if (!isNil(resolvedValue)) {
|
|
|
newValue = resolvedValue;
|
|
|
@@ -233,7 +215,7 @@
|
|
|
newValue = props.defaultValue;
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
return {
|
|
|
label: item.label,
|
|
|
value: newValue,
|
|
|
@@ -245,10 +227,10 @@
|
|
|
// 处理行点击
|
|
|
function handleRowClick(index: number) {
|
|
|
if (selectedRowIndex.value === index) return;
|
|
|
-
|
|
|
+
|
|
|
selectedRowIndex.value = index;
|
|
|
const rowData = props.tableData[index];
|
|
|
-
|
|
|
+
|
|
|
// 自动更新 board 数据
|
|
|
updateBoardData(rowData);
|
|
|
}
|
|
|
@@ -260,44 +242,47 @@
|
|
|
}
|
|
|
});
|
|
|
|
|
|
-
|
|
|
-// 在 script setup 中添加
|
|
|
-const riskMap = {
|
|
|
- '1': '低风险',
|
|
|
- '2': '一般风险',
|
|
|
- '3': '较高风险',
|
|
|
- '4': '高风险',
|
|
|
-};
|
|
|
-const riskColorMap = {
|
|
|
- '1': StatusColorEnum.blue, // 蓝
|
|
|
- '2': StatusColorEnum.yellow, // 黄
|
|
|
- '3': StatusColorEnum.gold, // 金
|
|
|
- '4': StatusColorEnum.red, // 红
|
|
|
-};
|
|
|
-
|
|
|
-// 修改 getter 或创建一个专门的渲染函数
|
|
|
-const renderCellComponent = (row: any, col: TableColumn) => {
|
|
|
- return {
|
|
|
- render() {
|
|
|
- const value = getter(row, col.prop);
|
|
|
- if (col.prop === 'alarmLevel') {
|
|
|
- const level = String(value);
|
|
|
- const text = riskMap[level] || value;
|
|
|
- const color = riskColorMap[level] || StatusColorEnum.blue;
|
|
|
- return h('span', { style: { color } }, text);
|
|
|
- }
|
|
|
- return h('span', {}, value);
|
|
|
- }
|
|
|
+ // 在 script setup 中添加
|
|
|
+ const riskMap = {
|
|
|
+ '1': '低风险',
|
|
|
+ '2': '一般风险',
|
|
|
+ '3': '较高风险',
|
|
|
+ '4': '高风险',
|
|
|
+ };
|
|
|
+ const riskColorMap = {
|
|
|
+ '1': StatusColorEnum.blue, // 蓝
|
|
|
+ '2': StatusColorEnum.yellow, // 黄
|
|
|
+ '3': StatusColorEnum.gold, // 金
|
|
|
+ '4': StatusColorEnum.red, // 红
|
|
|
+ };
|
|
|
+
|
|
|
+ // 修改 getter 或创建一个专门的渲染函数
|
|
|
+ const renderCellComponent = (row: any, col: TableColumn) => {
|
|
|
+ return {
|
|
|
+ render() {
|
|
|
+ const value = getter(row, col.prop);
|
|
|
+ if (col.prop === 'alarmLevel') {
|
|
|
+ const level = String(value);
|
|
|
+ const text = riskMap[level] || value;
|
|
|
+ const color = riskColorMap[level] || StatusColorEnum.blue;
|
|
|
+ return h('span', { style: { color } }, text);
|
|
|
+ }
|
|
|
+ return h('span', {}, value);
|
|
|
+ },
|
|
|
+ };
|
|
|
};
|
|
|
-};
|
|
|
|
|
|
// 监听 tableData 变化,重置选中状态
|
|
|
- watch(() => props.tableData, (newData) => {
|
|
|
- if (newData && newData.length > 0) {
|
|
|
- selectedRowIndex.value = 0;
|
|
|
- updateBoardData(newData[0]);
|
|
|
- }
|
|
|
- }, { immediate: true });
|
|
|
+ watch(
|
|
|
+ () => props.tableData,
|
|
|
+ (newData) => {
|
|
|
+ if (newData && newData.length > 0) {
|
|
|
+ selectedRowIndex.value = 0;
|
|
|
+ updateBoardData(newData[0]);
|
|
|
+ }
|
|
|
+ },
|
|
|
+ { immediate: true }
|
|
|
+ );
|
|
|
|
|
|
// 初始化时加载第一行数据
|
|
|
onMounted(() => {
|
|
|
@@ -309,7 +294,7 @@ const renderCellComponent = (row: any, col: TableColumn) => {
|
|
|
|
|
|
<style lang="less" scoped>
|
|
|
@import '/@/design/theme.less';
|
|
|
-
|
|
|
+
|
|
|
@font-face {
|
|
|
font-family: 'douyuFont';
|
|
|
src: url('/@/assets/font/douyuFont.otf');
|
|
|
@@ -321,7 +306,7 @@ const renderCellComponent = (row: any, col: TableColumn) => {
|
|
|
display: flex;
|
|
|
flex-direction: column;
|
|
|
box-sizing: border-box;
|
|
|
- overflow:hidden;
|
|
|
+ overflow: hidden;
|
|
|
border: 2px dashed #0070ff;
|
|
|
border-radius: 10px;
|
|
|
padding: 10px 5px;
|
|
|
@@ -348,7 +333,7 @@ const renderCellComponent = (row: any, col: TableColumn) => {
|
|
|
border: none;
|
|
|
background-color: transparent;
|
|
|
transition: all 0.2s ease;
|
|
|
-
|
|
|
+
|
|
|
&:hover {
|
|
|
background-color: #d0edff;
|
|
|
}
|
|
|
@@ -382,9 +367,9 @@ const renderCellComponent = (row: any, col: TableColumn) => {
|
|
|
flex-wrap: wrap;
|
|
|
justify-content: space-around;
|
|
|
flex: 1;
|
|
|
- overflow-y: auto;
|
|
|
+ // overflow-y: hidden;
|
|
|
}
|
|
|
- :deep(.mini-board){
|
|
|
+ :deep(.mini-board) {
|
|
|
margin-bottom: 10px;
|
|
|
}
|
|
|
}
|
|
|
@@ -549,7 +534,7 @@ const renderCellComponent = (row: any, col: TableColumn) => {
|
|
|
font-size: 15px;
|
|
|
color: #000000;
|
|
|
}
|
|
|
- .table__content_list_row{
|
|
|
+ .table__content_list_row {
|
|
|
color: #000000 !important;
|
|
|
}
|
|
|
.table__content_list_row .table__content__list_item_C:nth-child(1) {
|
|
|
@@ -572,7 +557,7 @@ const renderCellComponent = (row: any, col: TableColumn) => {
|
|
|
color: #000000;
|
|
|
text-align: center;
|
|
|
}
|
|
|
- .table__content_list_row{
|
|
|
+ .table__content_list_row {
|
|
|
color: #000000 !important;
|
|
|
}
|
|
|
|
|
|
@@ -596,4 +581,4 @@ const renderCellComponent = (row: any, col: TableColumn) => {
|
|
|
height: 14px;
|
|
|
}
|
|
|
}
|
|
|
-</style>
|
|
|
+</style>
|