From 67c560c0cad4224c41b36b2ec755bf3d5aa7e68f Mon Sep 17 00:00:00 2001
From: gaoluyang <2820782392@qq.com>
Date: 星期五, 06 二月 2026 10:51:51 +0800
Subject: [PATCH] Merge branch 'dev_New' into dev_湖南鹏创电子

---
 src/views/inventoryManagement/vehicleFuelManagement/index.vue |  556 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 556 insertions(+), 0 deletions(-)

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>
+

--
Gitblit v1.9.3