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