From e76403a881cbad2a4788c5a90e1318b1feb1b5ef Mon Sep 17 00:00:00 2001
From: zouyu <2723363702@qq.com>
Date: 星期日, 04 一月 2026 18:01:00 +0800
Subject: [PATCH] Merge branch 'dev_tide_sbjkxt' into dev_tide_sbjkxt_xindao
---
src/views/diagnosis/Modal/MaintainModal.vue | 58
src/views/diagnosis/Form/RepairForm.vue | 130 ++
src/views/measurementEquipment/index.vue | 270 ++++
src/views/calibration/index.vue | 246 +++
src/views/diagnosis/Form/MaintainForm.vue | 66 +
src/views/measurementEquipment/components/calibrationDia.vue | 268 ++++
src/views/device/index.vue | 322 +++++
src/views/measurementEquipment/filesDia.vue | 202 +++
src/views/diagnosis/index.vue | 327 +++++
src/views/maintenance/Form/MaintenanceForm.vue | 77 +
src/utils/auth.js | 6
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 +
src/api/equipmentManagement/calibration.js | 9
src/views/measurementEquipment/components/formDia.vue | 254 ++++
21 files changed, 3,205 insertions(+), 529 deletions(-)
diff --git a/src/api/equipmentManagement/calibration.js b/src/api/equipmentManagement/calibration.js
index 54b99f9..472a4ef 100644
--- a/src/api/equipmentManagement/calibration.js
+++ b/src/api/equipmentManagement/calibration.js
@@ -24,4 +24,13 @@
method: "post",
data: query,
});
+}
+
+// 鍒犻櫎璁板綍
+export function ledgerRecordDelete(ids) {
+ return request({
+ url: "/measuringInstrumentLedgerRecord/delete",
+ method: "delete",
+ data: ids,
+ });
}
\ No newline at end of file
diff --git a/src/utils/auth.js b/src/utils/auth.js
index 423545f..9295d59 100644
--- a/src/utils/auth.js
+++ b/src/utils/auth.js
@@ -3,17 +3,17 @@
const TokenKey = 'Admin-Token'
export function getToken() {
- // return Cookies.get(TokenKey)
+ // return Cookies.get(TokenKey)
return sessionStorage.getItem(TokenKey)
}
export function setToken(token) {
- // return Cookies.set(TokenKey, token)
+ // return Cookies.set(TokenKey, token)
return sessionStorage.setItem(TokenKey, token)
}
export function removeToken() {
- // return Cookies.remove(TokenKey)
+ // return Cookies.remove(TokenKey)
return sessionStorage.removeItem(TokenKey)
}
diff --git a/src/views/calibration/index.vue b/src/views/calibration/index.vue
new file mode 100644
index 0000000..12d5556
--- /dev/null
+++ b/src/views/calibration/index.vue
@@ -0,0 +1,246 @@
+<template>
+ <div class="app-container">
+ <div class="search_form">
+ <div>
+ <span class="search_title">妫�瀹氭棩鏈燂細</span>
+ <el-date-picker
+ v-model="searchForm.recordDate"
+ value-format="YYYY-MM-DD"
+ format="YYYY-MM-DD"
+ type="date"
+ placeholder="璇烽�夋嫨"
+ clearable
+ style="width: 160px"
+ @change="handleQuery"
+ />
+ <span class="search_title ml10">褰曞叆鏃ユ湡锛�</span>
+ <el-date-picker
+ v-model="searchForm.entryDate"
+ value-format="YYYY-MM-DD"
+ format="YYYY-MM-DD"
+ type="date"
+ placeholder="璇烽�夋嫨"
+ clearable
+ style="width: 160px"
+ @change="handleQuery"
+ />
+ <span class="search_title ml10">璁¢噺鍣ㄥ叿缂栧彿锛�</span>
+ <el-input v-model="searchForm.code" placeholder="璇疯緭鍏ョ紪鍙�" clearable style="width: 240px" @change="handleQuery"/>
+<!-- <span class="search_title ml10">鐘舵�侊細</span>-->
+<!-- <el-select v-model="searchForm.status" placeholder="璇烽�夋嫨鐘舵��" @change="handleQuery" style="width: 160px" clearable>-->
+<!-- <el-option label="鏈夋晥" :value="1"></el-option>-->
+<!-- <el-option label="閫炬湡" :value="2"></el-option>-->
+<!-- </el-select>-->
+ <el-button type="primary" @click="handleQuery" style="margin-left: 10px"
+ >鎼滅储</el-button
+ >
+ </div>
+ <div>
+ <el-button @click="handleOut">瀵煎嚭</el-button>
+ </div>
+ </div>
+ <div class="table_list">
+ <PIMTable
+ rowKey="id"
+ :column="tableColumn"
+ :tableData="tableData"
+ :page="page"
+ :isSelection="true"
+ @selection-change="handleSelectionChange"
+ :tableLoading="tableLoading"
+ @pagination="pagination"
+ ></PIMTable>
+ </div>
+ <calibration-dia ref="calibrationDia" @close="handleQuery"></calibration-dia>
+ </div>
+</template>
+
+<script setup>
+import {onMounted, ref} from "vue";
+import {ElMessageBox, ElMessage} from "element-plus";
+import useUserStore from "../../store/modules/user.js";
+import CalibrationDia from "../../views/measurementEquipment/components/calibrationDia.vue";
+import {ledgerRecordListPage, ledgerRecordDelete} from "../../api/equipmentManagement/calibration.js";
+const { proxy } = getCurrentInstance();
+const userStore = useUserStore()
+
+const data = reactive({
+ searchForm: {
+ recordDate: "",
+ code: "",
+ entryDate: "",
+ },
+});
+const { searchForm } = toRefs(data);
+
+const tableColumn = ref([
+ // {
+ // label: "鐘舵��",
+ // prop: "status",
+ // dataType: "tag",
+ // formatData: (params) => {
+ // if (params == 1) {
+ // return "鏈夋晥";
+ // } else if (params == 2) {
+ // return "閫炬湡";
+ // } else {
+ // return null;
+ // }
+ // },
+ // formatType: (params) => {
+ // if (params == 1) {
+ // return "success";
+ // } else if (params == 2) {
+ // return "danger";
+ // } else {
+ // return null;
+ // }
+ // },
+ // },
+ {
+ label: "妫�瀹氭棩鏈�",
+ prop: "recordDate",
+ width: 130,
+ },
+ {
+ label: "璁¢噺鍣ㄥ叿缂栧彿",
+ prop: "code",
+ width: 150,
+ },
+ {
+ label: "璁¢噺鍣ㄥ叿鍚嶇О",
+ prop: "name",
+ width: 200,
+ },
+ {
+ label: "瑙勬牸鍨嬪彿",
+ prop: "model",
+ width:200
+ },
+ {
+ label: "鏈夋晥鏈�",
+ prop: "valid",
+ width: 100,
+ },
+ {
+ label: "褰曞叆浜�",
+ prop: "userName",
+ },
+ {
+ label: "褰曞叆鏃ユ湡",
+ prop: "entryDate",
+ width: 130,
+ },
+ {
+ dataType: "action",
+ label: "鎿嶄綔",
+ width: 100,
+ align: "center",
+ fixed: 'right',
+ operation: [
+ {
+ name: "缂栬緫",
+ type: "text",
+ clickFun: (row) => {
+ openCalibrationDia("edit", row);
+ },
+ },
+ {
+ name: "鍒犻櫎",
+ type: "text",
+ style: {
+ color: "#F56C6C"
+ },
+ clickFun: (row) => {
+ handleDelete(row);
+ },
+ },
+ ],
+ },
+]);
+const tableData = ref([]);
+const tableLoading = ref(false);
+const page = reactive({
+ current: 1,
+ size: 100,
+ total: 0,
+});
+const selectedRows = ref([]);
+
+// 琛ㄦ牸閫夋嫨鏁版嵁
+const handleSelectionChange = (selection) => {
+ selectedRows.value = selection;
+};
+const calibrationDia = ref()
+
+// 鏌ヨ鍒楄〃
+/** 鎼滅储鎸夐挳鎿嶄綔 */
+const handleQuery = () => {
+ page.current = 1;
+ getList();
+};
+const pagination = (obj) => {
+ page.current = obj.page;
+ page.size = obj.limit;
+ getList();
+};
+const getList = () => {
+ tableLoading.value = true;
+ ledgerRecordListPage({ ...searchForm.value, ...page }).then((res) => {
+ tableLoading.value = false;
+ tableData.value = res.data.records;
+ page.total = res.data.total;
+ }).catch((err) => {
+ tableLoading.value = false;
+ })
+};
+
+// 鎵撳紑妫�瀹氭牎鍑嗗脊妗�
+const openCalibrationDia = (type, row) => {
+ nextTick(() => {
+ calibrationDia.value?.openDialog(type, row)
+ })
+}
+
+// 鍒犻櫎璁板綍
+const handleDelete = (row) => {
+ ElMessageBox.confirm(`纭鍒犻櫎璁¢噺鍣ㄥ叿缂栧彿涓�"${row.code}"鐨勬瀹氳褰曞悧锛焋, "鍒犻櫎纭", {
+ confirmButtonText: "纭",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ })
+ .then(() => {
+ ledgerRecordDelete([row.id]).then(() => {
+ ElMessage.success("鍒犻櫎鎴愬姛");
+ getList();
+ }).catch(() => {
+ ElMessage.error("鍒犻櫎澶辫触");
+ });
+ })
+ .catch(() => {
+ proxy.$modal.msg("宸插彇娑堝垹闄�");
+ });
+};
+
+// 瀵煎嚭
+const handleOut = () => {
+ ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚鍑猴紝鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
+ confirmButtonText: "纭",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ })
+ .then(() => {
+ proxy.download("/measuringInstrumentLedgerRecord/export", {}, "妫�瀹氭牎鍑嗚褰�.xlsx");
+ })
+ .catch(() => {
+ proxy.$modal.msg("宸插彇娑�");
+ });
+};
+onMounted(() => {
+ getList();
+});
+</script>
+
+<style scoped>
+
+</style>
\ No newline at end of file
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>
diff --git a/src/views/measurementEquipment/components/calibrationDia.vue b/src/views/measurementEquipment/components/calibrationDia.vue
new file mode 100644
index 0000000..4141f43
--- /dev/null
+++ b/src/views/measurementEquipment/components/calibrationDia.vue
@@ -0,0 +1,268 @@
+<template>
+ <div>
+ <el-dialog
+ v-model="dialogFormVisible"
+ title="璁¢噺鍣ㄥ叿"
+ width="50%"
+ @close="closeDia"
+ >
+ <el-form
+ :model="form"
+ label-width="140px"
+ label-position="top"
+ :rules="rules"
+ ref="formRef"
+ >
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="璁¢噺鍣ㄥ叿缂栧彿锛�" prop="customerName">
+ <el-input
+ v-model="form.code"
+ placeholder="璇疯緭鍏�"
+ clearable
+ disabled
+ />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="璁¢噺鍣ㄥ叿鍚嶇О锛�" prop="proDesc">
+ <el-input
+ v-model="form.name"
+ placeholder="璇疯緭鍏�"
+ clearable
+ disabled
+ />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="妫�瀹氭棩鏈燂細" prop="recordDate">
+ <el-date-picker
+ style="width: 100%"
+ v-model="form.recordDate"
+ value-format="YYYY-MM-DD"
+ format="YYYY-MM-DD"
+ type="date"
+ placeholder="璇烽�夋嫨"
+ clearable
+ />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="鏈夋晥鏈燂細" prop="valid">
+ <el-input
+ v-model="form.valid"
+ placeholder="璇疯緭鍏�"
+ clearable
+ >
+ <template #append>鏃�</template>
+ </el-input>
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="褰曞叆浜猴細" prop="userId">
+ <el-select
+ v-model="form.userId"
+ placeholder="璇烽�夋嫨"
+ filterable
+ default-first-option
+ :reserve-keyword="false"
+ clearable
+ >
+ <el-option
+ v-for="item in userList"
+ :key="item.userId"
+ :label="item.nickName"
+ :value="item.userId"
+ ></el-option>
+ </el-select>
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="褰曞叆鏃ユ湡锛�" prop="entryDate">
+ <el-date-picker
+ style="width: 100%"
+ v-model="form.entryDate"
+ value-format="YYYY-MM-DD"
+ format="YYYY-MM-DD"
+ type="date"
+ placeholder="璇烽�夋嫨"
+ clearable
+ />
+ </el-form-item>
+ </el-col>
+ </el-row>
+<!-- <el-row :gutter="30">-->
+<!-- <el-col :span="24">-->
+<!-- <el-form-item label="闄勪欢鏉愭枡锛�" prop="remark">-->
+<!-- <el-upload v-model:file-list="fileList" :action="upload.url" multiple ref="fileUpload" auto-upload-->
+<!-- :headers="upload.headers" :before-upload="handleBeforeUpload" :on-error="handleUploadError"-->
+<!-- :on-success="handleUploadSuccess" :on-remove="handleRemove">-->
+<!-- <el-button type="primary" v-if="operationType !== 'view'">涓婁紶</el-button>-->
+<!-- <template #tip v-if="operationType !== 'view'">-->
+<!-- <div class="el-upload__tip">-->
+<!-- 鏂囦欢鏍煎紡鏀寔-->
+<!-- doc锛宒ocx锛寈ls锛寈lsx锛宲pt锛宲ptx锛宲df锛宼xt锛寈ml锛宩pg锛宩peg锛宲ng锛実if锛宐mp锛宺ar锛寊ip锛�7z-->
+<!-- </div>-->
+<!-- </template>-->
+<!-- </el-upload>-->
+<!-- </el-form-item>-->
+<!-- </el-col>-->
+<!-- </el-row>-->
+ </el-form>
+ <template #footer>
+ <div class="dialog-footer">
+ <el-button type="primary" @click="submitForm">纭</el-button>
+ <el-button @click="closeDia">鍙栨秷</el-button>
+ </div>
+ </template>
+ </el-dialog>
+ </div>
+</template>
+
+<script setup>
+import {ref} from "vue";
+import useUserStore from "../../../store/modules/user.js";
+import {userListNoPageByTenantId} from "../../../api/system/user.js";
+import {afterSalesServiceAdd, afterSalesServiceUpdate} from "@/api/customerService/index.js";
+import {getToken} from "../../../utils/auth.js";
+import {ledgerRecordUpdate, ledgerRecordVerifying} from "../../../api/equipmentManagement/calibration.js";
+import {delLedgerFile} from "../../../api/salesManagement/salesLedger.js";
+const { proxy } = getCurrentInstance()
+const emit = defineEmits(['close'])
+const dialogFormVisible = ref(false);
+const operationType = ref('')
+const userStore = useUserStore();
+
+const data = reactive({
+ form: {
+ code: "",
+ name: "",
+ valid: "",
+ recordDate: "",
+ userId: "",
+ entryDate: "",
+ tempFileIds: []
+ },
+ rules: {
+ code: [{required: true, message: "璇疯緭鍏�", trigger: "blur"}],
+ name: [{required: true, message: "璇疯緭鍏�", trigger: "blur"}],
+ valid: [{required: true, message: "璇疯緭鍏�", trigger: "blur"}],
+ recordDate: [{required: true, message: "璇烽�夋嫨", trigger: "change"}],
+ userId: [{required: true, message: "璇烽�夋嫨", trigger: "change"}],
+ entryDate: [{required: true, message: "璇烽�夋嫨", trigger: "change"}],
+ }
+})
+const { form, rules } = toRefs(data);
+const userList = ref([])
+const fileList = ref([]);
+const upload = reactive({
+ // 涓婁紶鐨勫湴鍧�
+ url: import.meta.env.VITE_APP_BASE_API + "/file/upload",
+ // 璁剧疆涓婁紶鐨勮姹傚ご閮�
+ headers: { Authorization: "Bearer " + getToken() },
+});
+
+// 鎵撳紑寮规
+const openDialog = (type, row) => {
+ console.log(row)
+ operationType.value = type;
+ dialogFormVisible.value = true;
+ userListNoPageByTenantId().then((res) => {
+ userList.value = res.data;
+ });
+ fileList.value = []
+ if(type !== "add"){
+ form.value.tempFileIds = [];
+ }
+ if (type === "edit") {
+ form.value.valid = row.valid;
+ form.value.recordDate = row.recordDate;
+ fileList.value = row.commonFiles;
+ }
+ if(type === "add"){
+ fileList.value = row.commonFiles;
+ }
+
+ form.value.id = row.id;
+ form.value.code = row.code;
+ form.value.name = row.name;
+ form.value.userId = userStore.id;
+ form.value.entryDate = getCurrentDate();
+}
+
+// 涓婁紶鍓嶆牎妫�
+function handleBeforeUpload(file) {
+ proxy.$modal.loading("姝e湪涓婁紶鏂囦欢锛岃绋嶅��...");
+ return true;
+}
+// 涓婁紶澶辫触
+function handleUploadError(err) {
+ proxy.$modal.msgError("涓婁紶鏂囦欢澶辫触");
+ proxy.$modal.closeLoading();
+}
+// 涓婁紶鎴愬姛鍥炶皟
+function handleUploadSuccess(res, file, uploadFiles) {
+ proxy.$modal.closeLoading();
+ if (res.code === 200) {
+ file.tempId = res.data.tempId;
+ form.value.tempFileIds.push(file.tempId);
+ proxy.$modal.msgSuccess("涓婁紶鎴愬姛");
+ } else {
+ proxy.$modal.msgError(res.msg);
+ proxy.$refs.fileUpload.handleRemove(file);
+ }
+}
+// 绉婚櫎鏂囦欢
+function handleRemove(file) {
+ if (operationType.value === "edit") {
+ let ids = [];
+ ids.push(file.id);
+ delLedgerFile(ids).then((res) => {
+ proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+ });
+ }
+}
+
+const submitForm = () => {
+ proxy.$refs["formRef"].validate(valid => {
+ if (valid) {
+ if (operationType.value === "verifying") {
+ ledgerRecordVerifying(form.value).then(response => {
+ proxy.$modal.msgSuccess("妫�瀹氭牎鍑嗘垚鍔�")
+ closeDia()
+ })
+ } else {
+ ledgerRecordUpdate(form.value).then(response => {
+ proxy.$modal.msgSuccess("淇敼鎴愬姛")
+ closeDia()
+ })
+ }
+ }
+ })
+}
+// 鍏抽棴寮规
+const closeDia = () => {
+ proxy.resetForm("formRef");
+ dialogFormVisible.value = false;
+ emit('close')
+};
+// 鑾峰彇褰撳墠鏃ユ湡骞舵牸寮忓寲涓� YYYY-MM-DD
+function getCurrentDate() {
+ const today = new Date();
+ const year = today.getFullYear();
+ const month = String(today.getMonth() + 1).padStart(2, "0"); // 鏈堜唤浠�0寮�濮�
+ const day = String(today.getDate()).padStart(2, "0");
+ return `${year}-${month}-${day}`;
+}
+defineExpose({
+ openDialog,
+});
+</script>
+
+<style scoped>
+
+</style>
\ No newline at end of file
diff --git a/src/views/measurementEquipment/components/formDia.vue b/src/views/measurementEquipment/components/formDia.vue
new file mode 100644
index 0000000..55db4ca
--- /dev/null
+++ b/src/views/measurementEquipment/components/formDia.vue
@@ -0,0 +1,254 @@
+<template>
+ <div>
+ <el-dialog
+ v-model="dialogFormVisible"
+ title="璁¢噺鍣ㄥ叿"
+ width="50%"
+ @close="closeDia"
+ >
+ <el-form
+ :model="form"
+ label-width="140px"
+ label-position="top"
+ :rules="rules"
+ ref="formRef"
+ >
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="璁¢噺鍣ㄥ叿缂栧彿锛�" prop="code">
+ <el-input
+ v-model="form.code"
+ placeholder="璇疯緭鍏�"
+ clearable
+ />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="璁¢噺鍣ㄥ叿鍚嶇О锛�" prop="name">
+ <el-input
+ v-model="form.name"
+ placeholder="璇疯緭鍏�"
+ clearable
+ />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="瑙勬牸鍨嬪彿锛�" prop="model">
+ <el-input
+ v-model="form.model"
+ placeholder="璇疯緭鍏�"
+ clearable
+ />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="棰勮涓嬫妫�瀹氭棩鏈燂細" prop="nextDate">
+ <el-date-picker
+ style="width: 100%"
+ v-model="form.nextDate"
+ value-format="YYYY-MM-DD"
+ format="YYYY-MM-DD"
+ type="date"
+ placeholder="璇烽�夋嫨"
+ clearable
+ />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="褰曞叆浜猴細" prop="userId">
+ <el-select
+ v-model="form.userId"
+ placeholder="璇烽�夋嫨"
+ clearable
+ filterable
+ default-first-option
+ :reserve-keyword="false"
+ >
+ <el-option
+ v-for="item in userList"
+ :key="item.userId"
+ :label="item.nickName"
+ :value="item.userId"
+ ></el-option>
+ </el-select>
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="褰曞叆鏃ユ湡锛�" prop="recordDate">
+ <el-date-picker
+ style="width: 100%"
+ v-model="form.recordDate"
+ value-format="YYYY-MM-DD"
+ format="YYYY-MM-DD"
+ type="date"
+ placeholder="璇烽�夋嫨"
+ clearable
+ />
+ </el-form-item>
+ </el-col>
+ </el-row>
+<!-- <el-row :gutter="30">-->
+<!-- <el-col :span="24">-->
+<!-- <el-form-item label="闄勪欢鏉愭枡锛�" prop="remark">-->
+<!-- <el-upload v-model:file-list="fileList" :action="upload.url" multiple ref="fileUpload" auto-upload-->
+<!-- :headers="upload.headers" :before-upload="handleBeforeUpload" :on-error="handleUploadError"-->
+<!-- :on-success="handleUploadSuccess" :on-remove="handleRemove">-->
+<!-- <el-button type="primary" v-if="operationType !== 'view'">涓婁紶</el-button>-->
+<!-- <template #tip v-if="operationType !== 'view'">-->
+<!-- <div class="el-upload__tip">-->
+<!-- 鏂囦欢鏍煎紡鏀寔-->
+<!-- doc锛宒ocx锛寈ls锛寈lsx锛宲pt锛宲ptx锛宲df锛宼xt锛寈ml锛宩pg锛宩peg锛宲ng锛実if锛宐mp锛宺ar锛寊ip锛�7z-->
+<!-- </div>-->
+<!-- </template>-->
+<!-- </el-upload>-->
+<!-- </el-form-item>-->
+<!-- </el-col>-->
+<!-- </el-row>-->
+ </el-form>
+ <template #footer>
+ <div class="dialog-footer">
+ <el-button type="primary" @click="submitForm">纭</el-button>
+ <el-button @click="closeDia">鍙栨秷</el-button>
+ </div>
+ </template>
+ </el-dialog>
+ </div>
+</template>
+
+<script setup>
+import {ref} from "vue";
+import useUserStore from "../../../store/modules/user.js";
+import {userListNoPageByTenantId} from "../../../api/system/user.js";
+import {afterSalesServiceAdd, afterSalesServiceUpdate} from "@/api/customerService/index.js";
+import {getToken} from "../../../utils/auth.js";
+import {measuringInstrumentAdd, measuringInstrumentUpdate} from "../../../api/equipmentManagement/measurementEquipment.js";
+const { proxy } = getCurrentInstance()
+const emit = defineEmits(['close'])
+const dialogFormVisible = ref(false);
+const operationType = ref('')
+const userStore = useUserStore();
+
+const data = reactive({
+ form: {
+ code: "",
+ name: "",
+ model: "",
+ validDate: "",
+ nextDate: "",
+ userId: "",
+ recordDate: "",
+ tempFileIds: []
+ },
+ rules: {
+ code: [{required: true, message: "璇疯緭鍏�", trigger: "blur"}],
+ name: [{required: true, message: "璇疯緭鍏�", trigger: "blur"}],
+ model: [{required: true, message: "璇疯緭鍏�", trigger: "blur"}],
+ validDate: [{required: true, message: "璇疯緭鍏�", trigger: "blur"}],
+ nextDate: [{required: true, message: "璇烽�夋嫨", trigger: "change"}],
+ userId: [{required: true, message: "璇烽�夋嫨", trigger: "change"}],
+ recordDate: [{required: true, message: "璇烽�夋嫨", trigger: "change"}],
+ }
+})
+const { form, rules } = toRefs(data);
+const userList = ref([])
+const fileList = ref([]);
+const upload = reactive({
+ // 涓婁紶鐨勫湴鍧�
+ url: import.meta.env.VITE_APP_BASE_API + "/file/upload",
+ // 璁剧疆涓婁紶鐨勮姹傚ご閮�
+ headers: { Authorization: "Bearer " + getToken() },
+});
+
+// 鎵撳紑寮规
+const openDialog = (type, row) => {
+ operationType.value = type;
+ dialogFormVisible.value = true;
+ fileList.value = []
+ form.value.userId = userStore.id;
+ form.value.recordDate = getCurrentDate();
+ userListNoPageByTenantId().then((res) => {
+ userList.value = res.data;
+ });
+ if (type === "edit") {
+ form.value = {...row}
+ }
+}
+
+// 涓婁紶鍓嶆牎妫�
+function handleBeforeUpload(file) {
+ proxy.$modal.loading("姝e湪涓婁紶鏂囦欢锛岃绋嶅��...");
+ return true;
+}
+// 涓婁紶澶辫触
+function handleUploadError(err) {
+ proxy.$modal.msgError("涓婁紶鏂囦欢澶辫触");
+ proxy.$modal.closeLoading();
+}
+// 涓婁紶鎴愬姛鍥炶皟
+function handleUploadSuccess(res, file, uploadFiles) {
+ proxy.$modal.closeLoading();
+ if (res.code === 200) {
+ file.tempId = res.data.tempId;
+ form.value.tempFileIds.push(res.data.tempId)
+ proxy.$modal.msgSuccess("涓婁紶鎴愬姛");
+ } else {
+ proxy.$modal.msgError(res.msg);
+ proxy.$refs.fileUpload.handleRemove(file);
+ }
+}
+// 绉婚櫎鏂囦欢
+function handleRemove(file) {
+ if (operationType.value === "edit") {
+ let ids = [];
+ ids.push(file.id);
+ delLedgerFile(ids).then((res) => {
+ proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+ });
+ }
+}
+
+const submitForm = () => {
+ proxy.$refs["formRef"].validate(valid => {
+ if (valid) {
+ if (operationType.value === "add") {
+ measuringInstrumentAdd(form.value).then(response => {
+ proxy.$modal.msgSuccess("鏂板鎴愬姛")
+ form.value.tempFileIds = []
+ closeDia()
+ })
+ } else {
+ measuringInstrumentUpdate(form.value).then(response => {
+ proxy.$modal.msgSuccess("淇敼鎴愬姛")
+ form.value.tempFileIds = []
+ closeDia()
+ })
+ }
+ }
+ })
+}
+// 鍏抽棴寮规
+const closeDia = () => {
+ proxy.resetForm("formRef");
+ dialogFormVisible.value = false;
+ emit('close')
+};
+// 鑾峰彇褰撳墠鏃ユ湡骞舵牸寮忓寲涓� YYYY-MM-DD
+function getCurrentDate() {
+ const today = new Date();
+ const year = today.getFullYear();
+ const month = String(today.getMonth() + 1).padStart(2, "0"); // 鏈堜唤浠�0寮�濮�
+ const day = String(today.getDate()).padStart(2, "0");
+ return `${year}-${month}-${day}`;
+}
+defineExpose({
+ openDialog,
+});
+</script>
+
+<style scoped>
+
+</style>
\ No newline at end of file
diff --git a/src/views/measurementEquipment/filesDia.vue b/src/views/measurementEquipment/filesDia.vue
new file mode 100644
index 0000000..0751eac
--- /dev/null
+++ b/src/views/measurementEquipment/filesDia.vue
@@ -0,0 +1,202 @@
+<template>
+ <div>
+ <el-dialog
+ v-model="dialogFormVisible"
+ title="涓婁紶闄勪欢"
+ width="50%"
+ @close="closeDia"
+ >
+ <div style="margin-bottom: 10px;text-align: right">
+ <el-upload
+ v-model:file-list="fileList"
+ class="upload-demo"
+ :action="uploadUrl"
+ :on-success="handleUploadSuccess"
+ :on-error="handleUploadError"
+ name="file"
+ :show-file-list="false"
+ :headers="headers"
+ style="display: inline;margin-right: 10px"
+ >
+ <el-button type="primary">涓婁紶闄勪欢</el-button>
+ </el-upload>
+ <el-button type="danger" plain @click="handleDelete">鍒犻櫎</el-button>
+ </div>
+ <PIMTable
+ rowKey="id"
+ :column="tableColumn"
+ :tableData="tableData"
+ :tableLoading="tableLoading"
+ :isSelection="true"
+ @selection-change="handleSelectionChange"
+ height="500"
+ >
+ </PIMTable>
+ <pagination
+ style="margin: 10px 0"
+ v-show="total > 0"
+ @pagination="paginationSearch"
+ :total="total"
+ :page="page.current"
+ :limit="page.size"
+ />
+ <template #footer>
+ <div class="dialog-footer">
+ <el-button @click="closeDia">鍙栨秷</el-button>
+ </div>
+ </template>
+ </el-dialog>
+ <filePreview ref="filePreviewRef" />
+ </div>
+</template>
+
+<script setup>
+import {ref} from "vue";
+import {ElMessageBox} from "element-plus";
+import {getToken} from "../../utils/auth.js";
+import filePreview from '../../components/filePreview/index.vue'
+import {
+ fileAdd,
+ fileDel,
+ fileListPage
+} from "../../api/financialManagement/revenueManagement.js";
+import Pagination from "../../components/PIMTable/Pagination.vue";
+const { proxy } = getCurrentInstance()
+const emit = defineEmits(['close'])
+
+const dialogFormVisible = ref(false);
+const currentId = ref('')
+const selectedRows = ref([]);
+const filePreviewRef = ref()
+const tableColumn = ref([
+ {
+ label: "鏂囦欢鍚嶇О",
+ prop: "name",
+ },
+ {
+ dataType: "action",
+ label: "鎿嶄綔",
+ align: "center",
+ operation: [
+ {
+ name: "涓嬭浇",
+ type: "text",
+ clickFun: (row) => {
+ downLoadFile(row);
+ },
+ },
+ {
+ name: "棰勮",
+ type: "text",
+ clickFun: (row) => {
+ lookFile(row);
+ },
+ }
+ ],
+ },
+]);
+const page = reactive({
+ current: 1,
+ size: 100,
+});
+const total = ref(0);
+const tableData = ref([]);
+const fileList = ref([]);
+const tableLoading = ref(false);
+const accountType = ref('')
+const headers = ref({
+ Authorization: "Bearer " + getToken(),
+});
+const uploadUrl = ref(import.meta.env.VITE_APP_BASE_API + "/file/upload"); // 涓婁紶鐨勫浘鐗囨湇鍔″櫒鍦板潃
+
+// 鎵撳紑寮规
+const openDialog = (row,type) => {
+ accountType.value = type;
+ dialogFormVisible.value = true;
+ currentId.value = row.id;
+ getList()
+}
+const paginationSearch = (obj) => {
+ page.current = obj.page;
+ page.size = obj.limit;
+ getList();
+};
+const getList = () => {
+ fileListPage({accountId: currentId.value,accountType:accountType.value, ...page}).then(res => {
+ tableData.value = res.data.records;
+ total.value = res.data.total;
+ })
+}
+// 琛ㄦ牸閫夋嫨鏁版嵁
+const handleSelectionChange = (selection) => {
+ selectedRows.value = selection;
+};
+
+// 鍏抽棴寮规
+const closeDia = () => {
+ dialogFormVisible.value = false;
+ emit('close')
+};
+// 涓婁紶鎴愬姛澶勭悊
+function handleUploadSuccess(res, file) {
+ // 濡傛灉涓婁紶鎴愬姛
+ if (res.code == 200) {
+ const fileRow = {}
+ fileRow.name = res.data.originalName
+ fileRow.url = res.data.tempPath
+ uploadFile(fileRow)
+ } else {
+ proxy.$modal.msgError("鏂囦欢涓婁紶澶辫触");
+ }
+}
+function uploadFile(file) {
+ file.accountId = currentId.value;
+ file.accountType = accountType.value;
+ fileAdd(file).then(res => {
+ proxy.$modal.msgSuccess("鏂囦欢涓婁紶鎴愬姛");
+ getList()
+ })
+}
+// 涓婁紶澶辫触澶勭悊
+function handleUploadError() {
+ proxy.$modal.msgError("鏂囦欢涓婁紶澶辫触");
+}
+// 涓嬭浇闄勪欢
+const downLoadFile = (row) => {
+ proxy.$download.name(row.url);
+}
+// 鍒犻櫎
+const handleDelete = () => {
+ let ids = [];
+ if (selectedRows.value.length > 0) {
+ ids = selectedRows.value.map((item) => item.id);
+ } else {
+ proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
+ return;
+ }
+ ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "瀵煎嚭", {
+ confirmButtonText: "纭",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ }).then(() => {
+ fileDel(ids).then((res) => {
+ proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+ getList();
+ });
+ }).catch(() => {
+ proxy.$modal.msg("宸插彇娑�");
+ });
+};
+// 棰勮闄勪欢
+const lookFile = (row) => {
+ filePreviewRef.value.open(row.url)
+}
+
+defineExpose({
+ openDialog,
+});
+</script>
+
+<style scoped>
+
+</style>
\ No newline at end of file
diff --git a/src/views/measurementEquipment/index.vue b/src/views/measurementEquipment/index.vue
new file mode 100644
index 0000000..58bb003
--- /dev/null
+++ b/src/views/measurementEquipment/index.vue
@@ -0,0 +1,270 @@
+<template>
+ <div class="app-container">
+ <div class="search_form">
+ <div>
+ <span class="search_title">褰曞叆鏃ユ湡锛�</span>
+ <el-date-picker
+ v-model="searchForm.recordDate"
+ value-format="YYYY-MM-DD"
+ format="YYYY-MM-DD"
+ type="date"
+ placeholder="璇烽�夋嫨"
+ clearable
+ style="width: 160px"
+ @change="handleQuery"
+ />
+ <span class="search_title ml10">璁¢噺鍣ㄥ叿缂栧彿锛�</span>
+ <el-input v-model="searchForm.code" placeholder="璇疯緭鍏ョ紪鍙�" clearable style="width: 240px" @change="handleQuery"/>
+ <span class="search_title ml10">鐘舵�侊細</span>
+ <el-select v-model="searchForm.status" placeholder="璇烽�夋嫨鐘舵��" @change="handleQuery" style="width: 160px" clearable>
+ <el-option label="鏈夋晥" :value="1"></el-option>
+ <el-option label="閫炬湡" :value="2"></el-option>
+ </el-select>
+ <el-button type="primary" @click="handleQuery" style="margin-left: 10px"
+ >鎼滅储</el-button
+ >
+ </div>
+ <div>
+ <el-button type="primary" @click="openForm('add')">鏂板璁¢噺鍣ㄥ叿</el-button>
+ <el-button type="danger" plain @click="handleDelete">鍒犻櫎</el-button>
+ <el-button @click="handleOut">瀵煎嚭</el-button>
+ </div>
+ </div>
+ <div class="table_list">
+ <PIMTable
+ rowKey="id"
+ :column="tableColumn"
+ :tableData="tableData"
+ :page="page"
+ :isSelection="true"
+ @selection-change="handleSelectionChange"
+ :tableLoading="tableLoading"
+ @pagination="pagination"
+ ></PIMTable>
+ </div>
+ <form-dia ref="formDia" @close="handleQuery"></form-dia>
+ <calibration-dia ref="calibrationDia" @close="handleQuery"></calibration-dia>
+ <files-dia ref="filesDia"></files-dia>
+ </div>
+</template>
+
+<script setup>
+import {onMounted, ref} from "vue";
+import FormDia from "../measurementEquipment/components/formDia.vue";
+import {ElMessageBox} from "element-plus";
+import useUserStore from "../../store/modules/user.js";
+import CalibrationDia from "../measurementEquipment/components/calibrationDia.vue";
+import {
+ measuringInstrumentDelete,
+ measuringInstrumentListPage
+} from "../../api/equipmentManagement/measurementEquipment.js";
+import FilesDia from "./filesDia.vue";
+const { proxy } = getCurrentInstance();
+const userStore = useUserStore()
+
+const data = reactive({
+ searchForm: {
+ recordDate: "",
+ code: "",
+ status: "",
+ },
+});
+const { searchForm } = toRefs(data);
+
+const tableColumn = ref([
+ {
+ label: "鐘舵��",
+ prop: "status",
+ dataType: "tag",
+ formatData: (params) => {
+ if (params == 1) {
+ return "鏈夋晥";
+ } else if (params == 2) {
+ return "閫炬湡";
+ } else {
+ return null;
+ }
+ },
+ formatType: (params) => {
+ if (params == 1) {
+ return "success";
+ } else if (params == 2) {
+ return "danger";
+ } else {
+ return null;
+ }
+ },
+ },
+ {
+ label: "鏈�杩戜竴娆℃瀹氭棩鏈�",
+ prop: "mostDate",
+ width: 130,
+ },
+ {
+ label: "璁¢噺鍣ㄥ叿缂栧彿",
+ prop: "code",
+ width: 150,
+ },
+ {
+ label: "璁¢噺鍣ㄥ叿鍚嶇О",
+ prop: "name",
+ width: 200,
+ },
+ {
+ label: "瑙勬牸鍨嬪彿",
+ prop: "model",
+ width:200
+ },
+ {
+ label: "鏈夋晥鏈�",
+ prop: "valid",
+ width: 130,
+ },
+ {
+ label: "棰勮涓嬫妫�瀹氭棩鏈�",
+ prop: "nextDate",
+ width: 130,
+ },
+ {
+ label: "褰曞叆浜�",
+ prop: "userName",
+ },
+ {
+ label: "褰曞叆鏃ユ湡",
+ prop: "recordDate",
+ width: 130,
+ },
+ {
+ dataType: "action",
+ label: "鎿嶄綔",
+ align: "center",
+ width: '130',
+ fixed: 'right',
+ operation: [
+ {
+ name: "妫�瀹氭牎鍑�",
+ type: "text",
+ clickFun: (row) => {
+ openCalibrationDia("verifying", row);
+ },
+ },
+ // {
+ // name: "闄勪欢",
+ // type: "text",
+ // clickFun: (row) => {
+ // openFilesFormDia(row);
+ // },
+ // },
+ ],
+ },
+]);
+const tableData = ref([]);
+const tableLoading = ref(false);
+const filesDia = ref()
+const page = reactive({
+ current: 1,
+ size: 100,
+ total: 0,
+});
+const selectedRows = ref([]);
+
+// 鎵撳紑闄勪欢寮规
+const openFilesFormDia = (row) => {
+ console.log(row)
+ nextTick(() => {
+ filesDia.value?.openDialog( row,'璁¢噺鍣ㄥ叿鍙拌处')
+ })
+};
+
+// 琛ㄦ牸閫夋嫨鏁版嵁
+const handleSelectionChange = (selection) => {
+ selectedRows.value = selection;
+};
+const formDia = ref()
+const calibrationDia = ref()
+
+// 鏌ヨ鍒楄〃
+/** 鎼滅储鎸夐挳鎿嶄綔 */
+const handleQuery = () => {
+ page.current = 1;
+ getList();
+};
+const pagination = (obj) => {
+ page.current = obj.page;
+ page.size = obj.limit;
+ getList();
+};
+const getList = () => {
+ tableLoading.value = true;
+ measuringInstrumentListPage({ ...searchForm.value, ...page }).then((res) => {
+ tableLoading.value = false;
+ tableData.value = res.data.records;
+ page.total = res.data.total;
+ }).catch((err) => {
+ tableLoading.value = false;
+ })
+};
+
+// 鎵撳紑寮规
+const openForm = (type, row) => {
+ nextTick(() => {
+ formDia.value?.openDialog(type, row)
+ })
+};
+// 鎵撳紑妫�瀹氭牎鍑嗗脊妗�
+const openCalibrationDia = (type, row) => {
+ nextTick(() => {
+ calibrationDia.value?.openDialog(type, row)
+ })
+}
+
+const handleDelete = () => {
+ let ids = [];
+ if (selectedRows.value.length > 0) {
+ ids = selectedRows.value.map((item) => item.id);
+ } else {
+ proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
+ return;
+ }
+ ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "鍒犻櫎鎻愮ず", {
+ confirmButtonText: "纭",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ })
+ .then(() => {
+ tableLoading.value = true;
+ measuringInstrumentDelete(ids)
+ .then((res) => {
+ proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+ getList();
+ })
+ .finally(() => {
+ tableLoading.value = false;
+ });
+ })
+ .catch(() => {
+ proxy.$modal.msg("宸插彇娑�");
+ });
+};
+// 瀵煎嚭
+const handleOut = () => {
+ ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚鍑猴紝鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
+ confirmButtonText: "纭",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ })
+ .then(() => {
+ proxy.download("/measuringInstrumentLedger/export", {}, "璁¢噺鍣ㄥ叿鍙拌处.xlsx");
+ })
+ .catch(() => {
+ proxy.$modal.msg("宸插彇娑�");
+ });
+};
+onMounted(() => {
+ getList();
+});
+</script>
+
+<style scoped>
+
+</style>
\ No newline at end of file
--
Gitblit v1.9.3