| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871 |
- <!-- 物联感知设备管理 -->
- <template>
- <div class="app-container equipment-page">
- <div class="summary-grid">
- <el-card shadow="hover" class="summary-card primary">
- <div class="summary-label">设备总数</div>
- <div class="summary-value">{{ summary.total }}</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.active }}</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.warning }}</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.typeCount }}</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="equipmentCode">
- <el-input
- v-model="queryParams.equipmentCode"
- placeholder="请输入设备编码"
- clearable
- style="width: 220px"
- @keyup.enter="handleQuery"
- />
- </el-form-item>
- <el-form-item label="设备名称" prop="equipmentName">
- <el-input
- v-model="queryParams.equipmentName"
- placeholder="请输入设备名称"
- clearable
- style="width: 220px"
- @keyup.enter="handleQuery"
- />
- </el-form-item>
- <el-form-item label="设备型号" prop="equipmentModel">
- <el-input
- v-model="queryParams.equipmentModel"
- placeholder="请输入设备型号"
- clearable
- style="width: 220px"
- @keyup.enter="handleQuery"
- />
- </el-form-item>
- <el-form-item label="制造商" prop="manufacturer">
- <el-input
- v-model="queryParams.manufacturer"
- placeholder="请输入制造商"
- clearable
- style="width: 220px"
- @keyup.enter="handleQuery"
- />
- </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="16">
- <el-card shadow="never" class="table-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="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="equipmentList"
- 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="设备编码" align="center" prop="equipmentCode" min-width="140" />
- <el-table-column label="设备名称" align="center" prop="equipmentName" min-width="160" show-overflow-tooltip />
- <el-table-column label="设备型号" align="center" prop="equipmentModel" min-width="120" />
- <el-table-column label="设备类型" align="center" min-width="140">
- <template #default="scope">
- {{ typeNameMap[scope.row.equipmentTypeId] || scope.row.equipmentTypeId || "-" }}
- </template>
- </el-table-column>
- <el-table-column label="资产状态" align="center" width="130">
- <template #default="scope">
- <div class="status-cell">
- <el-tag :type="getStatusTagType(getRowStatus(scope.row.equipmentId))">
- {{ getStatusText(getRowStatus(scope.row.equipmentId)) }}
- </el-tag>
- <el-tooltip content="资产状态维护" placement="top">
- <el-button
- link
- type="warning"
- icon="Edit"
- aria-label="资产状态维护"
- class="status-edit-button"
- @click.stop="openStatusDialog(scope.row)"
- />
- </el-tooltip>
- </div>
- </template>
- </el-table-column>
- <el-table-column label="制造商" align="center" prop="manufacturer" min-width="140" show-overflow-tooltip />
- <el-table-column label="操作" align="center" width="160" class-name="small-padding fixed-width">
- <template #default="scope">
- <el-button link type="primary" icon="Edit" @click.stop="handleUpdate(scope.row)">修改</el-button>
- <el-button link type="success" icon="Aim" @click.stop="openTestDialog(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="8">
- <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>
- </template>
- <el-empty v-if="!selectedDetail.equipmentInfo" description="请从左侧选择一台设备" />
- <template v-else>
- <div class="detail-hero">
- <div class="hero-title">{{ selectedDetail.equipmentInfo.equipmentName }}</div>
- <div class="hero-meta">
- <span>{{ selectedDetail.equipmentInfo.equipmentCode }}</span>
- <span>{{ selectedDetail.typeInfo?.typeName || "-" }}</span>
- <span>{{ getStatusText(selectedDetail.statusInfo?.currentStatus) }}</span>
- </div>
- </div>
- <el-descriptions :column="1" border size="small">
- <el-descriptions-item label="设备型号">{{ selectedDetail.equipmentInfo.equipmentModel || "-" }}</el-descriptions-item>
- <el-descriptions-item label="制造商">{{ selectedDetail.equipmentInfo.manufacturer || "-" }}</el-descriptions-item>
- <el-descriptions-item label="设备位置">{{ selectedDetail.equipmentInfo.equipmentLocation || "-" }}</el-descriptions-item>
- <el-descriptions-item label="规格参数">{{ selectedDetail.equipmentInfo.equipmentSpec || "-" }}</el-descriptions-item>
- <el-descriptions-item label="维护人员">
- {{ selectedDetail.equipmentInfo.maintainer || "-" }}
- </el-descriptions-item>
- <el-descriptions-item label="联系电话">
- {{ selectedDetail.equipmentInfo.maintainerPhone || "-" }}
- </el-descriptions-item>
- </el-descriptions>
- <div class="section-block">
- <div class="section-title">关联点位</div>
- <el-table :data="selectedDetail.pointRelList || []" size="small" max-height="180">
- <el-table-column label="监测点编码" prop="pointCode" min-width="160" show-overflow-tooltip />
- <el-table-column label="监测点名称" prop="pointName" min-width="160" show-overflow-tooltip />
- </el-table>
- </div>
- <div class="section-block">
- <div class="section-title">测试记录</div>
- <el-table :data="selectedDetail.testList || []" size="small" max-height="180">
- <el-table-column label="时间" prop="testTime" min-width="150" />
- <el-table-column label="类型" prop="testType" min-width="100" />
- <el-table-column label="结果" prop="testResult" width="80" />
- </el-table>
- </div>
- </template>
- </el-card>
- </el-col>
- </el-row>
- <el-dialog :title="title" v-model="open" width="860px" append-to-body>
- <el-form ref="equipmentRef" :model="form" :rules="rules" label-width="110px">
- <el-row :gutter="16">
- <el-col :span="12">
- <el-form-item label="设备编码" prop="equipmentCode">
- <el-input v-model="form.equipmentCode" placeholder="请输入设备编码" />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="设备名称" prop="equipmentName">
- <el-input v-model="form.equipmentName" placeholder="请输入设备名称" />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="设备型号" prop="equipmentModel">
- <el-input v-model="form.equipmentModel" placeholder="请输入设备型号" />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="设备类型" prop="equipmentTypeId">
- <el-tree-select
- v-model="form.equipmentTypeId"
- :data="equipmentTypeTree"
- node-key="id"
- :props="{ label: 'typeName', children: 'children', disabled: 'disabled' }"
- default-expand-all
- :render-after-expand="false"
- placeholder="请选择设备类型"
- style="width: 100%"
- />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="制造商" prop="manufacturer">
- <el-input v-model="form.manufacturer" placeholder="请输入制造商" />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="生产日期" prop="productionDate">
- <el-date-picker
- v-model="form.productionDate"
- 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="equipmentSpec">
- <el-input v-model="form.equipmentSpec" placeholder="请输入设备规格参数" />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="资产价值(元)" prop="assetValue">
- <el-input-number v-model="form.assetValue" :precision="2" :step="100" style="width: 100%" />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="使用年限(年)" prop="useLife">
- <el-input-number v-model="form.useLife" :precision="0" :step="1" style="width: 100%" />
- </el-form-item>
- </el-col>
- <el-col :span="24">
- <el-form-item label="设备位置" prop="equipmentLocation">
- <el-input v-model="form.equipmentLocation" 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="12">
- <el-form-item label="安装时间" prop="installTime">
- <el-date-picker
- v-model="form.installTime"
- type="datetime"
- value-format="YYYY-MM-DD HH:mm:ss"
- placeholder="请选择安装时间"
- style="width: 100%"
- />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="维护人员" prop="maintainer">
- <el-input v-model="form.maintainer" placeholder="请输入维护人员" />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="联系电话" prop="maintainerPhone">
- <el-input v-model="form.maintainerPhone" placeholder="请输入联系电话" />
- </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="statusOpen" width="420px" append-to-body>
- <el-form label-width="90px">
- <el-form-item label="设备名称">
- <span>{{ currentRow.equipmentName || "-" }}</span>
- </el-form-item>
- <el-form-item label="资产状态">
- <el-select v-model="statusForm.currentStatus" style="width: 100%">
- <el-option
- v-for="item in equipmentStatusOptions"
- :key="item.value"
- :label="item.label"
- :value="item.value"
- />
- </el-select>
- </el-form-item>
- </el-form>
- <template #footer>
- <div class="dialog-footer">
- <el-button type="primary" @click="submitStatus">确 定</el-button>
- <el-button @click="statusOpen = false">取 消</el-button>
- </div>
- </template>
- </el-dialog>
- <el-dialog title="设备测试验证" v-model="testOpen" width="520px" append-to-body>
- <el-form ref="testRef" :model="testForm" label-width="90px">
- <el-form-item label="设备名称">
- <span>{{ currentRow.equipmentName || "-" }}</span>
- </el-form-item>
- <el-form-item label="测试类型">
- <el-input v-model="testForm.testType" placeholder="例如:通信测试" />
- </el-form-item>
- <el-form-item label="测试人员">
- <el-input v-model="testForm.testUser" placeholder="请输入测试人员" />
- </el-form-item>
- <el-form-item label="测试详情">
- <el-input v-model="testForm.testDetail" type="textarea" :rows="4" placeholder="请输入测试详情" />
- </el-form-item>
- </el-form>
- <template #footer>
- <div class="dialog-footer">
- <el-button type="primary" @click="submitTest">确 定</el-button>
- <el-button @click="testOpen = false">取 消</el-button>
- </div>
- </template>
- </el-dialog>
- </div>
- </template>
- <script setup>
- import { computed, getCurrentInstance, onMounted, reactive, ref, toRefs } from "vue";
- import {
- addEquipment,
- delEquipment,
- getEquipment,
- getEquipmentDetail,
- listEquipment,
- listEquipmentStatusAll,
- listEquipmentTypeAll,
- testEquipment,
- updateEquipment,
- updateEquipmentStatus
- } from "@/api/pipeNetwork/pdeviceInform";
- const { proxy } = getCurrentInstance();
- const equipmentList = ref([]);
- const equipmentTypeOptions = ref([]);
- const equipmentStatusList = ref([]);
- const loading = ref(false);
- const open = ref(false);
- const statusOpen = ref(false);
- const testOpen = ref(false);
- const showSearch = ref(true);
- const ids = ref([]);
- const multiple = ref(true);
- const total = ref(0);
- const title = ref("");
- const currentRow = ref({});
- const selectedDetail = ref({});
- const equipmentStatusOptions = [
- { label: "在用", value: 1 },
- { label: "闲置", value: 2 },
- { label: "维修", value: 3 },
- { label: "报废", value: 4 },
- { label: "待入库", value: 5 }
- ];
- const summary = reactive({
- total: 0,
- active: 0,
- warning: 0,
- typeCount: 0
- });
- const typeNameMap = computed(() => {
- return equipmentTypeOptions.value.reduce((acc, item) => {
- acc[item.id] = item.typeName;
- return acc;
- }, {});
- });
- // parentTypeId 为 0(或空)表示父类
- function isTopLevelType(item) {
- const parentTypeId = item?.parentTypeId;
- return parentTypeId === 0 || parentTypeId === "0" || parentTypeId === null || parentTypeId === undefined || parentTypeId === "";
- }
- const equipmentTypeTree = computed(() => {
- const list = equipmentTypeOptions.value || [];
- const entries = [];
- // 同时按 typeId / id 建索引,兼容 parentTypeId 指向不同主键字段的情况
- const nodeIndex = {};
- list.forEach((item) => {
- const node = {
- id: item.id,
- typeId: item.typeId,
- typeName: item.typeName,
- disabled: isTopLevelType(item),
- children: []
- };
- entries.push({ item, node });
- [item.typeId, item.id].forEach((key) => {
- if (key !== undefined && key !== null) {
- nodeIndex[String(key)] = node;
- }
- });
- });
- const roots = [];
- // 父节点不在返回列表中时兜底归类,避免子类型在下拉中丢失
- const fallbackNode = { id: "__other__", typeId: "__other__", typeName: "未分类", disabled: true, children: [] };
- entries.forEach(({ item, node }) => {
- if (isTopLevelType(item)) {
- roots.push(node);
- return;
- }
- const parent = nodeIndex[String(item.parentTypeId)];
- if (parent && parent !== node) {
- parent.children.push(node);
- } else {
- fallbackNode.children.push(node);
- }
- });
- // 带子级的节点(即父类)统一禁选,叶子节点可选;空 children 去掉渲染为叶子
- const prune = (node) => {
- if (node.children && node.children.length) {
- node.disabled = true;
- node.children.forEach(prune);
- } else {
- delete node.children;
- }
- return node;
- };
- const result = roots.map(prune);
- if (fallbackNode.children.length) {
- result.push(prune(fallbackNode));
- }
- return result;
- });
- const statusMap = computed(() => {
- return equipmentStatusList.value.reduce((acc, item) => {
- acc[item.equipmentId] = item;
- return acc;
- }, {});
- });
- const data = reactive({
- queryParams: {
- pageNum: 1,
- pageSize: 10,
- equipmentCode: undefined,
- equipmentName: undefined,
- equipmentModel: undefined,
- manufacturer: undefined
- },
- form: {},
- statusForm: {
- currentStatus: 1
- },
- testForm: {
- testType: undefined,
- testDetail: undefined,
- testUser: undefined
- },
- rules: {
- equipmentCode: [{ required: true, message: "设备编码不能为空", trigger: "blur" }],
- equipmentName: [{ required: true, message: "设备名称不能为空", trigger: "blur" }],
- equipmentTypeId: [{ required: true, message: "设备类型不能为空", trigger: "change" }]
- }
- });
- const { queryParams, form, statusForm, testForm, rules } = toRefs(data);
- function createEmptyForm() {
- return {
- equipmentId: undefined,
- equipmentCode: undefined,
- equipmentName: undefined,
- equipmentModel: undefined,
- equipmentSpec: undefined,
- manufacturer: undefined,
- productionDate: undefined,
- equipmentTypeId: undefined,
- assetValue: undefined,
- useLife: undefined,
- longitude: undefined,
- latitude: undefined,
- equipmentLocation: undefined,
- installTime: undefined,
- maintainer: undefined,
- maintainerPhone: undefined,
- remark: undefined
- };
- }
- function getRowStatus(equipmentId) {
- return statusMap.value[equipmentId]?.currentStatus;
- }
- function getStatusText(status) {
- const found = equipmentStatusOptions.find((item) => item.value === status);
- return found?.label || "未维护";
- }
- function getStatusTagType(status) {
- const map = {
- 1: "success",
- 2: "info",
- 3: "warning",
- 4: "danger",
- 5: ""
- };
- return map[status] || "";
- }
- function buildSummary() {
- summary.total = equipmentStatusList.value.length;
- summary.active = equipmentStatusList.value.filter((item) => item.currentStatus === 1).length;
- summary.warning = equipmentStatusList.value.filter((item) => item.currentStatus !== 1).length;
- summary.typeCount = new Set(equipmentTypeOptions.value.map((item) => item.typeName).filter(Boolean)).size;
- }
- function getList() {
- loading.value = true;
- return listEquipment(queryParams.value)
- .then((response) => {
- equipmentList.value = response.records || [];
- total.value = response.total || 0;
- if (!selectedDetail.value.equipmentInfo && equipmentList.value.length) {
- return handleView(equipmentList.value[0]);
- }
- return undefined;
- })
- .finally(() => {
- loading.value = false;
- });
- }
- function loadAssistData() {
- return Promise.all([listEquipmentTypeAll(), listEquipmentStatusAll()]).then(([typeRes, statusRes]) => {
- equipmentTypeOptions.value = typeRes.data || [];
- equipmentStatusList.value = statusRes.data || [];
- buildSummary();
- });
- }
- function reset() {
- form.value = createEmptyForm();
- proxy.resetForm("equipmentRef");
- }
- function handleQuery() {
- queryParams.value.pageNum = 1;
- getList();
- }
- function resetQuery() {
- proxy.resetForm("queryRef");
- handleQuery();
- }
- function handleSelectionChange(selection) {
- ids.value = selection.map((item) => item.equipmentId);
- multiple.value = !selection.length;
- }
- function handleCurrentChange(currentRow) {
- if (currentRow?.equipmentId) {
- handleView(currentRow);
- }
- }
- function handleRowClick(row) {
- handleView(row);
- }
- function handleAdd() {
- reset();
- open.value = true;
- title.value = "新增物联感知设备";
- }
- function handleUpdate(row) {
- reset();
- const equipmentId = row?.equipmentId || ids.value[0];
- if (!equipmentId) {
- return;
- }
- getEquipment(equipmentId).then((response) => {
- form.value = { ...createEmptyForm(), ...(response.data || {}) };
- open.value = true;
- title.value = "修改物联感知设备";
- });
- }
- function handleView(row) {
- return getEquipmentDetail(row.equipmentId).then((response) => {
- selectedDetail.value = response.data || {};
- });
- }
- function cancel() {
- open.value = false;
- reset();
- }
- function submitForm() {
- proxy.$refs.equipmentRef.validate((valid) => {
- if (!valid) {
- return;
- }
- const request = form.value.equipmentId ? updateEquipment(form.value) : addEquipment(form.value);
- request.then(() => {
- proxy.$modal.msgSuccess(form.value.equipmentId ? "修改成功" : "新增成功");
- open.value = false;
- Promise.all([getList(), loadAssistData()]).then(() => {
- if (form.value.equipmentId) {
- handleView({ equipmentId: form.value.equipmentId });
- }
- });
- });
- });
- }
- function handleDelete() {
- const deleteIds = ids.value;
- if (!deleteIds.length) {
- return;
- }
- proxy.$modal
- .confirm(`是否确认删除选中的 ${deleteIds.length} 台设备?`)
- .then(() => Promise.all(deleteIds.map((id) => delEquipment(id))))
- .then(() => {
- proxy.$modal.msgSuccess("删除成功");
- if (deleteIds.includes(selectedDetail.value?.equipmentInfo?.equipmentId)) {
- selectedDetail.value = {};
- }
- return Promise.all([getList(), loadAssistData()]);
- });
- }
- function openStatusDialog(row) {
- currentRow.value = row;
- statusForm.value.currentStatus = getRowStatus(row.equipmentId) || 1;
- statusOpen.value = true;
- }
- function submitStatus() {
- updateEquipmentStatus(currentRow.value.equipmentId, statusForm.value.currentStatus).then(() => {
- proxy.$modal.msgSuccess("状态维护成功");
- statusOpen.value = false;
- Promise.all([loadAssistData(), handleView(currentRow.value)]);
- });
- }
- function openTestDialog(row) {
- currentRow.value = row;
- testForm.value = {
- testType: "通信测试",
- testDetail: undefined,
- testUser: undefined
- };
- testOpen.value = true;
- }
- function submitTest() {
- testEquipment(currentRow.value.equipmentId, testForm.value).then(() => {
- proxy.$modal.msgSuccess("测试记录已提交");
- testOpen.value = false;
- handleView(currentRow.value);
- });
- }
- onMounted(() => {
- reset();
- Promise.all([getList(), loadAssistData()]);
- });
- </script>
- <style scoped>
- .equipment-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,
- .table-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 {
- margin-top: 4px;
- font-size: 12px;
- color: #6b7280;
- }
- .card-actions {
- display: flex;
- align-items: center;
- gap: 8px;
- flex-wrap: wrap;
- }
- .status-cell {
- display: inline-flex;
- align-items: center;
- gap: 4px;
- }
- .status-edit-button {
- padding: 2px;
- }
- .detail-hero {
- margin-bottom: 16px;
- padding: 16px;
- border-radius: 14px;
- background: linear-gradient(135deg, #eff6ff, #f8fbff);
- border: 1px solid #dbeafe;
- }
- .hero-title {
- font-size: 18px;
- font-weight: 700;
- color: #1d4ed8;
- }
- .hero-meta {
- display: flex;
- gap: 10px;
- flex-wrap: wrap;
- margin-top: 8px;
- font-size: 12px;
- color: #4b5563;
- }
- .section-block {
- margin-top: 16px;
- }
- .section-title {
- margin-bottom: 10px;
- font-size: 15px;
- font-weight: 600;
- color: #1f2937;
- }
- @media (max-width: 1200px) {
- .summary-grid {
- grid-template-columns: repeat(2, minmax(0, 1fr));
- }
- }
- @media (max-width: 768px) {
- .summary-grid {
- grid-template-columns: 1fr;
- }
- .card-header-row {
- flex-direction: column;
- align-items: flex-start;
- }
- }
- </style>
|