Bladeren bron

update 页面显示

bzd_lxf 3 maanden geleden
bovenliggende
commit
aff256b2ff

+ 10 - 10
pm_ui/src/api/driver/device.js → pm_ui/src/api/device/basic.js

@@ -1,44 +1,44 @@
 import request from '@/utils/request'
 
 // 查询设备基础信息列表
-export function listDevice(query) {
+export function listBasic(query) {
     return request({
-        url: '/driver/device/list',
+        url: '/device/basic/list',
         method: 'get',
         params: query
     })
 }
 
 // 查询设备基础信息详细
-export function getDevice(id) {
+export function getBasic(id) {
     return request({
-        url: '/driver/device/' + id,
+        url: '/device/basic/' + id,
         method: 'get'
     })
 }
 
 // 新增设备基础信息
-export function addDevice(data) {
+export function addBasic(data) {
     return request({
-        url: '/driver/device',
+        url: '/device/basic',
         method: 'post',
         data: data
     })
 }
 
 // 修改设备基础信息
-export function updateDevice(data) {
+export function updateBasic(data) {
     return request({
-        url: '/driver/device',
+        url: '/device/basic',
         method: 'put',
         data: data
     })
 }
 
 // 删除设备基础信息
-export function delDevice(id) {
+export function delBasic(id) {
     return request({
-        url: '/driver/device/' + id,
+        url: '/device/basic/' + id,
         method: 'delete'
     })
 }

+ 5 - 5
pm_ui/src/api/control/control.js → pm_ui/src/api/device/control.js

@@ -3,7 +3,7 @@ import request from '@/utils/request'
 // 查询设备控制记录列表
 export function listControl(query) {
     return request({
-        url: '/control/control/list',
+        url: '/device/control/list',
         method: 'get',
         params: query
     })
@@ -12,7 +12,7 @@ export function listControl(query) {
 // 查询设备控制记录详细
 export function getControl(id) {
     return request({
-        url: '/control/control/' + id,
+        url: '/device/control/' + id,
         method: 'get'
     })
 }
@@ -20,7 +20,7 @@ export function getControl(id) {
 // 新增设备控制记录
 export function addControl(data) {
     return request({
-        url: '/control/control',
+        url: '/device/control',
         method: 'post',
         data: data
     })
@@ -29,7 +29,7 @@ export function addControl(data) {
 // 修改设备控制记录
 export function updateControl(data) {
     return request({
-        url: '/control/control',
+        url: '/device/control',
         method: 'put',
         data: data
     })
@@ -38,7 +38,7 @@ export function updateControl(data) {
 // 删除设备控制记录
 export function delControl(id) {
     return request({
-        url: '/control/control/' + id,
+        url: '/device/control/' + id,
         method: 'delete'
     })
 }

+ 44 - 0
pm_ui/src/api/device/topology.js

@@ -0,0 +1,44 @@
+import request from '@/utils/request'
+
+// 查询项目拓扑列表
+export function listTopology(query) {
+    return request({
+        url: '/device/topology/list',
+        method: 'get',
+        params: query
+    })
+}
+
+// 查询项目拓扑详细
+export function getTopology(itemId) {
+    return request({
+        url: '/device/topology/' + itemId,
+        method: 'get'
+    })
+}
+
+// 新增项目拓扑
+export function addTopology(data) {
+    return request({
+        url: '/device/topology',
+        method: 'post',
+        data: data
+    })
+}
+
+// 修改项目拓扑
+export function updateTopology(data) {
+    return request({
+        url: '/device/topology',
+        method: 'put',
+        data: data
+    })
+}
+
+// 删除项目拓扑
+export function delTopology(itemId) {
+    return request({
+        url: '/device/topology/' + itemId,
+        method: 'delete'
+    })
+}

+ 5 - 5
pm_ui/src/api/waring/waring.js → pm_ui/src/api/device/waring.js

@@ -3,7 +3,7 @@ import request from '@/utils/request'
 // 查询设备告警列表
 export function listWaring(query) {
     return request({
-        url: '/waring/waring/list',
+        url: '/device/waring/list',
         method: 'get',
         params: query
     })
@@ -12,7 +12,7 @@ export function listWaring(query) {
 // 查询设备告警详细
 export function getWaring(id) {
     return request({
-        url: '/waring/waring/' + id,
+        url: '/device/waring/' + id,
         method: 'get'
     })
 }
@@ -20,7 +20,7 @@ export function getWaring(id) {
 // 新增设备告警
 export function addWaring(data) {
     return request({
-        url: '/waring/waring',
+        url: '/device/waring',
         method: 'post',
         data: data
     })
@@ -29,7 +29,7 @@ export function addWaring(data) {
 // 修改设备告警
 export function updateWaring(data) {
     return request({
-        url: '/waring/waring',
+        url: '/device/waring',
         method: 'put',
         data: data
     })
@@ -38,7 +38,7 @@ export function updateWaring(data) {
 // 删除设备告警
 export function delWaring(id) {
     return request({
-        url: '/waring/waring/' + id,
+        url: '/device/waring/' + id,
         method: 'delete'
     })
 }

+ 52 - 0
pm_ui/src/api/repairOrder/repairOrder.js

@@ -0,0 +1,52 @@
+import request from '@/utils/request'
+
+// 查询维修工单列表
+export function listRepairOrder(query) {
+    return request({
+        url: '/repairOrder/repairOrder/list',
+        method: 'get',
+        params: query
+    })
+}
+
+// 查询维修工单详细
+export function getRepairOrder(id) {
+    return request({
+        url: '/repairOrder/repairOrder/' + id,
+        method: 'get'
+    })
+}
+
+// 新增维修工单
+export function addRepairOrder(data) {
+    return request({
+        url: '/repairOrder/repairOrder',
+        method: 'post',
+        data: data
+    })
+}
+
+// 修改维修工单
+export function updateRepairOrder(data) {
+    return request({
+        url: '/repairOrder/repairOrder',
+        method: 'put',
+        data: data
+    })
+}
+
+// 删除维修工单
+export function delRepairOrder(id) {
+    return request({
+        url: '/repairOrder/repairOrder/' + id,
+        method: 'delete'
+    })
+}
+
+export function deleteFile(filePath) {
+    return request({
+        url: '/common/deleteFile',
+        method: 'post',
+        data: { filePath }
+    })
+}

+ 13 - 2
pm_ui/src/components/FileUpload/index.vue

@@ -68,6 +68,10 @@ const props = defineProps({
   disabled: {
     type: Boolean,
     default: false
+  },
+  onRemove: {
+    type: Function,
+    default: null
   }
 });
 
@@ -158,8 +162,15 @@ function handleUploadSuccess(res, file) {
 
 // 删除文件
 function handleDelete(index) {
-  fileList.value.splice(index, 1);
-  emit("update:modelValue", listToString(fileList.value));
+  // fileList.value.splice(index, 1);
+  // emit("update:modelValue", listToString(fileList.value));
+  if (props.onRemove) {
+    const file = fileList.value[index];
+    props.onRemove(file);
+  } else {
+    fileList.value.splice(index, 1);
+    emit("update:modelValue", listToString(fileList.value));
+  }
 }
 
 // 上传结束处理

+ 70 - 15
pm_ui/src/views/device/device/index.vue → pm_ui/src/views/device/basic/index.vue

@@ -30,7 +30,7 @@
             plain
             icon="Plus"
             @click="handleAdd"
-            v-hasPermi="['driver:device:add']"
+            v-hasPermi="['driver:basic:add']"
         >新增</el-button>
       </el-col>
       <el-col :span="1.5">
@@ -40,7 +40,7 @@
             icon="Edit"
             :disabled="single"
             @click="handleUpdate"
-            v-hasPermi="['driver:device:edit']"
+            v-hasPermi="['driver:basic:edit']"
         >修改</el-button>
       </el-col>
       <el-col :span="1.5">
@@ -50,7 +50,7 @@
             icon="Delete"
             :disabled="multiple"
             @click="handleDelete"
-            v-hasPermi="['driver:device:remove']"
+            v-hasPermi="['driver:basic:remove']"
         >删除</el-button>
       </el-col>
       <el-col :span="1.5">
@@ -59,7 +59,7 @@
             plain
             icon="Download"
             @click="handleExport"
-            v-hasPermi="['driver:device:export']"
+            v-hasPermi="['driver:basic:export']"
         >导出</el-button>
       </el-col>
       <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
@@ -67,7 +67,7 @@
 
     <el-table v-loading="loading" stripe border :data="deviceList" @selection-change="handleSelectionChange">
       <el-table-column type="selection" width="55" align="center" />
-      <el-table-column label="设备ID" align="center" prop="id" />
+<!--      <el-table-column label="设备ID" align="center" prop="id" />-->
       <el-table-column label="设备编码" align="center" prop="deviceCode" width="90"/>
       <el-table-column label="设备名称" align="center" prop="deviceName" width="120"/>
       <el-table-column label="设备类型" align="center" prop="deviceType" />
@@ -100,10 +100,11 @@
         </template>
       </el-table-column>
       <el-table-column label="设备描述" align="center" prop="description" width="140"/>
-      <el-table-column label="操作" min-width="140" fixed="right" align="center" class-name="small-padding fixed-width">
+      <el-table-column label="操作" min-width="140" fixed="right" width="200px" align="center" class-name="small-padding fixed-width">
         <template #default="scope">
-          <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['driver:device:edit']">修改</el-button>
-          <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['driver:device:remove']">删除</el-button>
+          <el-button link type="primary" icon="View" @click="handleDetail(scope.row)" v-hasPermi="['driver:basic:detail']">详情</el-button>
+          <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['driver:basic:edit']">修改</el-button>
+          <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['driver:basic:remove']">删除</el-button>
         </template>
       </el-table-column>
     </el-table>
@@ -125,7 +126,7 @@
         <el-form-item label="设备名称" prop="deviceName">
           <el-input v-model="form.deviceName" placeholder="请输入设备名称" />
         </el-form-item>
-        <el-form-item label="设备类型(空调/新风/配电等)" prop="deviceType">
+        <el-form-item label="设备类型" prop="deviceType">
           <el-input v-model="form.deviceType" placeholder="请输入设备类型" />
         </el-form-item>
         <el-form-item label="子系统类型" prop="subsystemType">
@@ -191,10 +192,53 @@
       </template>
     </el-dialog>
   </div>
+  <el-drawer
+      v-model="detailVisible"
+      title="设备监控"
+      direction="rtl"
+      size="50%"
+      :before-close="handleClose"
+  >
+    <el-tabs v-model="activeTab">
+      <el-tab-pane label="设备详情" name="detail">
+        <el-descriptions :column="2" border>
+          <el-descriptions-item label="设备编码">{{currentDevice.deviceCode}}</el-descriptions-item>
+          <el-descriptions-item label="设备名称">{{currentDevice.deviceName}}</el-descriptions-item>
+          <el-descriptions-item label="设备类型">{{currentDevice.deviceType}}</el-descriptions-item>
+          <el-descriptions-item label="子系统类型">{{currentDevice.subsystemType}}</el-descriptions-item>
+          <el-descriptions-item label="所属空间">{{currentDevice.spaceName}}</el-descriptions-item>
+          <el-descriptions-item label="品牌">{{currentDevice.brand}}</el-descriptions-item>
+          <el-descriptions-item label="型号">{{currentDevice.model}}</el-descriptions-item>
+          <el-descriptions-item label="序列号">{{currentDevice.serialNumber}}</el-descriptions-item>
+        </el-descriptions>
+      </el-tab-pane>
+      <el-tab-pane label="设备组态" name="configuration">
+        <!-- 设备组态内容 -->
+      </el-tab-pane>
+      <el-tab-pane label="设备告警" name="alarm">
+        <!-- 设备告警内容 -->
+      </el-tab-pane>
+      <el-tab-pane label="控制纪录" name="control">
+        <!-- 控制纪录内容 -->
+      </el-tab-pane>
+      <el-tab-pane label="实时数据" name="realtime">
+        <!-- 实时数据内容 -->
+      </el-tab-pane>
+      <el-tab-pane label="历史数据" name="instant">
+        <!-- 历史数据内容 -->
+      </el-tab-pane>
+      <el-tab-pane label="自动抄表" name="meter">
+        <!-- 自动抄表内容 -->
+      </el-tab-pane>
+      <el-tab-pane label="事件记录" name="event">
+        <!-- 事件记录内容 -->
+      </el-tab-pane>
+    </el-tabs>
+  </el-drawer>
 </template>
 
 <script setup name="Device">
-import {listDevice, getDevice, delDevice, addDevice, updateDevice} from "@/api/driver/device";
+import {listBasic, getBasic, delBasic, addBasic, updateBasic} from "@/api/device/basic";
 import {show} from "@/api/system/notice.js";
 
 const {proxy} = getCurrentInstance();
@@ -210,6 +254,17 @@ const multiple = ref(true);
 const total = ref(0);
 const title = ref("");
 
+const detailVisible = ref(false);
+const activeTab = ref('detail'); // 默认选中第一个标签页
+const currentDevice = ref({});
+
+function handleDetail(row) {
+  currentDevice.value = row;
+  activeTab.value = 'detail'; // 每次点击详情时重置为第一个标签页
+  detailVisible.value = true;
+}
+
+
 const data = reactive({
   form: {},
   queryParams: {
@@ -249,7 +304,7 @@ const {queryParams, form, rules} = toRefs(data);
 /** 查询设备基础信息列表 */
 function getList() {
   loading.value = true;
-  listDevice(queryParams.value).then(response => {
+  listBasic(queryParams.value).then(response => {
     deviceList.value = response.rows;
     total.value = response.total;
     loading.value = false;
@@ -317,7 +372,7 @@ function handleAdd() {
 function handleUpdate(row) {
   reset();
   const _id = row.id || ids.value
-  getDevice(_id).then(response => {
+  getBasic(_id).then(response => {
     form.value = response.data;
     open.value = true;
     title.value = "修改设备基础信息";
@@ -329,13 +384,13 @@ function submitForm() {
   proxy.$refs["deviceRef"].validate(valid => {
     if (valid) {
       if (form.value.id != null) {
-        updateDevice(form.value).then(response => {
+        updateBasic(form.value).then(response => {
           proxy.$modal.msgSuccess("修改成功");
           open.value = false;
           getList();
         });
       } else {
-        addDevice(form.value).then(response => {
+        addBasic(form.value).then(response => {
           proxy.$modal.msgSuccess("新增成功");
           open.value = false;
           getList();
@@ -349,7 +404,7 @@ function submitForm() {
 function handleDelete(row) {
   const _ids = row.id || ids.value;
   proxy.$modal.confirm('是否确认删除设备基础信息编号为"' + _ids + '"的数据项?').then(function () {
-    return delDevice(_ids);
+    return delBasic(_ids);
   }).then(() => {
     getList();
     proxy.$modal.msgSuccess("删除成功");

+ 9 - 9
pm_ui/src/views/control/control/index.vue → pm_ui/src/views/device/control/index.vue

@@ -46,7 +46,7 @@
             plain
             icon="Plus"
             @click="handleAdd"
-            v-hasPermi="['control:control:add']"
+            v-hasPermi="['device:control:add']"
         >新增</el-button>
       </el-col>
       <el-col :span="1.5">
@@ -56,7 +56,7 @@
             icon="Edit"
             :disabled="single"
             @click="handleUpdate"
-            v-hasPermi="['control:control:edit']"
+            v-hasPermi="['device:control:edit']"
         >修改</el-button>
       </el-col>
       <el-col :span="1.5">
@@ -66,7 +66,7 @@
             icon="Delete"
             :disabled="multiple"
             @click="handleDelete"
-            v-hasPermi="['control:control:remove']"
+            v-hasPermi="['device:control:remove']"
         >删除</el-button>
       </el-col>
       <el-col :span="1.5">
@@ -75,7 +75,7 @@
             plain
             icon="Download"
             @click="handleExport"
-            v-hasPermi="['control:control:export']"
+            v-hasPermi="['device:control:export']"
         >导出</el-button>
       </el-col>
       <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
@@ -83,7 +83,7 @@
 
     <el-table v-loading="loading" :data="controlList" @selection-change="handleSelectionChange">
       <el-table-column type="selection" width="55" align="center" />
-      <el-table-column label="主键ID" align="center" prop="id" />
+      <el-table-column label="主键ID1" align="center" prop="id" />
       <el-table-column label="设备ID" align="center" prop="deviceId" />
       <el-table-column label="点位ID" align="center" prop="pointId" />
       <el-table-column label="控制类型" align="center" prop="controlType" />
@@ -100,8 +100,8 @@
       <el-table-column label="备注" align="center" prop="remark" />
       <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
         <template #default="scope">
-          <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['control:control:edit']">修改</el-button>
-          <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['control:control:remove']">删除</el-button>
+          <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['device:control:edit']">修改</el-button>
+          <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['device:control:remove']">删除</el-button>
         </template>
       </el-table-column>
     </el-table>
@@ -161,7 +161,7 @@
 </template>
 
 <script setup name="Control">
-import { listControl, getControl, delControl, addControl, updateControl } from "@/api/control/control";
+import { listControl, getControl, delControl, addControl, updateControl } from "@/api/device/control";
 
 const { proxy } = getCurrentInstance();
 
@@ -319,7 +319,7 @@ function handleDelete(row) {
 
 /** 导出按钮操作 */
 function handleExport() {
-  proxy.download('control/control/export', {
+  proxy.download('device/control/export', {
     ...queryParams.value
   }, `control_${new Date().getTime()}.xlsx`)
 }

+ 443 - 0
pm_ui/src/views/device/topology/index.vue

@@ -0,0 +1,443 @@
+<template>
+  <div class="app-container">
+    <el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="68px">
+      <el-form-item label="项目名称" prop="itemName">
+        <el-input
+            v-model="queryParams.itemName"
+            placeholder="请输入项目名称"
+            clearable
+            @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 label="项目类型" prop="itemType">
+        <el-select v-model="queryParams.itemType" placeholder="请选择项目类型" clearable style="width: 240px">
+          <el-option
+              v-for="dict in root_node_type"
+              :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"
+            v-hasPermi="['topology:topology:add']"
+        >新增
+        </el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+            type="info"
+            plain
+            icon="Menu"
+            @click="toggleExpandAll"
+        >{{ isExpandAll ? '折叠' : '展开' }}</el-button>
+      </el-col>
+<!--      <el-col :span="1.5">
+        <el-button
+            type="success"
+            plain
+            icon="Edit"
+            :disabled="single"
+            @click="handleUpdate"
+            v-hasPermi="['topology:topology:edit']"
+        >修改
+        </el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+            type="danger"
+            plain
+            icon="Delete"
+            :disabled="multiple"
+            @click="handleDelete"
+            v-hasPermi="['topology:topology:remove']"
+        >删除
+        </el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+            type="warning"
+            plain
+            icon="Download"
+            @click="handleExport"
+            v-hasPermi="['topology:topology:export']"
+        >导出
+        </el-button>
+      </el-col>-->
+      <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+
+    <el-table
+        ref="tableRef"
+        v-loading="loading"
+        :data="topologyList"
+        @selection-change="handleSelectionChange"
+        row-key="itemId"
+        :tree-props="{children: 'children', hasChildren: 'hasChildren'}"
+    >
+      <el-table-column type="selection" width="55" align="center"/>
+      <!--      <el-table-column label="项目id" align="center" prop="itemId" />
+            <el-table-column label="父项目id" align="center" prop="parentId" />
+            <el-table-column label="祖级列表" align="center" prop="ancestors" />-->
+      <el-table-column label="项目名称" align="center" prop="itemName"/>
+      <el-table-column label="显示顺序" align="center" prop="orderNum"/>
+      <el-table-column label="部门状态" align="center" prop="status">
+        <template #default="scope">
+          <dict-tag :options="sys_normal_disable" :value="scope.row.status"/>
+        </template>
+      </el-table-column>
+      <el-table-column label="项目类型" align="center" prop="itemType">
+        <template #default="scope">
+          <dict-tag :options="root_node_type" :value="scope.row.itemType"/>
+        </template>
+      </el-table-column>
+      <!--      <el-table-column label="设备ids" align="center" prop="deviceId" />-->
+      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+        <template #default="scope">
+          <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)"
+                     v-hasPermi="['topology:topology:edit']">修改
+          </el-button>
+          <el-button link type="primary" icon="Plus" @click="handleAdd(scope.row)"
+                     v-hasPermi="['topology:topology:add']">新增
+          </el-button>
+          <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)"
+                     v-hasPermi="['topology:topology:remove']">删除
+          </el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+
+<!--    <pagination
+        v-show="total>0"
+        :total="total"
+        v-model:page="queryParams.pageNum"
+        v-model:limit="queryParams.pageSize"
+        @pagination="getList"
+    />-->
+
+    <!-- 添加或修改项目拓扑对话框 -->
+    <el-dialog :title="title" v-model="open" width="500px" append-to-body>
+      <el-form ref="topologyRef" :model="form" :rules="rules" label-width="80px">
+
+        <el-form-item label="上级项目" prop="parentId">
+          <el-tree-select
+              v-model="form.parentId"
+              :data="itemTopologyOptions"
+              :props="{
+                  label: 'itemName',
+                  children: 'children',
+                  value: 'itemId'
+              }"
+              :disabled="form.parentId === form.itemName"
+              filterable
+              check-strictly
+              style="width: 100%"
+          >
+            <template #default="{ node, data }">
+              <span>{{ data.itemName }}</span>
+            </template>
+          </el-tree-select>
+        </el-form-item>
+        <el-form-item label="项目名称" prop="itemName">
+          <el-input v-model="form.itemName" placeholder="请输入项目名称"/>
+        </el-form-item>
+        <el-form-item label="显示顺序" prop="orderNum">
+          <el-input v-model="form.orderNum" placeholder="请输入显示顺序"/>
+        </el-form-item>
+        <el-form-item label="部门状态" prop="status">
+          <el-select v-model="form.status" placeholder="请选择部门状态">
+            <el-option
+                v-for="dict in sys_normal_disable"
+                :key="dict.value"
+                :label="dict.label"
+                :value="dict.value"
+            ></el-option>
+          </el-select>
+        </el-form-item>
+        <!--        <el-form-item label="删除标志" prop="delFlag">
+                  <el-input v-model="form.delFlag" placeholder="请输入删除标志" />
+                </el-form-item>-->
+        <el-form-item label="项目类型" prop="itemType">
+          <el-select
+              v-model="form.itemType"
+              placeholder="请选择项目类型"
+              filterable
+              clearable
+          >
+            <el-option
+                v-for="dict in root_node_type"
+                :key="dict.value"
+                :label="dict.label"
+                :value="dict.value"
+            ></el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item label="关联设备" prop="deviceId">
+          <el-tree-select
+              v-model="form.deviceId"
+              :data="deviceOptions"
+              :props="{
+                  label: 'deviceName',
+                  children: 'children',
+                  value: 'id'
+              }"
+              multiple
+              filterable
+              check-strictly
+              placeholder="请选择设备"
+              style="width: 100%"
+          />
+        </el-form-item>
+      </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="Topology">
+import {listTopology, getTopology, delTopology, addTopology, updateTopology} from "@/api/device/topology";
+import {listBasic} from "@/api/device/basic";
+
+const {proxy} = getCurrentInstance();
+const {root_node_type, sys_normal_disable} = proxy.useDict('root_node_type', 'sys_normal_disable');
+
+const topologyList = 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 itemTopologyOptions = ref([]);
+const deviceOptions = ref([]);
+const isExpandAll = ref(false);
+const tableRef = ref();
+
+
+const data = reactive({
+  form: {},
+  queryParams: {
+    pageNum: 1,
+    pageSize: 10000,
+    itemName: null,
+    status: null,
+    itemType: null,
+    deviceId: null
+  },
+  rules: {}
+});
+
+const {queryParams, form, rules} = toRefs(data);
+
+/** 查询项目拓扑列表 */
+function getList() {
+  loading.value = true;
+  listTopology(queryParams.value).then(response => {
+    topologyList.value = proxy.handleTree(response.rows, "itemId", "parentId", "children");
+    total.value = response.total;
+    loading.value = false;
+  });
+}
+
+function toggleExpandAll() {
+  isExpandAll.value = !isExpandAll.value;
+
+  const toggleChildren = (items) => {
+    items.forEach(item => {
+      tableRef.value.toggleRowExpansion(item, isExpandAll.value);
+      if (item.children && item.children.length > 0) {
+        toggleChildren(item.children);
+      }
+    });
+  };
+
+  toggleChildren(topologyList.value);
+}
+
+// 取消按钮
+function cancel() {
+  open.value = false;
+  reset();
+}
+
+// 表单重置
+function reset() {
+  form.value = {
+    itemId: null,
+    parentId: null,
+    ancestors: null,
+    itemName: null,
+    orderNum: null,
+    status: null,
+    delFlag: null,
+    itemType: null,
+    createBy: null,
+    createTime: null,
+    updateBy: null,
+    updateTime: null,
+    deviceId: null
+  };
+  proxy.resetForm("topologyRef");
+}
+
+/** 搜索按钮操作 */
+function handleQuery() {
+  queryParams.value.pageNum = 1;
+  getList();
+}
+
+/** 重置按钮操作 */
+function resetQuery() {
+  proxy.resetForm("queryRef");
+  handleQuery();
+}
+
+// 多选框选中数据
+function handleSelectionChange(selection) {
+  ids.value = selection.map(item => item.itemId);
+  single.value = selection.length != 1;
+  multiple.value = !selection.length;
+}
+
+/** 新增按钮操作 */
+function handleAdd(row = null) {
+  reset();
+  open.value = true;
+  title.value = "添加项目拓扑";
+
+  form.value = {
+    ...form.value,
+    parentId: row ? row.itemId : null,
+    status: '0', // 默认部门状态为"正常"
+    itemType: row ? row.itemType : null,
+    deviceId: null
+  };
+
+  // 并行加载拓扑和设备数据
+  Promise.all([
+    listTopology({pageNum: 1, pageSize: 10000}),
+    listBasic({pageNum: 1, pageSize: 10000})
+  ]).then(([topologyRes, deviceRes]) => {
+    itemTopologyOptions.value = proxy.handleTree(topologyRes.rows, "itemId");
+    deviceOptions.value = deviceRes.rows.map(item => ({
+      id: item.id,
+      deviceName: `${item.deviceCode} - ${item.deviceName}`
+    }));
+  });
+}
+
+/** 修改按钮操作 */
+function handleUpdate(row) {
+  reset();
+  const _itemId = row.itemId;
+
+  getTopology(_itemId).then(response => {
+    // 处理关联设备数据
+    const deviceIds = response.data.deviceId ? response.data.deviceId.split(',').map(id => String(id)) : [];
+
+    // 处理上级项目数据
+    //const parentId = response.data.parentId === "0" ? response.data.itemName : response.data.parentId;
+    form.value = {
+      ...response.data,
+      parentId: response.data.parentId === "0" ? response.data.itemName : response.data.parentId,
+      deviceId: deviceIds
+    };
+
+    Promise.all([
+      listTopology({pageNum: 1, pageSize: 10000}),
+      listBasic({pageNum: 1, pageSize: 10000})
+    ]).then(([topologyRes, deviceRes]) => {
+      itemTopologyOptions.value = proxy.handleTree(topologyRes.rows, "itemId");
+      deviceOptions.value = deviceRes.rows.map(item => ({
+        id: String(item.id),  // 确保ID转为字符串
+        deviceName: `${item.deviceCode} - ${item.deviceName}`
+      }));
+    });
+
+    open.value = true;
+    title.value = "修改项目拓扑";
+  });
+}
+
+/** 提交按钮 */
+function submitForm() {
+  proxy.$refs["topologyRef"].validate(valid => {
+    if (valid) {
+      if (Array.isArray(form.value.deviceId)) {
+        form.value.deviceId = form.value.deviceId.join(',');
+      }
+      if (form.value.itemId != null) {
+        updateTopology(form.value).then(response => {
+          proxy.$modal.msgSuccess("修改成功");
+          open.value = false;
+          getList();
+        });
+      } else {
+        addTopology(form.value).then(response => {
+          proxy.$modal.msgSuccess("新增成功");
+          open.value = false;
+          getList();
+        });
+      }
+    }
+  });
+}
+
+/** 删除按钮操作 */
+function handleDelete(row) {
+  const _itemIds = row.itemId || ids.value;
+  proxy.$modal.confirm('是否确认删除项目拓扑编号为"' + _itemIds + '"的数据项?').then(function () {
+    return delTopology(_itemIds);
+  }).then(() => {
+    getList();
+    proxy.$modal.msgSuccess("删除成功");
+  }).catch(() => {
+  });
+}
+
+/** 导出按钮操作 */
+function handleExport() {
+  proxy.download('topology/topology/export', {
+    ...queryParams.value
+  }, `topology_${new Date().getTime()}.xlsx`)
+}
+
+function getListBasic() {
+  listBasic(queryParams.value).then(response => {
+    deviceOptions.value = response.rows;
+  });
+}
+
+getList();
+getListBasic();
+</script>

+ 4 - 3
pm_ui/src/views/waring/waring/index.vue → pm_ui/src/views/device/waring/index.vue

@@ -67,13 +67,13 @@
 
     <el-table v-loading="loading" :data="waringList" @selection-change="handleSelectionChange">
       <el-table-column type="selection" width="55" align="center" />
-      <el-table-column label="告警ID" align="center" prop="id" />
+<!--      <el-table-column label="告警ID" align="center" prop="id" />-->
       <el-table-column label="告警编码" align="center" prop="alarmCode" />
       <el-table-column label="设备ID" align="center" prop="deviceId" />
       <el-table-column label="点位ID" align="center" prop="pointId" />
       <el-table-column label="告警级别(1-一般,2-重要,3-紧急)" align="center" prop="alarmLevel">
         <template #default="scope">
-          <dict-tag :options="sys_drivce_status" :value="scope.row.alarmLevel"/>
+          <dict-tag :options="alarm_level" :value="scope.row.alarmLevel"/>
         </template>
       </el-table-column>
       <el-table-column label="告警类型" align="center" prop="alarmType" />
@@ -196,9 +196,10 @@
 </template>
 
 <script setup name="Waring">
-import { listWaring, getWaring, delWaring, addWaring, updateWaring } from "@/api/waring/waring";
+import { listWaring, getWaring, delWaring, addWaring, updateWaring } from "@/api/device/waring";
 
 const { proxy } = getCurrentInstance();
+const {alarm_level} = proxy.useDict('alarm_level');
 
 const waringList = ref([]);
 const open = ref(false);

+ 427 - 0
pm_ui/src/views/repairOrder/repairOrder/index.vue

@@ -0,0 +1,427 @@
+<template>
+  <div class="app-container">
+    <el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="68px">
+      <el-form-item label="工单编号" prop="orderNo">
+        <el-input
+            v-model="queryParams.orderNo"
+            placeholder="请输入工单编号"
+            clearable
+            @keyup.enter="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="项目名称" prop="projectName">
+        <el-input
+            v-model="queryParams.projectName"
+            placeholder="请输入项目名称"
+            clearable
+            @keyup.enter="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="工单状态" prop="orderStatus" style="width: 260px">
+        <el-select v-model="queryParams.orderStatus" placeholder="请选择工单状态" clearable >
+          <el-option
+              v-for="dict in repair_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"
+            v-hasPermi="['repairOrder:repairOrder:add']"
+        >新增</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+            type="success"
+            plain
+            icon="Edit"
+            :disabled="single"
+            @click="handleUpdate"
+            v-hasPermi="['repairOrder:repairOrder:edit']"
+        >修改</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+            type="danger"
+            plain
+            icon="Delete"
+            :disabled="multiple"
+            @click="handleDelete"
+            v-hasPermi="['repairOrder:repairOrder:remove']"
+        >删除</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+            type="warning"
+            plain
+            icon="Download"
+            @click="handleExport"
+            v-hasPermi="['repairOrder:repairOrder:export']"
+        >导出</el-button>
+      </el-col>
+      <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+
+    <el-table v-loading="loading" :data="repairOrderList" @selection-change="handleSelectionChange">
+      <el-table-column type="selection" width="55" align="center" />
+<!--      <el-table-column label="id" align="center" prop="id" />-->
+      <el-table-column label="工单编号" align="center" prop="orderNo" />
+      <el-table-column label="工单内容" align="center" prop="orderContent" />
+      <el-table-column label="项目名称" align="center" prop="projectName" />
+      <el-table-column label="派单时间" align="center" prop="assignTime" width="180" sortable>
+        <template #default="scope">
+          <span>{{ parseTime(scope.row.assignTime, '{y}-{m}-{d}') }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="完成时间" align="center" prop="finishTime" width="180">
+        <template #default="scope">
+          <span>{{ parseTime(scope.row.finishTime, '{y}-{m}-{d}') }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="完成人" align="center" prop="finishBy" />
+      <el-table-column label="附件" align="center" prop="annex" />
+<!--      <el-table-column label="完成人id" align="center" prop="userId" />-->
+      <el-table-column label="工单状态" align="center" prop="orderStatus">
+        <template #default="scope">
+          <dict-tag :options="repair_status" :value="scope.row.orderStatus"/>
+        </template>
+      </el-table-column>
+      <el-table-column label="工单备注" align="center" prop="orderRemark" />
+      <el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="200px">
+        <template #default="scope">
+<!--          <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['repairOrder:repairOrder:edit']">详情</el-button>-->
+          <el-button link type="primary" icon="View" @click="showDetail(scope.row)" v-hasPermi="['repairOrder:repairOrder:edit']">详情</el-button>
+          <el-button
+              v-if="scope.row.orderStatus === '0'"
+              link
+              type="primary"
+              icon="Share"
+              @click="handleUpdate(scope.row)"
+              v-hasPermi="['repairOrder:repairOrder:edit']"
+          >派单</el-button>
+          <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['repairOrder:repairOrder:remove']">删除</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <pagination
+        v-show="total>0"
+        :total="total"
+        v-model:page="queryParams.pageNum"
+        v-model:limit="queryParams.pageSize"
+        @pagination="getList"
+    />
+
+    <el-drawer
+        v-model="detailVisible"
+        title="工单详情"
+        direction="rtl"
+        size="40%">
+      <el-descriptions :column="1" border>
+        <el-descriptions-item label="工单编号">{{ detailData.orderNo }}</el-descriptions-item>
+        <el-descriptions-item label="工单内容">{{ detailData.orderContent }}</el-descriptions-item>
+        <el-descriptions-item label="项目名称">{{ detailData.projectName }}</el-descriptions-item>
+        <el-descriptions-item label="派单时间">{{ parseTime(detailData.assignTime) }}</el-descriptions-item>
+        <el-descriptions-item label="完成时间">{{ parseTime(detailData.finishTime) }}</el-descriptions-item>
+        <el-descriptions-item label="完成人">{{ detailData.finishBy }}</el-descriptions-item>
+        <el-descriptions-item label="工单状态">
+          <dict-tag :options="repair_status" :value="detailData.orderStatus"/>
+        </el-descriptions-item>
+        <el-descriptions-item label="工单备注">{{ detailData.orderRemark }}</el-descriptions-item>
+      </el-descriptions>
+    </el-drawer>
+
+    <!-- 添加或修改维修工单对话框 -->
+    <el-dialog :title="title" v-model="open" width="600px" append-to-body>
+      <el-form ref="repairOrderRef" :model="form" :rules="rules" label-width="80px">
+        <el-form-item label="工单编号" prop="orderNo">
+          <el-input v-model="form.orderNo" placeholder="请输入工单编号" disabled="disabled"/>
+        </el-form-item>
+        <el-form-item label="工单内容" prop="orderContent">
+          <el-input v-model="form.orderContent" type="textarea" placeholder="请输入内容" disabled="disabled"/>
+        </el-form-item>
+        <el-form-item label="项目名称" prop="projectName"  >
+          <el-input v-model="form.projectName" placeholder="请输入项目名称" disabled="disabled"/>
+        </el-form-item>
+<!--        <el-form-item label="派单时间" prop="assignTime">-->
+<!--          <el-date-picker clearable-->
+<!--                          v-model="form.assignTime"-->
+<!--                          type="date"-->
+<!--                          value-format="YYYY-MM-DD"-->
+<!--                          placeholder="请选择派单时间">-->
+<!--          </el-date-picker>-->
+<!--        </el-form-item>-->
+<!--        <el-form-item label="完成时间" prop="finishTime">-->
+<!--          <el-date-picker clearable-->
+<!--                          v-model="form.finishTime"-->
+<!--                          type="date"-->
+<!--                          value-format="YYYY-MM-DD"-->
+<!--                          placeholder="请选择完成时间">-->
+<!--          </el-date-picker>-->
+<!--        </el-form-item>-->
+        <el-form-item label="责任人" prop="finishBy">
+          <el-select
+              v-model="form.userId"
+              placeholder="请选择责任人"
+              clearable
+              filterable
+          >
+            <el-option
+                v-for="user in userOptions"
+                :key="user.userId"
+                :label="user.userName || user.userName"
+                :value="user.userId"
+            />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="附件" prop="annex">
+          <file-upload v-model="form.annex" :on-remove="handleRemoveFile" disabled="disabled"/> <b>点击文件名下载</b>
+        </el-form-item>
+        <!--
+        <el-form-item label="完成人id" prop="userId">
+          <el-input v-model="form.userId" placeholder="请输入完成人id" />
+        </el-form-item>-->
+<!--        <el-form-item label="工单状态" prop="orderStatus">
+          <el-radio-group v-model="form.orderStatus">
+            <el-radio
+                v-for="dict in repair_status"
+                :key="dict.value"
+                :label="dict.value"
+            >{{dict.label}}</el-radio>
+          </el-radio-group>
+        </el-form-item>-->
+        <el-form-item label="工单备注" prop="orderRemark">
+          <el-input v-model="form.orderRemark" type="textarea" placeholder="请输入内容" />
+        </el-form-item>
+      </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="RepairOrder">
+import { listRepairOrder, getRepairOrder, delRepairOrder, addRepairOrder, updateRepairOrder,deleteFile } from "@/api/repairOrder/repairOrder";
+import { listUser } from "@/api/system/user";
+
+const { proxy } = getCurrentInstance();
+const { repair_status } = proxy.useDict('repair_status');
+
+const repairOrderList = 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 userOptions = ref([]);
+
+const detailVisible = ref(false);
+const detailData = ref({});
+
+const data = reactive({
+  form: {},
+  queryParams: {
+    pageNum: 1,
+    pageSize: 10,
+    orderNo: null,
+    orderContent: null,
+    projectName: null,
+    orderStatus: null,
+  },
+  rules: {
+  }
+});
+
+const { queryParams, form, rules } = toRefs(data);
+
+function showDetail(row) {
+  detailData.value = {...row};
+  detailVisible.value = true;
+}
+
+/** 查询维修工单列表 */
+function getList() {
+  loading.value = true;
+  listRepairOrder(queryParams.value).then(response => {
+    repairOrderList.value = response.rows;
+    total.value = response.total;
+    loading.value = false;
+  });
+}
+function handleRemoveFile(file) {
+  // 这里可以添加调用后端API删除文件的逻辑
+  proxy.$modal.confirm('确认删除该附件吗?').then(() => {
+    deleteFile(file.url).then(() => {
+      form.value.annex = null;
+      proxy.$modal.msgSuccess("删除成功");
+    }).catch(() => {
+      proxy.$modal.msgError("删除失败");
+    });
+  }).catch(() => {});
+}
+// 取消按钮
+function cancel() {
+  open.value = false;
+  reset();
+}
+
+// 表单重置
+function reset() {
+  form.value = {
+    id: null,
+    orderNo: null,
+    orderContent: null,
+    projectName: null,
+    assignTime: null,
+    finishTime: null,
+    finishBy: null,
+    annex: null,
+    userId: null,
+    orderStatus: null,
+    orderRemark: null,
+    createBy: null,
+    createTime: null,
+    updateBy: null,
+    updateTime: null
+  };
+  proxy.resetForm("repairOrderRef");
+}
+
+/** 搜索按钮操作 */
+function handleQuery() {
+  queryParams.value.pageNum = 1;
+  getList();
+}
+
+/** 重置按钮操作 */
+function resetQuery() {
+  proxy.resetForm("queryRef");
+  handleQuery();
+}
+
+// 多选框选中数据
+function handleSelectionChange(selection) {
+  ids.value = selection.map(item => item.id);
+  single.value = selection.length != 1;
+  multiple.value = !selection.length;
+}
+
+/** 新增按钮操作 */
+function handleAdd() {
+  reset();
+  open.value = true;
+  title.value = "添加维修工单";
+}
+// 获取用户列表
+function getUserList() {
+  listUser().then(response => {
+    userOptions.value = response.rows || [];
+    console.log("userOptions.value"+userOptions.value)
+  });
+}
+
+// 在组件挂载时获取用户列表
+onMounted(() => {
+  getUserList();
+});
+/** 修改按钮操作 */
+function handleUpdate(row) {
+  reset();
+  const _id = row.id || ids.value
+  getRepairOrder(_id).then(response => {
+    form.value = response.data;
+    open.value = true;
+    title.value = "维修工单派单";
+  });
+
+}
+
+/** 提交按钮 */
+function submitForm() {
+  if (form.value.userId) {
+    const user = userOptions.value.find(u => u.userId === form.value.userId);
+    if (user) {
+      form.value.finishBy = user.nickName || user.userName;
+      form.value.userId = user.userId || user.userId;
+    }
+  }
+  proxy.$refs["repairOrderRef"].validate(valid => {
+    if (valid) {
+      if (form.value.id != null) {
+        updateRepairOrder(form.value).then(response => {
+          proxy.$modal.msgSuccess("修改成功");
+          open.value = false;
+          getList();
+        });
+      } else {
+        addRepairOrder(form.value).then(response => {
+          proxy.$modal.msgSuccess("新增成功");
+          open.value = false;
+          getList();
+        });
+      }
+    }
+  });
+}
+
+/** 删除按钮操作 */
+/** 删除按钮操作 */
+function handleDelete(row) {
+  const _ids = row.id || ids.value;
+  const deletePromises = [];
+  proxy.$modal.confirm('是否确认删除选中的数据项?').then(function() {
+    // 如果是批量删除,检查每个选中项是否有附件
+    if (Array.isArray(ids.value) && ids.value.length > 0) {
+      repairOrderList.value.forEach(item => {
+        if (ids.value.includes(item.id) && item.annex) {
+          deletePromises.push(deleteFile(item.annex));
+        }
+      });
+    }
+    // 如果是单个删除,检查是否有附件
+    else if (row.annex) {
+      deletePromises.push(deleteFile(row.annex));
+    }
+    // 先删除所有附件
+    return Promise.all(deletePromises)
+        .then(() => {
+          // 附件删除成功后删除数据
+          return delRepairOrder(_ids);
+        });
+  }).then(() => {
+    getList();
+    proxy.$modal.msgSuccess("删除成功");
+  }).catch(() => {
+    proxy.$modal.msgError("删除失败");
+  });
+}
+
+/** 导出按钮操作 */
+function handleExport() {
+  proxy.download('repairOrder/repairOrder/export', {
+    ...queryParams.value
+  }, `repairOrder_${new Date().getTime()}.xlsx`)
+}
+
+getList();
+</script>

+ 428 - 0
pm_ui/src/views/repairOrder/repairOrder/index2.vue

@@ -0,0 +1,428 @@
+<template>
+  <div class="app-container">
+    <el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="68px">
+      <el-form-item label="工单编号" prop="orderNo">
+        <el-input
+            v-model="queryParams.orderNo"
+            placeholder="请输入工单编号"
+            clearable
+            @keyup.enter="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="项目名称321" prop="projectName">
+        <el-input
+            v-model="queryParams.projectName"
+            placeholder="请输入项目名称"
+            clearable
+            @keyup.enter="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="工单状态" prop="orderStatus" style="width: 260px">
+        <el-select v-model="queryParams.orderStatus" placeholder="请选择工单状态" clearable >
+          <el-option
+              v-for="dict in repair_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"
+            v-hasPermi="['repairOrder:repairOrder:add']"
+        >新增</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+            type="success"
+            plain
+            icon="Edit"
+            :disabled="single"
+            @click="handleUpdate"
+            v-hasPermi="['repairOrder:repairOrder:edit']"
+        >修改</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+            type="danger"
+            plain
+            icon="Delete"
+            :disabled="multiple"
+            @click="handleDelete"
+            v-hasPermi="['repairOrder:repairOrder:remove']"
+        >删除</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+            type="warning"
+            plain
+            icon="Download"
+            @click="handleExport"
+            v-hasPermi="['repairOrder:repairOrder:export']"
+        >导出</el-button>
+      </el-col>
+      <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+
+    <el-table v-loading="loading" :data="repairOrderList" @selection-change="handleSelectionChange">
+      <el-table-column type="selection" width="55" align="center" />
+<!--      <el-table-column label="id" align="center" prop="id" />-->
+      <el-table-column label="工单编号" align="center" prop="orderNo" />
+      <el-table-column label="工单内容" align="center" prop="orderContent" />
+      <el-table-column label="项目名称" align="center" prop="projectName" />
+      <el-table-column label="派单时间" align="center" prop="assignTime" width="180" sortable>
+        <template #default="scope">
+          <span>{{ parseTime(scope.row.assignTime, '{y}-{m}-{d}') }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="完成时间" align="center" prop="finishTime" width="180">
+        <template #default="scope">
+          <span>{{ parseTime(scope.row.finishTime, '{y}-{m}-{d}') }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="完成人" align="center" prop="finishBy" />
+      <el-table-column label="附件" align="center" prop="annex" />
+<!--      <el-table-column label="完成人id" align="center" prop="userId" />-->
+      <el-table-column label="工单状态" align="center" prop="orderStatus">
+        <template #default="scope">
+          <dict-tag :options="repair_status" :value="scope.row.orderStatus"/>
+        </template>
+      </el-table-column>
+      <el-table-column label="工单备注" align="center" prop="orderRemark" />
+      <el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="200px">
+        <template #default="scope">
+<!--          <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['repairOrder:repairOrder:edit']">详情</el-button>-->
+          <el-button link type="primary" icon="View" @click="showDetail(scope.row)" v-hasPermi="['repairOrder:repairOrder:edit']">详情</el-button>
+          <el-button
+              v-if="scope.row.orderStatus === '1'"
+              link
+              type="primary"
+              icon="Edit"
+              @click="handleUpdate(scope.row)"
+              v-hasPermi="['repairOrder:repairOrder:edit']"
+          >处理</el-button>
+          <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['repairOrder:repairOrder:remove']">删除</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <pagination
+        v-show="total>0"
+        :total="total"
+        v-model:page="queryParams.pageNum"
+        v-model:limit="queryParams.pageSize"
+        @pagination="getList"
+    />
+
+    <el-drawer
+        v-model="detailVisible"
+        title="工单详情"
+        direction="rtl"
+        size="40%">
+      <el-descriptions :column="1" border>
+        <el-descriptions-item label="工单编号">{{ detailData.orderNo }}</el-descriptions-item>
+        <el-descriptions-item label="工单内容">{{ detailData.orderContent }}</el-descriptions-item>
+        <el-descriptions-item label="项目名称">{{ detailData.projectName }}</el-descriptions-item>
+        <el-descriptions-item label="派单时间">{{ parseTime(detailData.assignTime) }}</el-descriptions-item>
+        <el-descriptions-item label="完成时间">{{ parseTime(detailData.finishTime) }}</el-descriptions-item>
+        <el-descriptions-item label="完成人">{{ detailData.finishBy }}</el-descriptions-item>
+        <el-descriptions-item label="工单状态">
+          <dict-tag :options="repair_status" :value="detailData.orderStatus"/>
+        </el-descriptions-item>
+        <el-descriptions-item label="工单备注">{{ detailData.orderRemark }}</el-descriptions-item>
+      </el-descriptions>
+    </el-drawer>
+
+    <!-- 添加或修改维修工单对话框 -->
+    <el-dialog :title="title" v-model="open" width="600px" append-to-body>
+      <el-form ref="repairOrderRef" :model="form" :rules="rules" label-width="80px">
+        <el-form-item label="工单编号" prop="orderNo">
+          <el-input v-model="form.orderNo" placeholder="请输入工单编号" />
+        </el-form-item>
+        <el-form-item label="工单内容" prop="orderContent">
+          <el-input v-model="form.orderContent" type="textarea" placeholder="请输入内容" />
+        </el-form-item>
+        <el-form-item label="项目名称" prop="projectName">
+          <el-input v-model="form.projectName" placeholder="请输入项目名称" />
+        </el-form-item>
+        <el-form-item label="派单时间" prop="assignTime">
+          <el-date-picker clearable
+                          v-model="form.assignTime"
+                          type="date"
+                          value-format="YYYY-MM-DD"
+                          placeholder="请选择派单时间">
+          </el-date-picker>
+        </el-form-item>
+        <el-form-item label="完成时间" prop="finishTime">
+          <el-date-picker clearable
+                          v-model="form.finishTime"
+                          type="date"
+                          value-format="YYYY-MM-DD"
+                          placeholder="请选择完成时间">
+          </el-date-picker>
+        </el-form-item>
+        <el-form-item label="责任人" prop="finishBy">
+          <el-select
+              v-model="form.userId"
+              placeholder="请选择责任人"
+              clearable
+              filterable
+          >
+            <el-option
+                v-for="user in userOptions"
+                :key="user.userId"
+                :label="user.userName || user.userName"
+                :value="user.userId"
+            />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="附件" prop="annex">
+          <file-upload v-model="form.annex" :on-remove="handleRemoveFile"/>
+        </el-form-item>
+        <!--
+        <el-form-item label="完成人id" prop="userId">
+          <el-input v-model="form.userId" placeholder="请输入完成人id" />
+        </el-form-item>-->
+<!--        <el-form-item label="工单状态" prop="orderStatus">
+          <el-radio-group v-model="form.orderStatus">
+            <el-radio
+                v-for="dict in repair_status"
+                :key="dict.value"
+                :label="dict.value"
+            >{{dict.label}}</el-radio>
+          </el-radio-group>
+        </el-form-item>-->
+        <el-form-item label="工单备注" prop="orderRemark">
+          <el-input v-model="form.orderRemark" type="textarea" placeholder="请输入内容" />
+        </el-form-item>
+      </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="RepairOrder">
+import { listRepairOrder, getRepairOrder, delRepairOrder, addRepairOrder, updateRepairOrder,deleteFile } from "@/api/repairOrder/repairOrder";
+import { listUser } from "@/api/system/user";
+
+const { proxy } = getCurrentInstance();
+const { repair_status } = proxy.useDict('repair_status');
+
+const repairOrderList = 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 userOptions = ref([]);
+
+const detailVisible = ref(false);
+const detailData = ref({});
+
+const data = reactive({
+  form: {},
+  queryParams: {
+    pageNum: 1,
+    pageSize: 10,
+    orderNo: null,
+    orderContent: null,
+    projectName: null,
+    orderStatus: null,
+    state:Date.now(),
+  },
+  rules: {
+  }
+});
+
+const { queryParams, form, rules } = toRefs(data);
+
+function showDetail(row) {
+  detailData.value = {...row};
+  detailVisible.value = true;
+}
+
+/** 查询维修工单列表 */
+function getList() {
+  loading.value = true;
+  listRepairOrder(queryParams.value).then(response => {
+    repairOrderList.value = response.rows;
+    total.value = response.total;
+    loading.value = false;
+  });
+}
+function handleRemoveFile(file) {
+  // 这里可以添加调用后端API删除文件的逻辑
+  proxy.$modal.confirm('确认删除该附件吗?').then(() => {
+    deleteFile(file.url).then(() => {
+      form.value.annex = null;
+      proxy.$modal.msgSuccess("删除成功");
+    }).catch(() => {
+      proxy.$modal.msgError("删除失败");
+    });
+  }).catch(() => {});
+}
+// 取消按钮
+function cancel() {
+  open.value = false;
+  reset();
+}
+
+// 表单重置
+function reset() {
+  form.value = {
+    id: null,
+    orderNo: null,
+    orderContent: null,
+    projectName: null,
+    assignTime: null,
+    finishTime: null,
+    finishBy: null,
+    annex: null,
+    userId: null,
+    orderStatus: null,
+    orderRemark: null,
+    createBy: null,
+    createTime: null,
+    updateBy: null,
+    updateTime: null
+  };
+  proxy.resetForm("repairOrderRef");
+}
+
+/** 搜索按钮操作 */
+function handleQuery() {
+  queryParams.value.pageNum = 1;
+  getList();
+}
+
+/** 重置按钮操作 */
+function resetQuery() {
+  proxy.resetForm("queryRef");
+  handleQuery();
+}
+
+// 多选框选中数据
+function handleSelectionChange(selection) {
+  ids.value = selection.map(item => item.id);
+  single.value = selection.length != 1;
+  multiple.value = !selection.length;
+}
+
+/** 新增按钮操作 */
+function handleAdd() {
+  reset();
+  open.value = true;
+  title.value = "添加维修工单";
+}
+// 获取用户列表
+function getUserList() {
+  listUser().then(response => {
+    userOptions.value = response.rows || [];
+    console.log("userOptions.value"+userOptions.value)
+  });
+}
+
+// 在组件挂载时获取用户列表
+onMounted(() => {
+  getUserList();
+});
+/** 修改按钮操作 */
+function handleUpdate(row) {
+  reset();
+  const _id = row.id || ids.value
+  getRepairOrder(_id).then(response => {
+    form.value = response.data;
+    open.value = true;
+    title.value = "维修工单派单";
+  });
+
+}
+
+/** 提交按钮 */
+function submitForm() {
+  if (form.value.userId) {
+    const user = userOptions.value.find(u => u.userId === form.value.userId);
+    if (user) {
+      form.value.finishBy = user.nickName || user.userName;
+      form.value.userId = user.userId || user.userId;
+    }
+  }
+  proxy.$refs["repairOrderRef"].validate(valid => {
+    if (valid) {
+      if (form.value.id != null) {
+        updateRepairOrder(form.value).then(response => {
+          proxy.$modal.msgSuccess("修改成功");
+          open.value = false;
+          getList();
+        });
+      } else {
+        addRepairOrder(form.value).then(response => {
+          proxy.$modal.msgSuccess("新增成功");
+          open.value = false;
+          getList();
+        });
+      }
+    }
+  });
+}
+
+/** 删除按钮操作 */
+/** 删除按钮操作 */
+function handleDelete(row) {
+  const _ids = row.id || ids.value;
+  const deletePromises = [];
+  proxy.$modal.confirm('是否确认删除选中的数据项?').then(function() {
+    // 如果是批量删除,检查每个选中项是否有附件
+    if (Array.isArray(ids.value) && ids.value.length > 0) {
+      repairOrderList.value.forEach(item => {
+        if (ids.value.includes(item.id) && item.annex) {
+          deletePromises.push(deleteFile(item.annex));
+        }
+      });
+    }
+    // 如果是单个删除,检查是否有附件
+    else if (row.annex) {
+      deletePromises.push(deleteFile(row.annex));
+    }
+    // 先删除所有附件
+    return Promise.all(deletePromises)
+        .then(() => {
+          // 附件删除成功后删除数据
+          return delRepairOrder(_ids);
+        });
+  }).then(() => {
+    getList();
+    proxy.$modal.msgSuccess("删除成功");
+  }).catch(() => {
+    proxy.$modal.msgError("删除失败");
+  });
+}
+
+/** 导出按钮操作 */
+function handleExport() {
+  proxy.download('repairOrder/repairOrder/export', {
+    ...queryParams.value
+  }, `repairOrder_${new Date().getTime()}.xlsx`)
+}
+
+getList();
+</script>