From fea8a7c711e5042dcdbeaadea3b332acf7b8b152 Mon Sep 17 00:00:00 2001
From: chenhj <1263187585@qq.com>
Date: 星期日, 04 一月 2026 16:33:53 +0800
Subject: [PATCH] 设备台账,设备故障和保养

---
 src/views/diagnosis/Modal/MaintainModal.vue      |   58 +
 src/views/diagnosis/Form/RepairForm.vue          |  130 +++
 src/views/diagnosis/Form/MaintainForm.vue        |   66 +
 src/views/device/index.vue                       |  322 +++++++
 src/views/diagnosis/index.vue                    |  327 +++++++
 src/views/maintenance/Form/MaintenanceForm.vue   |   77 +
 src/views/maintenance/Form/PlanForm.vue          |  137 +++
 src/views/device/Form.vue                        |  239 +++++
 /dev/null                                        |  526 ------------
 src/views/maintenance/index.vue                  |  315 +++++++
 src/views/maintenance/Modal/MaintenanceModal.vue |   60 +
 src/views/diagnosis/Modal/RepairModal.vue        |   77 +
 src/views/maintenance/Modal/PlanModal.vue        |   76 +
 src/views/device/Modal.vue                       |   69 +
 14 files changed, 1,953 insertions(+), 526 deletions(-)

