| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870 |
- <!-- 关键监控点位管理 -->
- <template>
- <div class="app-container point-page">
- <div class="summary-grid">
- <el-card shadow="hover" class="summary-card primary">
- <div class="summary-label">点位总数</div>
- <div class="summary-value">{{ summary.totalPoints }}</div>
- <div class="summary-desc">平台已接入关键监控点位</div>
- </el-card>
- <el-card shadow="hover" class="summary-card success">
- <div class="summary-label">正常点位</div>
- <div class="summary-value">{{ summary.normalPoints }}</div>
- <div class="summary-desc">状态为正常或启用的点位</div>
- </el-card>
- <el-card shadow="hover" class="summary-card warning">
- <div class="summary-label">异常点位</div>
- <div class="summary-value">{{ summary.warningPoints }}</div>
- <div class="summary-desc">状态需关注的关键监控点</div>
- </el-card>
- <el-card shadow="hover" class="summary-card info">
- <div class="summary-label">已绑设备</div>
- <div class="summary-value">{{ summary.boundEquipments }}</div>
- <div class="summary-desc">监控点位已关联感知设备数量</div>
- </el-card>
- </div>
- <el-card shadow="never" class="query-card">
- <el-form ref="queryRef" :model="queryParams" :inline="true" v-show="showSearch">
- <el-form-item label="监测点编码" prop="pointCode">
- <el-input
- v-model="queryParams.pointCode"
- placeholder="请输入监测点编码"
- clearable
- style="width: 220px"
- @keyup.enter="handleQuery"
- />
- </el-form-item>
- <el-form-item label="监测点名称" prop="pointName">
- <el-input
- v-model="queryParams.pointName"
- placeholder="请输入监测点名称"
- clearable
- style="width: 220px"
- @keyup.enter="handleQuery"
- />
- </el-form-item>
- <el-form-item label="监测类型" prop="pointType">
- <el-select
- v-model="queryParams.pointType"
- placeholder="请选择监测类型"
- clearable
- filterable
- allow-create
- default-first-option
- style="width: 220px"
- >
- <el-option v-for="item in pointTypeOptions" :key="item" :label="item" :value="item" />
- </el-select>
- </el-form-item>
- <el-form-item label="状态" prop="status">
- <el-select
- v-model="queryParams.status"
- placeholder="请选择状态"
- clearable
- filterable
- allow-create
- default-first-option
- style="width: 180px"
- >
- <el-option v-for="item in statusOptions" :key="item" :label="item" :value="item" />
- </el-select>
- </el-form-item>
- <el-form-item>
- <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
- <el-button icon="Refresh" @click="resetQuery">重置</el-button>
- </el-form-item>
- </el-form>
- </el-card>
- <el-row :gutter="16" class="main-row">
- <el-col :xs="24" :lg="10">
- <el-card shadow="never" class="list-card">
- <template #header>
- <div class="card-header-row">
- <div>
- <div class="card-title">点位清单</div>
- <div class="card-subtitle">关键监控点位的查询、维护与定位管理</div>
- </div>
- <div class="card-actions">
- <el-button type="primary" plain icon="Plus" @click="handleAdd">新增</el-button>
- <el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()">修改</el-button>
- <el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()">删除</el-button>
- <right-toolbar v-model:showSearch="showSearch" @queryTable="getList" />
- </div>
- </div>
- </template>
- <el-table
- v-loading="loading"
- :data="pointList"
- highlight-current-row
- @selection-change="handleSelectionChange"
- @current-change="handleCurrentChange"
- @row-click="handleRowClick"
- >
- <el-table-column type="selection" width="55" align="center" />
- <el-table-column label="监测点编码" prop="pointCode" min-width="120" show-overflow-tooltip />
- <el-table-column label="监测点名称" prop="pointName" min-width="170" show-overflow-tooltip />
- <el-table-column label="监测类型" prop="pointType" min-width="110" />
- <el-table-column label="状态" width="90">
- <template #default="scope">
- <el-tag :type="getStatusTagType(scope.row.status)" size="small">
- {{ scope.row.status || "-" }}
- </el-tag>
- </template>
- </el-table-column>
- <el-table-column label="设施" min-width="140" show-overflow-tooltip>
- <template #default="scope">
- {{ networkNameMap[scope.row.networkId] || "-" }}
- </template>
- </el-table-column>
- <el-table-column label="操作" align="center" width="150">
- <template #default="scope">
- <el-button link type="primary" icon="Edit" @click.stop="handleUpdate(scope.row)">修改</el-button>
- </template>
- </el-table-column>
- </el-table>
- <pagination
- v-show="total > 0"
- :total="total"
- v-model:page="queryParams.pageNum"
- v-model:limit="queryParams.pageSize"
- @pagination="getList"
- />
- </el-card>
- </el-col>
- <el-col :xs="24" :lg="14">
- <el-card shadow="never" class="detail-card">
- <template #header>
- <div class="card-header-row">
- <div>
- <div class="card-title">点位详情与关联设备</div>
- <div class="card-subtitle">突出点位基础信息、所属设施和已绑定感知设备</div>
- </div>
- <div class="detail-top-actions" v-if="selectedPoint.pointInfo">
- <el-button link type="primary" icon="Connection" @click="openBindDialog(selectedPoint.pointInfo)">
- 设备关联
- </el-button>
- <el-button link type="primary" icon="Edit" @click="handleUpdate(selectedPoint.pointInfo)">编辑</el-button>
- </div>
- </div>
- </template>
- <el-empty v-if="!selectedPoint.pointInfo" description="请从左侧选择一个关键监控点位" />
- <template v-else>
- <div class="point-hero">
- <div class="hero-main">
- <div class="hero-title">{{ selectedPoint.pointInfo.pointName }}</div>
- <div class="hero-code">{{ selectedPoint.pointInfo.pointCode }}</div>
- </div>
- <div class="hero-tags">
- <el-tag>{{ selectedPoint.pointInfo.pointType || "未分类" }}</el-tag>
- <el-tag :type="getStatusTagType(selectedPoint.pointInfo.status)">
- {{ selectedPoint.pointInfo.status || "未设置状态" }}
- </el-tag>
- </div>
- </div>
- <div class="detail-panels">
- <el-card shadow="never" class="mini-panel">
- <template #header>
- <div class="mini-panel-title">点位基础信息</div>
- </template>
- <el-descriptions :column="1" border size="small">
- <el-descriptions-item label="关联设施">
- {{ selectedPoint.networkInfo?.networkName || "-" }}
- </el-descriptions-item>
- <el-descriptions-item label="位置描述">
- {{ selectedPoint.pointInfo.location || "-" }}
- </el-descriptions-item>
- <el-descriptions-item label="安装日期">
- {{ selectedPoint.pointInfo.installationDate || "-" }}
- </el-descriptions-item>
- <el-descriptions-item label="经纬度">
- {{ selectedPoint.pointInfo.longitude ?? "-" }} / {{ selectedPoint.pointInfo.latitude ?? "-" }}
- </el-descriptions-item>
- <el-descriptions-item label="备注">
- {{ selectedPoint.pointInfo.remark || "-" }}
- </el-descriptions-item>
- </el-descriptions>
- </el-card>
- <el-card shadow="never" class="mini-panel">
- <template #header>
- <div class="mini-panel-title">所属设施概况</div>
- </template>
- <el-descriptions :column="1" border size="small">
- <el-descriptions-item label="设施名称">
- {{ selectedPoint.networkInfo?.networkName || "-" }}
- </el-descriptions-item>
- <el-descriptions-item label="设施编码">
- {{ selectedPoint.networkInfo?.networkCode || "-" }}
- </el-descriptions-item>
- <el-descriptions-item label="设施类型">
- {{ selectedPoint.networkInfo?.networkType || "-" }}
- </el-descriptions-item>
- <el-descriptions-item label="管养单位">
- {{ selectedPoint.networkInfo?.managementUnit || "-" }}
- </el-descriptions-item>
- <el-descriptions-item label="设施状态">
- {{ selectedPoint.networkInfo?.status || "-" }}
- </el-descriptions-item>
- </el-descriptions>
- </el-card>
- </div>
- <el-card shadow="never" class="equipment-panel">
- <template #header>
- <div class="card-header-row">
- <div>
- <div class="mini-panel-title">关联监测设备</div>
- <div class="panel-tip">
- 当前共 {{ selectedEquipmentList.length }} 台设备,支持在右上角进行绑定和解绑
- </div>
- </div>
- <el-button type="primary" plain icon="Connection" @click="openBindDialog(selectedPoint.pointInfo)">
- 关联设备
- </el-button>
- </div>
- </template>
- <el-table :data="selectedEquipmentList" border size="small" max-height="320">
- <el-table-column label="设备编码" prop="equipmentCode" min-width="140" />
- <el-table-column label="设备名称" prop="equipmentName" min-width="160" show-overflow-tooltip />
- <el-table-column label="设备型号" prop="equipmentModel" min-width="120" />
- <el-table-column label="制造商" prop="manufacturer" min-width="120" show-overflow-tooltip />
- <el-table-column label="设备位置" prop="equipmentLocation" min-width="160" show-overflow-tooltip />
- <el-table-column label="操作" width="90" align="center">
- <template #default="scope">
- <el-button link type="danger" icon="Close" @click="handleUnbind(scope.row)">解绑</el-button>
- </template>
- </el-table-column>
- </el-table>
- </el-card>
- </template>
- </el-card>
- </el-col>
- </el-row>
- <el-dialog :title="title" v-model="open" width="780px" append-to-body>
- <el-form ref="pointRef" :model="form" :rules="rules" label-width="110px">
- <el-row :gutter="16">
- <el-col :span="12">
- <el-form-item label="监测点编码" prop="pointCode">
- <el-input v-model="form.pointCode" placeholder="请输入监测点编码" />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="监测点名称" prop="pointName">
- <el-input v-model="form.pointName" placeholder="请输入监测点名称" />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="关联设施" prop="networkId">
- <el-select v-model="form.networkId" clearable placeholder="请选择管网设施" style="width: 100%">
- <el-option
- v-for="item in networkOptions"
- :key="item.networkId"
- :label="`${item.networkName}(${item.networkCode})`"
- :value="item.networkId"
- />
- </el-select>
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="监测类型" prop="pointType">
- <el-select
- v-model="form.pointType"
- placeholder="请选择或输入监测类型"
- filterable
- allow-create
- default-first-option
- style="width: 100%"
- >
- <el-option v-for="item in pointTypeOptions" :key="item" :label="item" :value="item" />
- </el-select>
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="状态" prop="status">
- <el-select
- v-model="form.status"
- placeholder="请选择或输入状态"
- filterable
- allow-create
- default-first-option
- style="width: 100%"
- >
- <el-option v-for="item in statusOptions" :key="item" :label="item" :value="item" />
- </el-select>
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="安装日期" prop="installationDate">
- <el-date-picker
- v-model="form.installationDate"
- type="date"
- value-format="YYYY-MM-DD"
- placeholder="请选择安装日期"
- style="width: 100%"
- />
- </el-form-item>
- </el-col>
- <el-col :span="24">
- <el-form-item label="位置描述" prop="location">
- <el-input v-model="form.location" placeholder="请输入位置描述" />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="经度" prop="longitude">
- <el-input-number v-model="form.longitude" :precision="6" :step="0.000001" style="width: 100%" />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="纬度" prop="latitude">
- <el-input-number v-model="form.latitude" :precision="6" :step="0.000001" style="width: 100%" />
- </el-form-item>
- </el-col>
- <el-col :span="24">
- <el-form-item label="备注" prop="remark">
- <el-input v-model="form.remark" type="textarea" :rows="3" placeholder="请输入备注" />
- </el-form-item>
- </el-col>
- </el-row>
- </el-form>
- <template #footer>
- <div class="dialog-footer">
- <el-button type="primary" @click="submitForm">确 定</el-button>
- <el-button @click="cancel">取 消</el-button>
- </div>
- </template>
- </el-dialog>
- <el-dialog title="关联监测设备" v-model="bindOpen" width="860px" append-to-body>
- <el-form label-width="90px">
- <el-form-item label="当前点位">
- <span>{{ currentRow.pointName || "-" }}</span>
- </el-form-item>
- <el-form-item label="选择设备">
- <el-select
- v-model="bindForm.equipmentId"
- filterable
- clearable
- placeholder="请选择设备"
- style="width: 100%"
- >
- <el-option
- v-for="item in unboundEquipmentOptions"
- :key="item.equipmentId"
- :label="`${item.equipmentName}(${item.equipmentCode})`"
- :value="item.equipmentId"
- />
- </el-select>
- </el-form-item>
- </el-form>
- <div class="bind-toolbar">
- <el-button type="primary" @click="submitBind">添加关联</el-button>
- </div>
- <el-table :data="bindDetail.equipmentList || []" border>
- <el-table-column label="设备编码" prop="equipmentCode" min-width="140" />
- <el-table-column label="设备名称" prop="equipmentName" min-width="180" show-overflow-tooltip />
- <el-table-column label="设备型号" prop="equipmentModel" min-width="120" />
- <el-table-column label="制造商" prop="manufacturer" min-width="140" show-overflow-tooltip />
- <el-table-column label="设备位置" prop="equipmentLocation" min-width="180" show-overflow-tooltip />
- <el-table-column label="操作" align="center" width="100">
- <template #default="scope">
- <el-button link type="danger" icon="Close" @click="handleUnbind(scope.row)">解绑</el-button>
- </template>
- </el-table-column>
- </el-table>
- </el-dialog>
- </div>
- </template>
- <script setup>
- import { computed, getCurrentInstance, onMounted, reactive, ref, toRefs } from "vue";
- import {
- addMonitorPoint,
- bindPointEquipment,
- delMonitorPoint,
- getMonitorPoint,
- getMonitorPointDetail,
- listEquipment,
- listMonitorPoint,
- listMonitorPointAll,
- listPipeNetworkAll,
- unbindPointEquipment,
- updateMonitorPoint
- } from "@/api/pipeNetwork/pdeviceInform";
- const { proxy } = getCurrentInstance();
- const pointList = ref([]);
- const networkOptions = ref([]);
- const equipmentOptions = ref([]);
- const loading = ref(false);
- const open = ref(false);
- const bindOpen = ref(false);
- const showSearch = ref(true);
- const ids = ref([]);
- const single = ref(true);
- const multiple = ref(true);
- const total = ref(0);
- const title = ref("");
- const currentRow = ref({});
- const pointTypeOptions = ["水质监测", "空气质量", "压力监测", "流量监测", "温度监测", "泄漏检测"];
- const statusOptions = ["正常", "启用", "停用", "维修中", "预警"];
- const summary = reactive({
- totalPoints: 0,
- normalPoints: 0,
- warningPoints: 0,
- boundEquipments: 0
- });
- const networkNameMap = computed(() => {
- return networkOptions.value.reduce((acc, item) => {
- acc[item.networkId] = item.networkName;
- return acc;
- }, {});
- });
- const data = reactive({
- queryParams: {
- pageNum: 1,
- pageSize: 10,
- pointCode: undefined,
- pointName: undefined,
- pointType: undefined,
- status: undefined
- },
- form: {},
- selectedPoint: {},
- bindDetail: {},
- bindForm: {
- equipmentId: undefined
- },
- rules: {
- pointCode: [{ required: true, message: "监测点编码不能为空", trigger: "blur" }],
- pointName: [{ required: true, message: "监测点名称不能为空", trigger: "blur" }],
- pointType: [{ required: true, message: "监测类型不能为空", trigger: "change" }]
- }
- });
- const { queryParams, form, selectedPoint, bindDetail, bindForm, rules } = toRefs(data);
- const selectedEquipmentList = computed(() => {
- return selectedPoint.value.equipmentList || [];
- });
- const unboundEquipmentOptions = computed(() => {
- const boundIds = new Set((bindDetail.value.equipmentList || []).map((item) => item.equipmentId));
- return equipmentOptions.value.filter((item) => !boundIds.has(item.equipmentId));
- });
- function createEmptyForm() {
- return {
- pointId: undefined,
- pointCode: undefined,
- pointName: undefined,
- networkId: undefined,
- pointType: undefined,
- location: undefined,
- longitude: undefined,
- latitude: undefined,
- installationDate: undefined,
- status: "正常",
- remark: undefined
- };
- }
- function getStatusTagType(status) {
- if (["正常", "启用"].includes(status)) {
- return "success";
- }
- if (status === "预警") {
- return "warning";
- }
- if (["停用", "禁用"].includes(status)) {
- return "info";
- }
- if (["故障", "异常"].includes(status)) {
- return "danger";
- }
- return "";
- }
- function getList() {
- loading.value = true;
- return listMonitorPoint(queryParams.value)
- .then((response) => {
- pointList.value = response.records || [];
- total.value = response.total || 0;
- if (!selectedPoint.value.pointInfo && pointList.value.length) {
- return selectPoint(pointList.value[0]);
- }
- return undefined;
- })
- .finally(() => {
- loading.value = false;
- });
- }
- function loadAssistData() {
- return Promise.all([
- listPipeNetworkAll(),
- listEquipment({
- pageNum: 1,
- pageSize: 1000
- }),
- listMonitorPointAll()
- ]).then(([networkRes, equipmentRes, pointRes]) => {
- networkOptions.value = networkRes.data || [];
- equipmentOptions.value = equipmentRes.records || [];
- const allPoints = pointRes.data || [];
- summary.totalPoints = allPoints.length;
- summary.normalPoints = allPoints.filter((item) => ["正常", "启用"].includes(item.status)).length;
- summary.warningPoints = allPoints.filter((item) => !["正常", "启用"].includes(item.status)).length;
- });
- }
- function loadPointDetail(pointId, targetRef) {
- return getMonitorPointDetail(pointId).then((response) => {
- targetRef.value = response.data || {};
- });
- }
- function refreshBoundCount() {
- return listMonitorPoint({
- pageNum: 1,
- pageSize: 1000
- }).then((response) => {
- const records = response.records || [];
- const detailRequests = records.map((item) => getMonitorPointDetail(item.pointId));
- return Promise.all(detailRequests).then((detailResponses) => {
- summary.boundEquipments = detailResponses.reduce((count, item) => {
- return count + ((item.data?.equipmentList || []).length || 0);
- }, 0);
- });
- });
- }
- function selectPoint(row) {
- if (!row?.pointId) {
- return;
- }
- return loadPointDetail(row.pointId, selectedPoint);
- }
- function reset() {
- form.value = createEmptyForm();
- proxy.resetForm("pointRef");
- }
- function handleQuery() {
- queryParams.value.pageNum = 1;
- getList();
- }
- function resetQuery() {
- proxy.resetForm("queryRef");
- handleQuery();
- }
- function handleSelectionChange(selection) {
- ids.value = selection.map((item) => item.pointId);
- single.value = selection.length !== 1;
- multiple.value = !selection.length;
- }
- function handleCurrentChange(currentRow) {
- if (currentRow?.pointId) {
- selectPoint(currentRow);
- }
- }
- function handleRowClick(row) {
- selectPoint(row);
- }
- function handleAdd() {
- reset();
- open.value = true;
- title.value = "新增关键监控点位";
- }
- function handleUpdate(row) {
- reset();
- const pointId = row?.pointId || row?.pointInfo?.pointId || ids.value[0];
- if (!pointId) {
- return;
- }
- getMonitorPoint(pointId).then((response) => {
- form.value = { ...createEmptyForm(), ...(response.data || {}) };
- open.value = true;
- title.value = "修改关键监控点位";
- });
- }
- function cancel() {
- open.value = false;
- reset();
- }
- function submitForm() {
- proxy.$refs.pointRef.validate((valid) => {
- if (!valid) {
- return;
- }
- const request = form.value.pointId ? updateMonitorPoint(form.value) : addMonitorPoint(form.value);
- request.then(() => {
- proxy.$modal.msgSuccess(form.value.pointId ? "修改成功" : "新增成功");
- open.value = false;
- Promise.all([getList(), loadAssistData(), refreshBoundCount()]).then(() => {
- if (form.value.pointId) {
- selectPoint({ pointId: form.value.pointId });
- }
- });
- });
- });
- }
- function handleDelete(row) {
- const deleteIds = row?.pointId ? [row.pointId] : ids.value;
- if (!deleteIds.length) {
- return;
- }
- proxy.$modal
- .confirm(`是否确认删除选中的 ${deleteIds.length} 个监测点?`)
- .then(() => Promise.all(deleteIds.map((id) => delMonitorPoint(id))))
- .then(() => {
- proxy.$modal.msgSuccess("删除成功");
- if (deleteIds.includes(selectedPoint.value?.pointInfo?.pointId)) {
- selectedPoint.value = {};
- }
- return Promise.all([getList(), loadAssistData(), refreshBoundCount()]);
- });
- }
- function openBindDialog(row) {
- const pointId = row?.pointId || row?.pointInfo?.pointId;
- if (!pointId) {
- return;
- }
- currentRow.value = row.pointInfo ? row.pointInfo : row;
- bindForm.value.equipmentId = undefined;
- loadPointDetail(pointId, bindDetail).then(() => {
- bindOpen.value = true;
- });
- }
- function submitBind() {
- if (!bindForm.value.equipmentId) {
- proxy.$modal.msgError("请选择要关联的设备");
- return;
- }
- bindPointEquipment(currentRow.value.pointId, [bindForm.value.equipmentId]).then(() => {
- proxy.$modal.msgSuccess("关联成功");
- bindForm.value.equipmentId = undefined;
- Promise.all([
- loadPointDetail(currentRow.value.pointId, bindDetail),
- loadPointDetail(currentRow.value.pointId, selectedPoint),
- refreshBoundCount()
- ]);
- });
- }
- function handleUnbind(row) {
- const pointId = currentRow.value.pointId || selectedPoint.value?.pointInfo?.pointId;
- if (!pointId) {
- return;
- }
- proxy.$modal
- .confirm(`是否确认解绑设备“${row.equipmentName}”?`)
- .then(() => unbindPointEquipment(pointId, [row.equipmentId]))
- .then(() => {
- proxy.$modal.msgSuccess("解绑成功");
- return Promise.all([
- loadPointDetail(pointId, bindDetail),
- loadPointDetail(pointId, selectedPoint),
- refreshBoundCount()
- ]);
- });
- }
- onMounted(() => {
- reset();
- Promise.all([getList(), loadAssistData(), refreshBoundCount()]);
- });
- </script>
- <style scoped>
- .point-page {
- background: #f5f8fc;
- }
- .summary-grid {
- display: grid;
- grid-template-columns: repeat(4, minmax(0, 1fr));
- gap: 16px;
- margin-bottom: 16px;
- }
- .summary-card {
- border: none;
- color: #fff;
- }
- .summary-card :deep(.el-card__body) {
- padding: 20px;
- }
- .summary-card.primary {
- background: linear-gradient(135deg, #2563eb, #5b93ff);
- }
- .summary-card.success {
- background: linear-gradient(135deg, #059669, #34d399);
- }
- .summary-card.warning {
- background: linear-gradient(135deg, #d97706, #f7b955);
- }
- .summary-card.info {
- background: linear-gradient(135deg, #7c3aed, #9d72ff);
- }
- .summary-label {
- font-size: 14px;
- opacity: 0.9;
- }
- .summary-value {
- margin: 8px 0 10px;
- font-size: 30px;
- font-weight: 700;
- line-height: 1;
- }
- .summary-desc {
- font-size: 12px;
- opacity: 0.9;
- }
- .query-card,
- .list-card,
- .detail-card {
- border-radius: 16px;
- }
- .query-card {
- margin-bottom: 16px;
- }
- .card-header-row {
- display: flex;
- justify-content: space-between;
- align-items: center;
- gap: 12px;
- }
- .card-title {
- font-size: 16px;
- font-weight: 600;
- color: #1f2937;
- }
- .card-subtitle,
- .panel-tip {
- margin-top: 4px;
- font-size: 12px;
- color: #6b7280;
- }
- .card-actions,
- .detail-top-actions {
- display: flex;
- align-items: center;
- gap: 8px;
- flex-wrap: wrap;
- }
- .point-hero {
- display: flex;
- justify-content: space-between;
- gap: 12px;
- padding: 16px;
- border-radius: 14px;
- background: linear-gradient(135deg, #eff6ff, #f8fbff);
- border: 1px solid #dbeafe;
- margin-bottom: 16px;
- }
- .hero-title {
- font-size: 18px;
- font-weight: 700;
- color: #1d4ed8;
- }
- .hero-code {
- margin-top: 8px;
- font-size: 13px;
- color: #4b5563;
- }
- .hero-tags {
- display: flex;
- gap: 8px;
- flex-wrap: wrap;
- align-items: flex-start;
- }
- .detail-panels {
- display: grid;
- grid-template-columns: repeat(2, minmax(0, 1fr));
- gap: 16px;
- margin-bottom: 16px;
- }
- .mini-panel,
- .equipment-panel {
- border-radius: 14px;
- }
- .mini-panel-title {
- font-size: 15px;
- font-weight: 600;
- color: #1f2937;
- }
- .bind-toolbar {
- margin-bottom: 12px;
- }
- @media (max-width: 1200px) {
- .summary-grid {
- grid-template-columns: repeat(2, minmax(0, 1fr));
- }
- }
- @media (max-width: 768px) {
- .summary-grid,
- .detail-panels {
- grid-template-columns: 1fr;
- }
- .card-header-row,
- .point-hero {
- flex-direction: column;
- align-items: flex-start;
- }
- }
- </style>
|