From c344439875168ddcae23a0070e735e85717daa06 Mon Sep 17 00:00:00 2001
From: spring <2396852758@qq.com>
Date: 星期四, 05 二月 2026 16:51:11 +0800
Subject: [PATCH] fix: 完成车辆管理、车辆油耗管理、运输任务管理页面编辑
---
src/views/inventoryManagement/vehicleFuelManagement/index.vue | 556 +++++++++++++++++
src/views/inventoryManagement/transportTaskManagement/index.vue | 692 ++++++++++++++++++++++
src/views/inventoryManagement/vehicleManagement/index.vue | 581 ++++++++++++++++++
3 files changed, 1,829 insertions(+), 0 deletions(-)
diff --git a/src/views/inventoryManagement/transportTaskManagement/index.vue b/src/views/inventoryManagement/transportTaskManagement/index.vue
new file mode 100644
index 0000000..1feb54b
--- /dev/null
+++ b/src/views/inventoryManagement/transportTaskManagement/index.vue
@@ -0,0 +1,692 @@
+<template>
+ <div class="app-container">
+ <!-- 缁熻姒傝 -->
+ <el-row :gutter="16" style="margin-bottom: 16px">
+ <el-col :span="6">
+ <el-card shadow="never">
+ <div>鎬讳换鍔℃暟</div>
+ <div style="font-size: 22px; font-weight: 600; margin-top: 4px">
+ {{ totalTasks }}
+ </div>
+ </el-card>
+ </el-col>
+ <el-col :span="6">
+ <el-card shadow="never">
+ <div>杩涜涓换鍔�</div>
+ <div style="font-size: 22px; font-weight: 600; margin-top: 4px">
+ {{ runningTasks }}
+ </div>
+ </el-card>
+ </el-col>
+ <el-col :span="6">
+ <el-card shadow="never">
+ <div>宸插畬鎴愪换鍔�</div>
+ <div style="font-size: 22px; font-weight: 600; margin-top: 4px">
+ {{ finishedTasks }}
+ </div>
+ </el-card>
+ </el-col>
+ <el-col :span="6">
+ <el-card shadow="never">
+ <div>瀹屾垚鐜�</div>
+ <div style="font-size: 22px; font-weight: 600; margin-top: 4px">
+ {{ completionRate }}%
+ </div>
+ </el-card>
+ </el-col>
+ </el-row>
+
+ <!-- 鏌ヨ鏉′欢 -->
+ <div class="search_form">
+ <div>
+ <span class="search_title">浠诲姟缂栧彿锛�</span>
+ <el-input
+ v-model="searchForm.taskNo"
+ style="width: 200px"
+ placeholder="璇疯緭鍏ヤ换鍔$紪鍙�"
+ clearable
+ @keyup.enter.native="handleQuery"
+ />
+
+ <span class="search_title ml10">杞﹁締缂栧彿锛�</span>
+ <el-input
+ v-model="searchForm.vehicleCode"
+ style="width: 200px"
+ placeholder="璇疯緭鍏ヨ溅杈嗙紪鍙�"
+ clearable
+ @keyup.enter.native="handleQuery"
+ />
+
+ <span class="search_title ml10">浠诲姟鏃ユ湡锛�</span>
+ <el-date-picker
+ v-model="searchForm.dateRange"
+ type="daterange"
+ range-separator="鑷�"
+ start-placeholder="寮�濮嬫棩鏈�"
+ end-placeholder="缁撴潫鏃ユ湡"
+ value-format="YYYY-MM-DD"
+ format="YYYY-MM-DD"
+ clearable
+ @change="handleQuery"
+ />
+
+ <span class="search_title ml10">鐘舵�侊細</span>
+ <el-select
+ v-model="searchForm.status"
+ style="width: 140px"
+ placeholder="璇烽�夋嫨浠诲姟鐘舵��"
+ clearable
+ >
+ <el-option
+ v-for="item in statusOptions"
+ :key="item.value"
+ :label="item.label"
+ :value="item.value"
+ />
+ </el-select>
+
+ <el-button type="primary" @click="handleQuery" style="margin-left: 10px">
+ 鎼滅储
+ </el-button>
+ <el-button @click="resetSearch">閲嶇疆</el-button>
+ </div>
+ <div>
+ <el-button type="primary" icon="Plus" @click="openAdd">
+ 鏂板缓杩愯緭浠诲姟
+ </el-button>
+ </div>
+ </div>
+
+ <!-- 琛ㄦ牸 -->
+ <div class="table_list">
+ <el-table
+ :data="tableData"
+ border
+ style="width: 100%"
+ height="calc(100vh - 22em)"
+ :header-cell-style="{ background: '#F0F1F5', color: '#333333' }"
+ :row-class-name="tableRowClassName"
+ >
+ <el-table-column type="index" label="搴忓彿" width="60" align="center" />
+ <el-table-column
+ prop="taskNo"
+ label="浠诲姟缂栧彿"
+ width="150"
+ show-overflow-tooltip
+ />
+ <el-table-column
+ prop="outboundOrderNo"
+ label="鍑哄簱璁㈠崟鍙�"
+ width="180"
+ show-overflow-tooltip
+ />
+ <el-table-column
+ prop="vehicleCode"
+ label="杞﹁締缂栧彿"
+ width="130"
+ show-overflow-tooltip
+ />
+ <el-table-column
+ prop="plateNumber"
+ label="杞︾墝鍙风爜"
+ width="120"
+ show-overflow-tooltip
+ />
+ <el-table-column
+ prop="driverName"
+ label="鍙告満"
+ width="100"
+ show-overflow-tooltip
+ />
+ <el-table-column
+ prop="loadAddress"
+ label="瑁呰揣鍦扮偣"
+ width="160"
+ show-overflow-tooltip
+ />
+ <el-table-column
+ prop="deliveryAddress"
+ label="閫佽揣鍦扮偣"
+ width="160"
+ show-overflow-tooltip
+ />
+ <el-table-column
+ prop="loadTime"
+ label="瑁呰揣鏃堕棿"
+ width="160"
+ show-overflow-tooltip
+ />
+ <el-table-column
+ prop="deliveryTime"
+ label="閫佽揣鏃堕棿"
+ width="160"
+ show-overflow-tooltip
+ />
+ <el-table-column
+ prop="signTime"
+ label="绛炬敹鏃堕棿"
+ width="160"
+ show-overflow-tooltip
+ />
+ <el-table-column label="鐘舵��" width="110" align="center">
+ <template #default="scope">
+ <el-tag :type="statusTagType(scope.row.status)">
+ {{ scope.row.status }}
+ </el-tag>
+ </template>
+ </el-table-column>
+ <el-table-column label="杩涘害" width="150" align="center">
+ <template #default="scope">
+ <el-progress
+ :percentage="scope.row.progress"
+ :status="scope.row.status === '宸插畬鎴�' ? 'success' : undefined"
+ :stroke-width="12"
+ :show-text="false"
+ />
+ <div style="font-size: 12px; margin-top: 4px">
+ {{ scope.row.progress }}%
+ </div>
+ </template>
+ </el-table-column>
+ <el-table-column label="鎿嶄綔" fixed="right" width="160" align="center">
+ <template #default="scope">
+ <el-button
+ type="primary"
+ link
+ size="small"
+ @click="openEdit(scope.row)"
+ >
+ 缂栬緫
+ </el-button>
+ <el-button
+ type="danger"
+ link
+ size="small"
+ @click="removeRow(scope.row)"
+ >
+ 鍒犻櫎
+ </el-button>
+ </template>
+ </el-table-column>
+ </el-table>
+ </div>
+
+ <!-- 鏂板/缂栬緫寮圭獥 -->
+ <el-dialog
+ v-model="dialogVisible"
+ :title="dialogTitle"
+ width="780px"
+ destroy-on-close
+ >
+ <el-form
+ ref="formRef"
+ :model="form"
+ :rules="rules"
+ label-width="110px"
+ label-position="right"
+ >
+ <el-row :gutter="20">
+ <el-col :span="12">
+ <el-form-item label="浠诲姟缂栧彿锛�" prop="taskNo">
+ <el-input
+ v-model="form.taskNo"
+ placeholder="璇疯緭鍏ヤ换鍔$紪鍙�"
+ />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="鍑哄簱璁㈠崟鍙凤細" prop="outboundOrderNo">
+ <el-input
+ v-model="form.outboundOrderNo"
+ placeholder="璇疯緭鍏ュ叧鑱斿嚭搴撹鍗曞彿"
+ />
+ </el-form-item>
+ </el-col>
+ </el-row>
+
+ <el-row :gutter="20">
+ <el-col :span="12">
+ <el-form-item label="杞﹁締缂栧彿锛�" prop="vehicleCode">
+ <el-input
+ v-model="form.vehicleCode"
+ placeholder="璇疯緭鍏ヨ溅杈嗙紪鍙�"
+ />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="杞︾墝鍙风爜锛�" prop="plateNumber">
+ <el-input
+ v-model="form.plateNumber"
+ placeholder="璇疯緭鍏ヨ溅鐗屽彿鐮�"
+ />
+ </el-form-item>
+ </el-col>
+ </el-row>
+
+ <el-row :gutter="20">
+ <el-col :span="12">
+ <el-form-item label="鍙告満锛�" prop="driverName">
+ <el-input
+ v-model="form.driverName"
+ placeholder="璇疯緭鍏ュ徃鏈哄鍚�"
+ />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="鍙告満鐢佃瘽锛�" prop="driverPhone">
+ <el-input
+ v-model="form.driverPhone"
+ placeholder="璇疯緭鍏ュ徃鏈鸿仈绯荤數璇�"
+ />
+ </el-form-item>
+ </el-col>
+ </el-row>
+
+ <el-row :gutter="20">
+ <el-col :span="12">
+ <el-form-item label="瑁呰揣鍦扮偣锛�" prop="loadAddress">
+ <el-input
+ v-model="form.loadAddress"
+ placeholder="璇疯緭鍏ヨ璐у湴鐐�"
+ />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="閫佽揣鍦扮偣锛�" prop="deliveryAddress">
+ <el-input
+ v-model="form.deliveryAddress"
+ placeholder="璇疯緭鍏ラ�佽揣鍦扮偣"
+ />
+ </el-form-item>
+ </el-col>
+ </el-row>
+
+ <el-row :gutter="20">
+ <el-col :span="8">
+ <el-form-item label="瑁呰揣鏃堕棿锛�" prop="loadTime">
+ <el-date-picker
+ v-model="form.loadTime"
+ type="datetime"
+ value-format="YYYY-MM-DD HH:mm:ss"
+ format="YYYY-MM-DD HH:mm"
+ placeholder="璇烽�夋嫨瑁呰揣鏃堕棿"
+ style="width: 100%"
+ />
+ </el-form-item>
+ </el-col>
+ <el-col :span="8">
+ <el-form-item label="閫佽揣鏃堕棿锛�" prop="deliveryTime">
+ <el-date-picker
+ v-model="form.deliveryTime"
+ type="datetime"
+ value-format="YYYY-MM-DD HH:mm:ss"
+ format="YYYY-MM-DD HH:mm"
+ placeholder="璇烽�夋嫨閫佽揣鏃堕棿"
+ style="width: 100%"
+ />
+ </el-form-item>
+ </el-col>
+ <el-col :span="8">
+ <el-form-item label="绛炬敹鏃堕棿锛�" prop="signTime">
+ <el-date-picker
+ v-model="form.signTime"
+ type="datetime"
+ value-format="YYYY-MM-DD HH:mm:ss"
+ format="YYYY-MM-DD HH:mm"
+ placeholder="璇烽�夋嫨绛炬敹鏃堕棿"
+ style="width: 100%"
+ />
+ </el-form-item>
+ </el-col>
+ </el-row>
+
+ <el-row :gutter="20">
+ <el-col :span="12">
+ <el-form-item label="鐘舵�侊細" prop="status">
+ <el-select v-model="form.status" placeholder="璇烽�夋嫨浠诲姟鐘舵��">
+ <el-option
+ v-for="item in statusOptions"
+ :key="item.value"
+ :label="item.label"
+ :value="item.value"
+ />
+ </el-select>
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="璁″垝鏃ユ湡锛�" prop="planDate">
+ <el-date-picker
+ v-model="form.planDate"
+ type="date"
+ value-format="YYYY-MM-DD"
+ format="YYYY-MM-DD"
+ placeholder="璇烽�夋嫨璁″垝鏃ユ湡"
+ style="width: 100%"
+ />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ </el-form>
+
+ <template #footer>
+ <div class="dialog-footer">
+ <el-button @click="handleCancel">鍙� 娑�</el-button>
+ <el-button type="primary" @click="handleSubmit">淇� 瀛�</el-button>
+ </div>
+ </template>
+ </el-dialog>
+ </div>
+</template>
+
+<script setup>
+import { ref, reactive, computed, onMounted } from "vue";
+import { ElMessage, ElMessageBox } from "element-plus";
+
+// 妯℃嫙杩愯緭浠诲姟鏁版嵁
+const rawTasks = ref([
+ {
+ id: 1,
+ taskNo: "T2024-1201-001",
+ outboundOrderNo: "OUT-2024-1201-1001",
+ vehicleCode: "CL-202401",
+ plateNumber: "绮12345",
+ driverName: "寮犲笀鍌�",
+ driverPhone: "13800000001",
+ loadAddress: "娣卞湷浠撳簱A鍖�",
+ deliveryAddress: "骞垮窞瀹㈡埛涓�閮�",
+ planDate: "2024-12-01",
+ loadTime: "2024-12-01 09:00:00",
+ deliveryTime: "2024-12-01 14:30:00",
+ signTime: "2024-12-01 15:00:00",
+ status: "宸插畬鎴�",
+ },
+ {
+ id: 2,
+ taskNo: "T2024-1201-002",
+ outboundOrderNo: "OUT-2024-1201-1002",
+ vehicleCode: "CL-202402",
+ plateNumber: "绮67890",
+ driverName: "鏉庡笀鍌�",
+ driverPhone: "13800000002",
+ loadAddress: "娣卞湷浠撳簱B鍖�",
+ deliveryAddress: "涓滆帪瀹㈡埛浜岄儴",
+ planDate: "2024-12-01",
+ loadTime: "2024-12-01 10:00:00",
+ deliveryTime: "2024-12-01 13:00:00",
+ signTime: "",
+ status: "杩愯緭涓�",
+ },
+ {
+ id: 3,
+ taskNo: "T2024-1202-001",
+ outboundOrderNo: "OUT-2024-1202-1003",
+ vehicleCode: "CL-202401",
+ plateNumber: "绮12345",
+ driverName: "寮犲笀鍌�",
+ driverPhone: "13800000001",
+ loadAddress: "娣卞湷浠撳簱A鍖�",
+ deliveryAddress: "浣涘北瀹㈡埛涓夐儴",
+ planDate: "2024-12-02",
+ loadTime: "2024-12-02 08:30:00",
+ deliveryTime: "",
+ signTime: "",
+ status: "寰呭彂杞�",
+ },
+ {
+ id: 4,
+ taskNo: "T2024-1203-001",
+ outboundOrderNo: "OUT-2024-1203-1004",
+ vehicleCode: "CL-202403",
+ plateNumber: "绮11223",
+ driverName: "鐜嬪笀鍌�",
+ driverPhone: "13800000003",
+ loadAddress: "娣卞湷浠撳簱C鍖�",
+ deliveryAddress: "鎯犲窞瀹㈡埛鍥涢儴",
+ planDate: "2024-12-03",
+ loadTime: "",
+ deliveryTime: "",
+ signTime: "",
+ status: "鏈紑濮�",
+ },
+]);
+
+// 鐘舵�佹灇涓�
+const statusOptions = [
+ { label: "鏈紑濮�", value: "鏈紑濮�" },
+ { label: "寰呭彂杞�", value: "寰呭彂杞�" },
+ { label: "杩愯緭涓�", value: "杩愯緭涓�" },
+ { label: "寰呯鏀�", value: "寰呯鏀�" },
+ { label: "宸插畬鎴�", value: "宸插畬鎴�" },
+];
+
+// 鏌ヨ琛ㄥ崟
+const searchForm = reactive({
+ taskNo: "",
+ vehicleCode: "",
+ dateRange: [],
+ status: "",
+});
+
+// 琛ㄦ牸鏁版嵁锛堝甫杩涘害绛夎绠楀瓧娈碉級
+const tableData = ref([]);
+
+// 缁熻
+const totalTasks = computed(() => rawTasks.value.length);
+const finishedTasks = computed(
+ () => rawTasks.value.filter((t) => t.status === "宸插畬鎴�").length
+);
+const runningTasks = computed(
+ () =>
+ rawTasks.value.filter((t) =>
+ ["寰呭彂杞�", "杩愯緭涓�", "寰呯鏀�"].includes(t.status)
+ ).length
+);
+const completionRate = computed(() => {
+ if (!totalTasks.value) return 0;
+ return Math.round((finishedTasks.value / totalTasks.value) * 100);
+});
+
+// 璁$畻鍗曟潯浠诲姟杩涘害
+const computeProgress = (task) => {
+ if (task.status === "宸插畬鎴�" || task.signTime) return 100;
+ if (task.status === "寰呯鏀�" || task.deliveryTime) return 80;
+ if (task.status === "杩愯緭涓�") return 60;
+ if (task.status === "寰呭彂杞�" || task.loadTime) return 30;
+ if (task.status === "鏈紑濮�") return 0;
+ return 0;
+};
+
+// 鐘舵�� tag 鏍峰紡
+const statusTagType = (status) => {
+ if (status === "宸插畬鎴�") return "success";
+ if (status === "杩愯緭涓�") return "warning";
+ if (status === "寰呯鏀�" || status === "寰呭彂杞�") return "info";
+ return "default";
+};
+
+// 閲嶇畻琛ㄦ牸鏁版嵁
+const recomputeTable = () => {
+ const filtered = rawTasks.value
+ .filter((t) => {
+ if (searchForm.taskNo && !t.taskNo.includes(searchForm.taskNo.trim())) {
+ return false;
+ }
+ if (
+ searchForm.vehicleCode &&
+ !t.vehicleCode.includes(searchForm.vehicleCode.trim())
+ ) {
+ return false;
+ }
+ if (searchForm.status && t.status !== searchForm.status) {
+ return false;
+ }
+ if (Array.isArray(searchForm.dateRange) && searchForm.dateRange.length === 2) {
+ const [start, end] = searchForm.dateRange;
+ if (!t.planDate || t.planDate < start || t.planDate > end) {
+ return false;
+ }
+ }
+ return true;
+ })
+ .map((t) => ({
+ ...t,
+ progress: computeProgress(t),
+ }));
+
+ tableData.value = filtered;
+};
+
+// 鏌ヨ
+const handleQuery = () => {
+ recomputeTable();
+};
+
+const resetSearch = () => {
+ searchForm.taskNo = "";
+ searchForm.vehicleCode = "";
+ searchForm.dateRange = [];
+ searchForm.status = "";
+ recomputeTable();
+};
+
+// 琛屾牱寮�
+const tableRowClassName = ({ row }) => {
+ if (row.status === "宸插畬鎴�") {
+ return "row-finished";
+ }
+ if (row.status === "杩愯緭涓�") {
+ return "row-running";
+ }
+ return "";
+};
+
+// 寮圭獥 & 琛ㄥ崟
+const dialogVisible = ref(false);
+const dialogTitle = ref("鏂板缓杩愯緭浠诲姟");
+const isEdit = ref(false);
+const formRef = ref(null);
+const form = reactive({
+ id: null,
+ taskNo: "",
+ outboundOrderNo: "",
+ vehicleCode: "",
+ plateNumber: "",
+ driverName: "",
+ driverPhone: "",
+ loadAddress: "",
+ deliveryAddress: "",
+ planDate: "",
+ loadTime: "",
+ deliveryTime: "",
+ signTime: "",
+ status: "鏈紑濮�",
+});
+
+const rules = {
+ taskNo: [{ required: true, message: "璇疯緭鍏ヤ换鍔$紪鍙�", trigger: "blur" }],
+ outboundOrderNo: [
+ { required: true, message: "璇疯緭鍏ュ嚭搴撹鍗曞彿", trigger: "blur" },
+ ],
+ vehicleCode: [{ required: true, message: "璇疯緭鍏ヨ溅杈嗙紪鍙�", trigger: "blur" }],
+ plateNumber: [{ required: true, message: "璇疯緭鍏ヨ溅鐗屽彿鐮�", trigger: "blur" }],
+ driverName: [{ required: true, message: "璇疯緭鍏ュ徃鏈哄鍚�", trigger: "blur" }],
+ loadAddress: [{ required: true, message: "璇疯緭鍏ヨ璐у湴鐐�", trigger: "blur" }],
+ deliveryAddress: [
+ { required: true, message: "璇疯緭鍏ラ�佽揣鍦扮偣", trigger: "blur" },
+ ],
+ planDate: [{ required: true, message: "璇烽�夋嫨璁″垝鏃ユ湡", trigger: "change" }],
+};
+
+// 鏂板缓
+const openAdd = () => {
+ dialogTitle.value = "鏂板缓杩愯緭浠诲姟";
+ isEdit.value = false;
+ Object.assign(form, {
+ id: null,
+ taskNo: "",
+ outboundOrderNo: "",
+ vehicleCode: "",
+ plateNumber: "",
+ driverName: "",
+ driverPhone: "",
+ loadAddress: "",
+ deliveryAddress: "",
+ planDate: "",
+ loadTime: "",
+ deliveryTime: "",
+ signTime: "",
+ status: "鏈紑濮�",
+ });
+ dialogVisible.value = true;
+};
+
+// 缂栬緫
+const openEdit = (row) => {
+ dialogTitle.value = "缂栬緫杩愯緭浠诲姟";
+ isEdit.value = true;
+ Object.assign(form, row);
+ dialogVisible.value = true;
+};
+
+// 淇濆瓨
+const handleSubmit = () => {
+ if (!formRef.value) return;
+ formRef.value.validate((valid) => {
+ if (!valid) return;
+
+ if (isEdit.value) {
+ const index = rawTasks.value.findIndex((t) => t.id === form.id);
+ if (index !== -1) {
+ rawTasks.value[index] = { ...form };
+ }
+ ElMessage.success("杩愯緭浠诲姟宸叉洿鏂�");
+ } else {
+ const newId = rawTasks.value.length
+ ? Math.max(...rawTasks.value.map((t) => t.id)) + 1
+ : 1;
+ rawTasks.value.push({ ...form, id: newId });
+ ElMessage.success("杩愯緭浠诲姟宸叉柊澧�");
+ }
+ dialogVisible.value = false;
+ recomputeTable();
+ });
+};
+
+const handleCancel = () => {
+ dialogVisible.value = false;
+};
+
+// 鍒犻櫎
+const removeRow = (row) => {
+ ElMessageBox.confirm("鏄惁纭鍒犻櫎璇ヨ繍杈撲换鍔★紵", "鍒犻櫎鎻愮ず", {
+ confirmButtonText: "纭",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ })
+ .then(() => {
+ rawTasks.value = rawTasks.value.filter((t) => t.id !== row.id);
+ recomputeTable();
+ ElMessage.success("鍒犻櫎鎴愬姛");
+ })
+ .catch(() => {});
+};
+
+onMounted(() => {
+ recomputeTable();
+});
+</script>
+
+<style scoped lang="scss">
+.dialog-footer {
+ text-align: right;
+}
+
+::v-deep(.row-finished) {
+ background-color: #f6ffed;
+}
+
+::v-deep(.row-running) {
+ background-color: #fffbe6;
+}
+</style>
+
diff --git a/src/views/inventoryManagement/vehicleFuelManagement/index.vue b/src/views/inventoryManagement/vehicleFuelManagement/index.vue
new file mode 100644
index 0000000..8579cba
--- /dev/null
+++ b/src/views/inventoryManagement/vehicleFuelManagement/index.vue
@@ -0,0 +1,556 @@
+<template>
+ <div class="app-container">
+ <!-- 鏌ヨ鏉′欢 -->
+ <div class="search_form">
+ <div>
+ <span class="search_title">杞﹁締缂栧彿锛�</span>
+ <el-input
+ v-model="searchForm.vehicleCode"
+ style="width: 200px"
+ placeholder="璇疯緭鍏ヨ溅杈嗙紪鍙�"
+ clearable
+ @keyup.enter.native="handleQuery"
+ />
+
+ <span class="search_title ml10">鍔犳补鏃堕棿锛�</span>
+ <el-date-picker
+ v-model="searchForm.dateRange"
+ type="daterange"
+ range-separator="鑷�"
+ start-placeholder="寮�濮嬫棩鏈�"
+ end-placeholder="缁撴潫鏃ユ湡"
+ value-format="YYYY-MM-DD"
+ format="YYYY-MM-DD"
+ clearable
+ @change="handleQuery"
+ />
+
+ <el-button type="primary" @click="handleQuery" style="margin-left: 10px">
+ 鎼滅储
+ </el-button>
+ <el-button @click="resetSearch">閲嶇疆</el-button>
+ </div>
+ <div>
+ <el-button type="primary" icon="Plus" @click="openAdd">
+ 鏂板鍔犳补璁板綍
+ </el-button>
+ </div>
+ </div>
+
+ <!-- 琛ㄦ牸 -->
+ <div class="table_list">
+ <el-table
+ :data="tableData"
+ border
+ style="width: 100%"
+ height="calc(100vh - 18.5em)"
+ :header-cell-style="{ background: '#F0F1F5', color: '#333333' }"
+ :row-class-name="tableRowClassName"
+ >
+ <el-table-column type="index" label="搴忓彿" width="60" align="center" />
+ <el-table-column
+ prop="vehicleCode"
+ label="杞﹁締缂栧彿"
+ width="130"
+ show-overflow-tooltip
+ />
+ <el-table-column
+ prop="plateNumber"
+ label="杞︾墝鍙风爜"
+ width="120"
+ show-overflow-tooltip
+ />
+ <el-table-column
+ prop="fuelDate"
+ label="鍔犳补鏃ユ湡"
+ width="120"
+ show-overflow-tooltip
+ />
+ <el-table-column
+ prop="gunNo"
+ label="娌规灙鍙�"
+ width="90"
+ align="center"
+ />
+ <el-table-column
+ prop="amount"
+ label="閲戦(鍏�)"
+ width="100"
+ align="right"
+ >
+ <template #default="scope">
+ <span>{{ scope.row.amount?.toFixed(2) }}</span>
+ </template>
+ </el-table-column>
+ <el-table-column
+ prop="liters"
+ label="鍗囨暟(L)"
+ width="90"
+ align="right"
+ >
+ <template #default="scope">
+ <span>{{ scope.row.liters?.toFixed(2) }}</span>
+ </template>
+ </el-table-column>
+ <el-table-column
+ prop="startMileage"
+ label="璧峰閲岀▼(km)"
+ width="120"
+ align="right"
+ />
+ <el-table-column
+ prop="endMileage"
+ label="缁撴潫閲岀▼(km)"
+ width="120"
+ align="right"
+ />
+ <el-table-column
+ prop="distance"
+ label="琛岄┒閲岀▼(km)"
+ width="120"
+ align="right"
+ />
+ <el-table-column
+ prop="fuelConsumption"
+ label="娌硅��(L/100km)"
+ width="130"
+ align="center"
+ >
+ <template #default="scope">
+ <span
+ :style="scope.row.isAbnormal ? 'color:#F56C6C;font-weight:600;' : ''"
+ >
+ {{ scope.row.fuelConsumption != null ? scope.row.fuelConsumption.toFixed(2) : '-' }}
+ </span>
+ </template>
+ </el-table-column>
+ <el-table-column
+ prop="avgConsumption"
+ label="杞﹁締骞冲潎娌硅��"
+ width="130"
+ align="center"
+ >
+ <template #default="scope">
+ <span>
+ {{ scope.row.avgConsumption != null ? scope.row.avgConsumption.toFixed(2) : '-' }}
+ </span>
+ </template>
+ </el-table-column>
+ <el-table-column label="寮傚父棰勮" width="100" align="center">
+ <template #default="scope">
+ <el-tag v-if="scope.row.isAbnormal" type="danger" size="small">
+ 寮傚父
+ </el-tag>
+ <span v-else>-</span>
+ </template>
+ </el-table-column>
+ <el-table-column label="鎿嶄綔" fixed="right" width="140" align="center">
+ <template #default="scope">
+ <el-button
+ type="primary"
+ link
+ size="small"
+ @click="openEdit(scope.row)"
+ >
+ 缂栬緫
+ </el-button>
+ <el-button
+ type="danger"
+ link
+ size="small"
+ @click="removeRow(scope.row)"
+ >
+ 鍒犻櫎
+ </el-button>
+ </template>
+ </el-table-column>
+ </el-table>
+ </div>
+
+ <!-- 鏂板/缂栬緫寮圭獥 -->
+ <el-dialog
+ v-model="dialogVisible"
+ :title="dialogTitle"
+ width="640px"
+ destroy-on-close
+ >
+ <el-form
+ ref="formRef"
+ :model="form"
+ :rules="rules"
+ label-width="110px"
+ label-position="right"
+ >
+ <el-row :gutter="20">
+ <el-col :span="12">
+ <el-form-item label="杞﹁締缂栧彿锛�" prop="vehicleCode">
+ <el-input
+ v-model="form.vehicleCode"
+ placeholder="璇疯緭鍏ヨ溅杈嗙紪鍙�"
+ />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="杞︾墝鍙风爜锛�" prop="plateNumber">
+ <el-input
+ v-model="form.plateNumber"
+ placeholder="璇疯緭鍏ヨ溅鐗屽彿鐮�"
+ />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="20">
+ <el-col :span="12">
+ <el-form-item label="鍔犳补鏃ユ湡锛�" prop="fuelDate">
+ <el-date-picker
+ v-model="form.fuelDate"
+ type="date"
+ value-format="YYYY-MM-DD"
+ format="YYYY-MM-DD"
+ placeholder="璇烽�夋嫨鍔犳补鏃ユ湡"
+ style="width: 100%"
+ />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="娌规灙鍙凤細" prop="gunNo">
+ <el-input
+ v-model="form.gunNo"
+ placeholder="璇疯緭鍏ユ补鏋彿"
+ />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="20">
+ <el-col :span="12">
+ <el-form-item label="閲戦(鍏�)锛�" prop="amount">
+ <el-input-number
+ v-model="form.amount"
+ :min="0"
+ :step="0.01"
+ :precision="2"
+ placeholder="璇疯緭鍏ラ噾棰�"
+ style="width: 100%"
+ />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="鍗囨暟(L)锛�" prop="liters">
+ <el-input-number
+ v-model="form.liters"
+ :min="0"
+ :step="0.01"
+ :precision="2"
+ placeholder="璇疯緭鍏ュ崌鏁�"
+ style="width: 100%"
+ />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="20">
+ <el-col :span="12">
+ <el-form-item label="璧峰閲岀▼(km)锛�" prop="startMileage">
+ <el-input-number
+ v-model="form.startMileage"
+ :min="0"
+ :step="1"
+ placeholder="璇疯緭鍏ヨ捣濮嬮噷绋�"
+ style="width: 100%"
+ />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="缁撴潫閲岀▼(km)锛�" prop="endMileage">
+ <el-input-number
+ v-model="form.endMileage"
+ :min="0"
+ :step="1"
+ placeholder="璇疯緭鍏ョ粨鏉熼噷绋�"
+ style="width: 100%"
+ />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ </el-form>
+ <template #footer>
+ <div class="dialog-footer">
+ <el-button @click="handleCancel">鍙� 娑�</el-button>
+ <el-button type="primary" @click="handleSubmit">淇� 瀛�</el-button>
+ </div>
+ </template>
+ </el-dialog>
+ </div>
+</template>
+
+<script setup>
+import { ref, reactive, onMounted } from "vue";
+import { ElMessage, ElMessageBox } from "element-plus";
+
+// 妯℃嫙鍔犳补璁板綍鏁版嵁
+const rawRecords = ref([
+ {
+ id: 1,
+ vehicleCode: "CL-202401",
+ plateNumber: "绮12345",
+ fuelDate: "2024-12-01",
+ gunNo: "01",
+ amount: 500,
+ liters: 70,
+ startMileage: 12000,
+ endMileage: 12600,
+ },
+ {
+ id: 2,
+ vehicleCode: "CL-202401",
+ plateNumber: "绮12345",
+ fuelDate: "2024-12-15",
+ gunNo: "02",
+ amount: 520,
+ liters: 72,
+ startMileage: 12600,
+ endMileage: 13250,
+ },
+ {
+ id: 3,
+ vehicleCode: "CL-202402",
+ plateNumber: "绮67890",
+ fuelDate: "2024-12-05",
+ gunNo: "03",
+ amount: 430,
+ liters: 60,
+ startMileage: 8000,
+ endMileage: 8520,
+ },
+ {
+ id: 4,
+ vehicleCode: "CL-202402",
+ plateNumber: "绮67890",
+ fuelDate: "2024-12-20",
+ gunNo: "01",
+ amount: 450,
+ liters: 63,
+ startMileage: 8520,
+ endMileage: 9000,
+ },
+ {
+ id: 5,
+ vehicleCode: "CL-202401",
+ plateNumber: "绮12345",
+ fuelDate: "2025-01-05",
+ gunNo: "01",
+ amount: 700,
+ liters: 90,
+ startMileage: 13250,
+ endMileage: 13600, // 鏄庢樉寮傚父娌硅��
+ },
+]);
+
+// 鏌ヨ琛ㄥ崟
+const searchForm = reactive({
+ vehicleCode: "",
+ dateRange: [],
+});
+
+// 琛ㄦ牸鏁版嵁锛堝寘鍚绠楀瓧娈碉級
+const tableData = ref([]);
+
+// 寮圭獥 & 琛ㄥ崟
+const dialogVisible = ref(false);
+const dialogTitle = ref("鏂板鍔犳补璁板綍");
+const isEdit = ref(false);
+const formRef = ref(null);
+const form = reactive({
+ id: null,
+ vehicleCode: "",
+ plateNumber: "",
+ fuelDate: "",
+ gunNo: "",
+ amount: null,
+ liters: null,
+ startMileage: null,
+ endMileage: null,
+});
+
+const rules = {
+ vehicleCode: [{ required: true, message: "璇疯緭鍏ヨ溅杈嗙紪鍙�", trigger: "blur" }],
+ plateNumber: [{ required: true, message: "璇疯緭鍏ヨ溅鐗屽彿鐮�", trigger: "blur" }],
+ fuelDate: [{ required: true, message: "璇烽�夋嫨鍔犳补鏃ユ湡", trigger: "change" }],
+ gunNo: [{ required: true, message: "璇疯緭鍏ユ补鏋彿", trigger: "blur" }],
+ amount: [{ required: true, message: "璇疯緭鍏ラ噾棰�", trigger: "blur" }],
+ liters: [{ required: true, message: "璇疯緭鍏ュ崌鏁�", trigger: "blur" }],
+ startMileage: [{ required: true, message: "璇疯緭鍏ヨ捣濮嬮噷绋�", trigger: "blur" }],
+ endMileage: [{ required: true, message: "璇疯緭鍏ョ粨鏉熼噷绋�", trigger: "blur" }],
+};
+
+// 閲嶆柊璁$畻娌硅�椼�佸钩鍧囨补鑰楀拰寮傚父棰勮
+const recomputeTable = () => {
+ const records = rawRecords.value;
+
+ // 1. 鍏堟寜杞﹁締缁熻骞冲潎娌硅��
+ const stats = {};
+ records.forEach((r) => {
+ const distance = r.endMileage - r.startMileage;
+ if (distance <= 0 || !r.liters) return;
+ const cons = (r.liters / distance) * 100; // L/100km
+ if (!stats[r.vehicleCode]) {
+ stats[r.vehicleCode] = { totalCons: 0, count: 0 };
+ }
+ stats[r.vehicleCode].totalCons += cons;
+ stats[r.vehicleCode].count += 1;
+ });
+
+ const avgMap = {};
+ Object.keys(stats).forEach((key) => {
+ avgMap[key] = stats[key].totalCons / stats[key].count;
+ });
+
+ // 2. 鎸夌瓫閫夋潯浠惰繃婊ゅ苟琛ュ厖璁$畻瀛楁
+ const filtered = records
+ .filter((r) => {
+ if (
+ searchForm.vehicleCode &&
+ !r.vehicleCode.includes(searchForm.vehicleCode.trim())
+ ) {
+ return false;
+ }
+ if (Array.isArray(searchForm.dateRange) && searchForm.dateRange.length === 2) {
+ const [start, end] = searchForm.dateRange;
+ if (r.fuelDate < start || r.fuelDate > end) {
+ return false;
+ }
+ }
+ return true;
+ })
+ .map((r) => {
+ const distance = r.endMileage - r.startMileage;
+ const fuelConsumption =
+ distance > 0 && r.liters
+ ? (r.liters / distance) * 100
+ : null;
+ const avgConsumption =
+ avgMap[r.vehicleCode] != null ? avgMap[r.vehicleCode] : null;
+ const isAbnormal =
+ avgConsumption != null &&
+ fuelConsumption != null &&
+ fuelConsumption > avgConsumption * 1.2;
+
+ return {
+ ...r,
+ distance,
+ fuelConsumption,
+ avgConsumption,
+ isAbnormal,
+ };
+ });
+
+ tableData.value = filtered;
+};
+
+// 鏌ヨ
+const handleQuery = () => {
+ recomputeTable();
+};
+
+const resetSearch = () => {
+ searchForm.vehicleCode = "";
+ searchForm.dateRange = [];
+ recomputeTable();
+};
+
+// 琛屾牱寮忥紙寮傚父楂樹寒锛�
+const tableRowClassName = ({ row }) => {
+ if (row.isAbnormal) {
+ return "row-abnormal";
+ }
+ return "";
+};
+
+// 鏂板
+const openAdd = () => {
+ dialogTitle.value = "鏂板鍔犳补璁板綍";
+ isEdit.value = false;
+ Object.assign(form, {
+ id: null,
+ vehicleCode: "",
+ plateNumber: "",
+ fuelDate: "",
+ gunNo: "",
+ amount: null,
+ liters: null,
+ startMileage: null,
+ endMileage: null,
+ });
+ dialogVisible.value = true;
+};
+
+// 缂栬緫
+const openEdit = (row) => {
+ dialogTitle.value = "缂栬緫鍔犳补璁板綍";
+ isEdit.value = true;
+ Object.assign(form, row);
+ dialogVisible.value = true;
+};
+
+// 淇濆瓨
+const handleSubmit = () => {
+ if (!formRef.value) return;
+ formRef.value.validate((valid) => {
+ if (!valid) return;
+
+ if (form.endMileage <= form.startMileage) {
+ ElMessage.warning("缁撴潫閲岀▼蹇呴』澶т簬璧峰閲岀▼");
+ return;
+ }
+
+ if (isEdit.value) {
+ const index = rawRecords.value.findIndex((r) => r.id === form.id);
+ if (index !== -1) {
+ rawRecords.value[index] = { ...form };
+ }
+ ElMessage.success("鍔犳补璁板綍宸叉洿鏂�");
+ } else {
+ const newId = rawRecords.value.length
+ ? Math.max(...rawRecords.value.map((r) => r.id)) + 1
+ : 1;
+ rawRecords.value.push({ ...form, id: newId });
+ ElMessage.success("鍔犳补璁板綍宸叉柊澧�");
+ }
+ dialogVisible.value = false;
+ recomputeTable();
+ });
+};
+
+const handleCancel = () => {
+ dialogVisible.value = false;
+};
+
+// 鍒犻櫎
+const removeRow = (row) => {
+ ElMessageBox.confirm("鏄惁纭鍒犻櫎璇ュ姞娌硅褰曪紵", "鍒犻櫎鎻愮ず", {
+ confirmButtonText: "纭",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ })
+ .then(() => {
+ rawRecords.value = rawRecords.value.filter((r) => r.id !== row.id);
+ recomputeTable();
+ ElMessage.success("鍒犻櫎鎴愬姛");
+ })
+ .catch(() => {});
+};
+
+onMounted(() => {
+ recomputeTable();
+});
+</script>
+
+<style scoped lang="scss">
+.dialog-footer {
+ text-align: right;
+}
+
+::v-deep(.row-abnormal) {
+ background-color: #fff5f5;
+}
+</style>
+
diff --git a/src/views/inventoryManagement/vehicleManagement/index.vue b/src/views/inventoryManagement/vehicleManagement/index.vue
new file mode 100644
index 0000000..1e383c6
--- /dev/null
+++ b/src/views/inventoryManagement/vehicleManagement/index.vue
@@ -0,0 +1,581 @@
+<template>
+ <div class="app-container">
+ <!-- 鏌ヨ鏉′欢 -->
+ <div class="search_form">
+ <div>
+ <span class="search_title">杞︾墝鍙风爜锛�</span>
+ <el-input
+ v-model="searchForm.plateNumber"
+ style="width: 180px"
+ placeholder="璇疯緭鍏ヨ溅鐗屽彿鐮�"
+ clearable
+ @keyup.enter.native="handleQuery"
+ />
+
+ <span class="search_title ml10">杞﹁締绫诲瀷锛�</span>
+ <el-select
+ v-model="searchForm.vehicleType"
+ style="width: 160px"
+ placeholder="璇烽�夋嫨杞﹁締绫诲瀷"
+ clearable
+ >
+ <el-option
+ v-for="item in vehicleTypeOptions"
+ :key="item.value"
+ :label="item.label"
+ :value="item.value"
+ />
+ </el-select>
+
+ <span class="search_title ml10">鎵�灞為儴闂細</span>
+ <el-select
+ v-model="searchForm.department"
+ style="width: 160px"
+ placeholder="璇烽�夋嫨鎵�灞為儴闂�"
+ clearable
+ >
+ <el-option
+ v-for="item in departmentOptions"
+ :key="item.value"
+ :label="item.label"
+ :value="item.value"
+ />
+ </el-select>
+
+ <span class="search_title ml10">鐘舵�侊細</span>
+ <el-select
+ v-model="searchForm.status"
+ style="width: 140px"
+ placeholder="璇烽�夋嫨鐘舵��"
+ clearable
+ >
+ <el-option
+ v-for="item in statusOptions"
+ :key="item.value"
+ :label="item.label"
+ :value="item.value"
+ />
+ </el-select>
+
+ <span class="search_title ml10">褰掓。鐘舵�侊細</span>
+ <el-select
+ v-model="searchForm.archived"
+ style="width: 140px"
+ placeholder="璇烽�夋嫨褰掓。鐘舵��"
+ clearable
+ >
+ <el-option label="鏈綊妗�" value="false" />
+ <el-option label="宸插綊妗�" value="true" />
+ </el-select>
+
+ <el-button type="primary" @click="handleQuery" style="margin-left: 10px">
+ 鎼滅储
+ </el-button>
+ <el-button @click="resetSearch">閲嶇疆</el-button>
+ </div>
+ <div>
+ <el-button type="primary" icon="Plus" @click="openAdd">鏂板杞﹁締</el-button>
+ </div>
+ </div>
+
+ <!-- 琛ㄦ牸 -->
+ <div class="table_list">
+ <el-table
+ :data="tableData"
+ border
+ style="width: 100%"
+ height="calc(100vh - 18.5em)"
+ :header-cell-style="{ background: '#F0F1F5', color: '#333333' }"
+ >
+ <el-table-column type="index" label="搴忓彿" width="60" align="center" />
+ <el-table-column
+ prop="vehicleCode"
+ label="杞﹁締缂栧彿"
+ width="140"
+ show-overflow-tooltip
+ />
+ <el-table-column
+ prop="plateNumber"
+ label="杞︾墝鍙风爜"
+ width="120"
+ show-overflow-tooltip
+ />
+ <el-table-column
+ prop="vehicleType"
+ label="杞﹁締绫诲瀷"
+ width="120"
+ show-overflow-tooltip
+ />
+ <el-table-column
+ prop="department"
+ label="鎵�灞為儴闂�"
+ width="140"
+ show-overflow-tooltip
+ />
+ <el-table-column
+ prop="purchaseDate"
+ label="璐疆鏃ユ湡"
+ width="120"
+ show-overflow-tooltip
+ />
+ <el-table-column
+ prop="licenseNumber"
+ label="琛岄┒璇佺紪鍙�"
+ width="160"
+ show-overflow-tooltip
+ />
+ <el-table-column
+ prop="licenseIssueDate"
+ label="鍙戣瘉鏃ユ湡"
+ width="120"
+ show-overflow-tooltip
+ />
+ <el-table-column
+ prop="licenseExpireDate"
+ label="鍒版湡鏃ユ湡"
+ width="120"
+ show-overflow-tooltip
+ />
+ <el-table-column label="鐘舵��" width="100" align="center">
+ <template #default="scope">
+ <el-tag :type="statusTagType(scope.row.status)">
+ {{ scope.row.status }}
+ </el-tag>
+ </template>
+ </el-table-column>
+ <el-table-column label="褰掓。鐘舵��" width="100" align="center">
+ <template #default="scope">
+ <el-tag :type="scope.row.archived ? 'info' : 'success'">
+ {{ scope.row.archived ? '宸插綊妗�' : '鏈綊妗�' }}
+ </el-tag>
+ </template>
+ </el-table-column>
+ <el-table-column label="鎿嶄綔" fixed="right" width="220" align="center">
+ <template #default="scope">
+ <el-button
+ type="primary"
+ link
+ size="small"
+ @click="openEdit(scope.row)"
+ >
+ 缂栬緫
+ </el-button>
+ <el-button
+ type="warning"
+ link
+ size="small"
+ :disabled="scope.row.archived"
+ @click="archiveRow(scope.row)"
+ >
+ 褰掓。
+ </el-button>
+ <el-button
+ type="danger"
+ link
+ size="small"
+ @click="removeRow(scope.row)"
+ >
+ 鍒犻櫎
+ </el-button>
+ </template>
+ </el-table-column>
+ </el-table>
+ </div>
+
+ <!-- 鏂板/缂栬緫寮圭獥 -->
+ <el-dialog
+ v-model="dialogVisible"
+ :title="dialogTitle"
+ width="600px"
+ destroy-on-close
+ >
+ <el-form
+ ref="formRef"
+ :model="form"
+ :rules="rules"
+ label-width="100px"
+ label-position="right"
+ >
+ <el-row :gutter="20">
+ <el-col :span="12">
+ <el-form-item label="杞﹁締缂栧彿锛�" prop="vehicleCode">
+ <el-input v-model="form.vehicleCode" placeholder="璇疯緭鍏ヨ溅杈嗙紪鍙�" />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="杞︾墝鍙风爜锛�" prop="plateNumber">
+ <el-input v-model="form.plateNumber" placeholder="璇疯緭鍏ヨ溅鐗屽彿鐮�" />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="20">
+ <el-col :span="12">
+ <el-form-item label="杞﹁締绫诲瀷锛�" prop="vehicleType">
+ <el-select
+ v-model="form.vehicleType"
+ placeholder="璇烽�夋嫨杞﹁締绫诲瀷"
+ clearable
+ >
+ <el-option
+ v-for="item in vehicleTypeOptions"
+ :key="item.value"
+ :label="item.label"
+ :value="item.value"
+ />
+ </el-select>
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="鎵�灞為儴闂細" prop="department">
+ <el-select
+ v-model="form.department"
+ placeholder="璇烽�夋嫨鎵�灞為儴闂�"
+ clearable
+ >
+ <el-option
+ v-for="item in departmentOptions"
+ :key="item.value"
+ :label="item.label"
+ :value="item.value"
+ />
+ </el-select>
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="20">
+ <el-col :span="12">
+ <el-form-item label="璐疆鏃ユ湡锛�" prop="purchaseDate">
+ <el-date-picker
+ v-model="form.purchaseDate"
+ type="date"
+ value-format="YYYY-MM-DD"
+ format="YYYY-MM-DD"
+ placeholder="璇烽�夋嫨璐疆鏃ユ湡"
+ style="width: 100%"
+ />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="鐘舵�侊細" prop="status">
+ <el-select v-model="form.status" placeholder="璇烽�夋嫨鐘舵��">
+ <el-option
+ v-for="item in statusOptions"
+ :key="item.value"
+ :label="item.label"
+ :value="item.value"
+ />
+ </el-select>
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="20">
+ <el-col :span="12">
+ <el-form-item label="琛岄┒璇佺紪鍙凤細" prop="licenseNumber">
+ <el-input
+ v-model="form.licenseNumber"
+ placeholder="璇疯緭鍏ヨ椹惰瘉缂栧彿"
+ />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="鍙戣瘉鏃ユ湡锛�" prop="licenseIssueDate">
+ <el-date-picker
+ v-model="form.licenseIssueDate"
+ type="date"
+ value-format="YYYY-MM-DD"
+ format="YYYY-MM-DD"
+ placeholder="璇烽�夋嫨鍙戣瘉鏃ユ湡"
+ style="width: 100%"
+ />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="20">
+ <el-col :span="12">
+ <el-form-item label="鍒版湡鏃ユ湡锛�" prop="licenseExpireDate">
+ <el-date-picker
+ v-model="form.licenseExpireDate"
+ type="date"
+ value-format="YYYY-MM-DD"
+ format="YYYY-MM-DD"
+ placeholder="璇烽�夋嫨鍒版湡鏃ユ湡"
+ style="width: 100%"
+ />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ </el-form>
+ <template #footer>
+ <div class="dialog-footer">
+ <el-button @click="handleCancel">鍙� 娑�</el-button>
+ <el-button type="primary" @click="handleSubmit">淇� 瀛�</el-button>
+ </div>
+ </template>
+ </el-dialog>
+ </div>
+</template>
+
+<script setup>
+import { ref, reactive } from "vue";
+import { ElMessage, ElMessageBox } from "element-plus";
+
+// 妯℃嫙杞﹁締鍩虹鏁版嵁
+const allVehicles = ref([
+ {
+ id: 1,
+ vehicleCode: "CL-202401",
+ plateNumber: "绮12345",
+ vehicleType: "鍘㈠紡璐ц溅",
+ department: "鐗╂祦涓�閮�",
+ purchaseDate: "2022-03-15",
+ licenseNumber: "4401-2022-0001",
+ licenseIssueDate: "2022-03-10",
+ licenseExpireDate: "2026-03-10",
+ status: "鍦ㄧ敤",
+ archived: false,
+ },
+ {
+ id: 2,
+ vehicleCode: "CL-202402",
+ plateNumber: "绮67890",
+ vehicleType: "鍐疯棌杞�",
+ department: "鐗╂祦浜岄儴",
+ purchaseDate: "2021-08-01",
+ licenseNumber: "4401-2021-0123",
+ licenseIssueDate: "2021-07-28",
+ licenseExpireDate: "2025-07-28",
+ status: "缁翠慨",
+ archived: false,
+ },
+ {
+ id: 3,
+ vehicleCode: "CL-202403",
+ plateNumber: "绮11223",
+ vehicleType: "鐗靛紩杞�",
+ department: "椤圭洰杩愯緭閮�",
+ purchaseDate: "2020-05-20",
+ licenseNumber: "4401-2020-0456",
+ licenseIssueDate: "2020-05-18",
+ licenseExpireDate: "2024-05-18",
+ status: "闂茬疆",
+ archived: false,
+ },
+ {
+ id: 4,
+ vehicleCode: "CL-202404",
+ plateNumber: "绮33445",
+ vehicleType: "鍘㈠紡璐ц溅",
+ department: "璧勪骇绠$悊閮�",
+ purchaseDate: "2019-11-11",
+ licenseNumber: "4401-2019-0789",
+ licenseIssueDate: "2019-11-08",
+ licenseExpireDate: "2023-11-08",
+ status: "鍦ㄧ敤",
+ archived: true,
+ },
+]);
+
+// 涓嬫媺鏋氫妇
+const vehicleTypeOptions = [
+ { label: "鍘㈠紡璐ц溅", value: "鍘㈠紡璐ц溅" },
+ { label: "鍐疯棌杞�", value: "鍐疯棌杞�" },
+ { label: "鐗靛紩杞�", value: "鐗靛紩杞�" },
+ { label: "鍏朵粬", value: "鍏朵粬" },
+];
+
+const departmentOptions = [
+ { label: "鐗╂祦涓�閮�", value: "鐗╂祦涓�閮�" },
+ { label: "鐗╂祦浜岄儴", value: "鐗╂祦浜岄儴" },
+ { label: "椤圭洰杩愯緭閮�", value: "椤圭洰杩愯緭閮�" },
+ { label: "璧勪骇绠$悊閮�", value: "璧勪骇绠$悊閮�" },
+];
+
+const statusOptions = [
+ { label: "鍦ㄧ敤", value: "鍦ㄧ敤" },
+ { label: "闂茬疆", value: "闂茬疆" },
+ { label: "缁翠慨", value: "缁翠慨" },
+];
+
+// 鏌ヨ琛ㄥ崟
+const searchForm = reactive({
+ plateNumber: "",
+ vehicleType: "",
+ department: "",
+ status: "",
+ archived: "",
+});
+
+// 琛ㄦ牸鏁版嵁
+const tableData = ref([...allVehicles.value]);
+
+// 寮圭獥 & 琛ㄥ崟
+const dialogVisible = ref(false);
+const dialogTitle = ref("鏂板杞﹁締");
+const isEdit = ref(false);
+const formRef = ref(null);
+const form = reactive({
+ id: null,
+ vehicleCode: "",
+ plateNumber: "",
+ vehicleType: "",
+ department: "",
+ purchaseDate: "",
+ licenseNumber: "",
+ licenseIssueDate: "",
+ licenseExpireDate: "",
+ status: "鍦ㄧ敤",
+ archived: false,
+});
+
+const rules = {
+ vehicleCode: [{ required: true, message: "璇疯緭鍏ヨ溅杈嗙紪鍙�", trigger: "blur" }],
+ plateNumber: [{ required: true, message: "璇疯緭鍏ヨ溅鐗屽彿鐮�", trigger: "blur" }],
+ vehicleType: [{ required: true, message: "璇烽�夋嫨杞﹁締绫诲瀷", trigger: "change" }],
+ department: [{ required: true, message: "璇烽�夋嫨鎵�灞為儴闂�", trigger: "change" }],
+ purchaseDate: [{ required: true, message: "璇烽�夋嫨璐疆鏃ユ湡", trigger: "change" }],
+ status: [{ required: true, message: "璇烽�夋嫨鐘舵��", trigger: "change" }],
+ licenseNumber: [{ required: true, message: "璇疯緭鍏ヨ椹惰瘉缂栧彿", trigger: "blur" }],
+ licenseIssueDate: [{ required: true, message: "璇烽�夋嫨鍙戣瘉鏃ユ湡", trigger: "change" }],
+};
+
+// 鏌ヨ
+const handleQuery = () => {
+ tableData.value = allVehicles.value.filter((item) => {
+ if (
+ searchForm.plateNumber &&
+ !item.plateNumber.includes(searchForm.plateNumber.trim())
+ ) {
+ return false;
+ }
+ if (searchForm.vehicleType && item.vehicleType !== searchForm.vehicleType) {
+ return false;
+ }
+ if (searchForm.department && item.department !== searchForm.department) {
+ return false;
+ }
+ if (searchForm.status && item.status !== searchForm.status) {
+ return false;
+ }
+ if (searchForm.archived !== "") {
+ const targetArchived = searchForm.archived === "true";
+ if (item.archived !== targetArchived) return false;
+ }
+ return true;
+ });
+};
+
+const resetSearch = () => {
+ searchForm.plateNumber = "";
+ searchForm.vehicleType = "";
+ searchForm.department = "";
+ searchForm.status = "";
+ searchForm.archived = "";
+ handleQuery();
+};
+
+// 鏂板
+const openAdd = () => {
+ dialogTitle.value = "鏂板杞﹁締";
+ isEdit.value = false;
+ Object.assign(form, {
+ id: null,
+ vehicleCode: "",
+ plateNumber: "",
+ vehicleType: "",
+ department: "",
+ purchaseDate: "",
+ licenseInfo: "",
+ status: "鍦ㄧ敤",
+ archived: false,
+ });
+ dialogVisible.value = true;
+};
+
+// 缂栬緫
+const openEdit = (row) => {
+ dialogTitle.value = "缂栬緫杞﹁締";
+ isEdit.value = true;
+ Object.assign(form, row);
+ dialogVisible.value = true;
+};
+
+// 淇濆瓨
+const handleSubmit = () => {
+ if (!formRef.value) return;
+ formRef.value.validate((valid) => {
+ if (!valid) return;
+ if (isEdit.value) {
+ const index = allVehicles.value.findIndex((v) => v.id === form.id);
+ if (index !== -1) {
+ allVehicles.value[index] = { ...form };
+ }
+ ElMessage.success("杞﹁締淇℃伅宸叉洿鏂�");
+ } else {
+ const newId = allVehicles.value.length
+ ? Math.max(...allVehicles.value.map((v) => v.id)) + 1
+ : 1;
+ allVehicles.value.push({ ...form, id: newId });
+ ElMessage.success("杞﹁締淇℃伅宸叉柊澧�");
+ }
+ dialogVisible.value = false;
+ handleQuery();
+ });
+};
+
+const handleCancel = () => {
+ dialogVisible.value = false;
+};
+
+// 褰掓。
+const archiveRow = (row) => {
+ if (row.archived) return;
+ ElMessageBox.confirm(
+ "鏄惁纭灏嗚杞﹁締褰掓。锛熷綊妗e悗浠呬繚鐣欐煡璇紝涓嶅啀鍙備笌杩愯緭浠诲姟鍒嗛厤銆�",
+ "褰掓。鎻愮ず",
+ {
+ confirmButtonText: "纭",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ }
+ )
+ .then(() => {
+ row.archived = true;
+ if (row.status === "鍦ㄧ敤") {
+ row.status = "闂茬疆";
+ }
+ ElMessage.success("杞﹁締宸插綊妗�");
+ handleQuery();
+ })
+ .catch(() => {});
+};
+
+// 鍒犻櫎
+const removeRow = (row) => {
+ ElMessageBox.confirm("鏄惁纭鍒犻櫎璇ヨ溅杈嗗熀纭�淇℃伅锛�", "鍒犻櫎鎻愮ず", {
+ confirmButtonText: "纭",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ })
+ .then(() => {
+ allVehicles.value = allVehicles.value.filter((v) => v.id !== row.id);
+ handleQuery();
+ ElMessage.success("鍒犻櫎鎴愬姛");
+ })
+ .catch(() => {});
+};
+
+// 鐘舵�佹牱寮�
+const statusTagType = (status) => {
+ if (status === "鍦ㄧ敤") return "success";
+ if (status === "闂茬疆") return "info";
+ if (status === "缁翠慨") return "warning";
+ return "default";
+};
+</script>
+
+<style scoped lang="scss">
+.dialog-footer {
+ text-align: right;
+}
+</style>
+
--
Gitblit v1.9.3