diff --git a/src/views/device/DeviceManagement.vue b/src/views/device/DeviceManagement.vue
deleted file mode 100644
index 80ccd27..0000000
--- a/src/views/device/DeviceManagement.vue
+++ /dev/null
@@ -1,513 +0,0 @@
-<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/device/Form.vue b/src/views/device/Form.vue
new file mode 100644
index 0000000..2cc26c5
--- /dev/null
+++ b/src/views/device/Form.vue
@@ -0,0 +1,239 @@
+<template>
+  <el-form :model="form" label-width="100px" :rules="formRules" ref="formRef">
+    <el-row :gutter="20">
+      <el-col :span="12">
+        <el-form-item label="璁惧鍚嶇О" prop="deviceName">
+          <el-input v-model="form.deviceName" placeholder="璇疯緭鍏ヨ澶囧悕绉�" />
+        </el-form-item>
+      </el-col>
+      <el-col :span="12">
+        <el-form-item label="瑙勬牸鍨嬪彿" prop="deviceModel">
+          <el-input v-model="form.deviceModel" placeholder="璇疯緭鍏ヨ鏍煎瀷鍙�" />
+        </el-form-item>
+      </el-col>
+      <el-col :span="12">
+        <el-form-item label="璁惧鍝佺墝" prop="deviceBrand">
+          <el-input v-model="form.deviceBrand" placeholder="璇疯緭鍏ヨ澶囧搧鐗�" />
+        </el-form-item>
+      </el-col>
+      <el-col :span="12">
+        <el-form-item label="渚涘簲鍟�" prop="supplierName">
+          <el-input v-model="form.supplierName" placeholder="璇疯緭鍏ヤ緵搴斿晢" />
+        </el-form-item>
+      </el-col>
+      <el-col :span="12">
+        <el-form-item label="瀛樻斁浣嶇疆" prop="storageLocation">
+          <el-input v-model="form.storageLocation" placeholder="璇疯緭鍏ュ瓨鏀句綅缃�" />
+        </el-form-item>
+      </el-col>
+      <el-col :span="12">
+        <el-form-item label="鍗曚綅" prop="unit">
+          <el-input v-model="form.unit" placeholder="璇疯緭鍏ュ崟浣�" />
+        </el-form-item>
+      </el-col>
+      <el-col :span="12">
+        <el-form-item label="鍚敤鎶樻棫" prop="enableDepreciation">
+          <el-switch v-model="form.enableDepreciation" :active-value="true" :inactive-value="false" />
+        </el-form-item>
+      </el-col>
+      <el-col :span="12">
+        <el-form-item label="鏁伴噺" prop="number">
+          <el-input-number :min="1" style="width: 100%"
+            v-model="form.number"
+													 disabled
+            placeholder="璇疯緭鍏ユ暟閲�"
+            @change="mathNum"
+          />
+        </el-form-item>
+      </el-col>
+      <el-col :span="12">
+        <el-form-item label="鍚◣鍗曚环" prop="taxIncludingPriceUnit">
+          <el-input-number :step="0.01" :min="0" style="width: 100%"
+            v-model="form.taxIncludingPriceUnit"
+            placeholder="璇疯緭鍏ュ惈绋庡崟浠�"
+            maxlength="10"
+            @change="mathNum"
+          />
+        </el-form-item>
+      </el-col>
+      <el-col :span="12">
+        <el-form-item label="鍚◣鎬讳环" prop="taxIncludingPriceTotal">
+          <el-input
+            v-model="form.taxIncludingPriceTotal"
+            placeholder="鑷姩鐢熸垚"
+            type="number"
+            disabled
+          />
+        </el-form-item>
+      </el-col>
+      <el-col :span="12">
+        <el-form-item label="绋庣巼(%)" prop="taxRate">
+          <!-- <el-input
+            v-model="form.taxRate"
+            placeholder="璇疯緭鍏ョ◣鐜�"
+            type="number"
+          >
+            <template #append> % </template>
+          </el-input> -->
+          <el-select
+            v-model="form.taxRate"
+            placeholder="璇烽�夋嫨"
+            clearable
+            @change="mathNum"
+          >
+            <el-option label="1" :value="1" />
+            <el-option label="6" :value="6" />
+            <el-option label="13" :value="13" />
+          </el-select>
+        </el-form-item>
+      </el-col>
+      <el-col :span="12">
+        <el-form-item label="涓嶅惈绋庢�讳环" prop="unTaxIncludingPriceTotal">
+          <el-input
+            v-model="form.unTaxIncludingPriceTotal"
+            placeholder="鑷姩鐢熸垚"
+            type="number"
+            disabled
+          />
+        </el-form-item>
+      </el-col>
+      <!-- <el-col :span="12">
+        <el-form-item label="褰曞叆浜�" prop="createUser">
+          <el-input v-model="form.createUser" placeholder="璇疯緭鍏ュ綍鍏ヤ汉" />
+        </el-form-item>
+      </el-col> -->
+      <el-col :span="12">
+        <el-form-item label="褰曞叆鏃ユ湡" prop="createTime">
+          <el-date-picker
+            style="width: 100%"
+            v-model="form.createTime"
+            format="YYYY-MM-DD"
+            value-format="YYYY-MM-DD HH:mm:ss"
+            type="date"
+            placeholder="璇烽�夋嫨褰曞叆鏃ユ湡"
+            clearable
+          />
+        </el-form-item>
+      </el-col>
+			<el-col :span="12">
+				<el-form-item label="棰勮杩愯鏃堕棿" prop="planRuntimeTime">
+					<el-date-picker
+						style="width: 100%"
+						v-model="form.planRuntimeTime"
+						format="YYYY-MM-DD"
+						value-format="YYYY-MM-DD"
+						type="date"
+						placeholder="璇烽�夋嫨褰曞叆鏃ユ湡"
+						clearable
+					/>
+				</el-form-item>
+			</el-col>
+    </el-row>
+  </el-form>
+</template>
+
+<script setup>
+import useFormData from "../../hooks/useFormData";
+// import useUserStore from "@/store/modules/user";
+import { getLedgerById } from "../../api/equipmentManagement/ledger";
+import dayjs from "dayjs";
+import {
+  calculateTaxIncludeTotalPrice,
+  calculateTaxExclusiveTotalPrice,
+} from "../../utils/summarizeTable";
+import { ElMessage } from "element-plus";
+import {ref} from "vue";
+
+defineOptions({
+  name: "璁惧鍙拌处琛ㄥ崟",
+});
+const formRef = ref(null);
+const operationType = ref('');
+const formRules = {
+	deviceName: [{ required: true, trigger: "blur", message: "璇疯緭鍏�" }],
+	deviceModel: [{ required: true, trigger: "blur", message: "璇疯緭鍏�" }],
+	supplierName: [{ required: true, trigger: "blur", message: "璇疯緭鍏�" }],
+	unit: [{ required: true, trigger: "blur", message: "璇疯緭鍏�" }],
+	number: [{ required: true, trigger: "blur", message: "璇疯緭鍏�" }],
+	taxIncludingPriceUnit: [{ required: true, trigger: "blur", message: "璇疯緭鍏�" }],
+	taxRate: [{ required: true, trigger: "change", message: "璇疯緭鍏�" }],
+	planRuntimeTime: [{ required: true, trigger: "change", message: "璇烽�夋嫨" }],
+}
+
+const { form, resetForm } = useFormData({
+  deviceName: undefined, // 璁惧鍚嶇О
+  deviceModel: undefined, // 瑙勬牸鍨嬪彿
+  deviceBrand: undefined, // 璁惧鍝佺墝
+  supplierName: undefined, // 渚涘簲鍟�
+  storageLocation: undefined, // 瀛樻斁浣嶇疆
+  enableDepreciation: false, // 鏄惁鍚敤鎶樻棫
+  unit: undefined, // 鍗曚綅
+  number: 1, // 鏁伴噺
+  taxIncludingPriceUnit: undefined, // 鍚◣鍗曚环
+  taxIncludingPriceTotal: undefined, // 鍚◣鎬讳环
+  taxRate: undefined, // 绋庣巼
+  unTaxIncludingPriceTotal: undefined, // 涓嶅惈绋庢�讳环
+  // createUser: useUserStore().nickName, // 褰曞叆浜�
+  createTime: dayjs().format("YYYY-MM-DD HH:mm:ss"), // 褰曞叆鏃ユ湡
+	planRuntimeTime: dayjs().format("YYYY-MM-DD"), // 褰曞叆鏃ユ湡
+});
+
+const loadForm = async (id) => {
+	if (id) {
+		operationType.value = 'edit'
+	}
+  const { code, data } = await getLedgerById(id);
+  if (code == 200) {
+    form.deviceName = data.deviceName;
+    form.deviceModel = data.deviceModel;
+    form.deviceBrand = data.deviceBrand;
+    form.supplierName = data.supplierName;
+    form.storageLocation = data.storageLocation;
+    form.enableDepreciation = data.enableDepreciation;
+    form.unit = data.unit;
+    form.number = 1;
+    form.taxIncludingPriceUnit = data.taxIncludingPriceUnit;
+    form.taxIncludingPriceTotal = data.taxIncludingPriceTotal;
+    form.taxRate = data.taxRate;
+    form.unTaxIncludingPriceTotal = data.unTaxIncludingPriceTotal;
+    form.createTime = data.createTime;
+  }
+};
+
+const mathNum = () => {
+  if (!form.taxIncludingPriceUnit) {
+    ElMessage.error("璇疯緭鍏ュ崟浠�");
+    return;
+  }
+  form.taxIncludingPriceTotal = calculateTaxIncludeTotalPrice(
+    form.taxIncludingPriceUnit,
+    form.number
+  );
+  if (form.taxRate) {
+    form.unTaxIncludingPriceTotal = calculateTaxExclusiveTotalPrice(
+      form.taxIncludingPriceTotal,
+      form.taxRate
+    );
+  }
+};
+
+// 娓呴櫎琛ㄥ崟鏍¢獙鐘舵��
+const clearValidate = () => {
+  formRef.value?.clearValidate();
+};
+
+// 閲嶇疆琛ㄥ崟鏁版嵁鍜屾牎楠岀姸鎬�
+const resetFormAndValidate = () => {
+  resetForm();
+  clearValidate();
+};
+
+defineExpose({
+  form,
+  loadForm,
+  resetForm,
+  clearValidate,
+  resetFormAndValidate,
+	formRef,
+});
+</script>
diff --git a/src/views/device/Modal.vue b/src/views/device/Modal.vue
new file mode 100644
index 0000000..3824b86
--- /dev/null
+++ b/src/views/device/Modal.vue
@@ -0,0 +1,69 @@
+<template>
+  <el-dialog :title="modalOptions.title" v-model="visible" @close="close">
+    <Form ref="formRef"></Form>
+    <template #footer>
+			<el-button type="primary" @click="sendForm" :loading="loading">
+				{{ modalOptions.confirmText }}
+			</el-button>
+      <el-button @click="closeModal">{{ modalOptions.cancelText }}</el-button>
+    </template>
+  </el-dialog>
+</template>
+
+<script setup>
+import { useModal } from "../../hooks/useModal";
+import { addLedger, editLedger } from "../../api/equipmentManagement/ledger";
+import Form from "./Form.vue";
+import { ElMessage } from "element-plus";
+const { proxy } = getCurrentInstance()
+
+defineOptions({
+  name: "璁惧鍙拌处鏂板缂栬緫",
+});
+
+const emits = defineEmits(["success"]);
+
+const formRef = ref();
+const {
+  id,
+  visible,
+  loading,
+  openModal,
+  modalOptions,
+  handleConfirm,
+  closeModal,
+} = useModal({ title: "璁惧鍙拌处" });
+
+const sendForm = () => {
+	proxy.$refs.formRef.$refs.formRef.validate(async valid => {
+		if (valid) {
+			const {code} = id.value
+				? await editLedger({id: id.value, ...formRef.value.form})
+				: await addLedger(formRef.value.form);
+			if (code == 200) {
+				emits("success");
+				ElMessage({message: "鎿嶄綔鎴愬姛", type: "success"});
+				close();
+			} else {
+				loading.value = false;
+			}
+		}
+	})
+};
+
+const close = () => {
+	formRef.value.resetFormAndValidate();
+  closeModal();
+};
+
+const loadForm = async (id) => {
+  openModal(id);
+  await nextTick();
+  formRef.value.loadForm(id);
+};
+
+defineExpose({
+  openModal,
+  loadForm,
+});
+</script>
diff --git a/src/views/device/index.vue b/src/views/device/index.vue
new file mode 100644
index 0000000..e9fff64
--- /dev/null
+++ b/src/views/device/index.vue
@@ -0,0 +1,322 @@
+<template>
+  <div class="app-container">
+    <el-form :model="filters" :inline="true">
+      <el-form-item label="璁惧鍚嶇О">
+        <el-input
+          v-model="filters.deviceName"
+          style="width: 240px"
+          placeholder="璇疯緭鍏ヨ澶囧悕绉�"
+          clearable
+          :prefix-icon="Search"
+          @change="getTableData"
+        />
+      </el-form-item>
+      <el-form-item label="瑙勬牸鍨嬪彿">
+        <el-input
+            v-model="filters.deviceModel"
+            style="width: 240px"
+            placeholder="璇疯緭鍏ヨ鏍煎瀷鍙�"
+            clearable
+            :prefix-icon="Search"
+            @change="getTableData"
+        />
+      </el-form-item>
+      <el-form-item label="渚涘簲鍟�">
+        <el-input
+            v-model="filters.supplierName"
+            style="width: 240px"
+            placeholder="璇疯緭鍏ヤ緵搴斿晢"
+            clearable
+            :prefix-icon="Search"
+            @change="getTableData"
+        />
+      </el-form-item>
+      <el-form-item label="鍗曚綅">
+        <el-input
+            v-model="filters.unit"
+            style="width: 240px"
+            placeholder="璇疯緭鍏ュ崟浣�"
+            clearable
+            :prefix-icon="Search"
+            @change="getTableData"
+        />
+      </el-form-item>
+      <el-form-item label="褰曞叆鏃ユ湡:">
+        <el-date-picker v-model="filters.entryDate" value-format="YYYY-MM-DD" format="YYYY-MM-DD" type="daterange"
+                        placeholder="璇烽�夋嫨" clearable @change="changeDaterange" />
+      </el-form-item>
+      <el-form-item>
+        <el-button type="primary" @click="getTableData">鎼滅储</el-button>
+        <el-button @click="resetFilters">閲嶇疆</el-button>
+      </el-form-item>
+    </el-form>
+    <div class="table_list">
+      <div class="actions">
+        <div></div>
+        <div>
+          <el-button type="primary" @click="add" icon="Plus"> 鏂板 </el-button>
+          <el-button @click="handleOut" icon="download">瀵煎嚭</el-button>
+          <el-button
+            type="danger"
+            icon="Delete"
+            :disabled="multipleList.length <= 0"
+            @click="deleteRow(multipleList.map((item) => item.id))"
+          >
+            鎵归噺鍒犻櫎
+          </el-button>
+        </div>
+      </div>
+      <PIMTable
+        rowKey="id"
+        isSelection
+        :column="columns"
+        :tableData="dataList"
+        :page="{
+          current: pagination.currentPage,
+          size: pagination.pageSize,
+          total: pagination.total,
+        }"
+        @selection-change="handleSelectionChange"
+        @pagination="changePage"
+      >
+      </PIMTable>
+    </div>
+    <Modal ref="modalRef" @success="getTableData"></Modal>
+    <el-dialog v-model="qrDialogVisible" title="浜岀淮鐮�" width="300px">
+      <div style="text-align:center;">
+        <img :src="qrCodeUrl" alt="浜岀淮鐮�" style="width:200px;height:200px;" />
+        <div style="margin:10px 0;">
+          <el-button type="primary" @click="downloadQRCode">涓嬭浇浜岀淮鐮佸浘鐗�</el-button>
+        </div>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script setup>
+import { usePaginationApi } from "../../hooks/usePaginationApi";
+// import { Search } from "@element-plus/icons-vue";
+import { getLedgerPage, delLedger } from "../../api/equipmentManagement/ledger";
+import { onMounted, getCurrentInstance } from "vue";
+import Modal from "./Modal.vue";
+import { ElMessageBox, ElMessage } from "element-plus";
+import dayjs from "dayjs";
+import QRCode from "qrcode";
+import { ref } from "vue";
+
+defineOptions({
+  name: "璁惧鍙拌处",
+});
+
+// 琛ㄦ牸澶氶�夋閫変腑椤�
+const multipleList = ref([]);
+const { proxy } = getCurrentInstance();
+const modalRef = ref();
+const qrDialogVisible = ref(false);
+const qrCodeUrl = ref("");
+const qrRowData = ref(null);
+
+const {
+  filters,
+  columns,
+  dataList,
+  pagination,
+  getTableData,
+  resetFilters,
+  onCurrentChange,
+} = usePaginationApi(
+  getLedgerPage,
+  {
+    deviceName: undefined,
+    deviceModel: undefined,
+    supplierName: undefined,
+    unit: undefined,
+    entryDateStart: undefined,
+    entryDateEnd: undefined,
+  },
+  [
+    {
+      label: "璁惧鍚嶇О",
+      align: "center",
+      prop: "deviceName",
+    },
+    {
+      label: "瑙勬牸鍨嬪彿",
+      align: "center",
+      prop: "deviceModel",
+    },
+    {
+      label: "璁惧鍝佺墝",
+      align: "center",
+      prop: "deviceBrand",
+    },
+    {
+      label: "渚涘簲鍟�",
+      align: "center",
+      prop: "supplierName",
+    },
+    {
+      label: "鍗曚綅",
+      align: "center",
+      prop: "unit",
+    },
+    {
+      label: "瀛樻斁浣嶇疆",
+      align: "center",
+      prop: "storageLocation",
+    },
+    {
+      label: "鏁伴噺",
+      align: "center",
+      prop: "number",
+    },
+    {
+      label: "鍚◣鍗曚环",
+      align: "center",
+      prop: "taxIncludingPriceUnit",
+    },
+    {
+      label: "鍚◣鎬讳环",
+      align: "center",
+      prop: "taxIncludingPriceTotal",
+    },
+    {
+      label: "绋庣巼",
+      align: "center",
+      prop: "taxRate",
+    },
+    {
+      label: "涓嶅惈绋庢�讳环",
+      align: "center",
+      prop: "unTaxIncludingPriceTotal",
+    },
+    {
+      label: "鍚敤鎶樻棫",
+      align: "center",
+      prop: "enableDepreciation",
+      formatData: (v) => (v ? "鏄�" : "鍚�"),
+    },
+    {
+      label: "褰曞叆浜�",
+      align: "center",
+      prop: "createUser",
+    },
+    {
+      label: "褰曞叆鏃ユ湡",
+      align: "center",
+      prop: "createTime",
+    },
+		{
+			dataType: "action",
+			label: "鎿嶄綔",
+			align: "center",
+			fixed: 'right',
+			width: 150,
+			operation: [
+				{
+					name: "缂栬緫",
+					type: "text",
+					clickFun: (row) => {
+						edit(row.id)
+					},
+				},
+				{
+					name: "鐢熸垚浜岀淮鐮�",
+					type: "text",
+					clickFun: (row) => {
+						showQRCode(row)
+					},
+				},
+			],
+		},
+  ]
+);
+
+// 澶氶�夊悗鍋氫粈涔�
+const handleSelectionChange = (selectionList) => {
+  multipleList.value = selectionList;
+};
+
+const add = () => {
+  modalRef.value.openModal();
+};
+const edit = (id) => {
+  modalRef.value.loadForm(id);
+};
+const changePage = ({ page, limit }) => {
+  pagination.currentPage = page;
+	pagination.pageSize = limit;
+  onCurrentChange(page);
+};
+const deleteRow = (id) => {
+  ElMessageBox.confirm("姝ゆ搷浣滃皢姘镐箙鍒犻櫎璇ユ枃浠�, 鏄惁缁х画?", "鎻愮ず", {
+    confirmButtonText: "纭畾",
+    cancelButtonText: "鍙栨秷",
+    type: "warning",
+  }).then(async () => {
+    const { code } = await delLedger(id);
+    if (code == 200) {
+      ElMessage({
+        type: "success",
+        message: "鍒犻櫎鎴愬姛",
+      });
+      getTableData();
+    }
+  });
+};
+
+const changeDaterange = (value) => {
+  if (value) {
+    filters.entryDateStart = dayjs(value[0]).format("YYYY-MM-DD");
+    filters.entryDateEnd = dayjs(value[1]).format("YYYY-MM-DD");
+  } else {
+    filters.entryDateStart = undefined;
+    filters.entryDateEnd = undefined;
+  }
+  getTableData();
+};
+
+const handleOut = () => {
+  ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚鍑猴紝鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
+    confirmButtonText: "纭",
+    cancelButtonText: "鍙栨秷",
+    type: "warning",
+  })
+    .then(() => {
+      proxy.download(`/device/ledger/export`, {}, "璁惧鍙拌处妗f.xlsx");
+    })
+    .catch(() => {
+      proxy.$modal.msg("宸插彇娑�");
+    });
+};
+
+const showQRCode = async (row) => {
+  // 鐩存帴浣跨敤URL锛屼笉瑕佺敤JSON.stringify鍖呰
+  const qrContent = proxy.javaApi + '/device-info?deviceId=' + row.id;
+  qrCodeUrl.value = await QRCode.toDataURL(qrContent);
+  qrRowData.value = row;
+  qrDialogVisible.value = true;
+};
+
+const downloadQRCode = () => {
+  const a = document.createElement("a");
+  a.href = qrCodeUrl.value;
+  a.download = `${qrRowData.value.deviceName || "浜岀淮鐮�"}.png`;
+  a.click();
+};
+
+onMounted(() => {
+  getTableData();
+});
+</script>
+
+<style lang="scss" scoped>
+.table_list {
+  margin-top: unset;
+}
+.actions {
+  display: flex;
+  justify-content: space-between;
+  margin-bottom: 10px;
+}
+</style>
diff --git a/src/views/diagnosis/FaultDiagnosis.vue b/src/views/diagnosis/FaultDiagnosis.vue
deleted file mode 100644
index a1cb864..0000000
--- a/src/views/diagnosis/FaultDiagnosis.vue
+++ /dev/null
@@ -1,411 +0,0 @@
-<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/diagnosis/Form/MaintainForm.vue b/src/views/diagnosis/Form/MaintainForm.vue
new file mode 100644
index 0000000..339cfc5
--- /dev/null
+++ b/src/views/diagnosis/Form/MaintainForm.vue
@@ -0,0 +1,66 @@
+<template>
+  <el-form :model="form" label-width="80px">
+    <el-form-item label="缁翠慨浜�">
+      <el-input v-model="form.maintenanceName" placeholder="璇疯緭鍏ョ淮淇汉" />
+    </el-form-item>
+    <el-form-item label="缁翠慨缁撴灉">
+      <el-input v-model="form.maintenanceResult" placeholder="璇疯緭鍏ョ淮淇粨鏋�" />
+    </el-form-item>
+    <el-form-item label="鏁呴殰鐘舵��">
+      <el-select v-model="form.status">
+        <el-option label="寰呮晠闅�" :value="0"></el-option>
+        <el-option label="瀹岀粨" :value="1"></el-option>
+        <el-option label="澶辫触" :value="2"></el-option>
+      </el-select>
+    </el-form-item>
+    <el-form-item label="缁翠慨鏃ユ湡">
+      <el-date-picker
+        v-model="form.maintenanceTime"
+        placeholder="璇烽�夋嫨缁翠慨鏃ユ湡"
+        format="YYYY-MM-DD HH:mm:ss"
+        value-format="YYYY-MM-DD HH:mm:ss"
+        type="datetime"
+        clearable
+        style="width: 100%"
+      />
+    </el-form-item>
+  </el-form>
+</template>
+
+<script setup>
+import useFormData from "../../../hooks/useFormData";
+import useUserStore from "../../../store/modules/user";
+import dayjs from "dayjs";
+
+defineOptions({
+  name: "璁惧缁翠慨琛ㄥ崟",
+});
+
+const userStore = useUserStore();
+const { form, resetForm } = useFormData({
+  maintenanceName: undefined, // 缁翠慨鍚嶇О
+  maintenanceResult: undefined, // 缁翠慨缁撴灉
+  maintenanceTime: undefined, // 缁翠慨鏃ユ湡
+  status: 0,
+});
+
+const setForm = (data) => {
+  form.maintenanceName = data.maintenanceName ?? userStore.nickName;
+  form.maintenanceResult = data.maintenanceResult;
+  form.maintenanceTime =
+    dayjs(data.maintenanceTime).format("YYYY-MM-DD HH:mm:ss") ??
+    dayjs().format("YYYY-MM-DD HH:mm:ss");
+};
+
+const getForm = () => {
+  return form;
+};
+
+defineExpose({
+  getForm,
+  setForm,
+  resetForm,
+});
+</script>
+
+<style lang="scss" scoped></style>
diff --git a/src/views/diagnosis/Form/RepairForm.vue b/src/views/diagnosis/Form/RepairForm.vue
new file mode 100644
index 0000000..fc3ab81
--- /dev/null
+++ b/src/views/diagnosis/Form/RepairForm.vue
@@ -0,0 +1,130 @@
+<template>
+  <el-form :model="form" label-width="100px">
+    <el-row>
+      <el-col :span="12">
+        <el-form-item label="璁惧鍚嶇О">
+          <el-select v-model="form.deviceLedgerId" @change="setDeviceModel">
+            <el-option
+              v-for="(item, index) in deviceOptions"
+              :key="index"
+              :label="item.deviceName"
+              :value="item.id"
+            ></el-option>
+          </el-select>
+        </el-form-item>
+      </el-col>
+      <el-col :span="12">
+        <el-form-item label="瑙勬牸鍨嬪彿">
+          <el-input
+            v-model="form.deviceModel"
+            placeholder="璇疯緭鍏ヨ鏍煎瀷鍙�"
+            disabled
+          />
+        </el-form-item>
+      </el-col>
+      <el-col :span="12">
+        <el-form-item label="鏁呴殰鏃ユ湡">
+          <el-date-picker
+            v-model="form.repairTime"
+            placeholder="璇烽�夋嫨鏁呴殰鏃ユ湡"
+            format="YYYY-MM-DD"
+            value-format="YYYY-MM-DD"
+            type="date"
+            clearable
+            style="width: 100%"
+          />
+        </el-form-item>
+      </el-col>
+      <el-col :span="12">
+        <el-form-item label="涓婃姤浜�">
+          <el-input v-model="form.repairName" placeholder="璇疯緭鍏ヤ笂鎶ヤ汉" />
+        </el-form-item>
+      </el-col>
+    </el-row>
+    <el-row v-if="id">
+      <el-col :span="12">
+        <el-form-item label="鏁呴殰鐘舵��">
+          <el-select v-model="form.status">
+            <el-option label="寰呯淮淇�" :value="0"></el-option>
+            <el-option label="瀹岀粨" :value="1"></el-option>
+            <el-option label="澶辫触" :value="2"></el-option>
+          </el-select>
+        </el-form-item>
+      </el-col>
+    </el-row>
+    <el-row>
+      <el-col :span="24">
+        <el-form-item label="鏁呴殰鐜拌薄">
+          <el-input
+            v-model="form.remark"
+            :rows="2"
+            type="textarea"
+            placeholder="璇疯緭鍏ユ晠闅滅幇璞�"
+          />
+        </el-form-item>
+      </el-col>
+    </el-row>
+  </el-form>
+</template>
+
+<script setup>
+import useFormData from "../../../hooks/useFormData";
+import { getDeviceLedger } from "../../../api/equipmentManagement/ledger";
+import useUserStore from "../../../store/modules/user";
+
+const { id } = defineProps(["id"])
+
+defineOptions({
+  name: "璁惧鏁呴殰琛ㄥ崟",
+});
+
+const userStore = useUserStore();
+const deviceOptions = ref([]);
+
+const loadDeviceName = async () => {
+  const { data } = await getDeviceLedger();
+  deviceOptions.value = data;
+};
+
+const { form, resetForm } = useFormData({
+  deviceLedgerId: undefined, // 璁惧Id
+  deviceName: undefined, // 璁惧鍚嶇О
+  deviceModel: undefined, // 瑙勬牸鍨嬪彿
+  repairTime: undefined, // 鏁呴殰鏃ユ湡
+  repairName: userStore.nickName, // 鏁呴殰浜�
+  remark: undefined, // 鏁呴殰鐜拌薄
+  status: 0, // 鏁呴殰鐘舵��
+});
+
+const setDeviceModel = (id) => {
+  const option = deviceOptions.value.find((item) => item.id === id);
+  form.deviceModel = option.deviceModel;
+};
+
+const getForm = () => {
+  return form;
+};
+
+const setForm = (data) => {
+  form.deviceLedgerId = data.deviceLedgerId;
+  form.deviceName = data.deviceName;
+  form.deviceModel = data.deviceModel;
+  form.repairTime = data.repairTime;
+  form.repairName = data.repairName;
+  form.remark = data.remark;
+  form.status = data.status;
+};
+
+// onMounted(() => {
+//   loadDeviceName();
+// });
+
+defineExpose({
+  loadDeviceName,
+  resetForm,
+  getForm,
+  setForm,
+});
+</script>
+
+<style lang="scss" scoped></style>
diff --git a/src/views/diagnosis/Modal/MaintainModal.vue b/src/views/diagnosis/Modal/MaintainModal.vue
new file mode 100644
index 0000000..648614b
--- /dev/null
+++ b/src/views/diagnosis/Modal/MaintainModal.vue
@@ -0,0 +1,58 @@
+<template>
+  <el-dialog v-model="visible" :title="modalOptions.title" direction="ltr">
+    <MaintainForm ref="maintainFormRef" />
+    <template #footer>
+			<el-button type="primary" @click="sendForm" :loading="loading">
+				{{ modalOptions.confirmText }}
+			</el-button>
+      <el-button @click="closeModal">{{ modalOptions.cancelText }}</el-button>
+    </template>
+  </el-dialog>
+</template>
+
+<script setup>
+import { useModal } from "../../../hooks/useModal";
+import MaintainForm from "../Form/MaintainForm.vue";
+import { addMaintain } from "../../../api/equipmentManagement/repair";
+
+defineOptions({
+  name: "缁翠慨妯℃�佹",
+});
+
+const maintainFormRef = ref();
+const emits = defineEmits(["ok"]);
+
+const {
+  id,
+  visible,
+  loading,
+  openModal,
+  modalOptions,
+  handleConfirm,
+  closeModal,
+} = useModal({ title: "璁惧缁翠慨" });
+
+const sendForm = async () => {
+  loading.value = true;
+  const form = await maintainFormRef.value.getForm();
+  const { code } = await addMaintain({ id: id.value, ...form });
+  if (code == 200) {
+    emits("ok");
+    maintainFormRef.value.resetForm();
+    closeModal();
+  }
+  loading.value = false;
+};
+
+const open = async (id, row) => {
+  openModal(id);
+  await nextTick();
+  maintainFormRef.value.setForm(row);
+};
+
+defineExpose({
+  open,
+});
+</script>
+
+<style lang="scss" scoped></style>
diff --git a/src/views/diagnosis/Modal/RepairModal.vue b/src/views/diagnosis/Modal/RepairModal.vue
new file mode 100644
index 0000000..4e2ef55
--- /dev/null
+++ b/src/views/diagnosis/Modal/RepairModal.vue
@@ -0,0 +1,77 @@
+<template>
+  <el-dialog v-model="visible" :title="modalOptions.title" @close="close">
+    <RepairForm ref="repairFormRef" :id="id" />
+    <template #footer>
+			<el-button type="primary" @click="sendForm" :loading="loading">
+				{{ modalOptions.confirmText }}
+			</el-button>
+      <el-button @click="closeModal">{{ modalOptions.cancelText }}</el-button>
+    </template>
+  </el-dialog>
+</template>
+
+<script setup>
+import { useModal } from "../../../hooks/useModal";
+import RepairForm from "../Form/RepairForm.vue";
+import {
+  addRepair,
+  editRepair,
+  getRepairById,
+} from "../../../api/equipmentManagement/repair";
+import { ElMessage } from "element-plus";
+
+defineOptions({
+  name: "璁惧鏁呴殰寮圭獥",
+});
+
+const emits = defineEmits(["ok"]);
+
+const repairFormRef = ref();
+const {
+  id,
+  visible,
+  loading,
+  openModal,
+  modalOptions,
+  handleConfirm,
+  closeModal,
+} = useModal({ title: "璁惧鏁呴殰" });
+
+const sendForm = async () => {
+  loading.value = true;
+  const form = await repairFormRef.value.getForm();
+  const { code } = id.value
+    ? await editRepair({ id: unref(id), ...form })
+    : await addRepair(form);
+  if (code == 200) {
+    ElMessage.success(`${id ? "缂栬緫" : "鏂板"}鏁呴殰鎴愬姛`);
+    closeModal();
+    emits("ok");
+  }
+  loading.value = false;
+};
+
+const openAdd = async () => {
+  openModal();
+  await nextTick();
+  await repairFormRef.value.loadDeviceName();
+};
+
+const openEdit = async (id) => {
+  const { data } = await getRepairById(id);
+  openModal(id);
+  await nextTick();
+  await repairFormRef.value.loadDeviceName();
+  await repairFormRef.value.setForm(data);
+};
+
+const close = () => {
+  repairFormRef.value.resetForm();
+  closeModal();
+};
+
+defineExpose({
+  openAdd,
+  openEdit,
+});
+</script>
diff --git a/src/views/diagnosis/index.vue b/src/views/diagnosis/index.vue
new file mode 100644
index 0000000..69674e4
--- /dev/null
+++ b/src/views/diagnosis/index.vue
@@ -0,0 +1,327 @@
+<template>
+  <div class="app-container">
+    <el-form :model="filters" :inline="true">
+      <el-form-item label="璁惧鍚嶇О">
+        <el-input
+            v-model="filters.deviceName"
+            style="width: 240px"
+            placeholder="璇疯緭鍏ヨ澶囧悕绉�"
+            clearable
+            :prefix-icon="Search"
+            @change="getTableData"
+        />
+      </el-form-item>
+      <el-form-item label="瑙勬牸鍨嬪彿">
+        <el-input
+            v-model="filters.deviceModel"
+            style="width: 240px"
+            placeholder="璇烽�夋嫨瑙勬牸鍨嬪彿"
+            clearable
+            :prefix-icon="Search"
+            @change="getTableData"
+        />
+      </el-form-item>
+      <el-form-item label="鏁呴殰鐜拌薄">
+        <el-input
+            v-model="filters.remark"
+            style="width: 240px"
+            placeholder="璇疯緭鍏ユ晠闅滅幇璞�"
+            clearable
+            :prefix-icon="Search"
+            @change="getTableData"
+        />
+      </el-form-item>
+      <el-form-item label="缁翠慨浜�">
+        <el-input
+            v-model="filters.maintenanceName"
+            style="width: 240px"
+            placeholder="璇疯緭鍏ョ淮淇汉"
+            clearable
+            :prefix-icon="Search"
+            @change="getTableData"
+        />
+      </el-form-item>
+      <el-form-item label="鏁呴殰鏃ユ湡">
+        <el-date-picker
+            v-model="filters.repairTimeStr"
+            type="date"
+            placeholder="璇烽�夋嫨鏁呴殰鏃ユ湡"
+            size="default"
+            @change="(date) => handleDateChange(date,2)"
+        />
+      </el-form-item>
+      <el-form-item label="缁翠慨鏃ユ湡">
+        <el-date-picker
+            v-model="filters.maintenanceTimeStr"
+            type="date"
+            placeholder="璇烽�夋嫨缁翠慨鏃ユ湡"
+            size="default"
+            @change="(date) => handleDateChange(date,1)"
+        />
+      </el-form-item>
+      <el-form-item>
+        <el-button type="primary" @click="getTableData">鎼滅储</el-button>
+        <el-button @click="resetFilters">閲嶇疆</el-button>
+      </el-form-item>
+    </el-form>
+    <div class="table_list">
+      <div class="actions">
+        <el-text class="mx-1" size="large">璁惧鏁呴殰</el-text>
+        <div>
+          <el-button
+            type="primary"
+            icon="Plus"
+            :disabled="multipleList.length !== 1"
+            @click="addMaintain"
+          >
+            鏂板缁翠慨
+          </el-button>
+          <el-button type="success" icon="Van" @click="addRepair">
+            鏂板鏁呴殰
+          </el-button>
+          <el-button @click="handleOut">
+            瀵煎嚭
+          </el-button>
+          <el-button
+            type="danger"
+            icon="Delete"
+            :disabled="multipleList.length <= 0"
+            @click="delRepairByIds(multipleList.map((item) => item.id))"
+          >
+            鎵归噺鍒犻櫎
+          </el-button>
+        </div>
+      </div>
+      <PIMTable
+        rowKey="id"
+        isSelection
+        :column="columns"
+        :tableData="dataList"
+        :page="{
+          current: pagination.currentPage,
+          size: pagination.pageSize,
+          total: pagination.total,
+        }"
+        @selection-change="handleSelectionChange"
+        @pagination="changePage"
+      >
+        <template #statusRef="{ row }">
+          <el-tag v-if="row.status === 2" type="danger">澶辫触</el-tag>
+          <el-tag v-if="row.status === 1" type="success">瀹岀粨</el-tag>
+          <el-tag v-if="row.status === 0" type="warning">寰呯淮淇�</el-tag>
+        </template>
+        <template #operation="{ row }">
+          <el-button
+            type="primary"
+            text
+            icon="editPen"
+            @click="editRepair(row.id)"
+          >
+            缂栬緫
+          </el-button>
+          <el-button
+            type="danger"
+            text
+            icon="delete"
+            @click="delRepairByIds(row.id)"
+          >
+            鍒犻櫎
+          </el-button>
+        </template>
+      </PIMTable>
+    </div>
+    <RepairModal ref="repairModalRef" @ok="getTableData" />
+    <MaintainModal ref="maintainModalRef" @ok="getTableData" />
+  </div>
+</template>
+
+<script setup>
+import { usePaginationApi } from "../../hooks/usePaginationApi";
+import { getRepairPage, delRepair } from "../../api/equipmentManagement/repair";
+import { onMounted, getCurrentInstance } from "vue";
+import RepairModal from "./Modal/RepairModal.vue";
+import { ElMessageBox, ElMessage } from "element-plus";
+import dayjs from "dayjs";
+import MaintainModal from "./Modal/MaintainModal.vue";
+
+defineOptions({
+  name: "璁惧鏁呴殰",
+});
+
+const { proxy } = getCurrentInstance();
+
+// 妯℃�佹瀹炰緥
+const repairModalRef = ref();
+const maintainModalRef = ref();
+
+// 琛ㄦ牸澶氶�夋閫変腑椤�
+const multipleList = ref([]);
+
+// 琛ㄦ牸閽╁瓙
+const {
+  filters,
+  columns,
+  dataList,
+  pagination,
+  getTableData,
+  resetFilters,
+  onCurrentChange,
+} = usePaginationApi(
+  getRepairPage,
+  {
+    deviceName: undefined,
+    deviceModel: undefined,
+    remark: undefined,
+    maintenanceName: undefined,
+    repairTimeStr: undefined,
+    maintenanceTimeStr: undefined,
+  },
+  [
+    {
+      label: "璁惧鍚嶇О",
+      align: "center",
+      prop: "deviceName",
+    },
+    {
+      label: "瑙勬牸鍨嬪彿",
+      align: "center",
+      prop: "deviceModel",
+    },
+    {
+      label: "鏁呴殰鏃ユ湡",
+      align: "center",
+      prop: "repairTime",
+      formatData: (cell) => dayjs(cell).format("YYYY-MM-DD"),
+    },
+    {
+      label: "涓婃姤浜�",
+      align: "center",
+      prop: "repairName",
+    },
+    {
+      label: "鏁呴殰鐜拌薄",
+      align: "center",
+      prop: "remark",
+    },
+    {
+      label: "缁翠慨浜�",
+      align: "center",
+      prop: "maintenanceName",
+    },
+    {
+      label: "缁翠慨缁撴灉",
+      align: "center",
+      prop: "maintenanceResult",
+    },
+    {
+      label: "缁翠慨鏃ユ湡",
+      align: "center",
+      prop: "maintenanceTime",
+      formatData: (cell) => (cell ? dayjs(cell).format("YYYY-MM-DD") : ""),
+    },
+    {
+      label: "鐘舵��",
+      align: "center",
+      prop: "status",
+      dataType: "slot",
+      slot: "statusRef",
+    },
+    {
+      fixed: "right",
+      label: "鎿嶄綔",
+      dataType: "slot",
+      slot: "operation",
+      align: "center",
+      width: "200px",
+    },
+  ]
+);
+
+// type === 1 缁翠慨 2鏁呴殰闂�
+const handleDateChange = (value,type) => {
+  filters.maintenanceTimeStr = null
+  filters.c = null
+  if(type === 1){
+    if (value) {
+      filters.maintenanceTimeStr = dayjs(value).format("YYYY-MM-DD");
+    }
+  }else{
+    if (value) {
+      filters.repairTimeStr = dayjs(value).format("YYYY-MM-DD");
+    }
+  }
+  getTableData();
+};
+
+// 澶氶�夊悗鍋氫粈涔�
+const handleSelectionChange = (selectionList) => {
+  multipleList.value = selectionList;
+};
+
+// 鏂板鏁呴殰
+const addRepair = () => {
+  repairModalRef.value.openAdd();
+};
+
+// 缂栬緫鏁呴殰
+const editRepair = (id) => {
+  repairModalRef.value.openEdit(id);
+};
+
+// 鏂板缁翠慨
+const addMaintain = () => {
+  const row = multipleList.value[0];
+  maintainModalRef.value.open(row.id, row);
+};
+
+const changePage = ({ page, limit }) => {
+	pagination.currentPage = page;
+	pagination.pageSize = limit;
+	onCurrentChange(page);
+};
+
+// 鍗曡鍒犻櫎
+const delRepairByIds = async (ids) => {
+  ElMessageBox.confirm("纭鍒犻櫎鏁呴殰鏁版嵁, 姝ゆ搷浣滀笉鍙��?", "璀﹀憡", {
+    confirmButtonText: "纭畾",
+    cancelButtonText: "鍙栨秷",
+    type: "warning",
+  }).then(async () => {
+    const { code } = await delRepair(ids);
+    if (code === 200) {
+      ElMessage.success("鍒犻櫎鎴愬姛");
+      getTableData();
+    }
+  });
+};
+
+// 瀵煎嚭
+const handleOut = () => {
+  ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚鍑猴紝鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
+    confirmButtonText: "纭",
+    cancelButtonText: "鍙栨秷",
+    type: "warning",
+  })
+    .then(() => {
+      proxy.download("/device/repair/export", {}, "璁惧鏁呴殰.xlsx");
+    })
+    .catch(() => {
+      ElMessage.info("宸插彇娑�");
+    });
+};
+
+onMounted(() => {
+  getTableData();
+});
+</script>
+
+<style lang="scss" scoped>
+.table_list {
+  margin-top: unset;
+}
+.actions {
+  display: flex;
+  justify-content: space-between;
+  margin-bottom: 10px;
+}
+</style>
diff --git a/src/views/maintenance/Form/MaintenanceForm.vue b/src/views/maintenance/Form/MaintenanceForm.vue
new file mode 100644
index 0000000..16049e3
--- /dev/null
+++ b/src/views/maintenance/Form/MaintenanceForm.vue
@@ -0,0 +1,77 @@
+<template>
+  <el-form :model="form" label-width="100px">
+    <el-form-item label="瀹為檯淇濆吇浜�">
+      <el-input
+        v-model="form.maintenanceActuallyName"
+        placeholder="璇疯緭鍏ュ疄闄呬繚鍏讳汉"
+      ></el-input>
+    </el-form-item>
+    <el-form-item label="瀹為檯淇濆吇鏃ユ湡">
+      <el-date-picker
+        v-model="form.maintenanceActuallyTime"
+        placeholder="璇烽�夋嫨瀹為檯淇濆吇鏃ユ湡"
+        format="YYYY-MM-DD HH:mm:ss"
+        value-format="YYYY-MM-DD HH:mm:ss"
+        type="datetime"
+        clearable
+        style="width: 100%"
+      />
+    </el-form-item>
+    <el-form-item label="淇濆吇鐘舵��">
+      <el-select v-model="form.status">
+        <el-option label="寰呬繚鍏�" :value="0"></el-option>
+        <el-option label="瀹岀粨" :value="1"></el-option>
+        <el-option label="澶辫触" :value="2"></el-option>
+      </el-select>
+    </el-form-item>
+    <el-form-item label="淇濆吇缁撴灉">
+      <!-- <el-select v-model="form.maintenanceResult" placeholder="璇烽�夋嫨淇濆吇缁撴灉">
+        <el-option label="瀹屽ソ" :value="1"></el-option>
+        <el-option label="缁翠慨" :value="0"></el-option>
+      </el-select> -->
+      <el-input
+        v-model="form.maintenanceResult"
+        placeholder="璇疯緭鍏ヤ繚鍏荤粨鏋�"
+        type="text" />
+    </el-form-item>
+  </el-form>
+</template>
+
+<script setup>
+import useFormData from "../../../hooks/useFormData";
+import dayjs from "dayjs";
+import useUserStore from "../../../store/modules/user";
+
+defineOptions({
+  name: "淇濆吇琛ㄥ崟",
+});
+
+const userStore = useUserStore();
+const { form, resetForm } = useFormData({
+  maintenanceActuallyName: undefined, // 瀹為檯淇濆吇浜�
+  maintenanceActuallyTime: undefined, // 瀹為檯淇濆吇鏃ユ湡
+  maintenanceResult: undefined, // 淇濆吇缁撴灉
+  status: 0, // 淇濆吇鐘舵��
+});
+
+const setForm = (data) => {
+  form.maintenanceActuallyName =
+    data.maintenanceActuallyName ?? userStore.nickName;
+  form.maintenanceActuallyTime =
+    dayjs(data.maintenanceActuallyTime).format("YYYY-MM-DD HH:mm:ss") ??
+    dayjs().format("YYYY-MM-DD HH:mm:ss");
+  form.maintenanceResult = data.maintenanceResult;
+};
+
+const getForm = () => {
+  return form;
+};
+
+defineExpose({
+  getForm,
+  setForm,
+  resetForm,
+});
+</script>
+
+<style lang="scss" scoped></style>
diff --git a/src/views/maintenance/Form/PlanForm.vue b/src/views/maintenance/Form/PlanForm.vue
new file mode 100644
index 0000000..df7bb7d
--- /dev/null
+++ b/src/views/maintenance/Form/PlanForm.vue
@@ -0,0 +1,137 @@
+<template>
+  <el-form :model="form" label-width="100px">
+    <el-form-item label="璁惧鍚嶇О">
+      <el-select
+        v-model="form.deviceLedgerId"
+        @change="setDeviceModel"
+        placeholder="璇烽�夋嫨璁惧"
+        filterable
+        default-first-option
+        :reserve-keyword="false"
+      >
+        <el-option
+          v-for="(item, index) in deviceOptions"
+          :key="index"
+          :label="item.deviceName"
+          :value="item.id"
+        ></el-option>
+      </el-select>
+    </el-form-item>
+    <el-form-item label="瑙勬牸鍨嬪彿">
+      <el-input
+        v-model="form.deviceModel"
+        placeholder="璇疯緭鍏ヨ鏍煎瀷鍙�"
+        disabled
+      />
+    </el-form-item>
+    <el-form-item label="褰曞叆浜�">
+      <el-select
+        v-model="form.createUser"
+        placeholder="璇烽�夋嫨"
+        filterable
+        default-first-option
+        :reserve-keyword="false"
+        clearable
+      >
+        <el-option
+          v-for="item in userList"
+          :key="item.userId"
+          :label="item.userName"
+          :value="item.userId"
+        />
+      </el-select>
+    </el-form-item>
+    <el-form-item v-if="id" label="淇濅慨鐘舵��">
+      <el-select v-model="form.status">
+        <el-option label="寰呬繚淇�" :value="0"></el-option>
+        <el-option label="瀹岀粨" :value="1"></el-option>
+        <el-option label="澶辫触" :value="2"></el-option>
+      </el-select>
+    </el-form-item>
+    <el-form-item label="璁″垝淇濆吇鏃ユ湡">
+      <el-date-picker
+        style="width: 100%"
+        v-model="form.maintenancePlanTime"
+        format="YYYY-MM-DD"
+        value-format="YYYY-MM-DD HH:mm:ss"
+        type="date"
+        placeholder="璇烽�夋嫨璁″垝淇濆吇鏃ユ湡鏃ユ湡"
+        clearable
+      />
+    </el-form-item>
+  </el-form>
+</template>
+
+<script setup>
+import useFormData from "../../../hooks/useFormData";
+import { getDeviceLedger } from "../../../api/equipmentManagement/ledger";
+import { onMounted } from "vue";
+import dayjs from "dayjs";
+import { userListNoPage } from "../../../api/system/user.js";
+
+defineOptions({
+  name: "璁″垝琛ㄥ崟",
+});
+
+const deviceOptions = ref([]);
+const loadDeviceName = async () => {
+  const { data } = await getDeviceLedger();
+  deviceOptions.value = data;
+};
+
+const { id } = defineProps(['id']);
+
+const { form, resetForm } = useFormData({
+  deviceLedgerId: undefined, // 璁惧Id
+  deviceName: undefined, // 璁惧鍚嶇О
+  deviceModel: undefined, // 瑙勬牸鍨嬪彿
+  maintenancePlanTime: undefined, // 璁″垝淇濆吇鏃ユ湡
+  createUser: undefined, // 褰曞叆浜�
+  status: 0, //淇濅慨鐘舵��
+});
+
+const setDeviceModel = (id) => {
+  const option = deviceOptions.value.find((item) => item.id === id);
+  form.deviceModel = option.deviceModel;
+};
+
+const getForm = () => {
+  return form;
+};
+
+/**
+ * @desc 璁剧疆琛ㄥ崟鍐呭
+ * @param data 璁惧淇℃伅
+ */
+const setForm = (data) => {
+  form.deviceLedgerId = data.deviceLedgerId;
+  form.deviceName = data.deviceName;
+  form.deviceModel = data.deviceModel;
+  form.createUser = Number(data.createUser);
+  form.status = data.status;
+  form.maintenancePlanTime = dayjs(data.maintenancePlanTime).format(
+    "YYYY-MM-DD HH:mm:ss"
+  );
+};
+
+// 鐢ㄦ埛鍒楄〃
+const userList = ref([]);
+
+const loadForm = () => {};
+
+onMounted(() => {
+  loadDeviceName();
+  userListNoPage().then((res) => {
+    userList.value = res.data;
+  });
+});
+
+defineExpose({
+  loadForm,
+  resetForm,
+  getForm,
+  setForm,
+});
+</script>
+
+<style lang="scss" scoped></style>
diff --git a/src/views/maintenance/MaintenanceManagement.vue b/src/views/maintenance/MaintenanceManagement.vue
deleted file mode 100644
index 574f333..0000000
--- a/src/views/maintenance/MaintenanceManagement.vue
+++ /dev/null
@@ -1,526 +0,0 @@
-<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/maintenance/Modal/MaintenanceModal.vue b/src/views/maintenance/Modal/MaintenanceModal.vue
new file mode 100644
index 0000000..f41fb54
--- /dev/null
+++ b/src/views/maintenance/Modal/MaintenanceModal.vue
@@ -0,0 +1,60 @@
+<template>
+  <el-dialog v-model="visible" :title="modalOptions.title" direction="ltr">
+    <MaintenanceForm ref="maintenanceFormRef" />
+    <template #footer>
+			<el-button type="primary" @click="sendForm" :loading="loading">
+				{{ modalOptions.confirmText }}
+			</el-button>
+      <el-button @click="closeModal">{{ modalOptions.cancelText }}</el-button>
+    </template>
+  </el-dialog>
+</template>
+
+<script setup>
+import MaintenanceForm from "../Form/MaintenanceForm.vue";
+import { useModal } from "../../../hooks/useModal";
+import { addMaintenance } from "../../../api/equipmentManagement/upkeep";
+
+defineOptions({
+  name: "淇濆吇妯℃�佹",
+});
+
+const maintenanceFormRef = ref();
+const emits = defineEmits(["ok"]);
+
+const {
+  id,
+  visible,
+  loading,
+  openModal,
+  modalOptions,
+  handleConfirm,
+  closeModal,
+} = useModal({ title: "璁惧淇濆吇" });
+
+/**
+ * @desc 淇濆瓨淇濆吇
+ */
+const sendForm = async () => {
+  loading.value = true;
+  const form = await maintenanceFormRef.value.getForm();
+  const { code } = await addMaintenance({ id: id.value, ...form });
+  if (code == 200) {
+    emits("ok");
+    maintenanceFormRef.value.resetForm();
+    closeModal();
+  }
+  loading.value = false;
+};
+
+const open = async (id, row) => {
+  openModal(id);
+  await nextTick();
+  maintenanceFormRef.value.setForm(row);
+};
+defineExpose({
+  open,
+});
+</script>
+
+<style lang="scss" scoped></style>
diff --git a/src/views/maintenance/Modal/PlanModal.vue b/src/views/maintenance/Modal/PlanModal.vue
new file mode 100644
index 0000000..07d7e8a
--- /dev/null
+++ b/src/views/maintenance/Modal/PlanModal.vue
@@ -0,0 +1,76 @@
+<template>
+  <el-dialog
+    v-model="visible"
+    :title="modalOptions.title"
+    width="30%"
+    @close="close"
+  >
+    <PlanForm ref="planFormRef" :id="id"></PlanForm>
+    <template #footer>
+			<el-button type="primary" @click="sendForm" :loading="loading">
+				{{ modalOptions.confirmText }}
+			</el-button>
+      <el-button @click="closeModal">{{ modalOptions.cancelText }}</el-button>
+    </template>
+  </el-dialog>
+</template>
+
+<script setup>
+import { useModal } from "../../../hooks/useModal";
+import PlanForm from "../Form/PlanForm";
+import {
+  addUpkeep,
+  editUpkeep,
+  getUpkeepById,
+} from "../../../api/equipmentManagement/upkeep";
+import { ElMessage } from "element-plus";
+
+defineOptions({
+  name: "璁惧淇濆吇鏂板璁″垝",
+});
+
+const emits = defineEmits(["ok"]);
+const planFormRef = ref();
+const {
+  id,
+  visible,
+  loading,
+  openModal,
+  modalOptions,
+  handleConfirm,
+  closeModal,
+} = useModal({ title: "璁惧淇濆吇璁″垝" });
+
+const openEdit = async (id) => {
+  const { data } = await getUpkeepById(id);
+  openModal(id);
+  await nextTick();
+  await planFormRef.value.setForm(data);
+};
+
+const sendForm = async () => {
+  loading.value = true;
+  const form = await planFormRef.value.getForm();
+  const { code } = id.value
+    ? await editUpkeep({ id: unref(id), ...form })
+    : await addUpkeep(form);
+  if (code == 200) {
+    ElMessage.success(`${id ? "缂栬緫" : "鏂板"}璁″垝鎴愬姛`);
+    closeModal();
+    emits("ok");
+  }
+  loading.value = false;
+};
+
+const close = () => {
+  planFormRef.value.resetForm();
+  closeModal();
+};
+
+defineExpose({
+  openModal,
+  openEdit,
+});
+</script>
+
+<style lang="scss" scoped></style>
diff --git a/src/views/maintenance/index.vue b/src/views/maintenance/index.vue
new file mode 100644
index 0000000..53c7181
--- /dev/null
+++ b/src/views/maintenance/index.vue
@@ -0,0 +1,315 @@
+<template>
+  <div class="app-container">
+    <el-form :model="filters" :inline="true">
+      <el-form-item label="璁惧鍚嶇О">
+        <el-input
+            v-model="filters.deviceName"
+            style="width: 240px"
+            placeholder="璇疯緭鍏ヨ澶囧悕绉�"
+            clearable
+            :prefix-icon="Search"
+            @change="getTableData"
+        />
+      </el-form-item>
+      <el-form-item label="璁″垝淇濆吇鏃ユ湡">
+        <el-date-picker
+            v-model="filters.maintenancePlanTime"
+            type="date"
+            placeholder="璇烽�夋嫨璁″垝淇濆吇鏃ユ湡"
+            size="default"
+            @change="(date) => handleDateChange(date,2)"
+        />
+      </el-form-item>
+      <el-form-item label="瀹為檯淇濆吇鏃ユ湡">
+        <el-date-picker
+            v-model="filters.maintenanceActuallyTime"
+            type="date"
+            placeholder="璇烽�夋嫨瀹為檯淇濆吇鏃ユ湡"
+            size="default"
+            @change="(date) => handleDateChange(date,1)"
+        />
+      </el-form-item>
+      <el-form-item label="瀹為檯淇濆吇浜�">
+        <el-input
+            v-model="filters.maintenanceActuallyName"
+            style="width: 240px"
+            placeholder="璇疯緭鍏ュ疄闄呬繚鍏讳汉"
+            clearable
+            :prefix-icon="Search"
+            @change="getTableData"
+        />
+      </el-form-item>
+      <el-form-item>
+        <el-button type="primary" @click="getTableData">鎼滅储</el-button>
+        <el-button @click="resetFilters">閲嶇疆</el-button>
+      </el-form-item>
+    </el-form>
+    <div class="table_list">
+      <div class="actions">
+        <el-text class="mx-1" size="large">璁惧淇濆吇</el-text>
+        <div>
+          <el-button
+            type="primary"
+            icon="Plus"
+            :disabled="multipleList.length !== 1"
+            @click="addMaintain"
+          >
+            鏂板淇濆吇
+          </el-button>
+          <el-button type="success" icon="Van" @click="addPlan">
+            鏂板璁″垝
+          </el-button>
+          <el-button @click="handleOut">
+            瀵煎嚭
+          </el-button>
+          <el-button
+            type="danger"
+            icon="Delete"
+            :disabled="multipleList.length <= 0"
+            @click="delRepairByIds(multipleList.map((item) => item.id))"
+          >
+            鎵归噺鍒犻櫎
+          </el-button>
+        </div>
+      </div>
+      <PIMTable
+        rowKey="id"
+        isSelection
+        :column="columns"
+        :tableData="dataList"
+        :page="{
+          current: pagination.currentPage,
+          size: pagination.pageSize,
+          total: pagination.total,
+        }"
+        @selection-change="handleSelectionChange"
+        @pagination="changePage"
+      >
+        <template #maintenanceResultRef="{ row }">
+          <div>{{ row.maintenanceResult || '-' }}</div>
+          <!-- <el-tag v-if="row.maintenanceResult === 1" type="success">
+            瀹屽ソ
+          </el-tag>
+          <el-tag v-if="row.maintenanceResult === 0" type="danger">
+            缁翠慨
+          </el-tag> -->
+        </template>
+        <template #statusRef="{ row }">
+          <el-tag v-if="row.status === 2" type="danger">澶辫触</el-tag>
+          <el-tag v-if="row.status === 1" type="success">瀹岀粨</el-tag>
+          <el-tag v-if="row.status === 0" type="warning">寰呬繚鍏�</el-tag>
+        </template>
+        <template #operation="{ row }">
+          <el-button
+            type="primary"
+            text
+            icon="editPen"
+            @click="editPlan(row.id)"
+          >
+            缂栬緫
+          </el-button>
+          <el-button
+            type="danger"
+            text
+            icon="delete"
+            @click="delRepairByIds(row.id)"
+          >
+            鍒犻櫎
+          </el-button>
+        </template>
+      </PIMTable>
+    </div>
+    <PlanModal ref="planModalRef" @ok="getTableData" />
+    <MaintenanceModal ref="maintainModalRef" @ok="getTableData" />
+  </div>
+</template>
+
+<script setup>
+import { usePaginationApi } from "../../hooks/usePaginationApi";
+import { getUpkeepPage, delUpkeep } from "../../api/equipmentManagement/upkeep";
+import { onMounted, getCurrentInstance } from "vue";
+import PlanModal from "./Modal/PlanModal.vue";
+import MaintenanceModal from "./Modal/MaintenanceModal.vue";
+import dayjs from "dayjs";
+import { ElMessageBox, ElMessage } from "element-plus";
+
+defineOptions({
+  name: "璁惧淇濆吇",
+});
+
+const { proxy } = getCurrentInstance();
+
+// 璁″垝寮圭獥鎺у埗鍣�
+const planModalRef = ref();
+// 淇濆吇寮圭獥鎺у埗鍣�
+const maintainModalRef = ref();
+
+// 琛ㄦ牸澶氶�夋閫変腑椤�
+const multipleList = ref([]);
+
+// 澶氶�夊悗鍋氫粈涔�
+const handleSelectionChange = (selectionList) => {
+  multipleList.value = selectionList;
+};
+
+// 琛ㄦ牸閽╁瓙
+const {
+  filters,
+  columns,
+  dataList,
+  pagination,
+  getTableData,
+  resetFilters,
+  onCurrentChange,
+} = usePaginationApi(getUpkeepPage, {
+  deviceName: undefined,
+  maintenancePlanTime: undefined,
+  maintenanceActuallyTime: undefined,
+  maintenanceActuallyName: undefined,
+}, [
+  {
+    label: "璁惧鍚嶇О",
+    align: "center",
+    prop: "deviceName",
+  },
+  {
+    label: "瑙勬牸鍨嬪彿",
+    align: "center",
+    prop: "deviceModel",
+  },
+  {
+    label: "璁″垝淇濆吇鏃ユ湡",
+    align: "center",
+    prop: "maintenancePlanTime",
+    formatData: (cell) => dayjs(cell).format("YYYY-MM-DD"),
+  },
+  {
+    label: "褰曞叆浜�",
+    align: "center",
+    prop: "createUserName",
+  },
+  // {
+  //   label: "褰曞叆鏃ユ湡",
+  //   align: "center",
+  //   prop: "createTime",
+  //   formatData: (cell) => dayjs(cell).format("YYYY-MM-DD HH:mm:ss"),
+  //   width: 200,
+  // },
+  {
+    label: "瀹為檯淇濆吇浜�",
+    align: "center",
+    prop: "maintenanceActuallyName",
+  },
+  {
+    label: "瀹為檯淇濆吇鏃ユ湡",
+    align: "center",
+    prop: "maintenanceActuallyTime",
+    formatData: (cell) =>
+      cell ? dayjs(cell).format("YYYY-MM-DD HH:mm:ss") : "-",
+  },
+  {
+    label: "淇濆吇缁撴灉",
+    align: "center",
+    prop: "maintenanceResult",
+    dataType: "slot",
+    slot: "maintenanceResultRef",
+  },
+  {
+    label: "鐘舵��",
+    align: "center",
+    prop: "status",
+    dataType: "slot",
+    slot: "statusRef",
+  },
+  {
+    fixed: "right",
+    label: "鎿嶄綔",
+    dataType: "slot",
+    slot: "operation",
+    align: "center",
+    width: "200px",
+  },
+]);
+// type == 1瀹為檯淇濆吇鏃堕棿 2璁″垝淇濆吇鏃堕棿
+const handleDateChange = (value,type) => {
+  filters.maintenanceActuallyTimeReq = null
+  filters.maintenancePlanTimeReq = null
+  if(type === 1){
+    if (value) {
+      filters.maintenanceActuallyTimeReq = dayjs(value).format("YYYY-MM-DD");
+    }
+  }else{
+    if (value) {
+      filters.maintenancePlanTimeReq = dayjs(value).format("YYYY-MM-DD");
+    }
+  }
+  getTableData();
+};
+
+// 鏂板淇濆吇
+const addMaintain = () => {
+  const row = multipleList.value[0];
+  maintainModalRef.value.open(row.id, row);
+};
+
+// 鏂板璁″垝
+const addPlan = () => {
+  planModalRef.value.openModal();
+};
+
+// 缂栬緫璁″垝
+const editPlan = (id) => {
+  planModalRef.value.openEdit(id);
+};
+
+const changePage = ({ page, limit }) => {
+	pagination.currentPage = page;
+	pagination.pageSize = limit;
+	onCurrentChange(page);
+};
+
+// 鍗曡鍒犻櫎
+const delRepairByIds = async (ids) => {
+  ElMessageBox.confirm("纭鍒犻櫎鎶ヤ慨鏁版嵁, 姝ゆ搷浣滀笉鍙��?", "璀﹀憡", {
+    confirmButtonText: "纭畾",
+    cancelButtonText: "鍙栨秷",
+    type: "warning",
+  }).then(async () => {
+    const { code } = await delUpkeep(ids);
+    if (code === 200) {
+      ElMessage.success("鍒犻櫎鎴愬姛");
+      getTableData();
+    }
+  });
+};
+
+// 瀵煎嚭
+const handleOut = () => {
+  ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚鍑猴紝鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
+    confirmButtonText: "纭",
+    cancelButtonText: "鍙栨秷",
+    type: "warning",
+  })
+    .then(() => {
+      proxy.download("/device/maintenance/export", {}, "璁惧淇濆吇.xlsx");
+    })
+    .catch(() => {
+      ElMessage.info("宸插彇娑�");
+    });
+};
+
+onMounted(() => {
+  getTableData();
+});
+</script>
+
+<style lang="scss" scoped>
+.table_list {
+  margin-top: unset;
+}
+.actions {
+  display: flex;
+  justify-content: space-between;
+  margin-bottom: 10px;
+}
+</style>

--
Gitblit v1.9.3