feat: 重构计量设备页面UI样式与交互

main
zangch@mesnac.com 1 month ago
parent 6c9238c07c
commit a8971b0597

@ -1,144 +1,183 @@
<template>
<div class="app-container">
<el-form :model="queryParams" ref="queryFormRef" size="small" :inline="true" v-show="showSearch" label-width="100px">
<!-- <el-form-item label="计量设备编号" prop="monitorCode">-->
<!-- <el-input v-model="queryParams.monitorCode" placeholder="请输入计量设备编号" clearable-->
<!-- @keyup.enter="handleQuery" />-->
<!-- </el-form-item>-->
<el-form-item label="计量设备名称" prop="monitorName">
<el-input v-model="queryParams.monitorName" placeholder="请输入计量设备名称" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="能源类型" prop="monitorType">
<el-select v-model="queryParams.monitorType" placeholder="请选择能源类型">
<el-option v-for="item in energyTypeList" :key="item.energyTypeId" :label="item.energyName" :value="item.energyTypeId"></el-option>
</el-select>
</el-form-item>
<!-- <el-form-item label="计量设备位置" prop="monitorAddr">-->
<!-- <el-input v-model="queryParams.monitorAddr" placeholder="请输入计量设备位置" clearable-->
<!-- @keyup.enter="handleQuery" />-->
<!-- </el-form-item>-->
<el-form-item label="计量设备状态" prop="monitorStatus">
<el-select v-model="queryParams.monitorStatus" placeholder="请选择计量设备状态" clearable>
<el-option v-for="dict in dict.type.monitor_status" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</el-form-item>
<el-form-item label="点位类型" prop="pointType">
<el-input v-model="queryParams.pointType" placeholder="请输入点位类型" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="安装位置" prop="locationName">
<el-input v-model="queryParams.locationName" placeholder="请输入安装位置" clearable @keyup.enter="handleQuery" />
</el-form-item>
<!-- <el-form-item label="采集设备编号" prop="collectDeviceId">-->
<!-- <el-input v-model="queryParams.collectDeviceId" placeholder="请输入采集设备编号" clearable-->
<!-- @keyup.enter="handleQuery" />-->
<!-- </el-form-item>-->
<!-- <el-form-item label="是否虚拟" prop="isAmmeter">-->
<!-- <el-select v-model="queryParams.isAmmeter" placeholder="请选择是否虚拟" clearable>-->
<!-- <el-option v-for="dict in dict.type.is_ammeter" :key="dict.value" :label="dict.label" :value="dict.value" />-->
<!-- </el-select>-->
<!-- </el-form-item>-->
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery"></el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery"></el-button>
</el-form-item>
</el-form>
<div class="app-container page-shell">
<section class="page-hero">
<div class="hero-copy">
<span class="hero-eyebrow">IOT DEVICE CENTER</span>
<h2 class="hero-title">计量设备与阈值联动看板</h2>
<p class="hero-desc">围绕点位档案安装位置与采集接入做统一可视化整理让运维在同一页面快速完成查询维护与阈值联动</p>
</div>
<div class="hero-stats">
<article v-for="item in overviewStats" :key="item.label" class="stat-card">
<span class="stat-label">{{ item.label }}</span>
<strong class="stat-value">{{ item.value }}</strong>
<span class="stat-hint">{{ item.hint }}</span>
</article>
</div>
</section>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd" v-hasPermi="['ems/base:baseMonitorInfo:add']"
>新增</el-button
>
</el-col>
<el-col :span="1.5">
<el-button type="info" plain icon="el-icon-sort" size="mini" @click="toggleExpandAll">/</el-button>
</el-col>
<right-toolbar v-model:show-search="showSearch" @query-table="getList" :columns="columns"></right-toolbar>
</el-row>
<section v-show="showSearch" class="panel-shell search-shell">
<div class="panel-head">
<div>
<h3>快速筛选</h3>
<p>按设备能源类型状态和安装位置快速定位目标点位</p>
</div>
<span class="panel-badge">档案检索</span>
</div>
<el-form :model="queryParams" ref="queryFormRef" size="small" :inline="true" label-width="100px" class="query-form">
<!-- <el-form-item label="计量设备编号" prop="monitorCode">-->
<!-- <el-input v-model="queryParams.monitorCode" placeholder="请输入计量设备编号" clearable-->
<!-- @keyup.enter="handleQuery" />-->
<!-- </el-form-item>-->
<el-form-item label="计量设备名称" prop="monitorName">
<el-input v-model="queryParams.monitorName" placeholder="请输入计量设备名称" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="能源类型" prop="monitorType">
<el-select v-model="queryParams.monitorType" placeholder="请选择能源类型">
<el-option v-for="item in energyTypeList" :key="item.energyTypeId" :label="item.energyName" :value="item.energyTypeId"></el-option>
</el-select>
</el-form-item>
<!-- <el-form-item label="计量设备位置" prop="monitorAddr">-->
<!-- <el-input v-model="queryParams.monitorAddr" placeholder="请输入计量设备位置" clearable-->
<!-- @keyup.enter="handleQuery" />-->
<!-- </el-form-item>-->
<el-form-item label="计量设备状态" prop="monitorStatus">
<el-select v-model="queryParams.monitorStatus" placeholder="请选择计量设备状态" clearable>
<el-option v-for="dict in dict.type.monitor_status" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</el-form-item>
<el-form-item label="点位类型" prop="pointType">
<el-input v-model="queryParams.pointType" placeholder="请输入点位类型" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="安装位置" prop="locationName">
<el-input v-model="queryParams.locationName" placeholder="请输入安装位置" clearable @keyup.enter="handleQuery" />
</el-form-item>
<!-- <el-form-item label="采集设备编号" prop="collectDeviceId">-->
<!-- <el-input v-model="queryParams.collectDeviceId" placeholder="请输入采集设备编号" clearable-->
<!-- @keyup.enter="handleQuery" />-->
<!-- </el-form-item>-->
<!-- <el-form-item label="是否虚拟" prop="isAmmeter">-->
<!-- <el-select v-model="queryParams.isAmmeter" placeholder="请选择是否虚拟" clearable>-->
<!-- <el-option v-for="dict in dict.type.is_ammeter" :key="dict.value" :label="dict.label" :value="dict.value" />-->
<!-- </el-select>-->
<!-- </el-form-item>-->
<el-form-item class="query-actions">
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery"></el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery"></el-button>
</el-form-item>
</el-form>
</section>
<el-table
v-if="refreshTable"
v-loading="loading"
:data="baseMonitorInfoList"
row-key="objId"
:default-expand-all="isExpandAll"
:tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
>
<el-table-column label="序号" type="index" width="60" align="center" v-if="columns[0].visible" />
<el-table-column label="计量设备编号" align="center" prop="monitorCode" v-if="columns[1].visible" />
<el-table-column label="计量设备名称" align="center" prop="monitorName" v-if="columns[2].visible" />
<!-- <el-table-column label="能源类型" align="center" prop="monitorType" v-if="columns[4].visible">
<section class="panel-shell table-shell">
<div class="panel-head">
<div>
<h3>设备结构总览</h3>
<p>树形结构展示设备层级支持直接维护阈值档案与挂接关系</p>
</div>
<span class="panel-badge warm">树形维护</span>
</div>
<el-row :gutter="10" class="toolbar-row">
<el-col :span="1.5">
<el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd" v-hasPermi="['ems/base:baseMonitorInfo:add']"
>新增</el-button
>
</el-col>
<el-col :span="1.5">
<el-button type="info" plain icon="el-icon-sort" size="mini" @click="toggleExpandAll">/</el-button>
</el-col>
<right-toolbar v-model:show-search="showSearch" @query-table="getList" :columns="columns"></right-toolbar>
</el-row>
<el-table
v-if="refreshTable"
v-loading="loading"
:data="baseMonitorInfoList"
row-key="objId"
:default-expand-all="isExpandAll"
:tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
class="data-table"
>
<el-table-column label="序号" type="index" width="60" align="center" v-if="columns[0].visible" />
<el-table-column label="计量设备编号" align="center" prop="monitorCode" v-if="columns[1].visible" />
<el-table-column label="计量设备名称" align="center" prop="monitorName" v-if="columns[2].visible" />
<!-- <el-table-column label="能源类型" align="center" prop="monitorType" v-if="columns[4].visible">
<template #default="scope">
{{ dict.type.monitor_type.find(e=>e.value == scope.row.monitorType).label}}
</template>
</el-table-column> -->
<el-table-column label="能源类型" align="center" prop="energyName" v-if="columns[3].visible"> </el-table-column>
<el-table-column label="计量设备位置" align="center" prop="monitorAddr" v-if="columns[4].visible" />
<el-table-column label="计量设备状态" align="center" prop="monitorStatus" v-if="columns[5].visible">
<template #default="scope">
<dict-tag :options="dict.type.monitor_status" :value="scope.row.monitorStatus" />
</template>
</el-table-column>
<el-table-column label="采集设备名称" align="center" prop="collectDeviceName" v-if="columns[6].visible" />
<el-table-column label="点位类型" align="center" prop="pointType" v-if="columns[19].visible" />
<el-table-column label="单位" align="center" prop="unitName" v-if="columns[20].visible" />
<el-table-column label="安装位置" align="center" prop="locationName" v-if="columns[21].visible" />
<el-table-column label="传感器类型" align="center" prop="sensorType" v-if="columns[22].visible" />
<el-table-column label="启用报警" align="center" prop="alarmEnable" v-if="columns[23].visible">
<template #default="scope">
<dict-tag :options="dict.type.is_flag" :value="scope.row.alarmEnable" />
</template>
</el-table-column>
<el-table-column label="等级" align="center" prop="grade" v-if="columns[7].visible" />
<el-table-column label="传感器仪表" align="center" prop="meterTypeId" v-if="columns[8].visible" />
<el-table-column label="修正值" align="center" prop="correctValue" v-if="columns[9].visible" />
<el-table-column label="是否虚拟" align="center" prop="isAmmeter" v-if="columns[10].visible">
<template #default="scope">
<dict-tag :options="dict.type.is_ammeter" :value="scope.row.isAmmeter" />
</template>
</el-table-column>
<el-table-column label="通断复位" align="center" prop="isKeyMonitor" v-if="columns[11].visible" />
<el-table-column label="是否断路" align="center" prop="isCircuit" v-if="columns[12].visible" />
<el-table-column label="创建人" align="center" prop="createBy" v-if="columns[13].visible" />
<el-table-column label="创建时间" align="center" prop="createTime" width="180" v-if="columns[14].visible">
<template #default="scope">
<span>{{ parseTime(scope.row.createTime, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column label="更新人" align="center" prop="updateBy" v-if="columns[15].visible" />
<el-table-column label="更新时间" align="center" prop="updateTime" width="180" v-if="columns[16].visible">
<template #default="scope">
<span>{{ parseTime(scope.row.updateTime, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column label="公摊表类型" align="center" prop="publicShareType" v-if="columns[17].visible" />
<el-table-column label="表具层级" align="center" prop="monitorHierarchy" v-if="columns[18].visible" />
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="240">
<template #default="scope">
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)" v-hasPermi="['ems/base:baseMonitorInfo:edit']"
>修改</el-button
>
<el-button size="mini" type="text" icon="el-icon-plus" @click="handleAdd(scope.row)" v-hasPermi="['ems/base:baseMonitorInfo:add']"
>新增</el-button
>
<el-button
size="mini"
type="text"
icon="el-icon-setting"
@click="handleThreshold(scope.row)"
v-hasPermi="['ems/record:recordAlarmRule:list']"
v-if="scope.row.isAmmeter !== '0'"
>阈值</el-button
>
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)" v-hasPermi="['ems/base:baseMonitorInfo:remove']"
>删除</el-button
>
</template>
</el-table-column>
</el-table>
<el-table-column label="能源类型" align="center" prop="energyName" v-if="columns[3].visible"> </el-table-column>
<el-table-column label="计量设备位置" align="center" prop="monitorAddr" v-if="columns[4].visible" />
<el-table-column label="计量设备状态" align="center" prop="monitorStatus" v-if="columns[5].visible">
<template #default="scope">
<dict-tag :options="dict.type.monitor_status" :value="scope.row.monitorStatus" />
</template>
</el-table-column>
<el-table-column label="采集设备名称" align="center" prop="collectDeviceName" v-if="columns[6].visible" />
<el-table-column label="点位类型" align="center" prop="pointType" v-if="columns[19].visible" />
<el-table-column label="单位" align="center" prop="unitName" v-if="columns[20].visible" />
<el-table-column label="安装位置" align="center" prop="locationName" v-if="columns[21].visible" />
<el-table-column label="传感器类型" align="center" prop="sensorType" v-if="columns[22].visible" />
<el-table-column label="启用报警" align="center" prop="alarmEnable" v-if="columns[23].visible">
<template #default="scope">
<dict-tag :options="dict.type.is_flag" :value="scope.row.alarmEnable" />
</template>
</el-table-column>
<el-table-column label="等级" align="center" prop="grade" v-if="columns[7].visible" />
<el-table-column label="传感器仪表" align="center" prop="meterTypeId" v-if="columns[8].visible" />
<el-table-column label="修正值" align="center" prop="correctValue" v-if="columns[9].visible" />
<el-table-column label="是否虚拟" align="center" prop="isAmmeter" v-if="columns[10].visible">
<template #default="scope">
<dict-tag :options="dict.type.is_ammeter" :value="scope.row.isAmmeter" />
</template>
</el-table-column>
<el-table-column label="通断复位" align="center" prop="isKeyMonitor" v-if="columns[11].visible" />
<el-table-column label="是否断路" align="center" prop="isCircuit" v-if="columns[12].visible" />
<el-table-column label="创建人" align="center" prop="createBy" v-if="columns[13].visible" />
<el-table-column label="创建时间" align="center" prop="createTime" width="180" v-if="columns[14].visible">
<template #default="scope">
<span>{{ parseTime(scope.row.createTime, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column label="更新人" align="center" prop="updateBy" v-if="columns[15].visible" />
<el-table-column label="更新时间" align="center" prop="updateTime" width="180" v-if="columns[16].visible">
<template #default="scope">
<span>{{ parseTime(scope.row.updateTime, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column label="公摊表类型" align="center" prop="publicShareType" v-if="columns[17].visible" />
<el-table-column label="表具层级" align="center" prop="monitorHierarchy" v-if="columns[18].visible" />
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="240">
<template #default="scope">
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)" v-hasPermi="['ems/base:baseMonitorInfo:edit']"
>修改</el-button
>
<el-button size="mini" type="text" icon="el-icon-plus" @click="handleAdd(scope.row)" v-hasPermi="['ems/base:baseMonitorInfo:add']"
>新增</el-button
>
<el-button
size="mini"
type="text"
icon="el-icon-setting"
@click="handleThreshold(scope.row)"
v-hasPermi="['ems/record:recordAlarmRule:list']"
v-if="scope.row.isAmmeter !== '0'"
>阈值</el-button
>
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)" v-hasPermi="['ems/base:baseMonitorInfo:remove']"
>删除</el-button
>
</template>
</el-table-column>
</el-table>
</section>
<!-- 添加或修改计量设备信息对话框 -->
<el-dialog :title="title" v-model="open" width="500px" append-to-body>
<el-form ref="formRef" :model="form" :rules="rules" label-width="120px">
<el-dialog :title="title" v-model="open" width="500px" append-to-body class="themed-dialog">
<div class="dialog-tip">
<span class="tip-dot"></span>
设备档案字段较多这里按业务主数据录入隐藏技术字段继续保留在提交链路中避免影响 EMS 现有流程
</div>
<el-form ref="formRef" :model="form" :rules="rules" label-width="120px" class="dialog-form">
<el-form-item label="父级编号" prop="parentId">
<EmsTreeSelect v-model="form.parentId" :options="baseMonitorInfoOptions" :normalizer="normalizer" placeholder="请选择父级编号" />
</el-form-item>
@ -253,7 +292,7 @@
</el-dialog>
<!-- 阈值管理对话框 -->
<el-dialog :title="thresholdTitle" v-model="thresholdOpen" width="1200px" append-to-body>
<el-dialog :title="thresholdTitle" v-model="thresholdOpen" width="1200px" append-to-body class="themed-dialog threshold-dialog">
<div class="threshold-container">
<!-- 设备信息展示 -->
<el-card class="device-info-card" shadow="never">
@ -339,8 +378,12 @@
</el-dialog>
<!-- 阈值规则编辑对话框 -->
<el-dialog :title="thresholdFormTitle" v-model="thresholdFormOpen" width="500px" append-to-body>
<el-form ref="thresholdFormRef" :model="thresholdForm" :rules="thresholdRules" label-width="120px">
<el-dialog :title="thresholdFormTitle" v-model="thresholdFormOpen" width="500px" append-to-body class="themed-dialog">
<div class="dialog-tip soft">
<span class="tip-dot"></span>
阈值规则与点位技术字段自动联动页面只暴露运维真正需要维护的业务项减少误配概率
</div>
<el-form ref="thresholdFormRef" :model="thresholdForm" :rules="thresholdRules" label-width="120px" class="dialog-form">
<el-form-item label="规则名称" prop="ruleName">
<el-input v-model="thresholdForm.ruleName" placeholder="请输入规则名称" />
</el-form-item>
@ -777,6 +820,50 @@ const {
title
} = toRefs(state);
const flattenDeviceTree = (nodes = []) => {
return nodes.reduce((acc, node) => {
acc.push(node);
if (node.children?.length) {
acc.push(...flattenDeviceTree(node.children));
}
return acc;
}, []);
};
const flatDeviceList = computed(() => flattenDeviceTree(baseMonitorInfoList.value));
//
const overviewStats = computed(() => {
const devices = flatDeviceList.value;
const total = devices.length;
const withCollector = devices.filter((item) => item.collectDeviceId || item.collectDeviceName).length;
const withLocation = devices.filter((item) => item.locationName).length;
const withSensor = devices.filter((item) => item.sensorType).length;
return [
{
label: '设备总量',
value: total,
hint: '当前树形档案节点'
},
{
label: '已挂接采集',
value: withCollector,
hint: '已关联采集设备'
},
{
label: '位置已维护',
value: withLocation,
hint: '安装位置信息完整'
},
{
label: '传感已标注',
value: withSensor,
hint: '便于运维识别类型'
}
];
});
const getMonitorTypeLabel = (monitorType) => {
if (!monitorType || !dict.type.monitor_type) {
return '未设置';
@ -1023,7 +1110,8 @@ const resetThresholdForm = () => {
hysteresis: null,
durationSec: null,
alarmLevel: null,
notifyGroupId: null,
//
// notifyGroupId: null,
isEnable: '0'
};
nextTick(() => {
@ -1044,34 +1132,267 @@ onMounted(() => {
});
</script>
<style scoped>
<style scoped lang="scss">
.page-shell {
min-height: 100%;
padding: 20px;
background:
radial-gradient(circle at top left, rgba(14, 165, 233, 0.18), transparent 32%),
radial-gradient(circle at top right, rgba(34, 197, 94, 0.14), transparent 28%), linear-gradient(180deg, #f3f8ff 0%, #eef4f7 48%, #f7f9fc 100%);
}
.page-hero {
display: grid;
grid-template-columns: minmax(0, 1.35fr) minmax(320px, 1fr);
gap: 18px;
margin-bottom: 18px;
padding: 28px 30px;
border-radius: 28px;
background: linear-gradient(135deg, rgba(7, 63, 86, 0.96) 0%, rgba(16, 106, 125, 0.92) 52%, rgba(40, 166, 146, 0.9) 100%);
box-shadow: 0 24px 50px rgba(17, 75, 95, 0.18);
color: #fff;
position: relative;
overflow: hidden;
}
.page-hero::after {
content: '';
position: absolute;
inset: auto -100px -120px auto;
width: 260px;
height: 260px;
border-radius: 50%;
background: rgba(255, 255, 255, 0.08);
filter: blur(4px);
}
.hero-copy {
position: relative;
z-index: 1;
}
.hero-eyebrow {
display: inline-flex;
align-items: center;
gap: 8px;
padding: 6px 12px;
border-radius: 999px;
background: rgba(255, 255, 255, 0.12);
font-size: 12px;
letter-spacing: 0.18em;
}
.hero-title {
margin: 18px 0 12px;
font-size: 30px;
line-height: 1.2;
font-weight: 700;
}
.hero-desc {
max-width: 700px;
margin: 0;
color: rgba(255, 255, 255, 0.82);
line-height: 1.75;
}
.hero-stats {
position: relative;
z-index: 1;
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 14px;
}
.stat-card {
padding: 18px;
border-radius: 22px;
background: rgba(255, 255, 255, 0.12);
border: 1px solid rgba(255, 255, 255, 0.16);
backdrop-filter: blur(10px);
}
.stat-label,
.stat-hint {
display: block;
}
.stat-label {
color: rgba(255, 255, 255, 0.7);
font-size: 13px;
}
.stat-value {
display: block;
margin: 10px 0 8px;
font-size: 30px;
line-height: 1;
font-weight: 700;
}
.stat-hint {
color: rgba(255, 255, 255, 0.7);
font-size: 12px;
}
.panel-shell {
margin-bottom: 18px;
padding: 20px 22px;
border: 1px solid rgba(199, 211, 223, 0.55);
border-radius: 24px;
background: rgba(255, 255, 255, 0.84);
box-shadow: 0 18px 40px rgba(42, 63, 95, 0.08);
backdrop-filter: blur(14px);
}
.panel-head {
display: flex;
justify-content: space-between;
gap: 16px;
align-items: center;
margin-bottom: 18px;
}
.panel-head h3 {
margin: 0 0 6px;
color: #163047;
font-size: 20px;
}
.panel-head p {
margin: 0;
color: #6b7a90;
line-height: 1.6;
}
.panel-badge {
flex-shrink: 0;
display: inline-flex;
align-items: center;
padding: 8px 14px;
border-radius: 999px;
background: linear-gradient(135deg, #dbeafe, #ecfeff);
color: #0f5f8d;
font-size: 12px;
font-weight: 600;
}
.panel-badge.warm {
background: linear-gradient(135deg, #fef3c7, #ffedd5);
color: #a16207;
}
.query-form {
padding: 18px;
border-radius: 20px;
background: linear-gradient(180deg, rgba(248, 251, 255, 0.96) 0%, rgba(255, 255, 255, 0.92) 100%);
}
.query-actions {
:deep(.el-form-item__content) {
gap: 10px;
}
}
.toolbar-row {
margin-bottom: 14px;
padding: 14px 16px;
border-radius: 18px;
background: linear-gradient(90deg, rgba(16, 185, 129, 0.08), rgba(59, 130, 246, 0.08));
}
.data-table {
:deep(.el-table) {
--el-table-border-color: rgba(208, 219, 229, 0.7);
}
:deep(.el-table__header-wrapper th) {
background: #f4f9ff;
color: #17324a;
font-weight: 700;
}
:deep(.el-table__row td) {
transition: background-color 0.2s ease;
}
:deep(.el-table__body tr:hover > td) {
background: rgba(37, 99, 235, 0.06) !important;
}
}
.dialog-tip {
display: flex;
align-items: center;
gap: 10px;
margin-bottom: 18px;
padding: 12px 14px;
border-radius: 16px;
background: linear-gradient(90deg, rgba(14, 165, 233, 0.1), rgba(16, 185, 129, 0.08));
color: #28506c;
line-height: 1.65;
}
.dialog-tip.soft {
background: linear-gradient(90deg, rgba(59, 130, 246, 0.08), rgba(244, 114, 182, 0.08));
}
.tip-dot {
width: 10px;
height: 10px;
flex-shrink: 0;
border-radius: 50%;
background: linear-gradient(135deg, #0ea5e9, #22c55e);
box-shadow: 0 0 0 5px rgba(14, 165, 233, 0.12);
}
.dialog-form {
padding: 18px;
border-radius: 18px;
background: #f9fbff;
}
.threshold-container {
padding: 0;
}
.device-info-card,
.threshold-rules-card {
border: none;
border-radius: 22px;
background: linear-gradient(180deg, #ffffff 0%, #f7fbff 100%);
box-shadow: 0 16px 30px rgba(42, 63, 95, 0.08);
}
.device-info-card {
margin-bottom: 20px;
}
.device-info-card .el-card__body {
padding: 15px;
.device-info-card :deep(.el-card__header),
.threshold-rules-card :deep(.el-card__header) {
padding: 18px 20px;
border-bottom: 1px solid rgba(208, 219, 229, 0.75);
}
.threshold-rules-card .el-card__body {
padding: 15px;
.device-info-card :deep(.el-card__body),
.threshold-rules-card :deep(.el-card__body) {
padding: 18px 20px;
}
.info-item {
margin-bottom: 10px;
padding: 14px 16px;
border-radius: 16px;
background: linear-gradient(135deg, #f7fbff, #f2f7f6);
}
.info-item .label {
font-weight: bold;
color: #606266;
font-weight: 700;
color: #66758d;
}
.info-item .value {
color: #303133;
color: #17324a;
margin-left: 5px;
}
@ -1084,4 +1405,61 @@ onMounted(() => {
.clearfix:after {
clear: both;
}
:deep(.themed-dialog .el-dialog) {
border-radius: 26px;
overflow: hidden;
box-shadow: 0 28px 60px rgba(15, 23, 42, 0.2);
}
:deep(.themed-dialog .el-dialog__header) {
padding: 22px 24px 14px;
background: linear-gradient(135deg, rgba(11, 94, 129, 0.96), rgba(26, 142, 126, 0.92));
}
:deep(.themed-dialog .el-dialog__title),
:deep(.themed-dialog .el-dialog__headerbtn .el-dialog__close) {
color: #fff;
}
:deep(.themed-dialog .el-dialog__body) {
padding: 22px 24px;
background: linear-gradient(180deg, #f8fbff 0%, #ffffff 100%);
}
:deep(.themed-dialog .el-dialog__footer) {
padding: 0 24px 24px;
background: linear-gradient(180deg, #ffffff 0%, #f8fbff 100%);
}
@media (max-width: 992px) {
.page-hero {
grid-template-columns: 1fr;
}
.hero-stats {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
}
@media (max-width: 768px) {
.page-shell {
padding: 12px;
}
.page-hero,
.panel-shell {
padding: 18px;
border-radius: 20px;
}
.panel-head {
flex-direction: column;
align-items: flex-start;
}
.hero-stats {
grid-template-columns: 1fr;
}
}
</style>

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save