From 09f49269f00a1fa70bbf9d52476b01bf917c948e Mon Sep 17 00:00:00 2001
From: zouyu <2723363702@qq.com>
Date: 星期二, 16 十二月 2025 19:57:39 +0800
Subject: [PATCH] 代码调整5
---
src/views/index.vue | 934 +++++---------
.env.development | 2
/dev/null | 572 --------
src/views/diagnosis/FaultDiagnosis.vue | 411 ++++++
src/views/dashboard/Dashboard.vue | 301 ++++
src/views/monitoring/RealTimeMonitoring.vue | 515 ++++++++
src/main.js | 2
src/views/maintenance/MaintenanceManagement.vue | 526 ++++++++
.env.production | 2
vite.config.js | 4
src/views/device/DeviceManagement.vue | 513 ++++++++
11 files changed, 2,597 insertions(+), 1,185 deletions(-)
diff --git a/.env.development b/.env.development
index 47c7925..9729e7e 100644
--- a/.env.development
+++ b/.env.development
@@ -1,5 +1,5 @@
# 椤甸潰鏍囬
-VITE_APP_TITLE = 鎵垮寘鍟嗙鐞嗙郴缁�
+VITE_APP_TITLE = 璁惧鍦ㄧ嚎鐩戞祴璇婃柇鍙婄淮淇郴缁�
# 寮�鍙戠幆澧冮厤缃�
VITE_APP_ENV = 'development'
diff --git a/.env.production b/.env.production
index 119d6b5..042d296 100644
--- a/.env.production
+++ b/.env.production
@@ -1,5 +1,5 @@
# 椤甸潰鏍囬
-VITE_APP_TITLE = 鎵垮寘鍟嗙鐞嗙郴缁�
+VITE_APP_TITLE = 璁惧鍦ㄧ嚎鐩戞祴璇婃柇鍙婄淮淇郴缁�
# 鐢熶骇鐜閰嶇疆
VITE_APP_ENV = 'production'
diff --git a/src/main.js b/src/main.js
index 99e7fa4..a5339fb 100644
--- a/src/main.js
+++ b/src/main.js
@@ -76,7 +76,7 @@
app.config.globalProperties.addDateRange = addDateRange;
app.config.globalProperties.selectDictLabel = selectDictLabel;
app.config.globalProperties.selectDictLabels = selectDictLabels;
-app.config.globalProperties.javaApi = "http://10.136.12.71:8018";
+app.config.globalProperties.javaApi = "http://10.136.12.71:8020";
app.config.globalProperties.HaveJson = (val) => {
return JSON.parse(JSON.stringify(val));
};
diff --git a/src/views/contractor/assets/index.vue b/src/views/contractor/assets/index.vue
deleted file mode 100644
index ad8a641..0000000
--- a/src/views/contractor/assets/index.vue
+++ /dev/null
@@ -1,637 +0,0 @@
-<template>
- <div class="app-container">
- <el-form
- :model="queryParams"
- ref="queryRef"
- :inline="true"
- v-show="showSearch"
- label-width="90px"
- >
- <el-form-item label="璧勪骇鍚嶇О" prop="assetName">
- <el-input
- v-model="queryParams.assetName"
- placeholder="璇疯緭鍏ヨ祫浜у悕绉�"
- clearable
- style="width: 220px"
- @keyup.enter="handleQuery"
- />
- </el-form-item>
- <el-form-item label="璧勪骇缂栧彿" prop="assetCode">
- <el-input
- v-model="queryParams.assetCode"
- placeholder="璇疯緭鍏ヨ祫浜х紪鍙�"
- clearable
- style="width: 240px"
- @keyup.enter="handleQuery"
- />
- </el-form-item>
- <el-form-item label="鎵�灞炴壙鍖呭晢" prop="contractorId">
- <el-select
- v-model="queryParams.contractorId"
- placeholder="璇烽�夋嫨鎵垮寘鍟�"
- clearable
- style="width: 240px"
- >
- <el-option
- v-for="contractor in contractorOptions"
- :key="contractor.contractorId"
- :label="contractor.contractorName"
- :value="contractor.contractorId"
- />
- </el-select>
- </el-form-item>
- <el-form-item label="璧勪骇鐘舵��" prop="status">
- <el-select
- v-model="queryParams.status"
- placeholder="璧勪骇鐘舵��"
- clearable
- style="width: 240px"
- >
- <el-option
- v-for="dict in asset_status"
- :key="dict.value"
- :label="dict.label"
- :value="dict.value"
- />
- </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-row :gutter="10" class="mb8">
- <el-col :span="1.5">
- <el-button
- type="primary"
- plain
- icon="Plus"
- @click="handleAdd"
- >鏂板</el-button
- >
- </el-col>
- <el-col :span="1.5">
- <el-button
- type="success"
- plain
- icon="Edit"
- :disabled="single"
- @click="handleUpdate"
- >淇敼</el-button
- >
- </el-col>
- <el-col :span="1.5">
- <el-button
- type="danger"
- plain
- icon="Delete"
- :disabled="multiple"
- @click="handleDelete"
- >鍒犻櫎</el-button
- >
- </el-col>
- <right-toolbar
- v-model:showSearch="showSearch"
- @queryTable="getList"
- :columns="columns"
- ></right-toolbar>
- </el-row>
-
- <el-table
- v-loading="loading"
- :data="assetList"
- @selection-change="handleSelectionChange"
- stripe
- >
- <el-table-column type="selection" width="50" align="center" />
- <el-table-column
- label="璧勪骇缂栧彿"
- align="center"
- key="assetId"
- prop="assetId"
- v-if="columns[0].visible"
- />
- <el-table-column
- label="璧勪骇鍚嶇О"
- align="center"
- key="assetName"
- prop="assetName"
- v-if="columns[1].visible"
- :show-overflow-tooltip="true"
- />
- <el-table-column
- label="璧勪骇缂栧彿"
- align="center"
- key="assetCode"
- prop="assetCode"
- v-if="columns[2].visible"
- />
- <el-table-column
- label="鎵�灞炴壙鍖呭晢"
- align="center"
- key="contractorName"
- prop="contractorName"
- v-if="columns[3].visible"
- :show-overflow-tooltip="true"
- />
- <el-table-column
- label="璧勪骇绫诲瀷"
- align="center"
- key="assetType"
- prop="assetType"
- v-if="columns[4].visible"
- >
- <template #default="scope">
- {{ getAssetTypeLabel(scope.row.assetType) }}
- </template>
- </el-table-column>
- <el-table-column
- label="璧勪骇浠峰��"
- align="center"
- key="assetValue"
- prop="assetValue"
- v-if="columns[5].visible"
- >
- <template #default="scope">
- {{ scope.row.assetValue.toFixed(2) }}
- </template>
- </el-table-column>
- <el-table-column
- label="鐘舵��"
- align="center"
- key="status"
- v-if="columns[6].visible"
- >
- <template #default="scope">
- <el-switch
- v-model="scope.row.status"
- active-value="0"
- inactive-value="1"
- @change="handleStatusChange(scope.row)"
- ></el-switch>
- </template>
- </el-table-column>
- <el-table-column
- label="鍒涘缓鏃堕棿"
- align="center"
- prop="createTime"
- v-if="columns[7].visible"
- width="160"
- >
- <template #default="scope">
- <span>{{ parseTime(scope.row.createTime) }}</span>
- </template>
- </el-table-column>
- <el-table-column
- label="鎿嶄綔"
- align="center"
- width="150"
- class-name="small-padding fixed-width"
- >
- <template #default="scope">
- <el-tooltip
- content="淇敼"
- placement="top"
- >
- <el-button
- link
- type="primary"
- icon="Edit"
- @click="handleUpdate(scope.row)"
- ></el-button>
- </el-tooltip>
- <el-tooltip
- content="鍒犻櫎"
- placement="top"
- >
- <el-button
- link
- type="primary"
- icon="Delete"
- @click="handleDelete(scope.row)"
- ></el-button>
- </el-tooltip>
- </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-dialog :title="title" v-model="open" width="600px" append-to-body>
- <el-form :model="form" :rules="rules" ref="assetRef" label-width="80px">
- <el-row>
- <el-col :span="12">
- <el-form-item label="璧勪骇鍚嶇О" prop="assetName">
- <el-input
- v-model="form.assetName"
- placeholder="璇疯緭鍏ヨ祫浜у悕绉�"
- maxlength="50"
- />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="璧勪骇缂栧彿" prop="assetCode">
- <el-input
- v-model="form.assetCode"
- placeholder="璇疯緭鍏ヨ祫浜х紪鍙�"
- maxlength="20"
- />
- </el-form-item>
- </el-col>
- </el-row>
- <el-row>
- <el-col :span="12">
- <el-form-item label="鎵�灞炴壙鍖呭晢" prop="contractorId">
- <el-select
- v-model="form.contractorId"
- placeholder="璇烽�夋嫨鎵垮寘鍟�"
- clearable
- >
- <el-option
- v-for="contractor in contractorOptions"
- :key="contractor.contractorId"
- :label="contractor.contractorName"
- :value="contractor.contractorId"
- />
- </el-select>
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="璧勪骇绫诲瀷" prop="assetType">
- <el-select
- v-model="form.assetType"
- placeholder="璇烽�夋嫨璧勪骇绫诲瀷"
- clearable
- >
- <el-option
- v-for="type in asset_types"
- :key="type.value"
- :label="type.label"
- :value="type.value"
- />
- </el-select>
- </el-form-item>
- </el-col>
- </el-row>
- <el-row>
- <el-col :span="12">
- <el-form-item label="璧勪骇浠峰��" prop="assetValue">
- <el-input
- v-model="form.assetValue"
- placeholder="璇疯緭鍏ヨ祫浜т环鍊�"
- type="number"
- step="0.01"
- />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="鐘舵��">
- <el-radio-group v-model="form.status">
- <el-radio
- v-for="dict in sys_normal_disable"
- :key="dict.value"
- :value="dict.value"
- >{{ dict.label }}</el-radio
- >
- </el-radio-group>
- </el-form-item>
- </el-col>
- </el-row>
- <el-row>
- <el-col :span="24">
- <el-form-item label="澶囨敞">
- <el-input
- v-model="form.remark"
- type="textarea"
- placeholder="璇疯緭鍏ュ唴瀹�"
- ></el-input>
- </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>
- </div>
-</template>
-
-<script setup name="ContractorAssets">
-import { ref, reactive, toRefs, watch, onMounted } from 'vue';
-import { ElMessage } from 'element-plus';
-import { parseTime } from '@/utils/ruoyi';
-
-const assetList = ref([]);
-const open = ref(false);
-const loading = ref(true);
-const showSearch = ref(true);
-const ids = ref([]);
-const single = ref(true);
-const multiple = ref(true);
-const total = ref(0);
-const title = ref("");
-
-// 鍒楁樉闅愪俊鎭�
-const columns = ref([
- { key: 0, label: `璧勪骇缂栧彿`, visible: true },
- { key: 1, label: `璧勪骇鍚嶇О`, visible: true },
- { key: 2, label: `璧勪骇缂栧彿`, visible: true },
- { key: 3, label: `鎵�灞炴壙鍖呭晢`, visible: true },
- { key: 4, label: `璧勪骇绫诲瀷`, visible: true },
- { key: 5, label: `璧勪骇浠峰�糮, visible: true },
- { key: 6, label: `鐘舵�乣, visible: true },
- { key: 7, label: `鍒涘缓鏃堕棿`, visible: true },
-]);
-
-const data = reactive({
- form: {
- assetId: undefined,
- assetName: undefined,
- assetCode: undefined,
- contractorId: undefined,
- contractorName: undefined,
- assetType: undefined,
- assetValue: 0,
- status: "0",
- remark: undefined,
- },
- queryParams: {
- pageNum: 1,
- pageSize: 10,
- assetName: undefined,
- assetCode: undefined,
- contractorId: undefined,
- status: undefined,
- },
- rules: {
- assetName: [
- { required: true, message: "璧勪骇鍚嶇О涓嶈兘涓虹┖", trigger: "blur" },
- ],
- assetCode: [
- { required: true, message: "璧勪骇缂栧彿涓嶈兘涓虹┖", trigger: "blur" },
- ],
- contractorId: [
- { required: true, message: "鎵�灞炴壙鍖呭晢涓嶈兘涓虹┖", trigger: "blur" },
- ],
- assetType: [
- { required: true, message: "璧勪骇绫诲瀷涓嶈兘涓虹┖", trigger: "blur" },
- ],
- assetValue: [
- { required: true, message: "璧勪骇浠峰�间笉鑳戒负绌�", trigger: "blur" },
- { type: "number", message: "璇疯緭鍏ユ纭殑鏁板瓧", trigger: "blur" },
- ],
- },
-});
-
-const { queryParams, form, rules } = toRefs(data);
-
-// 妯℃嫙鎵垮寘鍟嗘暟鎹�
-const contractorOptions = ref([
- { contractorId: 1, contractorName: "鍖椾含寤哄伐闆嗗洟" },
- { contractorId: 2, contractorName: "涓婃捣鍩庡缓闆嗗洟" },
- { contractorId: 3, contractorName: "骞垮窞寤虹瓚闆嗗洟" },
- { contractorId: 4, contractorName: "娣卞湷寤哄伐闆嗗洟" },
- { contractorId: 5, contractorName: "鏉窞寤哄伐闆嗗洟" },
-]);
-
-// 璧勪骇绫诲瀷瀛楀吀
-const asset_types = ref([
- { value: "equipment", label: "璁惧" },
- { value: "material", label: "鏉愭枡" },
- { value: "vehicle", label: "杞﹁締" },
- { value: "tool", label: "宸ュ叿" },
- { value: "other", label: "鍏朵粬" },
-]);
-
-// 璧勪骇鐘舵�佸瓧鍏�
-const asset_status = ref([
- { value: "0", label: "姝e父" },
- { value: "1", label: "绂佺敤" },
- { value: "2", label: "缁翠慨涓�" },
- { value: "3", label: "宸叉姤搴�" },
-]);
-
-// 姝e父绂佺敤瀛楀吀
-const sys_normal_disable = ref([
- { value: "0", label: "姝e父" },
- { value: "1", label: "绂佺敤" },
-]);
-
-// 妯℃嫙璧勪骇鏁版嵁
-const mockAssets = ref([
- {
- assetId: 1,
- assetName: "鎸栨帢鏈�",
- assetCode: "ASSET001",
- contractorId: 1,
- contractorName: "鍖椾含寤哄伐闆嗗洟",
- assetType: "equipment",
- assetValue: 500000.00,
- status: "0",
- createTime: "2024-01-01 10:00:00",
- remark: "澶у瀷鎸栨帢鏈�",
- },
- {
- assetId: 2,
- assetName: "娣峰嚌鍦熸悈鎷屾満",
- assetCode: "ASSET002",
- contractorId: 2,
- contractorName: "涓婃捣鍩庡缓闆嗗洟",
- assetType: "equipment",
- assetValue: 150000.00,
- status: "0",
- createTime: "2024-01-02 10:00:00",
- remark: "娣峰嚌鍦熸悈鎷岃澶�",
- },
- {
- assetId: 3,
- assetName: "瑁呰浇鏈�",
- assetCode: "ASSET003",
- contractorId: 3,
- contractorName: "骞垮窞寤虹瓚闆嗗洟",
- assetType: "equipment",
- assetValue: 300000.00,
- status: "1",
- createTime: "2024-01-03 10:00:00",
- remark: "瑁呰浇鏈鸿澶�",
- },
- {
- assetId: 4,
- assetName: "杩愯緭鍗¤溅",
- assetCode: "ASSET004",
- contractorId: 4,
- contractorName: "娣卞湷寤哄伐闆嗗洟",
- assetType: "vehicle",
- assetValue: 400000.00,
- status: "0",
- createTime: "2024-01-04 10:00:00",
- remark: "閲嶅瀷杩愯緭鍗¤溅",
- },
- {
- assetId: 5,
- assetName: "閽㈢瓔鍒囨柇鏈�",
- assetCode: "ASSET005",
- contractorId: 5,
- contractorName: "鏉窞寤哄伐闆嗗洟",
- assetType: "tool",
- assetValue: 20000.00,
- status: "0",
- createTime: "2024-01-05 10:00:00",
- remark: "閽㈢瓔鍔犲伐璁惧",
- },
-]);
-
-/** 鑾峰彇璧勪骇绫诲瀷鏍囩 */
-function getAssetTypeLabel(value) {
- const type = asset_types.value.find(item => item.value === value);
- return type ? type.label : value;
-}
-
-/** 鏌ヨ璧勪骇鍒楄〃 */
-function getList() {
- loading.value = true;
- // 妯℃嫙API璇锋眰寤惰繜
- setTimeout(() => {
- let data = [...mockAssets];
- // 妯℃嫙鎼滅储杩囨护
- if (queryParams.value.assetName) {
- data = data.filter(item => item.assetName.includes(queryParams.value.assetName));
- }
- if (queryParams.value.assetCode) {
- data = data.filter(item => item.assetCode.includes(queryParams.value.assetCode));
- }
- if (queryParams.value.contractorId) {
- data = data.filter(item => item.contractorId === queryParams.value.contractorId);
- }
- if (queryParams.value.status) {
- data = data.filter(item => item.status === queryParams.value.status);
- }
- // 妯℃嫙鍒嗛〉
- const start = (queryParams.value.pageNum - 1) * queryParams.value.pageSize;
- const end = start + queryParams.value.pageSize;
- assetList.value = data.slice(start, end);
- total.value = data.length;
- loading.value = false;
- }, 500);
-}
-
-/** 鎼滅储鎸夐挳鎿嶄綔 */
-function handleQuery() {
- queryParams.value.pageNum = 1;
- getList();
-}
-
-/** 閲嶇疆鎸夐挳鎿嶄綔 */
-function resetQuery() {
- Object.assign(queryParams.value, {
- assetName: undefined,
- assetCode: undefined,
- contractorId: undefined,
- status: undefined,
- });
- handleQuery();
-}
-
-/** 鍒犻櫎鎸夐挳鎿嶄綔 */
-function handleDelete(row) {
- const assetIds = row.assetId || ids.value;
- ElMessage.confirm(`鏄惁纭鍒犻櫎璧勪骇缂栧彿涓�"${assetIds}"鐨勬暟鎹」锛焋).then(() => {
- // 妯℃嫙鍒犻櫎鎿嶄綔
- ElMessage.success("鍒犻櫎鎴愬姛");
- getList();
- }).catch(() => {});
-}
-
-/** 鐘舵�佷慨鏀� */
-function handleStatusChange(row) {
- let text = row.status === "0" ? "鍚敤" : "鍋滅敤";
- ElMessage.confirm(`纭瑕�"${text}""${row.assetName}"璧勪骇鍚�?`).then(() => {
- // 妯℃嫙鐘舵�佷慨鏀�
- ElMessage.success(text + "鎴愬姛");
- getList();
- }).catch(() => {
- row.status = row.status === "0" ? "1" : "0";
- });
-}
-
-/** 閫夋嫨鏉℃暟 */
-function handleSelectionChange(selection) {
- ids.value = selection.map((item) => item.assetId);
- single.value = selection.length != 1;
- multiple.value = !selection.length;
-}
-
-/** 閲嶇疆鎿嶄綔琛ㄥ崟 */
-function reset() {
- form.value = {
- assetId: undefined,
- assetName: undefined,
- assetCode: undefined,
- contractorId: undefined,
- contractorName: undefined,
- assetType: undefined,
- assetValue: 0,
- status: "0",
- remark: undefined,
- };
-}
-
-/** 鍙栨秷鎸夐挳 */
-function cancel() {
- open.value = false;
- reset();
-}
-
-/** 鏂板鎸夐挳鎿嶄綔 */
-function handleAdd() {
- reset();
- open.value = true;
- title.value = "娣诲姞璧勪骇";
-}
-
-/** 淇敼鎸夐挳鎿嶄綔 */
-function handleUpdate(row) {
- reset();
- const assetId = row.assetId || ids.value;
- // 妯℃嫙鑾峰彇璇︽儏
- const asset = mockAssets.find(item => item.assetId === assetId);
- if (asset) {
- form.value = { ...asset };
- open.value = true;
- title.value = "淇敼璧勪骇";
- }
-}
-
-/** 鎻愪氦鎸夐挳 */
-function submitForm() {
- // 妯℃嫙琛ㄥ崟楠岃瘉
- const requiredFields = ['assetName', 'assetCode', 'contractorId', 'assetType', 'assetValue'];
- const isInvalid = requiredFields.some(field => !form.value[field]);
-
- if (isInvalid) {
- ElMessage.error("璇峰~鍐欏繀濉瓧娈�");
- return;
- }
-
- // 妯℃嫙鎻愪氦鎿嶄綔
- ElMessage.success(title.value === "娣诲姞璧勪骇" ? "鏂板鎴愬姛" : "淇敼鎴愬姛");
- open.value = false;
- getList();
-}
-
-onMounted(() => {
- getList();
-});
-</script>
diff --git a/src/views/contractor/compliance/index.vue b/src/views/contractor/compliance/index.vue
deleted file mode 100644
index 7fbe1a2..0000000
--- a/src/views/contractor/compliance/index.vue
+++ /dev/null
@@ -1,664 +0,0 @@
-<template>
- <div class="app-container">
- <el-form
- :model="queryParams"
- ref="queryRef"
- :inline="true"
- v-show="showSearch"
- label-width="90px"
- >
- <el-form-item label="鍚堣鍚嶇О" prop="complianceName">
- <el-input
- v-model="queryParams.complianceName"
- placeholder="璇疯緭鍏ュ悎瑙勫悕绉�"
- clearable
- style="width: 220px"
- @keyup.enter="handleQuery"
- />
- </el-form-item>
- <el-form-item label="鍚堣缂栧彿" prop="complianceCode">
- <el-input
- v-model="queryParams.complianceCode"
- placeholder="璇疯緭鍏ュ悎瑙勭紪鍙�"
- clearable
- style="width: 240px"
- @keyup.enter="handleQuery"
- />
- </el-form-item>
- <el-form-item label="鎵�灞炴壙鍖呭晢" prop="contractorId">
- <el-select
- v-model="queryParams.contractorId"
- placeholder="璇烽�夋嫨鎵垮寘鍟�"
- clearable
- style="width: 240px"
- >
- <el-option
- v-for="contractor in contractorOptions"
- :key="contractor.contractorId"
- :label="contractor.contractorName"
- :value="contractor.contractorId"
- />
- </el-select>
- </el-form-item>
- <el-form-item label="鍚堣鐘舵��" prop="status">
- <el-select
- v-model="queryParams.status"
- placeholder="鍚堣鐘舵��"
- clearable
- style="width: 240px"
- >
- <el-option
- v-for="dict in compliance_status"
- :key="dict.value"
- :label="dict.label"
- :value="dict.value"
- />
- </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-row :gutter="10" class="mb8">
- <el-col :span="1.5">
- <el-button
- type="primary"
- plain
- icon="Plus"
- @click="handleAdd"
- >鏂板</el-button
- >
- </el-col>
- <el-col :span="1.5">
- <el-button
- type="success"
- plain
- icon="Edit"
- :disabled="single"
- @click="handleUpdate"
- >淇敼</el-button
- >
- </el-col>
- <el-col :span="1.5">
- <el-button
- type="danger"
- plain
- icon="Delete"
- :disabled="multiple"
- @click="handleDelete"
- >鍒犻櫎</el-button
- >
- </el-col>
- <right-toolbar
- v-model:showSearch="showSearch"
- @queryTable="getList"
- :columns="columns"
- ></right-toolbar>
- </el-row>
-
- <el-table
- v-loading="loading"
- :data="complianceList"
- @selection-change="handleSelectionChange"
- stripe
- >
- <el-table-column type="selection" width="50" align="center" />
- <el-table-column
- label="鍚堣ID"
- align="center"
- key="complianceId"
- prop="complianceId"
- v-if="columns[0].visible"
- />
- <el-table-column
- label="鍚堣鍚嶇О"
- align="center"
- key="complianceName"
- prop="complianceName"
- v-if="columns[1].visible"
- :show-overflow-tooltip="true"
- />
- <el-table-column
- label="鍚堣缂栧彿"
- align="center"
- key="complianceCode"
- prop="complianceCode"
- v-if="columns[2].visible"
- />
- <el-table-column
- label="鎵�灞炴壙鍖呭晢"
- align="center"
- key="contractorName"
- prop="contractorName"
- v-if="columns[3].visible"
- :show-overflow-tooltip="true"
- />
- <el-table-column
- label="鍚堣绫诲瀷"
- align="center"
- key="complianceType"
- prop="complianceType"
- v-if="columns[4].visible"
- >
- <template #default="scope">
- {{ getComplianceTypeLabel(scope.row.complianceType) }}
- </template>
- </el-table-column>
- <el-table-column
- label="鏈夋晥鏈熷紑濮�"
- align="center"
- key="validStartDate"
- prop="validStartDate"
- v-if="columns[5].visible"
- width="140"
- />
- <el-table-column
- label="鏈夋晥鏈熺粨鏉�"
- align="center"
- key="validEndDate"
- prop="validEndDate"
- v-if="columns[6].visible"
- width="140"
- />
- <el-table-column
- label="鐘舵��"
- align="center"
- key="status"
- v-if="columns[7].visible"
- >
- <template #default="scope">
- <el-switch
- v-model="scope.row.status"
- active-value="0"
- inactive-value="1"
- @change="handleStatusChange(scope.row)"
- ></el-switch>
- </template>
- </el-table-column>
- <el-table-column
- label="鍒涘缓鏃堕棿"
- align="center"
- prop="createTime"
- v-if="columns[8].visible"
- width="160"
- >
- <template #default="scope">
- <span>{{ parseTime(scope.row.createTime) }}</span>
- </template>
- </el-table-column>
- <el-table-column
- label="鎿嶄綔"
- align="center"
- width="150"
- class-name="small-padding fixed-width"
- >
- <template #default="scope">
- <el-tooltip
- content="淇敼"
- placement="top"
- >
- <el-button
- link
- type="primary"
- icon="Edit"
- @click="handleUpdate(scope.row)"
- ></el-button>
- </el-tooltip>
- <el-tooltip
- content="鍒犻櫎"
- placement="top"
- >
- <el-button
- link
- type="primary"
- icon="Delete"
- @click="handleDelete(scope.row)"
- ></el-button>
- </el-tooltip>
- </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-dialog :title="title" v-model="open" width="600px" append-to-body>
- <el-form :model="form" :rules="rules" ref="complianceRef" label-width="80px">
- <el-row>
- <el-col :span="12">
- <el-form-item label="鍚堣鍚嶇О" prop="complianceName">
- <el-input
- v-model="form.complianceName"
- placeholder="璇疯緭鍏ュ悎瑙勫悕绉�"
- maxlength="50"
- />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="鍚堣缂栧彿" prop="complianceCode">
- <el-input
- v-model="form.complianceCode"
- placeholder="璇疯緭鍏ュ悎瑙勭紪鍙�"
- maxlength="20"
- />
- </el-form-item>
- </el-col>
- </el-row>
- <el-row>
- <el-col :span="12">
- <el-form-item label="鎵�灞炴壙鍖呭晢" prop="contractorId">
- <el-select
- v-model="form.contractorId"
- placeholder="璇烽�夋嫨鎵垮寘鍟�"
- clearable
- >
- <el-option
- v-for="contractor in contractorOptions"
- :key="contractor.contractorId"
- :label="contractor.contractorName"
- :value="contractor.contractorId"
- />
- </el-select>
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="鍚堣绫诲瀷" prop="complianceType">
- <el-select
- v-model="form.complianceType"
- placeholder="璇烽�夋嫨鍚堣绫诲瀷"
- clearable
- >
- <el-option
- v-for="type in compliance_types"
- :key="type.value"
- :label="type.label"
- :value="type.value"
- />
- </el-select>
- </el-form-item>
- </el-col>
- </el-row>
- <el-row>
- <el-col :span="12">
- <el-form-item label="鏈夋晥鏈熷紑濮�" prop="validStartDate">
- <el-date-picker
- v-model="form.validStartDate"
- type="date"
- placeholder="閫夋嫨寮�濮嬫棩鏈�"
- value-format="YYYY-MM-DD"
- />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="鏈夋晥鏈熺粨鏉�" prop="validEndDate">
- <el-date-picker
- v-model="form.validEndDate"
- type="date"
- placeholder="閫夋嫨缁撴潫鏃ユ湡"
- value-format="YYYY-MM-DD"
- />
- </el-form-item>
- </el-col>
- </el-row>
- <el-row>
- <el-col :span="12">
- <el-form-item label="鐘舵��">
- <el-radio-group v-model="form.status">
- <el-radio
- v-for="dict in sys_normal_disable"
- :key="dict.value"
- :value="dict.value"
- >{{ dict.label }}</el-radio
- >
- </el-radio-group>
- </el-form-item>
- </el-col>
- </el-row>
- <el-row>
- <el-col :span="24">
- <el-form-item label="澶囨敞">
- <el-input
- v-model="form.remark"
- type="textarea"
- placeholder="璇疯緭鍏ュ唴瀹�"
- ></el-input>
- </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>
- </div>
-</template>
-
-<script setup name="ContractorCompliance">
-import { ref, reactive, toRefs, watch, onMounted } from 'vue';
-import { ElMessage } from 'element-plus';
-import { parseTime } from '@/utils/ruoyi';
-
-const complianceList = ref([]);
-const open = ref(false);
-const loading = ref(true);
-const showSearch = ref(true);
-const ids = ref([]);
-const single = ref(true);
-const multiple = ref(true);
-const total = ref(0);
-const title = ref("");
-
-// 鍒楁樉闅愪俊鎭�
-const columns = ref([
- { key: 0, label: `鍚堣ID`, visible: true },
- { key: 1, label: `鍚堣鍚嶇О`, visible: true },
- { key: 2, label: `鍚堣缂栧彿`, visible: true },
- { key: 3, label: `鎵�灞炴壙鍖呭晢`, visible: true },
- { key: 4, label: `鍚堣绫诲瀷`, visible: true },
- { key: 5, label: `鏈夋晥鏈熷紑濮媊, visible: true },
- { key: 6, label: `鏈夋晥鏈熺粨鏉焋, visible: true },
- { key: 7, label: `鐘舵�乣, visible: true },
- { key: 8, label: `鍒涘缓鏃堕棿`, visible: true },
-]);
-
-const data = reactive({
- form: {
- complianceId: undefined,
- complianceName: undefined,
- complianceCode: undefined,
- contractorId: undefined,
- contractorName: undefined,
- complianceType: undefined,
- validStartDate: undefined,
- validEndDate: undefined,
- status: "0",
- remark: undefined,
- },
- queryParams: {
- pageNum: 1,
- pageSize: 10,
- complianceName: undefined,
- complianceCode: undefined,
- contractorId: undefined,
- status: undefined,
- },
- rules: {
- complianceName: [
- { required: true, message: "鍚堣鍚嶇О涓嶈兘涓虹┖", trigger: "blur" },
- ],
- complianceCode: [
- { required: true, message: "鍚堣缂栧彿涓嶈兘涓虹┖", trigger: "blur" },
- ],
- contractorId: [
- { required: true, message: "鎵�灞炴壙鍖呭晢涓嶈兘涓虹┖", trigger: "blur" },
- ],
- complianceType: [
- { required: true, message: "鍚堣绫诲瀷涓嶈兘涓虹┖", trigger: "blur" },
- ],
- validStartDate: [
- { required: true, message: "鏈夋晥鏈熷紑濮嬩笉鑳戒负绌�", trigger: "blur" },
- ],
- validEndDate: [
- { required: true, message: "鏈夋晥鏈熺粨鏉熶笉鑳戒负绌�", trigger: "blur" },
- ],
- },
-});
-
-const { queryParams, form, rules } = toRefs(data);
-
-// 妯℃嫙鎵垮寘鍟嗘暟鎹�
-const contractorOptions = ref([
- { contractorId: 1, contractorName: "鍖椾含寤哄伐闆嗗洟" },
- { contractorId: 2, contractorName: "涓婃捣鍩庡缓闆嗗洟" },
- { contractorId: 3, contractorName: "骞垮窞寤虹瓚闆嗗洟" },
- { contractorId: 4, contractorName: "娣卞湷寤哄伐闆嗗洟" },
- { contractorId: 5, contractorName: "鏉窞寤哄伐闆嗗洟" },
-]);
-
-// 鍚堣绫诲瀷瀛楀吀
-const compliance_types = ref([
- { value: "license", label: "璁稿彲璇�" },
- { value: "certificate", label: "璇佷功" },
- { value: "regulation", label: "娉曡閬靛惊" },
- { value: "standard", label: "鏍囧噯鍚堣" },
- { value: "other", label: "鍏朵粬" },
-]);
-
-// 鍚堣鐘舵�佸瓧鍏�
-const compliance_status = ref([
- { value: "0", label: "姝e父" },
- { value: "1", label: "绂佺敤" },
- { value: "2", label: "鍗冲皢杩囨湡" },
- { value: "3", label: "宸茶繃鏈�" },
-]);
-
-// 姝e父绂佺敤瀛楀吀
-const sys_normal_disable = ref([
- { value: "0", label: "姝e父" },
- { value: "1", label: "绂佺敤" },
-]);
-
-// 妯℃嫙鍚堣鏁版嵁
-const mockCompliances = ref([
- {
- complianceId: 1,
- complianceName: "寤虹瓚鏂藉伐璁稿彲璇�",
- complianceCode: "COMP001",
- contractorId: 1,
- contractorName: "鍖椾含寤哄伐闆嗗洟",
- complianceType: "license",
- validStartDate: "2024-01-01",
- validEndDate: "2025-12-31",
- status: "0",
- createTime: "2024-01-01 10:00:00",
- remark: "寤虹瓚鏂藉伐璁稿彲璇�",
- },
- {
- complianceId: 2,
- complianceName: "瀹夊叏鐢熶骇璁稿彲璇�",
- complianceCode: "COMP002",
- contractorId: 2,
- contractorName: "涓婃捣鍩庡缓闆嗗洟",
- complianceType: "license",
- validStartDate: "2024-01-02",
- validEndDate: "2025-12-31",
- status: "0",
- createTime: "2024-01-02 10:00:00",
- remark: "瀹夊叏鐢熶骇璁稿彲璇�",
- },
- {
- complianceId: 3,
- complianceName: "璐ㄩ噺绠$悊浣撶郴璁よ瘉",
- complianceCode: "COMP003",
- contractorId: 3,
- contractorName: "骞垮窞寤虹瓚闆嗗洟",
- complianceType: "certificate",
- validStartDate: "2024-01-03",
- validEndDate: "2025-12-31",
- status: "1",
- createTime: "2024-01-03 10:00:00",
- remark: "ISO9001璐ㄩ噺绠$悊浣撶郴璁よ瘉",
- },
- {
- complianceId: 4,
- complianceName: "鐜绠$悊浣撶郴璁よ瘉",
- complianceCode: "COMP004",
- contractorId: 4,
- contractorName: "娣卞湷寤哄伐闆嗗洟",
- complianceType: "certificate",
- validStartDate: "2024-01-04",
- validEndDate: "2025-12-31",
- status: "0",
- createTime: "2024-01-04 10:00:00",
- remark: "ISO14001鐜绠$悊浣撶郴璁よ瘉",
- },
- {
- complianceId: 5,
- complianceName: "鑱屼笟鍋ュ悍瀹夊叏绠$悊浣撶郴璁よ瘉",
- complianceCode: "COMP005",
- contractorId: 5,
- contractorName: "鏉窞寤哄伐闆嗗洟",
- complianceType: "certificate",
- validStartDate: "2024-01-05",
- validEndDate: "2025-12-31",
- status: "0",
- createTime: "2024-01-05 10:00:00",
- remark: "ISO45001鑱屼笟鍋ュ悍瀹夊叏绠$悊浣撶郴璁よ瘉",
- },
-]);
-
-/** 鑾峰彇鍚堣绫诲瀷鏍囩 */
-function getComplianceTypeLabel(value) {
- const type = compliance_types.value.find(item => item.value === value);
- return type ? type.label : value;
-}
-
-/** 鏌ヨ鍚堣鍒楄〃 */
-function getList() {
- loading.value = true;
- // 妯℃嫙API璇锋眰寤惰繜
- setTimeout(() => {
- let data = [...mockCompliances.value];
- // 妯℃嫙鎼滅储杩囨护
- if (queryParams.value.complianceName) {
- data = data.filter(item => item.complianceName.includes(queryParams.value.complianceName));
- }
- if (queryParams.value.complianceCode) {
- data = data.filter(item => item.complianceCode.includes(queryParams.value.complianceCode));
- }
- if (queryParams.value.contractorId) {
- data = data.filter(item => item.contractorId === queryParams.value.contractorId);
- }
- if (queryParams.value.status) {
- data = data.filter(item => item.status === queryParams.value.status);
- }
- // 妯℃嫙鍒嗛〉
- const start = (queryParams.value.pageNum - 1) * queryParams.value.pageSize;
- const end = start + queryParams.value.pageSize;
- complianceList.value = data.slice(start, end);
- total.value = data.length;
- loading.value = false;
- }, 500);
-}
-
-/** 鎼滅储鎸夐挳鎿嶄綔 */
-function handleQuery() {
- queryParams.value.pageNum = 1;
- getList();
-}
-
-/** 閲嶇疆鎸夐挳鎿嶄綔 */
-function resetQuery() {
- Object.assign(queryParams.value, {
- complianceName: undefined,
- complianceCode: undefined,
- contractorId: undefined,
- status: undefined,
- });
- handleQuery();
-}
-
-/** 鍒犻櫎鎸夐挳鎿嶄綔 */
-function handleDelete(row) {
- const complianceIds = row.complianceId || ids.value;
- ElMessage.confirm(`鏄惁纭鍒犻櫎鍚堣缂栧彿涓�"${complianceIds}"鐨勬暟鎹」锛焋).then(() => {
- // 妯℃嫙鍒犻櫎鎿嶄綔
- ElMessage.success("鍒犻櫎鎴愬姛");
- getList();
- }).catch(() => {});
-}
-
-/** 鐘舵�佷慨鏀� */
-function handleStatusChange(row) {
- let text = row.status === "0" ? "鍚敤" : "鍋滅敤";
- ElMessage.confirm(`纭瑕�"${text}""${row.complianceName}"鍚堣璁板綍鍚�?`).then(() => {
- // 妯℃嫙鐘舵�佷慨鏀�
- ElMessage.success(text + "鎴愬姛");
- getList();
- }).catch(() => {
- row.status = row.status === "0" ? "1" : "0";
- });
-}
-
-/** 閫夋嫨鏉℃暟 */
-function handleSelectionChange(selection) {
- ids.value = selection.map((item) => item.complianceId);
- single.value = selection.length != 1;
- multiple.value = !selection.length;
-}
-
-/** 閲嶇疆鎿嶄綔琛ㄥ崟 */
-function reset() {
- form.value = {
- complianceId: undefined,
- complianceName: undefined,
- complianceCode: undefined,
- contractorId: undefined,
- contractorName: undefined,
- complianceType: undefined,
- validStartDate: undefined,
- validEndDate: undefined,
- status: "0",
- remark: undefined,
- };
-}
-
-/** 鍙栨秷鎸夐挳 */
-function cancel() {
- open.value = false;
- reset();
-}
-
-/** 鏂板鎸夐挳鎿嶄綔 */
-function handleAdd() {
- reset();
- open.value = true;
- title.value = "娣诲姞鍚堣璁板綍";
-}
-
-/** 淇敼鎸夐挳鎿嶄綔 */
-function handleUpdate(row) {
- reset();
- const complianceId = row.complianceId || ids.value;
- // 妯℃嫙鑾峰彇璇︽儏
- const compliance = mockCompliances.find(item => item.complianceId === complianceId);
- if (compliance) {
- form.value = { ...compliance };
- open.value = true;
- title.value = "淇敼鍚堣璁板綍";
- }
-}
-
-/** 鎻愪氦鎸夐挳 */
-function submitForm() {
- // 妯℃嫙琛ㄥ崟楠岃瘉
- const requiredFields = ['complianceName', 'complianceCode', 'contractorId', 'complianceType', 'validStartDate', 'validEndDate'];
- const isInvalid = requiredFields.some(field => !form.value[field]);
-
- if (isInvalid) {
- ElMessage.error("璇峰~鍐欏繀濉瓧娈�");
- return;
- }
-
- // 妯℃嫙鎻愪氦鎿嶄綔
- ElMessage.success(title.value === "娣诲姞鍚堣璁板綍" ? "鏂板鎴愬姛" : "淇敼鎴愬姛");
- open.value = false;
- getList();
-}
-
-onMounted(() => {
- getList();
-});
-</script>
diff --git a/src/views/contractor/list/index.vue b/src/views/contractor/list/index.vue
deleted file mode 100644
index 8767039..0000000
--- a/src/views/contractor/list/index.vue
+++ /dev/null
@@ -1,572 +0,0 @@
-<template>
- <div class="app-container">
- <el-form
- :model="queryParams"
- ref="queryRef"
- :inline="true"
- v-show="showSearch"
- label-width="90px"
- >
- <el-form-item label="鎵垮寘鍟嗗悕绉�" prop="contractorName">
- <el-input
- v-model="queryParams.contractorName"
- placeholder="璇疯緭鍏ユ壙鍖呭晢鍚嶇О"
- clearable
- style="width: 220px"
- @keyup.enter="handleQuery"
- />
- </el-form-item>
- <el-form-item label="鑱旂郴浜�" prop="contactPerson">
- <el-input
- v-model="queryParams.contactPerson"
- placeholder="璇疯緭鍏ヨ仈绯讳汉"
- clearable
- style="width: 240px"
- @keyup.enter="handleQuery"
- />
- </el-form-item>
- <el-form-item label="鑱旂郴鐢佃瘽" prop="contactPhone">
- <el-input
- v-model="queryParams.contactPhone"
- placeholder="璇疯緭鍏ヨ仈绯荤數璇�"
- clearable
- style="width: 240px"
- @keyup.enter="handleQuery"
- />
- </el-form-item>
- <el-form-item label="鐘舵��" prop="status">
- <el-select
- v-model="queryParams.status"
- placeholder="鎵垮寘鍟嗙姸鎬�"
- clearable
- style="width: 240px"
- >
- <el-option
- v-for="dict in sys_normal_disable"
- :key="dict.value"
- :label="dict.label"
- :value="dict.value"
- />
- </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-row :gutter="10" class="mb8">
- <el-col :span="1.5">
- <el-button
- type="primary"
- plain
- icon="Plus"
- @click="handleAdd"
- >鏂板</el-button
- >
- </el-col>
- <el-col :span="1.5">
- <el-button
- type="success"
- plain
- icon="Edit"
- :disabled="single"
- @click="handleUpdate"
- >淇敼</el-button
- >
- </el-col>
- <el-col :span="1.5">
- <el-button
- type="danger"
- plain
- icon="Delete"
- :disabled="multiple"
- @click="handleDelete"
- >鍒犻櫎</el-button
- >
- </el-col>
- <right-toolbar
- v-model:showSearch="showSearch"
- @queryTable="getList"
- :columns="columns"
- ></right-toolbar>
- </el-row>
-
- <el-table
- v-loading="loading"
- :data="contractorList"
- @selection-change="handleSelectionChange"
- stripe
- >
- <el-table-column type="selection" width="50" align="center" />
- <el-table-column
- label="鎵垮寘鍟嗙紪鍙�"
- align="center"
- key="contractorId"
- prop="contractorId"
- v-if="columns[0].visible"
- />
- <el-table-column
- label="鎵垮寘鍟嗗悕绉�"
- align="center"
- key="contractorName"
- prop="contractorName"
- v-if="columns[1].visible"
- :show-overflow-tooltip="true"
- />
- <el-table-column
- label="鑱旂郴浜�"
- align="center"
- key="contactPerson"
- prop="contactPerson"
- v-if="columns[2].visible"
- />
- <el-table-column
- label="鑱旂郴鐢佃瘽"
- align="center"
- key="contactPhone"
- prop="contactPhone"
- v-if="columns[3].visible"
- />
- <el-table-column
- label="鑱旂郴閭"
- align="center"
- key="contactEmail"
- prop="contactEmail"
- v-if="columns[4].visible"
- :show-overflow-tooltip="true"
- />
- <el-table-column
- label="鍦板潃"
- align="center"
- key="address"
- prop="address"
- v-if="columns[5].visible"
- :show-overflow-tooltip="true"
- />
- <el-table-column
- label="鐘舵��"
- align="center"
- key="status"
- v-if="columns[6].visible"
- >
- <template #default="scope">
- <el-switch
- v-model="scope.row.status"
- active-value="0"
- inactive-value="1"
- @change="handleStatusChange(scope.row)"
- ></el-switch>
- </template>
- </el-table-column>
- <el-table-column
- label="鍒涘缓鏃堕棿"
- align="center"
- prop="createTime"
- v-if="columns[7].visible"
- width="160"
- >
- <template #default="scope">
- <span>{{ parseTime(scope.row.createTime) }}</span>
- </template>
- </el-table-column>
- <el-table-column
- label="鎿嶄綔"
- align="center"
- width="150"
- class-name="small-padding fixed-width"
- >
- <template #default="scope">
- <el-tooltip
- content="淇敼"
- placement="top"
- >
- <el-button
- link
- type="primary"
- icon="Edit"
- @click="handleUpdate(scope.row)"
- ></el-button>
- </el-tooltip>
- <el-tooltip
- content="鍒犻櫎"
- placement="top"
- >
- <el-button
- link
- type="primary"
- icon="Delete"
- @click="handleDelete(scope.row)"
- ></el-button>
- </el-tooltip>
- </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-dialog :title="title" v-model="open" width="600px" append-to-body>
- <el-form :model="form" :rules="rules" ref="contractorRef" label-width="80px">
- <el-row>
- <el-col :span="12">
- <el-form-item label="鎵垮寘鍟嗗悕绉�" prop="contractorName">
- <el-input
- v-model="form.contractorName"
- placeholder="璇疯緭鍏ユ壙鍖呭晢鍚嶇О"
- maxlength="50"
- />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="鑱旂郴浜�" prop="contactPerson">
- <el-input
- v-model="form.contactPerson"
- placeholder="璇疯緭鍏ヨ仈绯讳汉"
- maxlength="20"
- />
- </el-form-item>
- </el-col>
- </el-row>
- <el-row>
- <el-col :span="12">
- <el-form-item label="鑱旂郴鐢佃瘽" prop="contactPhone">
- <el-input
- v-model="form.contactPhone"
- placeholder="璇疯緭鍏ヨ仈绯荤數璇�"
- maxlength="11"
- />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="鑱旂郴閭" prop="contactEmail">
- <el-input
- v-model="form.contactEmail"
- placeholder="璇疯緭鍏ヨ仈绯婚偖绠�"
- maxlength="50"
- />
- </el-form-item>
- </el-col>
- </el-row>
- <el-row>
- <el-col :span="24">
- <el-form-item label="鍦板潃" prop="address">
- <el-input
- v-model="form.address"
- placeholder="璇疯緭鍏ュ湴鍧�"
- maxlength="100"
- />
- </el-form-item>
- </el-col>
- </el-row>
- <el-row>
- <el-col :span="12">
- <el-form-item label="鐘舵��">
- <el-radio-group v-model="form.status">
- <el-radio
- v-for="dict in sys_normal_disable"
- :key="dict.value"
- :value="dict.value"
- >{{ dict.label }}</el-radio
- >
- </el-radio-group>
- </el-form-item>
- </el-col>
- </el-row>
- <el-row>
- <el-col :span="24">
- <el-form-item label="澶囨敞">
- <el-input
- v-model="form.remark"
- type="textarea"
- placeholder="璇疯緭鍏ュ唴瀹�"
- ></el-input>
- </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>
- </div>
-</template>
-
-<script setup name="Contractor">
-import { ref, reactive, toRefs, watch, onMounted } from 'vue';
-import { ElMessage } from 'element-plus';
-import { parseTime } from '@/utils/ruoyi';
-
-const contractorList = ref([]);
-const open = ref(false);
-const loading = ref(true);
-const showSearch = ref(true);
-const ids = ref([]);
-const single = ref(true);
-const multiple = ref(true);
-const total = ref(0);
-const title = ref("");
-
-// 鍒楁樉闅愪俊鎭�
-const columns = ref([
- { key: 0, label: `鎵垮寘鍟嗙紪鍙穈, visible: true },
- { key: 1, label: `鎵垮寘鍟嗗悕绉癭, visible: true },
- { key: 2, label: `鑱旂郴浜篳, visible: true },
- { key: 3, label: `鑱旂郴鐢佃瘽`, visible: true },
- { key: 4, label: `鑱旂郴閭`, visible: true },
- { key: 5, label: `鍦板潃`, visible: true },
- { key: 6, label: `鐘舵�乣, visible: true },
- { key: 7, label: `鍒涘缓鏃堕棿`, visible: true },
-]);
-
-const data = reactive({
- form: {
- contractorId: undefined,
- contractorName: undefined,
- contactPerson: undefined,
- contactPhone: undefined,
- contactEmail: undefined,
- address: undefined,
- status: "0",
- remark: undefined,
- },
- queryParams: {
- pageNum: 1,
- pageSize: 10,
- contractorName: undefined,
- contactPerson: undefined,
- contactPhone: undefined,
- status: undefined,
- },
- rules: {
- contractorName: [
- { required: true, message: "鎵垮寘鍟嗗悕绉颁笉鑳戒负绌�", trigger: "blur" },
- ],
- contactPerson: [
- { required: true, message: "鑱旂郴浜轰笉鑳戒负绌�", trigger: "blur" },
- ],
- contactPhone: [
- { required: true, message: "鑱旂郴鐢佃瘽涓嶈兘涓虹┖", trigger: "blur" },
- { pattern: /^1[3|4|5|6|7|8|9][0-9]\d{8}$/, message: "璇疯緭鍏ユ纭殑鎵嬫満鍙风爜", trigger: "blur" },
- ],
- contactEmail: [
- { type: "email", message: "璇疯緭鍏ユ纭殑閭鍦板潃", trigger: ["blur", "change"] },
- ],
- address: [
- { required: true, message: "鍦板潃涓嶈兘涓虹┖", trigger: "blur" },
- ],
- },
-});
-
-const { queryParams, form, rules } = toRefs(data);
-
-// 妯℃嫙鏁版嵁
-const mockContractors = [
- {
- contractorId: 1,
- contractorName: "鍖椾含寤哄伐闆嗗洟",
- contactPerson: "寮犱笁",
- contactPhone: "13800138001",
- contactEmail: "zhangsan@example.com",
- address: "鍖椾含甯傛湞闃冲尯寤哄浗璺�88鍙�",
- status: "0",
- createTime: "2024-01-01 10:00:00",
- remark: "澶у瀷寤虹瓚鏂藉伐浼佷笟",
- },
- {
- contractorId: 2,
- contractorName: "涓婃捣鍩庡缓闆嗗洟",
- contactPerson: "鏉庡洓",
- contactPhone: "13800138002",
- contactEmail: "lisi@example.com",
- address: "涓婃捣甯傛郸涓滄柊鍖轰笘绾ぇ閬�100鍙�",
- status: "0",
- createTime: "2024-01-02 10:00:00",
- remark: "鍩庡競鍩虹璁炬柦寤鸿浼佷笟",
- },
- {
- contractorId: 3,
- contractorName: "骞垮窞寤虹瓚闆嗗洟",
- contactPerson: "鐜嬩簲",
- contactPhone: "13800138003",
- contactEmail: "wangwu@example.com",
- address: "骞垮窞甯傚ぉ娌冲尯鐝犳睙鏂板煄鍐兼潙璺�5鍙�",
- status: "1",
- createTime: "2024-01-03 10:00:00",
- remark: "骞夸笢鐪佺煡鍚嶅缓绛戜紒涓�",
- },
- {
- contractorId: 4,
- contractorName: "娣卞湷寤哄伐闆嗗洟",
- contactPerson: "璧靛叚",
- contactPhone: "13800138004",
- contactEmail: "zhaoliu@example.com",
- address: "娣卞湷甯傜鐢板尯绂忎腑涓夎矾1006鍙�",
- status: "0",
- createTime: "2024-01-04 10:00:00",
- remark: "娣卞湷甯傞噸鐐瑰缓绛戜紒涓�",
- },
- {
- contractorId: 5,
- contractorName: "鏉窞寤哄伐闆嗗洟",
- contactPerson: "瀛欎竷",
- contactPhone: "13800138005",
- contactEmail: "sunqi@example.com",
- address: "鏉窞甯傛睙骞插尯閽辨睙鏂板煄瀵屾槬璺�188鍙�",
- status: "0",
- createTime: "2024-01-05 10:00:00",
- remark: "娴欐睙鐪佺煡鍚嶅缓绛戜紒涓�",
- },
-];
-
-/** 鏌ヨ鎵垮寘鍟嗗垪琛� */
-function getList() {
- loading.value = true;
- // 妯℃嫙API璇锋眰寤惰繜
- setTimeout(() => {
- let data = [...mockContractors];
- // 妯℃嫙鎼滅储杩囨护
- if (queryParams.value.contractorName) {
- data = data.filter(item => item.contractorName.includes(queryParams.value.contractorName));
- }
- if (queryParams.value.contactPerson) {
- data = data.filter(item => item.contactPerson.includes(queryParams.value.contactPerson));
- }
- if (queryParams.value.contactPhone) {
- data = data.filter(item => item.contactPhone.includes(queryParams.value.contactPhone));
- }
- if (queryParams.value.status) {
- data = data.filter(item => item.status === queryParams.value.status);
- }
- // 妯℃嫙鍒嗛〉
- const start = (queryParams.value.pageNum - 1) * queryParams.value.pageSize;
- const end = start + queryParams.value.pageSize;
- contractorList.value = data.slice(start, end);
- total.value = data.length;
- loading.value = false;
- }, 500);
-}
-
-/** 鎼滅储鎸夐挳鎿嶄綔 */
-function handleQuery() {
- queryParams.value.pageNum = 1;
- getList();
-}
-
-/** 閲嶇疆鎸夐挳鎿嶄綔 */
-function resetQuery() {
- Object.assign(queryParams.value, {
- contractorName: undefined,
- contactPerson: undefined,
- contactPhone: undefined,
- status: undefined,
- });
- handleQuery();
-}
-
-/** 鍒犻櫎鎸夐挳鎿嶄綔 */
-function handleDelete(row) {
- const contractorIds = row.contractorId || ids.value;
- ElMessage.confirm(`鏄惁纭鍒犻櫎鎵垮寘鍟嗙紪鍙蜂负"${contractorIds}"鐨勬暟鎹」锛焋).then(() => {
- // 妯℃嫙鍒犻櫎鎿嶄綔
- ElMessage.success("鍒犻櫎鎴愬姛");
- getList();
- }).catch(() => {});
-}
-
-/** 鐘舵�佷慨鏀� */
-function handleStatusChange(row) {
- let text = row.status === "0" ? "鍚敤" : "鍋滅敤";
- ElMessage.confirm(`纭瑕�"${text}""${row.contractorName}"鎵垮寘鍟嗗悧?`).then(() => {
- // 妯℃嫙鐘舵�佷慨鏀�
- ElMessage.success(text + "鎴愬姛");
- getList();
- }).catch(() => {
- row.status = row.status === "0" ? "1" : "0";
- });
-}
-
-/** 閫夋嫨鏉℃暟 */
-function handleSelectionChange(selection) {
- ids.value = selection.map((item) => item.contractorId);
- single.value = selection.length != 1;
- multiple.value = !selection.length;
-}
-
-/** 閲嶇疆鎿嶄綔琛ㄥ崟 */
-function reset() {
- form.value = {
- contractorId: undefined,
- contractorName: undefined,
- contactPerson: undefined,
- contactPhone: undefined,
- contactEmail: undefined,
- address: undefined,
- status: "0",
- remark: undefined,
- };
-}
-
-/** 鍙栨秷鎸夐挳 */
-function cancel() {
- open.value = false;
- reset();
-}
-
-/** 鏂板鎸夐挳鎿嶄綔 */
-function handleAdd() {
- reset();
- open.value = true;
- title.value = "娣诲姞鎵垮寘鍟�";
-}
-
-/** 淇敼鎸夐挳鎿嶄綔 */
-function handleUpdate(row) {
- reset();
- const contractorId = row.contractorId || ids.value;
- // 妯℃嫙鑾峰彇璇︽儏
- const contractor = mockContractors.find(item => item.contractorId === contractorId);
- if (contractor) {
- form.value = { ...contractor };
- open.value = true;
- title.value = "淇敼鎵垮寘鍟�";
- }
-}
-
-/** 鎻愪氦鎸夐挳 */
-function submitForm() {
- // 妯℃嫙琛ㄥ崟楠岃瘉
- const requiredFields = ['contractorName', 'contactPerson', 'contactPhone', 'address'];
- const isInvalid = requiredFields.some(field => !form.value[field]);
-
- if (isInvalid) {
- ElMessage.error("璇峰~鍐欏繀濉瓧娈�");
- return;
- }
-
- // 妯℃嫙鎻愪氦鎿嶄綔
- ElMessage.success(title.value === "娣诲姞鎵垮寘鍟�" ? "鏂板鎴愬姛" : "淇敼鎴愬姛");
- open.value = false;
- getList();
-}
-
-// 妯℃嫙瀛楀吀鏁版嵁
-const sys_normal_disable = [
- { value: "0", label: "姝e父" },
- { value: "1", label: "绂佺敤" },
-];
-
-onMounted(() => {
- getList();
-});
-</script>
diff --git a/src/views/dashboard/Dashboard.vue b/src/views/dashboard/Dashboard.vue
new file mode 100644
index 0000000..08a21ec
--- /dev/null
+++ b/src/views/dashboard/Dashboard.vue
@@ -0,0 +1,301 @@
+<template>
+ <div class="dashboard-container">
+ <!-- 缁熻鍗$墖 -->
+ <el-row :gutter="20">
+ <el-col :span="6">
+ <el-card class="statistics-card" shadow="hover">
+ <div class="card-content">
+ <div class="card-title">璁惧鍦ㄧ嚎鐜�</div>
+ <div class="card-value">{{ onlineRate }}%</div>
+ <div class="card-desc">褰撳墠鍦ㄧ嚎璁惧鏁帮細{{ onlineCount }} / {{ totalDevices }}</div>
+ </div>
+ </el-card>
+ </el-col>
+ <el-col :span="6">
+ <el-card class="statistics-card" shadow="hover">
+ <div class="card-content">
+ <div class="card-title">鏁呴殰棰勮鏁�</div>
+ <div class="card-value">{{ warningCount }}</div>
+ <div class="card-desc">楂橀闄╋細{{ highRiskCount }} | 涓闄╋細{{ mediumRiskCount }} | 浣庨闄╋細{{ lowRiskCount }}</div>
+ </div>
+ </el-card>
+ </el-col>
+ <el-col :span="6">
+ <el-card class="statistics-card" shadow="hover">
+ <div class="card-content">
+ <div class="card-title">寰呭鐞嗙淮淇崟</div>
+ <div class="card-value">{{ pendingOrders }}</div>
+ <div class="card-desc">澶勭悊涓細{{ processingOrders }} | 宸插畬鎴愶細{{ completedOrders }}</div>
+ </div>
+ </el-card>
+ </el-col>
+ <el-col :span="6">
+ <el-card class="statistics-card" shadow="hover">
+ <div class="card-content">
+ <div class="card-title">閲嶇偣璁惧杩愯鐘舵��</div>
+ <div class="card-value">{{ normalDevices }} 姝e父</div>
+ <div class="card-desc">寮傚父锛歿{ abnormalDevices }} | 鏁呴殰锛歿{ faultDevices }}</div>
+ </div>
+ </el-card>
+ </el-col>
+ </el-row>
+
+ <!-- 鍥捐〃鍖哄煙 -->
+ <el-row :gutter="20" style="margin-top: 20px;">
+ <!-- 璁惧鍋ュ悍搴﹁秼鍔垮浘 -->
+ <el-col :span="12">
+ <el-card shadow="hover">
+ <template #header>
+ <div class="card-header">
+ <span>璁惧鍋ュ悍搴﹁秼鍔垮浘</span>
+ </div>
+ </template>
+ <div ref="healthChartRef" class="chart-container"></div>
+ </el-card>
+ </el-col>
+ <!-- 杩�7鏃ユ晠闅滅被鍨嬬粺璁� -->
+ <el-col :span="12">
+ <el-card shadow="hover">
+ <template #header>
+ <div class="card-header">
+ <span>杩�7鏃ユ晠闅滅被鍨嬬粺璁�</span>
+ </div>
+ </template>
+ <div ref="faultChartRef" class="chart-container"></div>
+ </el-card>
+ </el-col>
+ </el-row>
+
+ <!-- 閲嶇偣璁惧杩愯鐘舵�佸崱鐗� -->
+ <el-card shadow="hover" style="margin-top: 20px;">
+ <template #header>
+ <div class="card-header">
+ <span>閲嶇偣璁惧杩愯鐘舵��</span>
+ </div>
+ </template>
+ <el-table :data="keyDevices" stripe style="width: 100%">
+ <el-table-column prop="name" label="璁惧鍚嶇О" width="180"></el-table-column>
+ <el-table-column prop="model" label="鍨嬪彿" width="120"></el-table-column>
+ <el-table-column prop="ip" label="IP鍦板潃" width="150"></el-table-column>
+ <el-table-column prop="status" label="鐘舵��" width="100">
+ <template #default="scope">
+ <el-tag :type="scope.row.status === 'online' ? 'success' : scope.row.status === 'warning' ? 'warning' : 'danger'">
+ {{ scope.row.status === 'online' ? '鍦ㄧ嚎' : scope.row.status === 'warning' ? '棰勮' : '鏁呴殰' }}
+ </el-tag>
+ </template>
+ </el-table-column>
+ <el-table-column prop="temperature" label="娓╁害(鈩�)" width="100"></el-table-column>
+ <el-table-column prop="pressure" label="鍘嬪姏(MPa)" width="100"></el-table-column>
+ <el-table-column prop="speed" label="杞��(rpm)" width="100"></el-table-column>
+ <el-table-column prop="health" label="鍋ュ悍搴�" width="120">
+ <template #default="scope">
+ <el-progress :percentage="scope.row.health" :stroke-width="10"></el-progress>
+ </template>
+ </el-table-column>
+ </el-table>
+ </el-card>
+ </div>
+</template>
+
+<script setup>
+import { ref, onMounted, onUnmounted } from 'vue'
+import * as echarts from 'echarts'
+
+// 缁熻鏁版嵁
+const onlineRate = ref(85)
+const onlineCount = ref(170)
+const totalDevices = ref(200)
+const warningCount = ref(23)
+const highRiskCount = ref(5)
+const mediumRiskCount = ref(12)
+const lowRiskCount = ref(6)
+const pendingOrders = ref(15)
+const processingOrders = ref(8)
+const completedOrders = ref(45)
+const normalDevices = ref(162)
+const abnormalDevices = ref(18)
+const faultDevices = ref(10)
+
+// 閲嶇偣璁惧鍒楄〃
+const keyDevices = ref([
+ { name: '绌哄帇鏈篈-001', model: 'KA-200', ip: '192.168.1.101', status: 'online', temperature: 42, pressure: 0.8, speed: 1450, health: 92 },
+ { name: '鍐峰嵈濉擝-002', model: 'CT-300', ip: '192.168.1.102', status: 'warning', temperature: 58, pressure: 0.6, speed: 980, health: 75 },
+ { name: '姘存车C-003', model: 'WP-150', ip: '192.168.1.103', status: 'online', temperature: 38, pressure: 1.2, speed: 1200, health: 88 },
+ { name: '鍙戠數鏈篋-004', model: 'GE-500', ip: '192.168.1.104', status: 'danger', temperature: 75, pressure: 0.5, speed: 1500, health: 60 },
+ { name: '鍙樺帇鍣‥-005', model: 'TR-1000', ip: '192.168.1.105', status: 'online', temperature: 45, pressure: 0, speed: 0, health: 95 }
+])
+
+// 鍥捐〃寮曠敤
+const healthChartRef = ref(null)
+const faultChartRef = ref(null)
+let healthChart = null
+let faultChart = null
+
+// 鍋ュ悍搴﹁秼鍔挎暟鎹�
+const healthTrendData = {
+ dates: ['12-10', '12-11', '12-12', '12-13', '12-14', '12-15', '12-16'],
+ values: [88, 90, 85, 87, 92, 91, 93]
+}
+
+// 鏁呴殰绫诲瀷缁熻鏁版嵁
+const faultTypeData = {
+ types: ['娓╁害寮傚父', '鍘嬪姏瓒呮爣', '杞�熷紓甯�', '鎸姩杩囧ぇ', '鍏朵粬'],
+ values: [15, 8, 12, 6, 3]
+}
+
+// 鍒濆鍖栧仴搴峰害瓒嬪娍鍥�
+const initHealthChart = () => {
+ if (healthChartRef.value) {
+ healthChart = echarts.init(healthChartRef.value)
+ const option = {
+ tooltip: {
+ trigger: 'axis',
+ axisPointer: {
+ type: 'cross',
+ label: {
+ backgroundColor: '#6a7985'
+ }
+ }
+ },
+ grid: {
+ left: '3%',
+ right: '4%',
+ bottom: '3%',
+ containLabel: true
+ },
+ xAxis: {
+ type: 'category',
+ boundaryGap: false,
+ data: healthTrendData.dates
+ },
+ yAxis: {
+ type: 'value',
+ min: 70,
+ max: 100,
+ name: '鍋ュ悍搴�(%)'
+ },
+ series: [
+ {
+ name: '鍋ュ悍搴�',
+ type: 'line',
+ stack: '鎬婚噺',
+ areaStyle: {},
+ emphasis: {
+ focus: 'series'
+ },
+ data: healthTrendData.values,
+ itemStyle: {
+ color: '#67c23a'
+ },
+ lineStyle: {
+ width: 3
+ }
+ }
+ ]
+ }
+ healthChart.setOption(option)
+ }
+}
+
+// 鍒濆鍖栨晠闅滅被鍨嬬粺璁¢ゼ鍥�
+const initFaultChart = () => {
+ if (faultChartRef.value) {
+ faultChart = echarts.init(faultChartRef.value)
+ const option = {
+ tooltip: {
+ trigger: 'item'
+ },
+ legend: {
+ orient: 'vertical',
+ left: 'left'
+ },
+ series: [
+ {
+ name: '鏁呴殰绫诲瀷',
+ type: 'pie',
+ radius: '50%',
+ data: faultTypeData.types.map((type, index) => ({
+ name: type,
+ value: faultTypeData.values[index]
+ })),
+ emphasis: {
+ itemStyle: {
+ shadowBlur: 10,
+ shadowOffsetX: 0,
+ shadowColor: 'rgba(0, 0, 0, 0.5)'
+ }
+ }
+ }
+ ]
+ }
+ faultChart.setOption(option)
+ }
+}
+
+// 鐩戝惉绐楀彛澶у皬鍙樺寲锛岃皟鏁村浘琛ㄥぇ灏�
+const handleResize = () => {
+ healthChart?.resize()
+ faultChart?.resize()
+}
+
+onMounted(() => {
+ initHealthChart()
+ initFaultChart()
+ window.addEventListener('resize', handleResize)
+})
+
+onUnmounted(() => {
+ window.removeEventListener('resize', handleResize)
+ healthChart?.dispose()
+ faultChart?.dispose()
+})
+</script>
+
+<style scoped>
+.dashboard-container {
+ padding: 20px;
+ background-color: #f5f7fa;
+ min-height: 100vh;
+}
+
+.statistics-card {
+ height: 180px;
+}
+
+.card-content {
+ display: flex;
+ flex-direction: column;
+ height: 100%;
+ justify-content: center;
+ align-items: center;
+}
+
+.card-title {
+ font-size: 16px;
+ color: #606266;
+ margin-bottom: 10px;
+}
+
+.card-value {
+ font-size: 32px;
+ font-weight: bold;
+ color: #303133;
+ margin-bottom: 8px;
+}
+
+.card-desc {
+ font-size: 14px;
+ color: #909399;
+}
+
+.card-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+}
+
+.chart-container {
+ width: 100%;
+ height: 350px;
+}
+</style>
\ No newline at end of file
diff --git a/src/views/device/DeviceManagement.vue b/src/views/device/DeviceManagement.vue
new file mode 100644
index 0000000..80ccd27
--- /dev/null
+++ b/src/views/device/DeviceManagement.vue
@@ -0,0 +1,513 @@
+<template>
+ <div class="device-management-container">
+ <el-card shadow="hover">
+ <template #header>
+ <div class="card-header">
+ <span>璁惧绠$悊</span>
+ <div class="header-buttons">
+ <el-button type="primary" @click="showAddDeviceDialog">
+ <el-icon-plus /> 娣诲姞璁惧
+ </el-button>
+ <el-button @click="exportDevices">
+ <el-icon-download /> 瀵煎嚭
+ </el-button>
+ <el-button @click="showImportDialog">
+ <el-icon-upload /> 瀵煎叆
+ </el-button>
+ </div>
+ </div>
+ </template>
+
+ <!-- 绛涢�夋潯浠� -->
+ <el-form :inline="true" :model="filterForm" class="device-filter-form">
+ <el-form-item label="璁惧鍚嶇О">
+ <el-input v-model="filterForm.name" placeholder="璇疯緭鍏ヨ澶囧悕绉�" clearable></el-input>
+ </el-form-item>
+ <el-form-item label="鍨嬪彿">
+ <el-input v-model="filterForm.model" placeholder="璇疯緭鍏ュ瀷鍙�" clearable></el-input>
+ </el-form-item>
+ <el-form-item label="鐘舵��">
+ <el-select v-model="filterForm.status" placeholder="璇烽�夋嫨鐘舵��" clearable>
+ <el-option label="鍦ㄧ嚎" value="online"></el-option>
+ <el-option label="绂荤嚎" value="offline"></el-option>
+ <el-option label="鏁呴殰" value="fault"></el-option>
+ </el-select>
+ </el-form-item>
+ <el-form-item>
+ <el-button type="primary" @click="handleFilter">鏌ヨ</el-button>
+ <el-button @click="resetFilter">閲嶇疆</el-button>
+ </el-form-item>
+ </el-form>
+
+ <!-- 璁惧鍒楄〃 -->
+ <el-table :data="filteredDevices" stripe style="width: 100%" @selection-change="handleSelectionChange">
+ <el-table-column type="selection" width="55"></el-table-column>
+ <el-table-column prop="id" label="璁惧ID" width="100"></el-table-column>
+ <el-table-column prop="name" label="璁惧鍚嶇О" width="180"></el-table-column>
+ <el-table-column prop="model" label="鍨嬪彿" width="120"></el-table-column>
+ <el-table-column prop="ip" label="IP鍦板潃" width="150"></el-table-column>
+ <el-table-column prop="status" label="鐘舵��" width="100">
+ <template #default="scope">
+ <el-tag :type="scope.row.status === 'online' ? 'success' : scope.row.status === 'offline' ? 'info' : 'danger'">
+ {{ scope.row.status === 'online' ? '鍦ㄧ嚎' : scope.row.status === 'offline' ? '绂荤嚎' : '鏁呴殰' }}
+ </el-tag>
+ </template>
+ </el-table-column>
+ <el-table-column prop="location" label="瀹夎浣嶇疆" width="180"></el-table-column>
+ <el-table-column prop="installDate" label="瀹夎鏃ユ湡" width="150"></el-table-column>
+ <el-table-column prop="manufacturer" label="鍒堕�犲晢" width="150"></el-table-column>
+ <el-table-column label="鎿嶄綔" width="220" fixed="right">
+ <template #default="scope">
+ <el-button type="text" size="small" @click="showDeviceDetail(scope.row)">
+ 璇︽儏
+ </el-button>
+ <el-button type="text" size="small" @click="showEditDeviceDialog(scope.row)">
+ 缂栬緫
+ </el-button>
+ <el-button type="text" size="small" @click="handleDelete(scope.row)">
+ 鍒犻櫎
+ </el-button>
+ </template>
+ </el-table-column>
+ </el-table>
+
+ <!-- 鍒嗛〉 -->
+ <div class="pagination-container">
+ <el-pagination
+ background
+ layout="total, sizes, prev, pager, next, jumper"
+ :total="filteredDevices.length"
+ :current-page="currentPage"
+ :page-sizes="[10, 20, 50, 100]"
+ :page-size="pageSize"
+ @size-change="handleSizeChange"
+ @current-change="handleCurrentChange"
+ ></el-pagination>
+ </div>
+ </el-card>
+
+ <!-- 娣诲姞璁惧瀵硅瘽妗� -->
+ <el-dialog v-model="addDeviceDialogVisible" title="娣诲姞璁惧" width="600px">
+ <el-form :model="deviceForm" :rules="deviceRules" ref="deviceFormRef" label-width="100px">
+ <el-form-item label="璁惧鍚嶇О" prop="name">
+ <el-input v-model="deviceForm.name" placeholder="璇疯緭鍏ヨ澶囧悕绉�"></el-input>
+ </el-form-item>
+ <el-form-item label="鍨嬪彿" prop="model">
+ <el-input v-model="deviceForm.model" placeholder="璇疯緭鍏ュ瀷鍙�"></el-input>
+ </el-form-item>
+ <el-form-item label="IP鍦板潃" prop="ip">
+ <el-input v-model="deviceForm.ip" placeholder="璇疯緭鍏P鍦板潃"></el-input>
+ </el-form-item>
+ <el-form-item label="瀹夎浣嶇疆" prop="location">
+ <el-input v-model="deviceForm.location" placeholder="璇疯緭鍏ュ畨瑁呬綅缃�"></el-input>
+ </el-form-item>
+ <el-form-item label="鍒堕�犲晢" prop="manufacturer">
+ <el-input v-model="deviceForm.manufacturer" placeholder="璇疯緭鍏ュ埗閫犲晢"></el-input>
+ </el-form-item>
+ <el-form-item label="瀹夎鏃ユ湡" prop="installDate">
+ <el-date-picker v-model="deviceForm.installDate" type="date" placeholder="閫夋嫨瀹夎鏃ユ湡" style="width: 100%"></el-date-picker>
+ </el-form-item>
+ <el-form-item label="鐘舵��" prop="status">
+ <el-select v-model="deviceForm.status" placeholder="璇烽�夋嫨鐘舵��">
+ <el-option label="鍦ㄧ嚎" value="online"></el-option>
+ <el-option label="绂荤嚎" value="offline"></el-option>
+ <el-option label="鏁呴殰" value="fault"></el-option>
+ </el-select>
+ </el-form-item>
+ </el-form>
+ <template #footer>
+ <span class="dialog-footer">
+ <el-button @click="addDeviceDialogVisible = false">鍙栨秷</el-button>
+ <el-button type="primary" @click="handleAddDevice">纭畾</el-button>
+ </span>
+ </template>
+ </el-dialog>
+
+ <!-- 缂栬緫璁惧瀵硅瘽妗� -->
+ <el-dialog v-model="editDeviceDialogVisible" title="缂栬緫璁惧" width="600px">
+ <el-form :model="deviceForm" :rules="deviceRules" ref="deviceFormRef" label-width="100px">
+ <el-form-item label="璁惧鍚嶇О" prop="name">
+ <el-input v-model="deviceForm.name" placeholder="璇疯緭鍏ヨ澶囧悕绉�"></el-input>
+ </el-form-item>
+ <el-form-item label="鍨嬪彿" prop="model">
+ <el-input v-model="deviceForm.model" placeholder="璇疯緭鍏ュ瀷鍙�"></el-input>
+ </el-form-item>
+ <el-form-item label="IP鍦板潃" prop="ip">
+ <el-input v-model="deviceForm.ip" placeholder="璇疯緭鍏P鍦板潃"></el-input>
+ </el-form-item>
+ <el-form-item label="瀹夎浣嶇疆" prop="location">
+ <el-input v-model="deviceForm.location" placeholder="璇疯緭鍏ュ畨瑁呬綅缃�"></el-input>
+ </el-form-item>
+ <el-form-item label="鍒堕�犲晢" prop="manufacturer">
+ <el-input v-model="deviceForm.manufacturer" placeholder="璇疯緭鍏ュ埗閫犲晢"></el-input>
+ </el-form-item>
+ <el-form-item label="瀹夎鏃ユ湡" prop="installDate">
+ <el-date-picker v-model="deviceForm.installDate" type="date" placeholder="閫夋嫨瀹夎鏃ユ湡" style="width: 100%"></el-date-picker>
+ </el-form-item>
+ <el-form-item label="鐘舵��" prop="status">
+ <el-select v-model="deviceForm.status" placeholder="璇烽�夋嫨鐘舵��">
+ <el-option label="鍦ㄧ嚎" value="online"></el-option>
+ <el-option label="绂荤嚎" value="offline"></el-option>
+ <el-option label="鏁呴殰" value="fault"></el-option>
+ </el-select>
+ </el-form-item>
+ </el-form>
+ <template #footer>
+ <span class="dialog-footer">
+ <el-button @click="editDeviceDialogVisible = false">鍙栨秷</el-button>
+ <el-button type="primary" @click="handleEditDevice">纭畾</el-button>
+ </span>
+ </template>
+ </el-dialog>
+
+ <!-- 璁惧璇︽儏瀵硅瘽妗� -->
+ <el-dialog v-model="deviceDetailDialogVisible" title="璁惧璇︽儏" width="600px">
+ <el-descriptions :column="1" border>
+ <el-descriptions-item label="璁惧鍚嶇О">{{ selectedDevice.name }}</el-descriptions-item>
+ <el-descriptions-item label="璁惧ID">{{ selectedDevice.id }}</el-descriptions-item>
+ <el-descriptions-item label="鍨嬪彿">{{ selectedDevice.model }}</el-descriptions-item>
+ <el-descriptions-item label="IP鍦板潃">{{ selectedDevice.ip }}</el-descriptions-item>
+ <el-descriptions-item label="鐘舵��">
+ <el-tag :type="selectedDevice.status === 'online' ? 'success' : selectedDevice.status === 'offline' ? 'info' : 'danger'">
+ {{ selectedDevice.status === 'online' ? '鍦ㄧ嚎' : selectedDevice.status === 'offline' ? '绂荤嚎' : '鏁呴殰' }}
+ </el-tag>
+ </el-descriptions-item>
+ <el-descriptions-item label="瀹夎浣嶇疆">{{ selectedDevice.location }}</el-descriptions-item>
+ <el-descriptions-item label="鍒堕�犲晢">{{ selectedDevice.manufacturer }}</el-descriptions-item>
+ <el-descriptions-item label="瀹夎鏃ユ湡">{{ selectedDevice.installDate }}</el-descriptions-item>
+ <el-descriptions-item label="鍒涘缓鏃堕棿">{{ selectedDevice.createTime }}</el-descriptions-item>
+ </el-descriptions>
+ <template #footer>
+ <span class="dialog-footer">
+ <el-button @click="deviceDetailDialogVisible = false">鍏抽棴</el-button>
+ </span>
+ </template>
+ </el-dialog>
+
+ <!-- 瀵煎叆瀵硅瘽妗� -->
+ <el-dialog v-model="importDialogVisible" title="瀵煎叆璁惧" width="400px">
+ <el-upload
+ class="upload-demo"
+ action="#"
+ :on-change="handleFileChange"
+ :auto-upload="false"
+ accept=".xlsx,.xls"
+ >
+ <el-button type="primary">閫夋嫨鏂囦欢</el-button>
+ <template #tip>
+ <div class="el-upload__tip">
+ 鍙兘涓婁紶 xlsx/xls 鏂囦欢锛屼笖涓嶈秴杩� 2MB
+ </div>
+ </template>
+ </el-upload>
+ <template #footer>
+ <span class="dialog-footer">
+ <el-button @click="importDialogVisible = false">鍙栨秷</el-button>
+ <el-button type="primary" @click="handleImport">纭畾</el-button>
+ </span>
+ </template>
+ </el-dialog>
+ </div>
+</template>
+
+<script setup>
+import { ref, computed } from 'vue'
+
+// 璁惧鍒楄〃鏁版嵁
+const devices = ref([
+ {
+ id: 'D001',
+ name: '绌哄帇鏈篈-001',
+ model: 'KA-200',
+ ip: '192.168.1.101',
+ status: 'online',
+ location: '杞﹂棿A-1鍖�',
+ manufacturer: '搴锋櫘鏂�',
+ installDate: '2023-05-10',
+ createTime: '2023-05-10 10:30:00'
+ },
+ {
+ id: 'D002',
+ name: '鍐峰嵈濉擝-002',
+ model: 'CT-300',
+ ip: '192.168.1.102',
+ status: 'warning',
+ location: '杞﹂棿B-2鍖�',
+ manufacturer: '鑹満',
+ installDate: '2023-06-15',
+ createTime: '2023-06-15 14:20:00'
+ },
+ {
+ id: 'D003',
+ name: '姘存车C-003',
+ model: 'WP-150',
+ ip: '192.168.1.103',
+ status: 'online',
+ location: '杞﹂棿C-3鍖�',
+ manufacturer: '鏍煎叞瀵�',
+ installDate: '2023-07-20',
+ createTime: '2023-07-20 09:15:00'
+ },
+ {
+ id: 'D004',
+ name: '鍙戠數鏈篋-004',
+ model: 'GE-500',
+ ip: '192.168.1.104',
+ status: 'fault',
+ location: '鏈烘埧',
+ manufacturer: '鍗$壒褰煎嫆',
+ installDate: '2023-08-25',
+ createTime: '2023-08-25 16:45:00'
+ },
+ {
+ id: 'D005',
+ name: '鍙樺帇鍣‥-005',
+ model: 'TR-1000',
+ ip: '192.168.1.105',
+ status: 'online',
+ location: '閰嶇數鎴�',
+ manufacturer: 'ABB',
+ installDate: '2023-09-30',
+ createTime: '2023-09-30 11:20:00'
+ }
+])
+
+// 绛涢�夎〃鍗�
+const filterForm = ref({
+ name: '',
+ model: '',
+ status: ''
+})
+
+// 鍒嗛〉鏁版嵁
+const currentPage = ref(1)
+const pageSize = ref(10)
+
+// 瀵硅瘽妗嗙姸鎬�
+const addDeviceDialogVisible = ref(false)
+const editDeviceDialogVisible = ref(false)
+const deviceDetailDialogVisible = ref(false)
+const importDialogVisible = ref(false)
+
+// 璁惧琛ㄥ崟鏁版嵁
+const deviceForm = ref({
+ id: '',
+ name: '',
+ model: '',
+ ip: '',
+ status: 'online',
+ location: '',
+ manufacturer: '',
+ installDate: ''
+})
+
+// 琛ㄥ崟楠岃瘉瑙勫垯
+const deviceRules = ref({
+ name: [{ required: true, message: '璇疯緭鍏ヨ澶囧悕绉�', trigger: 'blur' }],
+ model: [{ required: true, message: '璇疯緭鍏ュ瀷鍙�', trigger: 'blur' }],
+ ip: [{ required: true, message: '璇疯緭鍏P鍦板潃', trigger: 'blur' }],
+ location: [{ required: true, message: '璇疯緭鍏ュ畨瑁呬綅缃�', trigger: 'blur' }],
+ manufacturer: [{ required: true, message: '璇疯緭鍏ュ埗閫犲晢', trigger: 'blur' }],
+ installDate: [{ required: true, message: '璇烽�夋嫨瀹夎鏃ユ湡', trigger: 'change' }],
+ status: [{ required: true, message: '璇烽�夋嫨鐘舵��', trigger: 'change' }]
+})
+
+// 琛ㄥ崟寮曠敤
+const deviceFormRef = ref(null)
+
+// 閫変腑鐨勮澶�
+const selectedDevice = ref({})
+
+// 閫変腑鐨勮澶囧垪琛紙鐢ㄤ簬鎵归噺鎿嶄綔锛�
+const selectedDevices = ref([])
+
+// 瀵煎叆鐨勬枃浠�
+const importFile = ref(null)
+
+// 杩囨护鍚庣殑璁惧鍒楄〃
+const filteredDevices = computed(() => {
+ let result = [...devices.value]
+
+ // 鎸夊悕绉扮瓫閫�
+ if (filterForm.value.name) {
+ result = result.filter(device => device.name.includes(filterForm.value.name))
+ }
+
+ // 鎸夊瀷鍙风瓫閫�
+ if (filterForm.value.model) {
+ result = result.filter(device => device.model.includes(filterForm.value.model))
+ }
+
+ // 鎸夌姸鎬佺瓫閫�
+ if (filterForm.value.status) {
+ result = result.filter(device => device.status === filterForm.value.status)
+ }
+
+ return result
+})
+
+// 鏄剧ず娣诲姞璁惧瀵硅瘽妗�
+const showAddDeviceDialog = () => {
+ // 閲嶇疆琛ㄥ崟
+ deviceForm.value = {
+ id: '',
+ name: '',
+ model: '',
+ ip: '',
+ status: 'online',
+ location: '',
+ manufacturer: '',
+ installDate: ''
+ }
+ addDeviceDialogVisible.value = true
+}
+
+// 鏄剧ず缂栬緫璁惧瀵硅瘽妗�
+const showEditDeviceDialog = (device) => {
+ deviceForm.value = { ...device }
+ editDeviceDialogVisible.value = true
+}
+
+// 鏄剧ず璁惧璇︽儏
+const showDeviceDetail = (device) => {
+ selectedDevice.value = { ...device }
+ deviceDetailDialogVisible.value = true
+}
+
+// 鏄剧ず瀵煎叆瀵硅瘽妗�
+const showImportDialog = () => {
+ importDialogVisible.value = true
+}
+
+// 澶勭悊娣诲姞璁惧
+const handleAddDevice = () => {
+ // 妯℃嫙娣诲姞璁惧
+ const newDevice = {
+ ...deviceForm.value,
+ id: `D${String(devices.value.length + 1).padStart(3, '0')}`,
+ createTime: new Date().toLocaleString()
+ }
+ devices.value.push(newDevice)
+ addDeviceDialogVisible.value = false
+ ElMessage.success('璁惧娣诲姞鎴愬姛')
+}
+
+// 澶勭悊缂栬緫璁惧
+const handleEditDevice = () => {
+ // 妯℃嫙缂栬緫璁惧
+ const index = devices.value.findIndex(device => device.id === deviceForm.value.id)
+ if (index !== -1) {
+ devices.value[index] = { ...deviceForm.value }
+ editDeviceDialogVisible.value = false
+ ElMessage.success('璁惧缂栬緫鎴愬姛')
+ }
+}
+
+// 澶勭悊鍒犻櫎璁惧
+const handleDelete = (device) => {
+ ElMessageBox.confirm('纭畾瑕佸垹闄よ璁惧鍚楋紵', '鎻愮ず', {
+ confirmButtonText: '纭畾',
+ cancelButtonText: '鍙栨秷',
+ type: 'warning'
+ }).then(() => {
+ // 妯℃嫙鍒犻櫎璁惧
+ const index = devices.value.findIndex(item => item.id === device.id)
+ if (index !== -1) {
+ devices.value.splice(index, 1)
+ ElMessage.success('璁惧鍒犻櫎鎴愬姛')
+ }
+ }).catch(() => {
+ // 鍙栨秷鍒犻櫎
+ })
+}
+
+// 澶勭悊绛涢��
+const handleFilter = () => {
+ // 绛涢�夐�昏緫宸茬粡鍦╟omputed涓疄鐜�
+}
+
+// 閲嶇疆绛涢�夋潯浠�
+const resetFilter = () => {
+ filterForm.value = {
+ name: '',
+ model: '',
+ status: ''
+ }
+}
+
+// 澶勭悊鍒嗛〉澶у皬鍙樺寲
+const handleSizeChange = (size) => {
+ pageSize.value = size
+ currentPage.value = 1
+}
+
+// 澶勭悊褰撳墠椤靛彉鍖�
+const handleCurrentChange = (current) => {
+ currentPage.value = current
+}
+
+// 澶勭悊鏂囦欢鍙樺寲锛堝鍏ワ級
+const handleFileChange = (file) => {
+ importFile.value = file
+}
+
+// 澶勭悊瀵煎叆
+const handleImport = () => {
+ // 妯℃嫙瀵煎叆
+ if (importFile.value) {
+ importDialogVisible.value = false
+ ElMessage.success('璁惧瀵煎叆鎴愬姛')
+ importFile.value = null
+ } else {
+ ElMessage.warning('璇烽�夋嫨瑕佸鍏ョ殑鏂囦欢')
+ }
+}
+
+// 瀵煎嚭璁惧
+const exportDevices = () => {
+ // 妯℃嫙瀵煎嚭
+ ElMessage.success('璁惧瀵煎嚭鎴愬姛')
+}
+
+// 澶勭悊閫夋嫨鍙樺寲锛堢敤浜庢壒閲忔搷浣滐級
+const handleSelectionChange = (selection) => {
+ selectedDevices.value = selection
+}
+</script>
+
+<style scoped>
+.device-management-container {
+ padding: 20px;
+ background-color: #f5f7fa;
+ min-height: 100vh;
+}
+
+.card-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+}
+
+.header-buttons {
+ display: flex;
+ gap: 10px;
+}
+
+.device-filter-form {
+ margin-bottom: 20px;
+ padding: 10px 0;
+ border-bottom: 1px solid #ebeef5;
+}
+
+.pagination-container {
+ display: flex;
+ justify-content: flex-end;
+ margin-top: 20px;
+}
+
+:deep(.el-icon-plus),
+:deep(.el-icon-download),
+:deep(.el-icon-upload) {
+ margin-right: 5px;
+}
+</style>
diff --git a/src/views/diagnosis/FaultDiagnosis.vue b/src/views/diagnosis/FaultDiagnosis.vue
new file mode 100644
index 0000000..a1cb864
--- /dev/null
+++ b/src/views/diagnosis/FaultDiagnosis.vue
@@ -0,0 +1,411 @@
+<template>
+ <div class="fault-diagnosis-container">
+ <el-row :gutter="20">
+ <!-- 宸︿晶锛氭晠闅滈璀﹀垪琛� -->
+ <el-col :span="12">
+ <el-card shadow="hover">
+ <template #header>
+ <div class="card-header">
+ <span>鏁呴殰棰勮鍒楄〃</span>
+ </div>
+ </template>
+ <el-table :data="warningList" stripe style="width: 100%" @row-click="handleWarningClick">
+ <el-table-column prop="deviceName" label="璁惧鍚嶇О" width="180"></el-table-column>
+ <el-table-column prop="warningType" label="棰勮绫诲瀷" width="120"></el-table-column>
+ <el-table-column prop="riskLevel" label="椋庨櫓绛夌骇" width="100">
+ <template #default="scope">
+ <el-tag :type="scope.row.riskLevel === 'high' ? 'danger' : scope.row.riskLevel === 'medium' ? 'warning' : 'info'">
+ {{ scope.row.riskLevel === 'high' ? '楂�' : scope.row.riskLevel === 'medium' ? '涓�' : '浣�' }}
+ </el-tag>
+ </template>
+ </el-table-column>
+ <el-table-column prop="occurTime" label="鍙戠敓鏃堕棿" width="180"></el-table-column>
+ <el-table-column prop="status" label="澶勭悊鐘舵��" width="100">
+ <template #default="scope">
+ <el-tag :type="scope.row.status === 'pending' ? 'warning' : 'success'">
+ {{ scope.row.status === 'pending' ? '寰呭鐞�' : '宸插鐞�' }}
+ </el-tag>
+ </template>
+ </el-table-column>
+ </el-table>
+ </el-card>
+
+ <!-- 鏁呴殰鍘嗗彶璁板綍鏌ヨ -->
+ <el-card shadow="hover" style="margin-top: 20px;">
+ <template #header>
+ <div class="card-header">
+ <span>鏁呴殰鍘嗗彶璁板綍</span>
+ </div>
+ </template>
+ <el-form :inline="true" :model="historyFilterForm" class="history-filter-form">
+ <el-form-item label="璁惧">
+ <el-select v-model="historyFilterForm.deviceId" placeholder="璇烽�夋嫨璁惧" clearable>
+ <el-option
+ v-for="device in devices"
+ :key="device.id"
+ :label="device.name"
+ :value="device.id"
+ ></el-option>
+ </el-select>
+ </el-form-item>
+ <el-form-item label="鏃堕棿鑼冨洿">
+ <el-date-picker
+ v-model="historyTimeRange"
+ type="daterange"
+ range-separator="鑷�"
+ start-placeholder="寮�濮嬫棩鏈�"
+ end-placeholder="缁撴潫鏃ユ湡"
+ ></el-date-picker>
+ </el-form-item>
+ <el-form-item>
+ <el-button type="primary" @click="handleHistorySearch">鏌ヨ</el-button>
+ </el-form-item>
+ </el-form>
+ <el-table :data="historyList" stripe style="width: 100%" size="small">
+ <el-table-column prop="deviceName" label="璁惧鍚嶇О" width="150"></el-table-column>
+ <el-table-column prop="faultType" label="鏁呴殰绫诲瀷" width="120"></el-table-column>
+ <el-table-column prop="occurTime" label="鍙戠敓鏃堕棿" width="150"></el-table-column>
+ <el-table-column prop="dealTime" label="澶勭悊鏃堕棿" width="150"></el-table-column>
+ <el-table-column prop="status" label="鐘舵��" width="100">
+ <template #default="scope">
+ <el-tag type="success">{{ scope.row.status }}</el-tag>
+ </template>
+ </el-table-column>
+ </el-table>
+ <div class="pagination-container">
+ <el-pagination
+ background
+ layout="total, prev, pager, next"
+ :total="historyList.length"
+ :page-size="5"
+ size="small"
+ ></el-pagination>
+ </div>
+ </el-card>
+ </el-col>
+
+ <!-- 鍙充晶锛氭晠闅滆瘖鏂粨鏋� -->
+ <el-col :span="12">
+ <!-- 鏁呴殰璇婃柇缁撴灉 -->
+ <el-card shadow="hover">
+ <template #header>
+ <div class="card-header">
+ <span>鏁呴殰璇婃柇缁撴灉</span>
+ <el-button type="primary" size="small" @click="handleDiagnosis">閲嶆柊璇婃柇</el-button>
+ </div>
+ </template>
+ <div v-if="currentWarning" class="diagnosis-result">
+ <h3>{{ currentWarning.deviceName }} - {{ currentWarning.warningType }}</h3>
+ <el-descriptions :column="1" border>
+ <el-descriptions-item label="椋庨櫓绛夌骇">
+ <el-tag :type="currentWarning.riskLevel === 'high' ? 'danger' : currentWarning.riskLevel === 'medium' ? 'warning' : 'info'">
+ {{ currentWarning.riskLevel === 'high' ? '楂�' : currentWarning.riskLevel === 'medium' ? '涓�' : '浣�' }}
+ </el-tag>
+ </el-descriptions-item>
+ <el-descriptions-item label="鍙戠敓鏃堕棿">{{ currentWarning.occurTime }}</el-descriptions-item>
+ <el-descriptions-item label="鍘熷洜鎺ㄦ祴">{{ diagnosisResult.reason }}</el-descriptions-item>
+ <el-descriptions-item label="褰卞搷鑼冨洿">{{ diagnosisResult.impact }}</el-descriptions-item>
+ <el-descriptions-item label="澶勭悊寤鸿">{{ diagnosisResult.suggestion }}</el-descriptions-item>
+ </el-descriptions>
+ </div>
+ <div v-else class="no-selection">
+ <el-empty description="璇烽�夋嫨涓�涓璀﹂」鏌ョ湅璇婃柇缁撴灉"></el-empty>
+ </div>
+ </el-card>
+
+ <!-- 棰勬祴鎬ц瘖鏂粨鏋� -->
+ <el-card shadow="hover" style="margin-top: 20px;">
+ <template #header>
+ <div class="card-header">
+ <span>棰勬祴鎬ц瘖鏂粨鏋滐紙鏈潵7鏃ユ晠闅滈闄╋級</span>
+ </div>
+ </template>
+ <div class="prediction-result">
+ <el-timeline>
+ <el-timeline-item
+ v-for="item in predictionList"
+ :key="item.date"
+ :timestamp="item.date"
+ :type="item.riskLevel === 'high' ? 'danger' : item.riskLevel === 'medium' ? 'warning' : 'success'"
+ >
+ <div class="timeline-content">
+ <h4>{{ item.deviceName }}</h4>
+ <p class="risk-level">
+ 椋庨櫓绛夌骇锛�
+ <el-tag :type="item.riskLevel === 'high' ? 'danger' : item.riskLevel === 'medium' ? 'warning' : 'success'">
+ {{ item.riskLevel === 'high' ? '楂�' : item.riskLevel === 'medium' ? '涓�' : '浣�' }}
+ </el-tag>
+ </p>
+ <p class="fault-type">鍙兘鏁呴殰绫诲瀷锛歿{ item.possibleFault }}</p>
+ <p class="probability">鍙戠敓姒傜巼锛歿{ item.probability }}%</p>
+ </div>
+ </el-timeline-item>
+ </el-timeline>
+ </div>
+ </el-card>
+ </el-col>
+ </el-row>
+ </div>
+</template>
+
+<script setup>
+import { ref, reactive } from 'vue'
+
+// 璁惧鍒楄〃
+const devices = ref([
+ { id: 'D001', name: '绌哄帇鏈篈-001' },
+ { id: 'D002', name: '鍐峰嵈濉擝-002' },
+ { id: 'D003', name: '姘存车C-003' },
+ { id: 'D004', name: '鍙戠數鏈篋-004' },
+ { id: 'D005', name: '鍙樺帇鍣‥-005' }
+])
+
+// 鏁呴殰棰勮鍒楄〃
+const warningList = ref([
+ {
+ id: 1,
+ deviceName: '绌哄帇鏈篈-001',
+ warningType: '鍘嬪姏寮傚父',
+ riskLevel: 'high',
+ occurTime: '2024-12-16 14:32:15',
+ status: 'pending'
+ },
+ {
+ id: 2,
+ deviceName: '鍐峰嵈濉擝-002',
+ warningType: '娓╁害杩囬珮',
+ riskLevel: 'medium',
+ occurTime: '2024-12-16 14:30:45',
+ status: 'pending'
+ },
+ {
+ id: 3,
+ deviceName: '姘存车C-003',
+ warningType: '鎸姩杩囧ぇ',
+ riskLevel: 'medium',
+ occurTime: '2024-12-16 14:28:30',
+ status: 'pending'
+ },
+ {
+ id: 4,
+ deviceName: '鍙戠數鏈篋-004',
+ warningType: '鐢垫祦寮傚父',
+ riskLevel: 'high',
+ occurTime: '2024-12-16 14:25:10',
+ status: 'pending'
+ },
+ {
+ id: 5,
+ deviceName: '鍙樺帇鍣‥-005',
+ warningType: '鐢靛帇娉㈠姩',
+ riskLevel: 'low',
+ occurTime: '2024-12-16 14:20:05',
+ status: 'pending'
+ }
+])
+
+// 褰撳墠閫変腑鐨勯璀﹂」
+const currentWarning = ref(warningList.value[0])
+
+// 鏁呴殰璇婃柇缁撴灉
+const diagnosisResult = reactive({
+ reason: '鏍规嵁璁惧杩愯鏁版嵁鎺ㄦ祴锛屾晠闅滃師鍥犲彲鑳芥槸璁惧鍐呴儴閮ㄤ欢纾ㄦ崯瀵艰嚧鐨勫帇鍔涘紓甯革紝闇�瑕佽繘涓�姝ユ鏌ヨ澶囩殑娲诲鐜拰姘旂几濂椼��',
+ impact: '濡傛灉涓嶅強鏃跺鐞嗭紝鍙兘瀵艰嚧璁惧鍋滄満锛屽奖鍝嶇敓浜х嚎鐨勬甯歌繍琛岋紝棰勮鍋滄満鏃堕棿涓�4-6灏忔椂銆�',
+ suggestion: '1. 绔嬪嵆瀹夋帓缁翠慨浜哄憳杩涜璁惧妫�鏌ワ紱2. 妫�鏌ヨ澶囩殑娲诲鐜拰姘旂几濂楋紱3. 鏇存崲纾ㄦ崯涓ラ噸鐨勯儴浠讹紱4. 妫�鏌ヨ澶囩殑娑︽粦绯荤粺锛岀‘淇濇鼎婊戞甯搞��'
+})
+
+// 棰勬祴鎬ц瘖鏂粨鏋�
+const predictionList = ref([
+ {
+ date: '2024-12-17',
+ deviceName: '绌哄帇鏈篈-001',
+ riskLevel: 'medium',
+ possibleFault: '鍘嬪姏寮傚父',
+ probability: 65
+ },
+ {
+ date: '2024-12-18',
+ deviceName: '鍐峰嵈濉擝-002',
+ riskLevel: 'high',
+ possibleFault: '娓╁害杩囬珮',
+ probability: 85
+ },
+ {
+ date: '2024-12-19',
+ deviceName: '姘存车C-003',
+ riskLevel: 'medium',
+ possibleFault: '鎸姩杩囧ぇ',
+ probability: 70
+ },
+ {
+ date: '2024-12-20',
+ deviceName: '鍙戠數鏈篋-004',
+ riskLevel: 'high',
+ possibleFault: '鐢垫祦寮傚父',
+ probability: 90
+ },
+ {
+ date: '2024-12-21',
+ deviceName: '鍙樺帇鍣‥-005',
+ riskLevel: 'low',
+ possibleFault: '鐢靛帇娉㈠姩',
+ probability: 45
+ },
+ {
+ date: '2024-12-22',
+ deviceName: '绌哄帇鏈篈-001',
+ riskLevel: 'high',
+ possibleFault: '鍘嬪姏寮傚父',
+ probability: 80
+ },
+ {
+ date: '2024-12-23',
+ deviceName: '鍐峰嵈濉擝-002',
+ riskLevel: 'medium',
+ possibleFault: '娓╁害杩囬珮',
+ probability: 60
+ }
+])
+
+// 鏁呴殰鍘嗗彶璁板綍鏌ヨ琛ㄥ崟
+const historyFilterForm = ref({
+ deviceId: ''
+})
+
+// 鍘嗗彶璁板綍鏃堕棿鑼冨洿
+const historyTimeRange = ref([])
+
+// 鏁呴殰鍘嗗彶璁板綍
+const historyList = ref([
+ {
+ id: 1,
+ deviceName: '绌哄帇鏈篈-001',
+ faultType: '鍘嬪姏寮傚父',
+ occurTime: '2024-12-15 08:30:00',
+ dealTime: '2024-12-15 10:45:00',
+ status: '宸插鐞�'
+ },
+ {
+ id: 2,
+ deviceName: '鍐峰嵈濉擝-002',
+ faultType: '娓╁害杩囬珮',
+ occurTime: '2024-12-14 14:20:00',
+ dealTime: '2024-12-14 16:15:00',
+ status: '宸插鐞�'
+ },
+ {
+ id: 3,
+ deviceName: '姘存车C-003',
+ faultType: '鎸姩杩囧ぇ',
+ occurTime: '2024-12-13 09:15:00',
+ dealTime: '2024-12-13 11:30:00',
+ status: '宸插鐞�'
+ },
+ {
+ id: 4,
+ deviceName: '鍙戠數鏈篋-004',
+ faultType: '鐢垫祦寮傚父',
+ occurTime: '2024-12-12 16:45:00',
+ dealTime: '2024-12-12 18:30:00',
+ status: '宸插鐞�'
+ },
+ {
+ id: 5,
+ deviceName: '鍙樺帇鍣‥-005',
+ faultType: '鐢靛帇娉㈠姩',
+ occurTime: '2024-12-11 11:20:00',
+ dealTime: '2024-12-11 13:15:00',
+ status: '宸插鐞�'
+ }
+])
+
+// 澶勭悊棰勮椤圭偣鍑�
+const handleWarningClick = (row) => {
+ currentWarning.value = row
+}
+
+// 閲嶆柊璇婃柇
+const handleDiagnosis = () => {
+ // 妯℃嫙閲嶆柊璇婃柇
+ ElMessage.success('閲嶆柊璇婃柇瀹屾垚')
+}
+
+// 澶勭悊鍘嗗彶璁板綍鏌ヨ
+const handleHistorySearch = () => {
+ // 妯℃嫙鏌ヨ鍘嗗彶璁板綍
+ ElMessage.success('鍘嗗彶璁板綍鏌ヨ鎴愬姛')
+}
+</script>
+
+<style scoped>
+.fault-diagnosis-container {
+ padding: 20px;
+ background-color: #f5f7fa;
+ min-height: 100vh;
+}
+
+.card-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+}
+
+.diagnosis-result h3 {
+ margin-bottom: 20px;
+ color: #303133;
+}
+
+.no-selection {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ height: 200px;
+}
+
+.prediction-result {
+ padding: 10px 0;
+}
+
+.timeline-content {
+ padding: 10px;
+ background-color: #fafafa;
+ border-radius: 4px;
+}
+
+.timeline-content h4 {
+ margin-bottom: 10px;
+ color: #303133;
+}
+
+.timeline-content p {
+ margin: 5px 0;
+ font-size: 14px;
+ color: #606266;
+}
+
+.risk-level {
+ display: flex;
+ align-items: center;
+ gap: 5px;
+}
+
+.fault-type {
+ color: #606266;
+}
+
+.probability {
+ color: #606266;
+}
+
+.history-filter-form {
+ margin-bottom: 20px;
+ padding: 10px 0;
+ border-bottom: 1px solid #ebeef5;
+}
+
+.pagination-container {
+ display: flex;
+ justify-content: flex-end;
+ margin-top: 20px;
+}
+</style>
\ No newline at end of file
diff --git a/src/views/index.vue b/src/views/index.vue
index dfd56e3..e9453f2 100644
--- a/src/views/index.vue
+++ b/src/views/index.vue
@@ -1,674 +1,392 @@
<template>
- <div class="dashboard">
- <!-- 椤堕儴妯悜涓ゆ爮 -->
- <div class="dashboard-top">
- <!-- 宸︼細绯荤粺姒傝+鏁版嵁鍗$墖 -->
- <div class="top-left">
- <div class="system-info">
- <div class="section-title">鎵垮寘鍟嗙鐞嗙郴缁�</div>
- <div style="display: flex; align-items: center; gap: 20px">
- <div class="system-card">
- <div class="system-name">鎵垮寘鍟嗙鐞嗙郴缁�</div>
- <div class="system-meta">璧勮川瀹℃牳 路 鍚堝悓绠$悊 路 缁╂晥璇勪及</div>
- </div>
- <div style="display: flex; align-items: center; gap: 8px">
- <el-icon color="#5053B5" size="22"><Clock /></el-icon>
- <span>褰撳墠鏃堕棿锛歿{ currentTime }}</span>
+ <div class="dashboard-container">
+ <!-- 缁熻鍗$墖 -->
+ <el-row :gutter="20">
+ <el-col :span="6">
+ <el-card class="statistics-card" shadow="hover">
+ <div class="card-content">
+ <div class="card-title">璁惧鍦ㄧ嚎鐜�</div>
+ <div class="card-value">{{ onlineRate }}%</div>
+ <div class="card-desc">
+ 褰撳墠鍦ㄧ嚎璁惧鏁帮細{{ onlineCount }} / {{ totalDevices }}
</div>
</div>
+ </el-card>
+ </el-col>
+ <el-col :span="6">
+ <el-card class="statistics-card" shadow="hover">
+ <div class="card-content">
+ <div class="card-title">鏁呴殰棰勮鏁�</div>
+ <div class="card-value">{{ warningCount }}</div>
+ <div class="card-desc">
+ 楂橀闄╋細{{ highRiskCount }} | 涓闄╋細{{ mediumRiskCount }} |
+ 浣庨闄╋細{{ lowRiskCount }}
+ </div>
+ </div>
+ </el-card>
+ </el-col>
+ <el-col :span="6">
+ <el-card class="statistics-card" shadow="hover">
+ <div class="card-content">
+ <div class="card-title">寰呭鐞嗙淮淇崟</div>
+ <div class="card-value">{{ pendingOrders }}</div>
+ <div class="card-desc">
+ 澶勭悊涓細{{ processingOrders }} | 宸插畬鎴愶細{{ completedOrders }}
+ </div>
+ </div>
+ </el-card>
+ </el-col>
+ <el-col :span="6">
+ <el-card class="statistics-card" shadow="hover">
+ <div class="card-content">
+ <div class="card-title">閲嶇偣璁惧杩愯鐘舵��</div>
+ <div class="card-value">{{ normalDevices }} 姝e父</div>
+ <div class="card-desc">
+ 寮傚父锛歿{ abnormalDevices }} | 鏁呴殰锛歿{ faultDevices }}
+ </div>
+ </div>
+ </el-card>
+ </el-col>
+ </el-row>
+
+ <!-- 鍥捐〃鍖哄煙 -->
+ <el-row :gutter="20" style="margin-top: 20px">
+ <!-- 璁惧鍋ュ悍搴﹁秼鍔垮浘 -->
+ <el-col :span="12">
+ <el-card shadow="hover">
+ <template #header>
+ <div class="card-header">
+ <span>璁惧鍋ュ悍搴﹁秼鍔垮浘</span>
+ </div>
+ </template>
+ <div ref="healthChartRef" class="chart-container"></div>
+ </el-card>
+ </el-col>
+ <!-- 杩�7鏃ユ晠闅滅被鍨嬬粺璁� -->
+ <el-col :span="12">
+ <el-card shadow="hover">
+ <template #header>
+ <div class="card-header">
+ <span>杩�7鏃ユ晠闅滅被鍨嬬粺璁�</span>
+ </div>
+ </template>
+ <div ref="faultChartRef" class="chart-container"></div>
+ </el-card>
+ </el-col>
+ </el-row>
+
+ <!-- 閲嶇偣璁惧杩愯鐘舵�佸崱鐗� -->
+ <el-card shadow="hover" style="margin-top: 20px">
+ <template #header>
+ <div class="card-header">
+ <span>閲嶇偣璁惧杩愯鐘舵��</span>
</div>
- <div class="data-cards">
- <div class="data-card total">
- <div class="data-title">鎬绘壙鍖呭晢鏁�</div>
- <div class="data-value">{{ contractorStats.total }}</div>
- <div class="data-desc">
- 宸插鏍� {{ contractorStats.approved }} | 寰呭鏍�
- {{ contractorStats.pending }}
- </div>
- </div>
- <div class="data-card pending">
- <div class="data-title">寰呭鏍告壙鍖呭晢</div>
- <div class="data-value">{{ contractorStats.pending }}</div>
- <div class="data-desc">
- A绾� {{ contractorStats.aPending }} | B绾�
- {{ contractorStats.bPending }} | C绾�
- {{ contractorStats.cPending }}
- </div>
- </div>
- <div class="data-card today">
- <div class="data-title">鏈湀鏂板</div>
- <div class="data-value">{{ contractorStats.monthly }}</div>
- <div class="data-desc">
- 鍚屾瘮 {{ contractorStats.monthly鍚屾瘮 }}% | 鐜瘮
- {{ contractorStats.monthly鐜瘮 }}%
- </div>
- </div>
- </div>
- </div>
- <!-- 鍙筹細寰呭鐞嗘姤璀﹀垪琛� -->
- <div class="alarm-panel">
- <div class="section-title">寰呭鏍告壙鍖呭晢</div>
- <ul class="alarm-list" v-if="pendingContractors.length > 0">
- <li v-for="item in pendingContractors" :key="item.id">
- <div
- style="
- display: flex;
- flex-direction: column;
- justify-content: space-between;
- width: 100%;
- gap: 10px;
+ </template>
+ <el-table :data="keyDevices" stripe style="width: 100%">
+ <el-table-column
+ prop="name"
+ label="璁惧鍚嶇О"
+ width="180"
+ ></el-table-column>
+ <el-table-column
+ prop="model"
+ label="鍨嬪彿"
+ width="120"
+ ></el-table-column>
+ <el-table-column prop="ip" label="IP鍦板潃" width="150"></el-table-column>
+ <el-table-column prop="status" label="鐘舵��" width="100">
+ <template #default="scope">
+ <el-tag
+ :type="
+ scope.row.status === 'online'
+ ? 'success'
+ : scope.row.status === 'warning'
+ ? 'warning'
+ : 'danger'
"
>
- <div
- style="
- display: flex;
- justify-content: space-between;
- align-items: center;
- "
- >
- <div class="alarm-title">{{ item.name }} - {{ item.type }}</div>
- <el-tag :type="getContractorLevelType(item.level)"
- >{{ item.level }}绾�</el-tag
- >
- </div>
- <div
- style="
- display: flex;
- justify-content: space-between;
- align-items: center;
- "
- >
- <div class="alarm-value">
- 鑱旂郴浜�: {{ item.contact }} | 娉ㄥ唽鏃堕棿: {{ item.registerDate }}
- </div>
- <div class="alarm-time">{{ item.applyDate }}</div>
- </div>
- </div>
- </li>
- </ul>
- <div v-else style="text-align: center; color: #909399; padding: 20px">
- 鏆傛棤寰呭鏍告壙鍖呭晢
- </div>
- </div>
- </div>
-
- <!-- 涓儴妯悜涓ゆ爮 -->
- <div class="dashboard-row">
- <div class="main-panel">
- <div class="section-title">鎵垮寘鍟嗗闀胯秼鍔�</div>
- <Echarts
- ref="chart"
- :chartStyle="chartStyle"
- :grid="grid"
- :legend="lineLegend"
- :series="lineSeries"
- :tooltip="tooltipLine"
- :xAxis="xAxis"
- :yAxis="yAxis"
- style="height: 300px"
- ></Echarts>
- </div>
- <div class="main-panel">
- <div class="section-title">鎵垮寘鍟嗚祫璐ㄥ垎甯�</div>
- <div
- style="
- display: flex;
- align-items: center;
- gap: 20px;
- justify-content: space-evenly;
- height: 300px;
- "
- >
- <div style="width: 50%">
- <Echarts
- ref="chart"
- :legend="pieLegend"
- :chartStyle="chartStylePie"
- :series="levelPieSeries"
- :tooltip="pieTooltip"
- ></Echarts>
- </div>
- <ul class="level-list" style="width: 50%">
- <li v-for="item in levelPieSeries[0].data" :key="item.name">
- <div
- style="
- display: flex;
- align-items: center;
- justify-content: space-between;
- width: 100%;
- "
- >
- <div class="line" :style="{ color: item.itemStyle.color }">
- 鈼弡{ item.name }}
- </div>
- <div style="width: 60px">{{ item.value }}瀹�</div>
- <div style="width: 60px">{{ item.rate }}%</div>
- </div>
- </li>
- </ul>
- </div>
- </div>
- </div>
-
- <!-- 搴曢儴妯悜涓ゆ爮 -->
- <div class="dashboard-row">
- <div class="main-panel">
- <div class="section-title">鎵垮寘鍟嗙被鍨嬪垎甯�</div>
- <Echarts
- ref="chart"
- :color="barColors"
- :chartStyle="chartStyle"
- :grid="grid"
- :series="equipmentBarSeries"
- :tooltip="tooltip"
- :xAxis="equipmentXAxis"
- :yAxis="yAxis"
- style="height: 300px"
- ></Echarts>
- </div>
- <div class="main-panel">
- <div class="section-title">鎵垮寘鍟嗗鏍告椂鏁�</div>
- <Echarts
- ref="chart"
- :color="barColors"
- :chartStyle="chartStyle"
- :grid="grid"
- :series="handlingTimeSeries"
- :tooltip="tooltip"
- :xAxis="handlingTimeXAxis"
- :yAxis="yAxis"
- style="height: 300px"
- ></Echarts>
- </div>
- </div>
+ {{
+ scope.row.status === "online"
+ ? "鍦ㄧ嚎"
+ : scope.row.status === "warning"
+ ? "棰勮"
+ : "鏁呴殰"
+ }}
+ </el-tag>
+ </template>
+ </el-table-column>
+ <el-table-column
+ prop="temperature"
+ label="娓╁害(鈩�)"
+ width="100"
+ ></el-table-column>
+ <el-table-column
+ prop="pressure"
+ label="鍘嬪姏(MPa)"
+ width="100"
+ ></el-table-column>
+ <el-table-column
+ prop="speed"
+ label="杞��(rpm)"
+ width="100"
+ ></el-table-column>
+ <el-table-column prop="health" label="鍋ュ悍搴�" width="120">
+ <template #default="scope">
+ <el-progress
+ :percentage="scope.row.health"
+ :stroke-width="10"
+ ></el-progress>
+ </template>
+ </el-table-column>
+ </el-table>
+ </el-card>
</div>
</template>
<script setup>
-import { ref, onMounted, reactive, computed } from "vue";
-import Echarts from "@/components/Echarts/echarts.vue";
-import { Clock } from "@element-plus/icons-vue";
+import { ref, onMounted, onUnmounted } from "vue";
+import * as echarts from "echarts";
-// 褰撳墠鏃堕棿
-const currentTime = computed(() => {
- const now = new Date();
- return now.toLocaleString("zh-CN");
-});
+// 缁熻鏁版嵁
+const onlineRate = ref(85);
+const onlineCount = ref(170);
+const totalDevices = ref(200);
+const warningCount = ref(23);
+const highRiskCount = ref(5);
+const mediumRiskCount = ref(12);
+const lowRiskCount = ref(6);
+const pendingOrders = ref(15);
+const processingOrders = ref(8);
+const completedOrders = ref(45);
+const normalDevices = ref(162);
+const abnormalDevices = ref(18);
+const faultDevices = ref(10);
-// 鎵垮寘鍟嗙粺璁℃暟鎹�
-const contractorStats = reactive({
- total: 156,
- approved: 132,
- pending: 24,
- aPending: 8,
- bPending: 12,
- cPending: 4,
- monthly: 28,
- monthly鍚屾瘮: "+18.5",
- monthly鐜瘮: "+5.2",
-});
-
-// 寰呭鏍告壙鍖呭晢鍒楄〃
-const pendingContractors = ref([
+// 閲嶇偣璁惧鍒楄〃
+const keyDevices = ref([
{
- id: 1,
- name: "寤虹瓚宸ョ▼鏈夐檺鍏徃",
- type: "寤虹瓚鏂藉伐",
- contact: "寮犱笁",
- registerDate: "2025-01-15",
- applyDate: "2025-12-16 14:30:23",
- level: "A",
+ name: "绌哄帇鏈篈-001",
+ model: "KA-200",
+ ip: "192.168.1.101",
+ status: "online",
+ temperature: 42,
+ pressure: 0.8,
+ speed: 1450,
+ health: 92,
},
{
- id: 2,
- name: "鏈虹數瀹夎宸ョ▼鍏徃",
- type: "鏈虹數瀹夎",
- contact: "鏉庡洓",
- registerDate: "2025-03-20",
- applyDate: "2025-12-16 14:28:15",
- level: "B",
+ name: "鍐峰嵈濉擝-002",
+ model: "CT-300",
+ ip: "192.168.1.102",
+ status: "warning",
+ temperature: 58,
+ pressure: 0.6,
+ speed: 980,
+ health: 75,
},
{
- id: 3,
- name: "瑁呴グ瑁呬慨宸ョ▼鍏徃",
- type: "瑁呴グ瑁呬慨",
- contact: "鐜嬩簲",
- registerDate: "2025-05-10",
- applyDate: "2025-12-16 14:22:18",
- level: "B",
+ name: "姘存车C-003",
+ model: "WP-150",
+ ip: "192.168.1.103",
+ status: "online",
+ temperature: 38,
+ pressure: 1.2,
+ speed: 1200,
+ health: 88,
},
{
- id: 4,
- name: "缁垮寲宸ョ▼鏈夐檺鍏徃",
- type: "鍥灄缁垮寲",
- contact: "璧靛叚",
- registerDate: "2025-08-05",
- applyDate: "2025-12-16 14:18:55",
- level: "C",
+ name: "鍙戠數鏈篋-004",
+ model: "GE-500",
+ ip: "192.168.1.104",
+ status: "danger",
+ temperature: 75,
+ pressure: 0.5,
+ speed: 1500,
+ health: 60,
+ },
+ {
+ name: "鍙樺帇鍣‥-005",
+ model: "TR-1000",
+ ip: "192.168.1.105",
+ status: "online",
+ temperature: 45,
+ pressure: 0,
+ speed: 0,
+ health: 95,
},
]);
-// 鍥捐〃鏍峰紡
-const chartStyle = {
- width: "100%",
- height: "100%",
+// 鍥捐〃寮曠敤
+const healthChartRef = ref(null);
+const faultChartRef = ref(null);
+let healthChart = null;
+let faultChart = null;
+
+// 鍋ュ悍搴﹁秼鍔挎暟鎹�
+const healthTrendData = {
+ dates: ["12-10", "12-11", "12-12", "12-13", "12-14", "12-15", "12-16"],
+ values: [88, 90, 85, 87, 92, 91, 93],
};
-const chartStylePie = {
- width: "100%",
- height: "100%",
+// 鏁呴殰绫诲瀷缁熻鏁版嵁
+const faultTypeData = {
+ types: ["娓╁害寮傚父", "鍘嬪姏瓒呮爣", "杞�熷紓甯�", "鎸姩杩囧ぇ", "鍏朵粬"],
+ values: [15, 8, 12, 6, 3],
};
-const grid = {
- left: "3%",
- right: "4%",
- bottom: "3%",
- containLabel: true,
-};
-
-// 鎵垮寘鍟嗗闀胯秼鍔� - 鎶樼嚎鍥�
-const lineLegend = {
- show: true,
- data: ["A绾�", "B绾�", "C绾�"],
-};
-
-const tooltipLine = {
- trigger: "axis",
- axisPointer: {
- type: "cross",
- },
-};
-
-const xAxis = ref({
- type: "category",
- data: ["12-01", "12-02", "12-03", "12-04", "12-05", "12-06", "12-07"],
-});
-
-const yAxis = ref({
- type: "value",
- name: "鎵垮寘鍟嗘暟閲�",
-});
-
-const lineSeries = ref([
- {
- name: "A绾�",
- type: "line",
- data: [15, 18, 20, 22, 25, 28, 30],
- itemStyle: {
- color: "#f56c6c",
- },
- lineStyle: {
- width: 2,
- },
- showSymbol: true,
- },
- {
- name: "B绾�",
- type: "line",
- data: [45, 52, 58, 65, 70, 75, 80],
- itemStyle: {
- color: "#e6a23c",
- },
- lineStyle: {
- width: 2,
- },
- showSymbol: true,
- },
- {
- name: "C绾�",
- type: "line",
- data: [30, 35, 40, 45, 50, 55, 60],
- itemStyle: {
- color: "#67c23a",
- },
- lineStyle: {
- width: 2,
- },
- showSymbol: true,
- },
-]);
-
-// 鎵垮寘鍟嗚祫璐ㄥ垎甯� - 楗煎浘
-const pieLegend = {
- show: false,
-};
-
-const pieTooltip = {
- trigger: "item",
- formatter: "{b}: {c}瀹� ({d}%)",
-};
-
-const levelPieSeries = ref([
- {
- type: "pie",
- radius: ["60%", "80%"],
- avoidLabelOverlap: false,
- itemStyle: {
- borderColor: "#fff",
- borderWidth: 2,
- },
- label: {
- show: false,
- },
- data: [
- {
- name: "A绾�",
- value: 45,
- rate: 28.85,
- itemStyle: { color: "#f56c6c" },
+// 鍒濆鍖栧仴搴峰害瓒嬪娍鍥�
+const initHealthChart = () => {
+ if (healthChartRef.value) {
+ healthChart = echarts.init(healthChartRef.value);
+ const option = {
+ tooltip: {
+ trigger: "axis",
+ axisPointer: {
+ type: "cross",
+ label: {
+ backgroundColor: "#6a7985",
+ },
+ },
},
- {
- name: "B绾�",
- value: 70,
- rate: 44.87,
- itemStyle: { color: "#e6a23c" },
+ grid: {
+ left: "3%",
+ right: "4%",
+ bottom: "3%",
+ containLabel: true,
},
- {
- name: "C绾�",
- value: 41,
- rate: 26.28,
- itemStyle: { color: "#67c23a" },
+ xAxis: {
+ type: "category",
+ boundaryGap: false,
+ data: healthTrendData.dates,
},
- ],
- },
-]);
-
-// 鎵垮寘鍟嗙被鍨嬪垎甯� - 鏌辩姸鍥�
-const barColors = ["#409eff", "#67c23a", "#e6a23c", "#f56c6c", "#909399"];
-
-const tooltip = {
- trigger: "axis",
- axisPointer: {
- type: "shadow",
- },
-};
-
-const equipmentXAxis = ref({
- type: "category",
- data: ["寤虹瓚鏂藉伐", "鏈虹數瀹夎", "瑁呴グ瑁呬慨", "鍥灄缁垮寲", "鍏朵粬"],
-});
-
-const equipmentBarSeries = ref([
- {
- name: "鎵垮寘鍟嗘暟閲�",
- type: "bar",
- data: [45, 35, 25, 20, 31],
- itemStyle: {
- color: function (params) {
- return barColors[params.dataIndex % barColors.length];
+ yAxis: {
+ type: "value",
+ min: 70,
+ max: 100,
+ name: "鍋ュ悍搴�(%)",
},
- },
- label: {
- show: true,
- position: "top",
- },
- },
-]);
-
-// 鎵垮寘鍟嗗鏍告椂鏁堝垎鏋� - 鏌辩姸鍥�
-const handlingTimeXAxis = ref({
- type: "category",
- data: ["0-1澶�", "1-3澶�", "3-7澶�", "7澶╀互涓�"],
-});
-
-const handlingTimeSeries = ref([
- {
- name: "瀹℃牳鏁伴噺",
- type: "bar",
- data: [85, 45, 20, 10],
- itemStyle: {
- color: function (params) {
- return barColors[params.dataIndex % barColors.length];
- },
- },
- label: {
- show: true,
- position: "top",
- },
- },
-]);
-
-// 鑾峰彇鎵垮寘鍟嗙骇鍒牱寮�
-const getContractorLevelType = (level) => {
- switch (level) {
- case "A":
- return "danger";
- case "B":
- return "warning";
- case "C":
- return "info";
- default:
- return "info";
+ series: [
+ {
+ name: "鍋ュ悍搴�",
+ type: "line",
+ stack: "鎬婚噺",
+ areaStyle: {},
+ emphasis: {
+ focus: "series",
+ },
+ data: healthTrendData.values,
+ itemStyle: {
+ color: "#67c23a",
+ },
+ lineStyle: {
+ width: 3,
+ },
+ },
+ ],
+ };
+ healthChart.setOption(option);
}
};
+// 鍒濆鍖栨晠闅滅被鍨嬬粺璁¢ゼ鍥�
+const initFaultChart = () => {
+ if (faultChartRef.value) {
+ faultChart = echarts.init(faultChartRef.value);
+ const option = {
+ tooltip: {
+ trigger: "item",
+ },
+ legend: {
+ orient: "vertical",
+ left: "left",
+ },
+ series: [
+ {
+ name: "鏁呴殰绫诲瀷",
+ type: "pie",
+ radius: "50%",
+ data: faultTypeData.types.map((type, index) => ({
+ name: type,
+ value: faultTypeData.values[index],
+ })),
+ emphasis: {
+ itemStyle: {
+ shadowBlur: 10,
+ shadowOffsetX: 0,
+ shadowColor: "rgba(0, 0, 0, 0.5)",
+ },
+ },
+ },
+ ],
+ };
+ faultChart.setOption(option);
+ }
+};
+
+// 鐩戝惉绐楀彛澶у皬鍙樺寲锛岃皟鏁村浘琛ㄥぇ灏�
+const handleResize = () => {
+ healthChart?.resize();
+ faultChart?.resize();
+};
+
onMounted(() => {
- // 椤甸潰鍔犺浇瀹屾垚鍚庣殑鍒濆鍖栨搷浣�
+ initHealthChart();
+ initFaultChart();
+ window.addEventListener("resize", handleResize);
+});
+
+onUnmounted(() => {
+ window.removeEventListener("resize", handleResize);
+ healthChart?.dispose();
+ faultChart?.dispose();
});
</script>
<style scoped>
-.dashboard {
- background: #f5f7fa;
+.dashboard-container {
+ padding: 20px;
+ background-color: #f5f7fa;
min-height: 100vh;
- padding: 20px;
- box-sizing: border-box;
}
-.dashboard-top {
- display: flex;
- gap: 20px;
- margin-bottom: 20px;
+.statistics-card {
+ height: 180px;
}
-.system-info {
+.card-content {
display: flex;
flex-direction: column;
- gap: 8px;
- padding: 20px;
- min-width: 0;
- background-color: #eff2fb;
- border-radius: 12px;
- height: 138px;
-}
-
-.system-card {
- display: flex;
- flex-direction: column;
- gap: 10px;
- position: relative;
- padding-right: 15px;
-}
-
-.system-name {
- font-weight: 600;
- font-size: 18px;
- color: #161a9a;
-}
-
-.system-meta {
- font-weight: 400;
- font-size: 12px;
- color: #818185;
-}
-
-.data-cards {
- display: flex;
- gap: 16px;
- justify-content: flex-start;
- background: #ffffff;
- border-radius: 12px;
- padding: 20px;
-}
-
-.data-card {
- background: #fff;
- border-radius: 12px;
- padding: 16px;
- min-width: 160px;
- box-shadow: 0 2px 8px #eee;
- display: flex;
- flex-direction: column;
- align-items: center;
+ height: 100%;
justify-content: center;
- width: 32%;
- height: 140px;
- transition: all 0.3s ease;
+ align-items: center;
}
-.data-card:hover {
- transform: translateY(-2px);
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
-}
-
-.data-card.total {
- background: linear-gradient(135deg, #409eff 0%, #66b1ff 100%);
- color: #fff;
-}
-
-.data-card.pending {
- background: linear-gradient(135deg, #f56c6c 0%, #f78989 100%);
- color: #fff;
-}
-
-.data-card.today {
- background: linear-gradient(135deg, #67c23a 0%, #85ce61 100%);
- color: #fff;
-}
-
-.data-title {
- font-weight: 600;
+.card-title {
font-size: 16px;
- margin-bottom: 12px;
+ color: #606266;
+ margin-bottom: 10px;
}
-.data-value {
+.card-value {
font-size: 32px;
font-weight: bold;
+ color: #303133;
margin-bottom: 8px;
}
-.data-desc {
- font-size: 12px;
- opacity: 0.9;
-}
-
-.top-left {
- display: flex;
- flex-direction: column;
- gap: 20px;
- width: 60%;
-}
-
-.alarm-panel {
- background: #fff;
- border-radius: 12px;
- padding: 20px;
- width: 40%;
-}
-
-.alarm-list {
- list-style: none;
- padding: 0;
- margin: 0;
+.card-desc {
font-size: 14px;
- overflow-y: auto;
- height: 260px;
-}
-
-.alarm-list li {
- border-radius: 8px;
- margin-bottom: 12px;
- padding: 12px 20px;
- display: flex;
- justify-content: space-between;
- align-items: center;
- background: #f8f9fa;
- border-left: 4px solid #409eff;
- transition: all 0.3s ease;
-}
-
-.alarm-list li:hover {
- background: #e9ecef;
- transform: translateX(4px);
-}
-
-.alarm-title {
- font-weight: 600;
- font-size: 14px;
- color: #303133;
-}
-
-.alarm-value {
- font-size: 12px;
- color: #606266;
-}
-
-.alarm-time {
- font-size: 12px;
color: #909399;
}
-.dashboard-row {
+.card-header {
display: flex;
- gap: 20px;
- margin-bottom: 20px;
+ justify-content: space-between;
+ align-items: center;
}
-.main-panel {
- background: #fff;
- border-radius: 12px;
- padding: 20px;
- flex: 1;
- min-width: 0;
- display: flex;
- flex-direction: column;
-}
-
-.section-title {
- position: relative;
- font-size: 18px;
- color: #333;
- padding-left: 10px;
- margin-bottom: 20px;
- font-weight: 700;
-}
-
-.section-title::before {
- position: absolute;
- left: 0;
- top: 4px;
- content: "";
- width: 4px;
- height: 18px;
- background-color: #409eff;
- border-radius: 2px;
-}
-
-.level-list {
- margin: 0;
- padding: 0;
- list-style: none;
- height: 200px;
- overflow-y: auto;
+.chart-container {
width: 100%;
-}
-
-.level-list li {
- margin-bottom: 15px;
- padding: 10px;
- background: #f8f9fa;
- border-radius: 6px;
- transition: all 0.3s ease;
-}
-
-.level-list li:hover {
- background: #e9ecef;
-}
-
-.line {
- position: relative;
- width: 80px;
- font-weight: 500;
+ height: 350px;
}
</style>
diff --git a/src/views/maintenance/MaintenanceManagement.vue b/src/views/maintenance/MaintenanceManagement.vue
new file mode 100644
index 0000000..574f333
--- /dev/null
+++ b/src/views/maintenance/MaintenanceManagement.vue
@@ -0,0 +1,526 @@
+<template>
+ <div class="maintenance-management-container">
+ <!-- 椤堕儴鎿嶄綔鏍� -->
+ <el-card shadow="hover" style="margin-bottom: 20px;">
+ <div class="card-header">
+ <span>缁翠慨绠$悊</span>
+ <div class="header-buttons">
+ <el-button type="primary" @click="showCreateWorkOrderDialog">
+ <el-icon-plus /> 鍒涘缓宸ュ崟
+ </el-button>
+ </div>
+ </div>
+ </el-card>
+
+ <el-row :gutter="20">
+ <!-- 宸︿晶锛氬伐鍗曞垪琛� -->
+ <el-col :span="16">
+ <el-card shadow="hover">
+ <!-- 宸ュ崟鐘舵�佹爣绛鹃〉 -->
+ <el-tabs v-model="activeTab" @tab-change="handleTabChange">
+ <el-tab-pane label="寰呭鐞�" name="pending"></el-tab-pane>
+ <el-tab-pane label="澶勭悊涓�" name="processing"></el-tab-pane>
+ <el-tab-pane label="宸插畬鎴�" name="completed"></el-tab-pane>
+ </el-tabs>
+
+ <!-- 宸ュ崟鍒楄〃 -->
+ <el-table :data="filteredWorkOrders" stripe style="width: 100%" @row-click="handleWorkOrderClick">
+ <el-table-column prop="orderNo" label="宸ュ崟缂栧彿" width="180"></el-table-column>
+ <el-table-column prop="deviceName" label="璁惧鍚嶇О" width="150"></el-table-column>
+ <el-table-column prop="faultType" label="鏁呴殰绫诲瀷" width="120"></el-table-column>
+ <el-table-column prop="createTime" label="鍒涘缓鏃堕棿" width="180"></el-table-column>
+ <el-table-column prop="assignee" label="璐熻矗浜�" width="120"></el-table-column>
+ <el-table-column prop="priority" label="浼樺厛绾�" width="100">
+ <template #default="scope">
+ <el-tag :type="scope.row.priority === 'high' ? 'danger' : scope.row.priority === 'medium' ? 'warning' : 'info'">
+ {{ scope.row.priority === 'high' ? '楂�' : scope.row.priority === 'medium' ? '涓�' : '浣�' }}
+ </el-tag>
+ </template>
+ </el-table-column>
+ <el-table-column label="鎿嶄綔" width="150">
+ <template #default="scope">
+ <el-button size="small" @click="showEditWorkOrderDialog(scope.row)">缂栬緫</el-button>
+ <el-button type="danger" size="small" @click="handleDeleteWorkOrder(scope.row.id)">鍒犻櫎</el-button>
+ </template>
+ </el-table-column>
+ </el-table>
+
+ <!-- 鍒嗛〉 -->
+ <div class="pagination-container">
+ <el-pagination
+ background
+ layout="total, sizes, prev, pager, next, jumper"
+ :total="filteredWorkOrders.length"
+ :current-page="currentPage"
+ :page-sizes="[10, 20, 50, 100]"
+ :page-size="pageSize"
+ @size-change="handleSizeChange"
+ @current-change="handleCurrentChange"
+ ></el-pagination>
+ </div>
+ </el-card>
+ </el-col>
+
+ <!-- 鍙充晶锛氱淮淇粺璁″拰澶囦欢鎺ㄨ崘 -->
+ <el-col :span="8">
+ <!-- 缁翠慨鍘嗗彶缁熻 -->
+ <el-card shadow="hover" style="margin-bottom: 20px;">
+ <template #header>
+ <div class="card-header">
+ <span>缁翠慨鍘嗗彶缁熻</span>
+ </div>
+ </template>
+ <div class="statistics-content">
+ <div class="stat-item">
+ <div class="stat-label">鏈湀瀹屾垚宸ュ崟</div>
+ <div class="stat-value">{{ monthlyCompleted }}</div>
+ </div>
+ <div class="stat-item">
+ <div class="stat-label">骞冲潎缁翠慨鏃堕暱</div>
+ <div class="stat-value">{{ averageRepairTime }}灏忔椂</div>
+ </div>
+ <div class="stat-item">
+ <div class="stat-label">璁惧鏁呴殰鐜�</div>
+ <div class="stat-value">{{ failureRate }}%</div>
+ </div>
+ <div class="stat-item">
+ <div class="stat-label">甯哥敤缁翠慨璁惧</div>
+ <div class="stat-value">{{ commonDevice }}</div>
+ </div>
+ </div>
+ </el-card>
+
+ <!-- 甯哥敤澶囦欢鍏宠仈鎺ㄨ崘 -->
+ <el-card shadow="hover">
+ <template #header>
+ <div class="card-header">
+ <span>甯哥敤澶囦欢鎺ㄨ崘</span>
+ </div>
+ </template>
+ <div class="spare-parts-content">
+ <el-table :data="spareParts" stripe style="width: 100%" size="small">
+ <el-table-column prop="name" label="澶囦欢鍚嶇О" width="120"></el-table-column>
+ <el-table-column prop="model" label="鍨嬪彿" width="100"></el-table-column>
+ <el-table-column prop="stock" label="搴撳瓨" width="80">
+ <template #default="scope">
+ <el-tag :type="scope.row.stock < 10 ? 'danger' : 'success'">
+ {{ scope.row.stock }}
+ </el-tag>
+ </template>
+ </el-table-column>
+ <el-table-column prop="usageCount" label="浣跨敤娆℃暟" width="80"></el-table-column>
+ </el-table>
+ </div>
+ </el-card>
+ </el-col>
+ </el-row>
+
+ <!-- 鍒涘缓宸ュ崟瀵硅瘽妗� -->
+ <el-dialog v-model="createWorkOrderDialogVisible" title="鍒涘缓缁翠慨宸ュ崟" width="600px">
+ <el-form :model="workOrderForm" :rules="workOrderRules" ref="workOrderFormRef" label-width="100px">
+ <el-form-item label="璁惧" prop="deviceId">
+ <el-select v-model="workOrderForm.deviceId" placeholder="璇烽�夋嫨璁惧">
+ <el-option
+ v-for="device in devices"
+ :key="device.id"
+ :label="device.name"
+ :value="device.id"
+ ></el-option>
+ </el-select>
+ </el-form-item>
+ <el-form-item label="鏁呴殰绫诲瀷" prop="faultType">
+ <el-input v-model="workOrderForm.faultType" placeholder="璇疯緭鍏ユ晠闅滅被鍨�"></el-input>
+ </el-form-item>
+ <el-form-item label="鏁呴殰鎻忚堪" prop="faultDescription">
+ <el-input v-model="workOrderForm.faultDescription" type="textarea" placeholder="璇疯缁嗘弿杩版晠闅滄儏鍐�" :rows="3"></el-input>
+ </el-form-item>
+ <el-form-item label="浼樺厛绾�" prop="priority">
+ <el-select v-model="workOrderForm.priority" placeholder="璇烽�夋嫨浼樺厛绾�">
+ <el-option label="楂�" value="high"></el-option>
+ <el-option label="涓�" value="medium"></el-option>
+ <el-option label="浣�" value="low"></el-option>
+ </el-select>
+ </el-form-item>
+ </el-form>
+ <template #footer>
+ <span class="dialog-footer">
+ <el-button @click="createWorkOrderDialogVisible = false">鍙栨秷</el-button>
+ <el-button type="primary" @click="handleCreateWorkOrder">纭畾</el-button>
+ </span>
+ </template>
+ </el-dialog>
+
+ <!-- 缂栬緫宸ュ崟瀵硅瘽妗� -->
+ <el-dialog v-model="editWorkOrderDialogVisible" title="缂栬緫缁翠慨宸ュ崟" width="600px">
+ <el-form :model="workOrderForm" :rules="workOrderRules" ref="workOrderFormRef" label-width="100px">
+ <el-form-item label="宸ュ崟缂栧彿" disabled>
+ <el-input v-model="workOrderForm.orderNo"></el-input>
+ </el-form-item>
+ <el-form-item label="璁惧" disabled>
+ <el-input v-model="workOrderForm.deviceName"></el-input>
+ </el-form-item>
+ <el-form-item label="鏁呴殰绫诲瀷" disabled>
+ <el-input v-model="workOrderForm.faultType"></el-input>
+ </el-form-item>
+ <el-form-item label="璐熻矗浜�" prop="assignee">
+ <el-select v-model="workOrderForm.assignee" placeholder="璇烽�夋嫨璐熻矗浜�">
+ <el-option
+ v-for="user in users"
+ :key="user.id"
+ :label="user.name"
+ :value="user.name"
+ ></el-option>
+ </el-select>
+ </el-form-item>
+ <el-form-item label="缁翠慨鐘舵��" prop="status">
+ <el-select v-model="workOrderForm.status" placeholder="璇烽�夋嫨鐘舵��">
+ <el-option label="寰呭鐞�" value="pending"></el-option>
+ <el-option label="澶勭悊涓�" value="processing"></el-option>
+ <el-option label="宸插畬鎴�" value="completed"></el-option>
+ </el-select>
+ </el-form-item>
+ <el-form-item label="缁翠慨缁撴灉" prop="repairResult">
+ <el-input v-model="workOrderForm.repairResult" type="textarea" placeholder="璇峰~鍐欑淮淇粨鏋�" :rows="3"></el-input>
+ </el-form-item>
+ <el-form-item label="澶囦欢浣跨敤" prop="usedParts">
+ <el-input v-model="workOrderForm.usedParts" type="textarea" placeholder="璇峰~鍐欎娇鐢ㄧ殑澶囦欢" :rows="2"></el-input>
+ </el-form-item>
+ </el-form>
+ <template #footer>
+ <span class="dialog-footer">
+ <el-button @click="editWorkOrderDialogVisible = false">鍙栨秷</el-button>
+ <el-button type="primary" @click="handleEditWorkOrder">纭畾</el-button>
+ </span>
+ </template>
+ </el-dialog>
+ </div>
+</template>
+
+<script setup>
+import { ref, computed } from 'vue'
+
+// 璁惧鍒楄〃
+const devices = ref([
+ { id: 'D001', name: '绌哄帇鏈篈-001' },
+ { id: 'D002', name: '鍐峰嵈濉擝-002' },
+ { id: 'D003', name: '姘存车C-003' },
+ { id: 'D004', name: '鍙戠數鏈篋-004' },
+ { id: 'D005', name: '鍙樺帇鍣‥-005' }
+])
+
+// 鐢ㄦ埛鍒楄〃锛堢敤浜庡垎閰嶈礋璐d汉锛�
+const users = ref([
+ { id: 'U001', name: '寮犱笁' },
+ { id: 'U002', name: '鏉庡洓' },
+ { id: 'U003', name: '鐜嬩簲' },
+ { id: 'U004', name: '璧靛叚' }
+])
+
+// 宸ュ崟鍒楄〃鏁版嵁
+const workOrders = ref([
+ {
+ id: 1,
+ orderNo: 'WO20241216001',
+ deviceId: 'D001',
+ deviceName: '绌哄帇鏈篈-001',
+ faultType: '鍘嬪姏寮傚父',
+ faultDescription: '璁惧杩愯鏃跺帇鍔涜秴杩囪瀹氶槇鍊硷紝浼存湁寮傚父鍣煶',
+ priority: 'high',
+ assignee: '',
+ status: 'pending',
+ repairResult: '',
+ usedParts: '',
+ createTime: '2024-12-16 14:32:15',
+ startTime: '',
+ endTime: ''
+ },
+ {
+ id: 2,
+ orderNo: 'WO20241216002',
+ deviceId: 'D002',
+ deviceName: '鍐峰嵈濉擝-002',
+ faultType: '娓╁害杩囬珮',
+ faultDescription: '鍐峰嵈濉斿嚭姘存俯搴﹁秴杩囪瀹氬�硷紝鍐峰嵈鏁堟灉涓嶄匠',
+ priority: 'medium',
+ assignee: '寮犱笁',
+ status: 'processing',
+ repairResult: '',
+ usedParts: '',
+ createTime: '2024-12-16 14:30:45',
+ startTime: '2024-12-16 15:00:00',
+ endTime: ''
+ },
+ {
+ id: 3,
+ orderNo: 'WO20241215001',
+ deviceId: 'D003',
+ deviceName: '姘存车C-003',
+ faultType: '鎸姩杩囧ぇ',
+ faultDescription: '姘存车杩愯鏃舵尟鍔ㄥ�艰秴杩囨爣鍑嗭紝鍙兘褰卞搷璁惧瀵垮懡',
+ priority: 'medium',
+ assignee: '鏉庡洓',
+ status: 'completed',
+ repairResult: '鏇存崲浜嗘按娉佃酱鎵匡紝璋冩暣浜嗚仈杞村櫒锛屾尟鍔ㄥ�兼仮澶嶆甯�',
+ usedParts: '杞存壙脳2锛岃仈杞村櫒脳1',
+ createTime: '2024-12-15 08:30:00',
+ startTime: '2024-12-15 09:00:00',
+ endTime: '2024-12-15 10:45:00'
+ },
+ {
+ id: 4,
+ orderNo: 'WO20241214001',
+ deviceId: 'D004',
+ deviceName: '鍙戠數鏈篋-004',
+ faultType: '鐢垫祦寮傚父',
+ faultDescription: '鍙戠數鏈鸿繍琛屾椂鐢垫祦娉㈠姩杈冨ぇ锛屽彲鑳藉瓨鍦ㄧ煭璺闄�',
+ priority: 'high',
+ assignee: '鐜嬩簲',
+ status: 'completed',
+ repairResult: '妫�鏌ュ苟淇浜嗗彂鐢垫満缁曠粍鐭矾闂锛岀數娴佹仮澶嶆甯�',
+ usedParts: '缁濈紭鏉愭枡脳1锛屽绾棵�5绫�',
+ createTime: '2024-12-14 14:20:00',
+ startTime: '2024-12-14 14:30:00',
+ endTime: '2024-12-14 16:15:00'
+ },
+ {
+ id: 5,
+ orderNo: 'WO20241213001',
+ deviceId: 'D005',
+ deviceName: '鍙樺帇鍣‥-005',
+ faultType: '鐢靛帇娉㈠姩',
+ faultDescription: '鍙樺帇鍣ㄨ緭鍑虹數鍘嬫尝鍔ㄨ緝澶э紝褰卞搷涓嬫父璁惧杩愯',
+ priority: 'low',
+ assignee: '璧靛叚',
+ status: 'completed',
+ repairResult: '璋冩暣浜嗗彉鍘嬪櫒鍒嗘帴寮�鍏筹紝鐢靛帇绋冲畾鍦ㄦ甯歌寖鍥村唴',
+ usedParts: '',
+ createTime: '2024-12-13 09:15:00',
+ startTime: '2024-12-13 10:00:00',
+ endTime: '2024-12-13 11:30:00'
+ }
+])
+
+// 褰撳墠婵�娲荤殑鏍囩椤碉紙宸ュ崟鐘舵�侊級
+const activeTab = ref('pending')
+
+// 鍒嗛〉鏁版嵁
+const currentPage = ref(1)
+const pageSize = ref(10)
+
+// 瀵硅瘽妗嗙姸鎬�
+const createWorkOrderDialogVisible = ref(false)
+const editWorkOrderDialogVisible = ref(false)
+
+// 宸ュ崟琛ㄥ崟鏁版嵁
+const workOrderForm = ref({
+ id: '',
+ orderNo: '',
+ deviceId: '',
+ deviceName: '',
+ faultType: '',
+ faultDescription: '',
+ priority: 'medium',
+ assignee: '',
+ status: 'pending',
+ repairResult: '',
+ usedParts: '',
+ createTime: '',
+ startTime: '',
+ endTime: ''
+})
+
+// 琛ㄥ崟楠岃瘉瑙勫垯
+const workOrderRules = ref({
+ deviceId: [{ required: true, message: '璇烽�夋嫨璁惧', trigger: 'change' }],
+ faultType: [{ required: true, message: '璇疯緭鍏ユ晠闅滅被鍨�', trigger: 'blur' }],
+ faultDescription: [{ required: true, message: '璇疯缁嗘弿杩版晠闅滄儏鍐�', trigger: 'blur' }],
+ priority: [{ required: true, message: '璇烽�夋嫨浼樺厛绾�', trigger: 'change' }],
+ assignee: [{ required: true, message: '璇烽�夋嫨璐熻矗浜�', trigger: 'change' }],
+ status: [{ required: true, message: '璇烽�夋嫨鐘舵��', trigger: 'change' }]
+})
+
+// 琛ㄥ崟寮曠敤
+const workOrderFormRef = ref(null)
+
+// 绛涢�夊悗鐨勫伐鍗曞垪琛�
+const filteredWorkOrders = computed(() => {
+ return workOrders.value.filter(order => order.status === activeTab.value)
+})
+
+// 缁翠慨缁熻鏁版嵁
+const monthlyCompleted = ref(28)
+const averageRepairTime = ref(2.5)
+const failureRate = ref(3.2)
+const commonDevice = ref('绌哄帇鏈篈-001')
+
+// 甯哥敤澶囦欢鎺ㄨ崘
+const spareParts = ref([
+ { id: 1, name: '杞存壙', model: '6308', stock: 15, usageCount: 23 },
+ { id: 2, name: '瀵嗗皝浠�', model: 'MS-25', stock: 8, usageCount: 18 },
+ { id: 3, name: '鑱旇酱鍣�', model: 'CL-50', stock: 5, usageCount: 12 },
+ { id: 4, name: '浼犳劅鍣�', model: 'TS-100', stock: 3, usageCount: 15 },
+ { id: 5, name: '娑︽粦娌�', model: 'L-46', stock: 20, usageCount: 30 }
+])
+
+// 鏄剧ず鍒涘缓宸ュ崟瀵硅瘽妗�
+const showCreateWorkOrderDialog = () => {
+ // 閲嶇疆琛ㄥ崟
+ workOrderForm.value = {
+ id: '',
+ orderNo: '',
+ deviceId: '',
+ deviceName: '',
+ faultType: '',
+ faultDescription: '',
+ priority: 'medium',
+ assignee: '',
+ status: 'pending',
+ repairResult: '',
+ usedParts: '',
+ createTime: '',
+ startTime: '',
+ endTime: ''
+ }
+ createWorkOrderDialogVisible.value = true
+}
+
+// 鏄剧ず缂栬緫宸ュ崟瀵硅瘽妗�
+const showEditWorkOrderDialog = (order) => {
+ workOrderForm.value = { ...order }
+ editWorkOrderDialogVisible.value = true
+}
+
+// 澶勭悊宸ュ崟鐐瑰嚮
+const handleWorkOrderClick = (row) => {
+ // 鍙互鍦ㄨ繖閲屾坊鍔犳煡鐪嬪伐鍗曡鎯呯殑閫昏緫
+}
+
+// 澶勭悊鏍囩椤靛垏鎹�
+const handleTabChange = (tab) => {
+ activeTab.value = tab
+ currentPage.value = 1 // 鍒囨崲鏍囩椤垫椂閲嶇疆椤电爜
+}
+
+// 澶勭悊鍒涘缓宸ュ崟
+const handleCreateWorkOrder = () => {
+ // 妯℃嫙鍒涘缓宸ュ崟
+ const newOrder = {
+ ...workOrderForm.value,
+ id: workOrders.value.length + 1,
+ orderNo: `WO${new Date().getFullYear()}${String(new Date().getMonth() + 1).padStart(2, '0')}${String(new Date().getDate()).padStart(2, '0')}${String(workOrders.value.length + 1).padStart(3, '0')}`,
+ deviceName: devices.value.find(d => d.id === workOrderForm.value.deviceId)?.name || '',
+ createTime: new Date().toLocaleString(),
+ status: 'pending'
+ }
+ workOrders.value.unshift(newOrder)
+ createWorkOrderDialogVisible.value = false
+ ElMessage.success('宸ュ崟鍒涘缓鎴愬姛')
+}
+
+// 澶勭悊缂栬緫宸ュ崟
+const handleEditWorkOrder = () => {
+ // 妯℃嫙缂栬緫宸ュ崟
+ const index = workOrders.value.findIndex(order => order.id === workOrderForm.value.id)
+ if (index !== -1) {
+ // 濡傛灉鐘舵�佷粠寰呭鐞嗗彉涓哄鐞嗕腑锛岃缃紑濮嬫椂闂�
+ if (workOrders.value[index].status === 'pending' && workOrderForm.value.status === 'processing') {
+ workOrderForm.value.startTime = new Date().toLocaleString()
+ }
+ // 濡傛灉鐘舵�佷粠澶勭悊涓彉涓哄凡瀹屾垚锛岃缃粨鏉熸椂闂�
+ if (workOrders.value[index].status === 'processing' && workOrderForm.value.status === 'completed') {
+ workOrderForm.value.endTime = new Date().toLocaleString()
+ }
+ workOrders.value[index] = { ...workOrderForm.value }
+ editWorkOrderDialogVisible.value = false
+ ElMessage.success('宸ュ崟缂栬緫鎴愬姛')
+ }
+}
+
+// 澶勭悊鍒犻櫎宸ュ崟
+const handleDeleteWorkOrder = (id) => {
+ ElMessageBox.confirm('纭畾瑕佸垹闄よ宸ュ崟鍚楋紵', '鎻愮ず', {
+ confirmButtonText: '纭畾',
+ cancelButtonText: '鍙栨秷',
+ type: 'warning'
+ }).then(() => {
+ // 妯℃嫙鍒犻櫎宸ュ崟
+ const index = workOrders.value.findIndex(order => order.id === id)
+ if (index !== -1) {
+ workOrders.value.splice(index, 1)
+ ElMessage.success('宸ュ崟鍒犻櫎鎴愬姛')
+ }
+ }).catch(() => {
+ // 鍙栨秷鍒犻櫎
+ })
+}
+
+// 澶勭悊鍒嗛〉澶у皬鍙樺寲
+const handleSizeChange = (size) => {
+ pageSize.value = size
+ currentPage.value = 1
+}
+
+// 澶勭悊褰撳墠椤靛彉鍖�
+const handleCurrentChange = (current) => {
+ currentPage.value = current
+}
+</script>
+
+<style scoped>
+.maintenance-management-container {
+ padding: 20px;
+ background-color: #f5f7fa;
+ min-height: 100vh;
+}
+
+.card-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+}
+
+.header-buttons {
+ display: flex;
+ gap: 10px;
+}
+
+.pagination-container {
+ display: flex;
+ justify-content: flex-end;
+ margin-top: 20px;
+}
+
+.statistics-content {
+ display: grid;
+ grid-template-columns: 1fr 1fr;
+ gap: 20px;
+ padding: 10px 0;
+}
+
+.stat-item {
+ text-align: center;
+ padding: 15px;
+ background-color: #fafafa;
+ border-radius: 4px;
+}
+
+.stat-label {
+ font-size: 14px;
+ color: #606266;
+ margin-bottom: 10px;
+}
+
+.stat-value {
+ font-size: 24px;
+ font-weight: bold;
+ color: #303133;
+}
+
+.spare-parts-content {
+ padding: 10px 0;
+}
+
+:deep(.el-icon-plus) {
+ margin-right: 5px;
+}
+</style>
\ No newline at end of file
diff --git a/src/views/monitoring/RealTimeMonitoring.vue b/src/views/monitoring/RealTimeMonitoring.vue
new file mode 100644
index 0000000..c449958
--- /dev/null
+++ b/src/views/monitoring/RealTimeMonitoring.vue
@@ -0,0 +1,515 @@
+<template>
+ <div class="real-time-monitoring-container">
+ <!-- 璁惧閫夋嫨 -->
+ <el-card shadow="hover" style="margin-bottom: 20px;">
+ <el-form :inline="true" :model="deviceSelectForm" class="device-select-form">
+ <el-form-item label="璁惧">
+ <el-select v-model="deviceSelectForm.deviceId" placeholder="璇烽�夋嫨璁惧" @change="handleDeviceChange">
+ <el-option
+ v-for="device in devices"
+ :key="device.id"
+ :label="device.name"
+ :value="device.id"
+ ></el-option>
+ </el-select>
+ </el-form-item>
+ <el-form-item label="鏃堕棿鑼冨洿">
+ <el-date-picker
+ v-model="timeRange"
+ type="daterange"
+ range-separator="鑷�"
+ start-placeholder="寮�濮嬫棩鏈�"
+ end-placeholder="缁撴潫鏃ユ湡"
+ :default-time="['00:00:00', '23:59:59']"
+ ></el-date-picker>
+ </el-form-item>
+ <el-form-item>
+ <el-button type="primary" @click="handleHistoryQuery">鏌ヨ鍘嗗彶鏁版嵁</el-button>
+ </el-form-item>
+ </el-form>
+ </el-card>
+
+ <!-- 瀹炴椂鍙傛暟鍗$墖 -->
+ <el-row :gutter="20" style="margin-bottom: 20px;">
+ <el-col :span="8" v-for="param in realTimeParams" :key="param.name">
+ <el-card class="param-card" :shadow="param.isAlarm ? 'always' : 'hover'" :class="{ 'alarm-card': param.isAlarm }">
+ <div class="param-content">
+ <div class="param-title">
+ <span>{{ param.name }}</span>
+ <el-tag v-if="param.isAlarm" type="danger">鍛婅</el-tag>
+ </div>
+ <div class="param-value">{{ param.value }} {{ param.unit }}</div>
+ <div class="param-range">
+ 姝e父鑼冨洿锛歿{ param.min }} - {{ param.max }} {{ param.unit }}
+ </div>
+ </div>
+ </el-card>
+ </el-col>
+ </el-row>
+
+ <!-- 鍛婅鎻愮ず -->
+ <el-card shadow="hover" v-if="alarmList.length > 0" style="margin-bottom: 20px;">
+ <template #header>
+ <div class="card-header">
+ <span>鍛婅鎻愮ず</span>
+ </div>
+ </template>
+ <el-scrollbar height="200px">
+ <div class="alarm-item" v-for="alarm in alarmList" :key="alarm.id">
+ <el-alert
+ :title="alarm.message"
+ :type="alarm.level === 'high' ? 'error' : alarm.level === 'medium' ? 'warning' : 'info'"
+ show-icon
+ closable
+ @close="handleAlarmClose(alarm.id)"
+ >
+ <template #default>
+ <div class="alarm-detail">
+ <span>璁惧锛歿{ alarm.deviceName }}</span>
+ <span>鏃堕棿锛歿{ alarm.time }}</span>
+ </div>
+ </template>
+ </el-alert>
+ </div>
+ </el-scrollbar>
+ </el-card>
+
+ <!-- 鍘嗗彶鏁版嵁瓒嬪娍鍥� -->
+ <el-card shadow="hover">
+ <template #header>
+ <div class="card-header">
+ <span>鍘嗗彶鏁版嵁瓒嬪娍</span>
+ <div class="param-tabs">
+ <el-radio-group v-model="activeParam" size="small" @change="handleParamChange">
+ <el-radio-button v-for="param in historyParams" :key="param" :label="param">
+ {{ param }}
+ </el-radio-button>
+ </el-radio-group>
+ </div>
+ </div>
+ </template>
+ <div ref="historyChartRef" class="chart-container"></div>
+ </el-card>
+
+ <!-- 鍗曡澶囧弬鏁拌鎯呴〉 -->
+ <el-dialog v-model="deviceDetailVisible" title="璁惧鍙傛暟璇︽儏" width="800px">
+ <div class="device-detail-content">
+ <h3>{{ selectedDevice.name }} - 瀹炴椂鍙傛暟</h3>
+ <el-row :gutter="20" style="margin-bottom: 20px;">
+ <el-col :span="12" v-for="param in realTimeParams" :key="param.name">
+ <div class="detail-param-item">
+ <span class="param-label">{{ param.name }}锛�</span>
+ <span class="param-value" :class="{ 'alarm-value': param.isAlarm }">
+ {{ param.value }} {{ param.unit }}
+ </span>
+ <span class="param-range">
+ 锛坽{ param.min }} - {{ param.max }} {{ param.unit }}锛�
+ </span>
+ </div>
+ </el-col>
+ </el-row>
+
+ <h3>鍙傛暟闃堝�艰缃�</h3>
+ <el-form :model="thresholdForm" label-width="100px" style="margin-top: 20px;">
+ <el-form-item v-for="param in realTimeParams" :key="param.name" :label="param.name">
+ <el-input-number
+ v-model="thresholdForm[param.name + 'Min']"
+ :min="0"
+ :max="1000"
+ size="small"
+ style="width: 120px; margin-right: 10px;"
+ placeholder="鏈�灏忓��"
+ ></el-input-number>
+ <span style="margin: 0 10px;">-</span>
+ <el-input-number
+ v-model="thresholdForm[param.name + 'Max']"
+ :min="0"
+ :max="1000"
+ size="small"
+ style="width: 120px; margin-right: 10px;"
+ placeholder="鏈�澶у��"
+ ></el-input-number>
+ <span>{{ param.unit }}</span>
+ </el-form-item>
+ </el-form>
+ </div>
+ <template #footer>
+ <span class="dialog-footer">
+ <el-button @click="deviceDetailVisible = false">鍙栨秷</el-button>
+ <el-button type="primary" @click="saveThresholds">淇濆瓨璁剧疆</el-button>
+ </span>
+ </template>
+ </el-dialog>
+ </div>
+</template>
+
+<script setup>
+import { ref, onMounted, onUnmounted, computed } from 'vue'
+import * as echarts from 'echarts'
+
+// 璁惧鍒楄〃
+const devices = ref([
+ { id: 'D001', name: '绌哄帇鏈篈-001' },
+ { id: 'D002', name: '鍐峰嵈濉擝-002' },
+ { id: 'D003', name: '姘存车C-003' },
+ { id: 'D004', name: '鍙戠數鏈篋-004' },
+ { id: 'D005', name: '鍙樺帇鍣‥-005' }
+])
+
+// 璁惧閫夋嫨琛ㄥ崟
+const deviceSelectForm = ref({
+ deviceId: 'D001' // 榛樿閫夋嫨绗竴涓澶�
+})
+
+// 鏃堕棿鑼冨洿
+const timeRange = ref([])
+
+// 褰撳墠閫変腑鐨勮澶�
+const selectedDevice = ref(devices.value[0])
+
+// 瀹炴椂鍙傛暟鏁版嵁
+const realTimeParams = ref([
+ { name: '娓╁害', value: 45, unit: '鈩�', min: 0, max: 60, isAlarm: false },
+ { name: '鍘嬪姏', value: 0.85, unit: 'MPa', min: 0.5, max: 0.8, isAlarm: true },
+ { name: '杞��', value: 1450, unit: 'rpm', min: 1000, max: 1500, isAlarm: false },
+ { name: '鎸姩', value: 3.2, unit: 'mm/s', min: 0, max: 2.5, isAlarm: true },
+ { name: '鐢垫祦', value: 25.6, unit: 'A', min: 0, max: 30, isAlarm: false },
+ { name: '鐢靛帇', value: 380, unit: 'V', min: 360, max: 400, isAlarm: false }
+])
+
+// 鍛婅鍒楄〃
+const alarmList = ref([
+ { id: 1, deviceName: '绌哄帇鏈篈-001', message: '鍘嬪姏瓒呮爣', level: 'high', time: '2024-12-16 14:32:15' },
+ { id: 2, deviceName: '绌哄帇鏈篈-001', message: '鎸姩杩囧ぇ', level: 'medium', time: '2024-12-16 14:30:45' },
+ { id: 3, deviceName: '鍐峰嵈濉擝-002', message: '娓╁害寮傚父', level: 'warning', time: '2024-12-16 14:28:30' }
+])
+
+// 鍘嗗彶鍙傛暟閫夐」
+const historyParams = ref(['娓╁害', '鍘嬪姏', '杞��', '鎸姩', '鐢垫祦', '鐢靛帇'])
+const activeParam = ref('娓╁害')
+
+// 鍘嗗彶鏁版嵁
+const historyData = ref({
+ dates: [],
+ values: []
+})
+
+// 鍥捐〃寮曠敤
+const historyChartRef = ref(null)
+let historyChart = null
+
+// 璁惧璇︽儏瀵硅瘽妗�
+const deviceDetailVisible = ref(false)
+
+// 闃堝�艰缃〃鍗�
+const thresholdForm = ref({})
+
+// 鍒濆鍖栭槇鍊艰〃鍗�
+const initThresholdForm = () => {
+ const form = {}
+ realTimeParams.value.forEach(param => {
+ form[param.name + 'Min'] = param.min
+ form[param.name + 'Max'] = param.max
+ })
+ thresholdForm.value = form
+}
+
+// 澶勭悊璁惧鍙樻洿
+const handleDeviceChange = (deviceId) => {
+ selectedDevice.value = devices.value.find(device => device.id === deviceId) || devices.value[0]
+ // 妯℃嫙鍒囨崲璁惧鍚庢洿鏂板疄鏃跺弬鏁�
+ updateRealTimeParams()
+ // 鍒锋柊鍘嗗彶鏁版嵁鍥捐〃
+ initHistoryChart()
+}
+
+// 鏇存柊瀹炴椂鍙傛暟锛堟ā鎷燂級
+const updateRealTimeParams = () => {
+ realTimeParams.value = realTimeParams.value.map(param => {
+ // 鐢熸垚闅忔満鍊硷紝閮ㄥ垎鍙傛暟鍙兘瑙﹀彂鍛婅
+ const randomFactor = Math.random() * 0.2 - 0.1 // -0.1 鍒� 0.1 涔嬮棿鐨勯殢鏈烘暟
+ const baseValue = (param.min + param.max) / 2
+ const newValue = baseValue + baseValue * randomFactor
+ const isAlarm = newValue < param.min || newValue > param.max
+
+ return {
+ ...param,
+ value: Number(newValue.toFixed(2)),
+ isAlarm
+ }
+ })
+}
+
+// 澶勭悊鍘嗗彶鏁版嵁鏌ヨ
+const handleHistoryQuery = () => {
+ // 妯℃嫙鏌ヨ鍘嗗彶鏁版嵁
+ generateHistoryData()
+ initHistoryChart()
+ ElMessage.success('鍘嗗彶鏁版嵁鏌ヨ鎴愬姛')
+}
+
+// 鐢熸垚鍘嗗彶鏁版嵁锛堟ā鎷燂級
+const generateHistoryData = () => {
+ const dates = []
+ const values = []
+
+ // 鐢熸垚杩囧幓7澶╃殑鏃ユ湡鍜屽搴旀暟鎹�
+ for (let i = 6; i >= 0; i--) {
+ const date = new Date()
+ date.setDate(date.getDate() - i)
+ dates.push(date.toLocaleDateString())
+
+ // 鐢熸垚闅忔満鍊�
+ const baseValue = (realTimeParams.value.find(p => p.name === activeParam.value).min +
+ realTimeParams.value.find(p => p.name === activeParam.value).max) / 2
+ const randomValue = baseValue + (Math.random() - 0.5) * baseValue * 0.4
+ values.push(Number(randomValue.toFixed(2)))
+ }
+
+ historyData.value = {
+ dates,
+ values
+ }
+}
+
+// 鍒濆鍖栧巻鍙叉暟鎹秼鍔垮浘
+const initHistoryChart = () => {
+ if (historyChartRef.value) {
+ historyChart = echarts.init(historyChartRef.value)
+
+ // 濡傛灉娌℃湁鍘嗗彶鏁版嵁锛岀敓鎴愭ā鎷熸暟鎹�
+ if (historyData.value.dates.length === 0) {
+ generateHistoryData()
+ }
+
+ const paramConfig = realTimeParams.value.find(p => p.name === activeParam.value)
+ const option = {
+ tooltip: {
+ trigger: 'axis',
+ axisPointer: {
+ type: 'cross',
+ label: {
+ backgroundColor: '#6a7985'
+ }
+ }
+ },
+ grid: {
+ left: '3%',
+ right: '4%',
+ bottom: '3%',
+ containLabel: true
+ },
+ xAxis: {
+ type: 'category',
+ boundaryGap: false,
+ data: historyData.value.dates
+ },
+ yAxis: {
+ type: 'value',
+ name: `${activeParam.value}(${paramConfig.unit})`,
+ min: paramConfig.min * 0.9,
+ max: paramConfig.max * 1.1
+ },
+ series: [
+ {
+ name: activeParam.value,
+ type: 'line',
+ stack: '鎬婚噺',
+ areaStyle: {},
+ emphasis: {
+ focus: 'series'
+ },
+ data: historyData.value.values,
+ itemStyle: {
+ color: '#409eff'
+ },
+ lineStyle: {
+ width: 3
+ }
+ }
+ ]
+ }
+ historyChart.setOption(option)
+ }
+}
+
+// 澶勭悊鍙傛暟鍒囨崲
+const handleParamChange = () => {
+ // 鐢熸垚鏂板弬鏁扮殑鍘嗗彶鏁版嵁
+ generateHistoryData()
+ initHistoryChart()
+}
+
+// 澶勭悊鍛婅鍏抽棴
+const handleAlarmClose = (alarmId) => {
+ const index = alarmList.value.findIndex(alarm => alarm.id === alarmId)
+ if (index !== -1) {
+ alarmList.value.splice(index, 1)
+ }
+}
+
+// 鎵撳紑璁惧璇︽儏椤�
+const openDeviceDetail = () => {
+ initThresholdForm()
+ deviceDetailVisible.value = true
+}
+
+// 淇濆瓨闃堝�艰缃�
+const saveThresholds = () => {
+ // 妯℃嫙淇濆瓨闃堝��
+ realTimeParams.value = realTimeParams.value.map(param => {
+ return {
+ ...param,
+ min: thresholdForm.value[param.name + 'Min'],
+ max: thresholdForm.value[param.name + 'Max']
+ }
+ })
+ deviceDetailVisible.value = false
+ ElMessage.success('闃堝�艰缃繚瀛樻垚鍔�')
+}
+
+// 鐩戝惉绐楀彛澶у皬鍙樺寲锛岃皟鏁村浘琛ㄥぇ灏�
+const handleResize = () => {
+ historyChart?.resize()
+}
+
+// 姣�5绉掓洿鏂颁竴娆″疄鏃跺弬鏁帮紙妯℃嫙锛�
+let updateTimer = null
+const startRealTimeUpdate = () => {
+ updateTimer = setInterval(() => {
+ updateRealTimeParams()
+ }, 5000)
+}
+
+onMounted(() => {
+ // 鍒濆鍖栧浘琛�
+ initHistoryChart()
+ // 鍒濆鍖栭槇鍊艰〃鍗�
+ initThresholdForm()
+ // 寮�濮嬪疄鏃舵洿鏂�
+ startRealTimeUpdate()
+ // 鐩戝惉绐楀彛澶у皬鍙樺寲
+ window.addEventListener('resize', handleResize)
+})
+
+onUnmounted(() => {
+ // 娓呴櫎瀹氭椂鍣�
+ if (updateTimer) {
+ clearInterval(updateTimer)
+ }
+ // 閿�姣佸浘琛�
+ historyChart?.dispose()
+ // 绉婚櫎浜嬩欢鐩戝惉
+ window.removeEventListener('resize', handleResize)
+})
+</script>
+
+<style scoped>
+.real-time-monitoring-container {
+ padding: 20px;
+ background-color: #f5f7fa;
+ min-height: 100vh;
+}
+
+.device-select-form {
+ margin-bottom: 0;
+}
+
+.card-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+}
+
+.param-tabs {
+ display: flex;
+ gap: 10px;
+}
+
+.param-card {
+ transition: all 0.3s;
+}
+
+.alarm-card {
+ border-left: 4px solid #f56c6c;
+ box-shadow: 0 2px 12px 0 rgba(245, 108, 108, 0.1);
+}
+
+.param-content {
+ text-align: center;
+}
+
+.param-title {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ gap: 10px;
+ font-size: 16px;
+ color: #606266;
+ margin-bottom: 10px;
+}
+
+.param-value {
+ font-size: 32px;
+ font-weight: bold;
+ color: #303133;
+ margin-bottom: 10px;
+ display: block;
+}
+
+.alarm-value {
+ color: #f56c6c;
+}
+
+.param-range {
+ font-size: 14px;
+ color: #909399;
+}
+
+.alarm-item {
+ margin-bottom: 10px;
+}
+
+.alarm-detail {
+ display: flex;
+ justify-content: space-between;
+ margin-top: 5px;
+ font-size: 14px;
+ color: #606266;
+}
+
+.chart-container {
+ width: 100%;
+ height: 400px;
+}
+
+.device-detail-content {
+ padding: 10px 0;
+}
+
+.device-detail-content h3 {
+ margin-bottom: 20px;
+ color: #303133;
+}
+
+.detail-param-item {
+ display: flex;
+ align-items: center;
+ margin-bottom: 15px;
+ padding: 10px;
+ background-color: #fafafa;
+ border-radius: 4px;
+}
+
+.param-label {
+ font-size: 14px;
+ color: #606266;
+ width: 80px;
+}
+
+.param-range {
+ font-size: 12px;
+ color: #909399;
+ margin-left: 10px;
+}
+</style>
\ No newline at end of file
diff --git a/vite.config.js b/vite.config.js
index 6821c23..4647827 100644
--- a/vite.config.js
+++ b/vite.config.js
@@ -8,8 +8,8 @@
const { VITE_APP_ENV } = env;
const baseUrl =
VITE_APP_ENV == "development"
- ? "http://127.0.0.1:8018" // 寮�鍙戠幆澧冨悗绔帴鍙�
- : "http://10.136.12.71:8018"; // 鐢熶骇鐜鍚庣鎺ュ彛
+ ? "http://127.0.0.1:8020" // 寮�鍙戠幆澧冨悗绔帴鍙�
+ : "http://10.136.12.71:8020"; // 鐢熶骇鐜鍚庣鎺ュ彛
return {
// 閮ㄧ讲鐢熶骇鐜鍜屽紑鍙戠幆澧冧笅鐨刄RL銆�
--
Gitblit v1.9.3