From c5487f431545d0d8eaec017595cc2316fea9d45a Mon Sep 17 00:00:00 2001
From: tuqin <tuqin@tuqin.cn>
Date: 星期三, 21 十月 2026 15:16:47 +0800
Subject: [PATCH] feat(芯导-环保门禁): 设备远程监控、车辆信息采集手机端,修复车辆列表分页

---
 /dev/null                                                |   48 -----
 src/views/environmentAccess/remoteMonitor/index.vue      |  189 +++++++++++++++++++++
 src/views/environmentAccess/vehicleInfoAudit/index.vue   |    5 
 src/views/environmentAccess/vehicleInfoCollect/index.vue |  189 +++++++++++++++++++++
 src/views/environmentAccess/vehicleInfoCenter/index.vue  |   43 ++++
 src/api/environmentAccess/deviceCommand.js               |   21 ++
 6 files changed, 445 insertions(+), 50 deletions(-)

diff --git a/src/api/environmentAccess/accessVehicle.js b/src/api/environmentAccess/accessVehicle.js
deleted file mode 100644
index a8f8e14..0000000
--- a/src/api/environmentAccess/accessVehicle.js
+++ /dev/null
@@ -1,29 +0,0 @@
-import request from "@/utils/request";
-
-// ===== 闂ㄧ杞﹁締/绉诲姩鏈烘鍙拌处 =====
-export function listVehicle(query) {
-  return request({ url: "/environmentAccess/vehicle/page", method: "get", params: query });
-}
-export function addVehicle(data) {
-  return request({ url: "/environmentAccess/vehicle/add", method: "post", data });
-}
-export function updateVehicle(data) {
-  return request({ url: "/environmentAccess/vehicle/update", method: "post", data });
-}
-export function deleteVehicle(ids) {
-  return request({ url: "/environmentAccess/vehicle/delete", method: "delete", data: ids });
-}
-
-// ===== 璁惧鏁呴殰锛堝鐢� device 妯″潡 /defect锛�=====
-export function listDefect(query) {
-  return request({ url: "/defect/page", method: "get", params: query });
-}
-export function addDefect(data) {
-  return request({ url: "/defect/add", method: "post", data });
-}
-export function updateDefect(data) {
-  return request({ url: "/defect/update", method: "post", data });
-}
-export function deleteDefect(ids) {
-  return request({ url: "/defect/delete", method: "delete", data: ids });
-}
diff --git a/src/api/environmentAccess/deviceCommand.js b/src/api/environmentAccess/deviceCommand.js
new file mode 100644
index 0000000..7bdfaeb
--- /dev/null
+++ b/src/api/environmentAccess/deviceCommand.js
@@ -0,0 +1,21 @@
+import request from "@/utils/request";
+
+// 璁惧鍒楄〃锛堣繙绋嬫帶鍒跺璞★級
+export function getDeviceList() {
+  return request({ url: "/environmentAccess/deviceCommand/deviceList", method: "get" });
+}
+
+// 寮傚父鎶ヨ鍒楄〃
+export function getAlarmList() {
+  return request({ url: "/environmentAccess/deviceCommand/alarmList", method: "get" });
+}
+
+// 鎸囦护璁板綍鍒嗛〉
+export function getCommandPage(params) {
+  return request({ url: "/environmentAccess/deviceCommand/listPage", method: "get", params });
+}
+
+// 涓嬪彂鍚仠鎸囦护
+export function sendCommand(data) {
+  return request({ url: "/environmentAccess/deviceCommand/send", method: "post", data });
+}
\ No newline at end of file
diff --git a/src/api/environmentAccess/inspection.js b/src/api/environmentAccess/inspection.js
deleted file mode 100644
index da5b22f..0000000
--- a/src/api/environmentAccess/inspection.js
+++ /dev/null
@@ -1,19 +0,0 @@
-import request from "@/utils/request";
-
-// ===== 鏅鸿兘宸℃鍙拌处 =====
-export function listInspection(query) {
-  return request({ url: "/environmentAccess/inspection/page", method: "get", params: query });
-}
-export function addInspection(data) {
-  return request({ url: "/environmentAccess/inspection/add", method: "post", data });
-}
-export function updateInspection(data) {
-  return request({ url: "/environmentAccess/inspection/update", method: "post", data });
-}
-export function deleteInspection(ids) {
-  return request({ url: "/environmentAccess/inspection/delete", method: "delete", data: ids });
-}
-// 鑷姩鐢熸垚宸℃鎶ュ憡
-export function generateInspectionReport(id) {
-  return request({ url: "/environmentAccess/inspection/report/" + id, method: "get" });
-}
diff --git a/src/api/environmentAccess/reportCenter.js b/src/api/environmentAccess/reportCenter.js
deleted file mode 100644
index ffcb738..0000000
--- a/src/api/environmentAccess/reportCenter.js
+++ /dev/null
@@ -1,13 +0,0 @@
-import request from "@/utils/request";
-
-/**
- * 姣忔棩杩囩缁熻鎶ヨ〃锛氳溅娆°�佽揣閲忋�佸亸宸巼
- * @param {Object} params - { startDate, endDate }
- */
-export function getDailyWeighbridgeReport(params) {
-  return request({
-    url: "/environmentAccess/weighbridgeDailyReport",
-    method: "get",
-    params,
-  });
-}
diff --git a/src/api/environmentAccess/unattendedWeighbridgeSystem.js b/src/api/environmentAccess/unattendedWeighbridgeSystem.js
deleted file mode 100644
index b9ca1bb..0000000
--- a/src/api/environmentAccess/unattendedWeighbridgeSystem.js
+++ /dev/null
@@ -1,46 +0,0 @@
-import request from "@/utils/request";
-
-// 鏌ヨ鏃犱汉鍊煎畧鍦扮绯荤粺鍒嗛〉鍒楄〃
-export function listWeighbridgeSystem(query) {
-  return request({
-    url: "/environmentAccess/weighbridgeSystemPage",
-    method: "get",
-    params: query,
-  });
-}
-
-// 鏂板鏃犱汉鍊煎畧鍦扮绯荤粺
-export function addWeighbridgeSystem(data) {
-  return request({
-    url: "/environmentAccess/weighbridgeSystemAdd",
-    method: "post",
-    data,
-  });
-}
-
-// 淇敼鏃犱汉鍊煎畧鍦扮绯荤粺
-export function updateWeighbridgeSystem(data) {
-  return request({
-    url: "/environmentAccess/weighbridgeSystemUpdate",
-    method: "put",
-    data,
-  });
-}
-
-// 鍒犻櫎鏃犱汉鍊煎畧鍦扮绯荤粺锛堟敮鎸佹壒閲忥級
-export function delWeighbridgeSystem(ids) {
-  return request({
-    url: "/environmentAccess/weighbridgeSystemDelete",
-    method: "delete",
-    data: ids,
-  });
-}
-
-// 鏌ヨ鍗曟潯璁板綍璇︽儏
-export function getWeighbridgeSystem(id) {
-  return request({
-    url: "/environmentAccess/weighbridgeSystemInfo",
-    method: "get",
-    params: { id },
-  });
-}
diff --git a/src/api/environmentAccess/vehicleInfo.js b/src/api/environmentAccess/vehicleInfo.js
deleted file mode 100644
index 5b25f18..0000000
--- a/src/api/environmentAccess/vehicleInfo.js
+++ /dev/null
@@ -1,48 +0,0 @@
-import request from "@/utils/request";
-
-// 鏌ヨ杞﹁締淇℃伅鍒嗛〉鍒楄〃
-export function listVehicleInfo(query) {
-  return request({
-    // 涓ょ骇璺緞锛氭ā鍧� + 鍏蜂綋鍔熻兘鍚�
-    url: "/environmentAccess/vehicleInfoPage",
-    method: "get",
-    params: query,
-  });
-}
-
-// 鏂板杞﹁締淇℃伅
-export function addVehicleInfo(data) {
-  return request({
-    url: "/environmentAccess/vehicleInfoAdd",
-    method: "post",
-    data,
-  });
-}
-
-// 淇敼杞﹁締淇℃伅
-export function updateVehicleInfo(data) {
-  return request({
-    url: "/environmentAccess/vehicleInfoUpdate",
-    method: "put",
-    data,
-  });
-}
-
-// 鍒犻櫎杞﹁締淇℃伅锛堟敮鎸佹壒閲忥級
-export function delVehicleInfo(ids) {
-  return request({
-    url: "/environmentAccess/vehicleInfoDelete",
-    method: "delete",
-    data: ids,
-  });
-}
-
-// 瀹℃牳杞﹁締淇℃伅
-export function reviewVehicleInfo(data) {
-  return request({
-    // 瀹℃牳鍗曠嫭璧勬簮锛歷ehicleInfoReview
-    url: "/environmentAccess/vehicleInfoReview",
-    method: "post",
-    data,
-  });
-}
diff --git a/src/views/environmentAccess/remoteMonitor/index.vue b/src/views/environmentAccess/remoteMonitor/index.vue
new file mode 100644
index 0000000..217b28b
--- /dev/null
+++ b/src/views/environmentAccess/remoteMonitor/index.vue
@@ -0,0 +1,189 @@
+<template>
+  <div class="app-container">
+    <el-tabs v-model="activeTab">
+      <el-tab-pane label="璁惧鍙拌处" name="ledger" />
+      <el-tab-pane label="杩滅▼鎺у埗" name="control" />
+      <el-tab-pane label="寮傚父鎶ヨ" name="alarm">
+        <template #label>
+          <span>寮傚父鎶ヨ<el-badge v-if="unhandledCount > 0" :value="unhandledCount" style="margin-left: 6px" /></span>
+        </template>
+      </el-tab-pane>
+    </el-tabs>
+
+    <!-- 杩滅▼鎺у埗 -->
+    <div v-if="activeTab === 'ledger'">
+      <LedgerPage />
+    </div>
+
+    <div v-else-if="activeTab === 'control'">
+      <div class="section-title">璁惧鍒楄〃锛堣繙绋嬪惎鍋滐級</div>
+      <el-table :data="deviceList" border v-loading="deviceLoading" height="300">
+        <el-table-column align="center" label="搴忓彿" type="index" width="60" />
+        <el-table-column label="璁惧鍚嶇О" prop="deviceName" show-overflow-tooltip />
+        <el-table-column label="瑙勬牸鍨嬪彿" prop="deviceModel" show-overflow-tooltip />
+        <el-table-column label="鍗曚綅" prop="unit" width="80" />
+        <el-table-column fixed="right" label="杩滅▼鎺у埗" width="180" align="center">
+          <template #default="scope">
+            <el-button link type="success" size="small" @click="handleSend(scope.row, 'start')">鍚姩</el-button>
+            <el-button link type="danger" size="small" @click="handleSend(scope.row, 'stop')">鍋滄</el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+
+      <div class="section-title" style="margin-top: 16px">鎸囦护璁板綍</div>
+      <el-table :data="commandList" border v-loading="commandLoading" height="300">
+        <el-table-column align="center" label="搴忓彿" type="index" width="60" />
+        <el-table-column label="璁惧鍚嶇О" prop="deviceName" show-overflow-tooltip />
+        <el-table-column label="鎸囦护" prop="commandType" width="90" align="center">
+          <template #default="scope">
+            <el-tag :type="scope.row.commandType === 'start' ? 'success' : 'danger'">
+              {{ scope.row.commandType === 'start' ? '鍚姩' : '鍋滄' }}
+            </el-tag>
+          </template>
+        </el-table-column>
+        <el-table-column label="鐘舵��" prop="commandStatus" width="100" align="center">
+          <template #default="scope">
+            <el-tag :type="scope.row.commandStatus === 'success' ? 'success' : (scope.row.commandStatus === 'failed' ? 'danger' : 'info')">
+              {{ scope.row.commandStatus === 'success' ? '鎴愬姛' : (scope.row.commandStatus === 'failed' ? '澶辫触' : '涓嬪彂涓�') }}
+            </el-tag>
+          </template>
+        </el-table-column>
+        <el-table-column label="鎿嶄綔浜�" prop="operator" width="110" />
+        <el-table-column label="涓嬪彂鏃堕棿" prop="commandTime" width="170" />
+        <el-table-column label="鎵ц缁撴灉" prop="resultMsg" show-overflow-tooltip />
+      </el-table>
+      <pagination v-show="commandPage.total > 0" :total="commandPage.total" layout="total, prev, pager, next"
+        :page="commandPage.current" :limit="commandPage.size" @pagination="commandPageChange" />
+    </div>
+
+    <!-- 寮傚父鎶ヨ -->
+    <div v-else>
+      <el-alert type="info" :closable="false" show-icon style="margin-bottom: 10px"
+        title="绯荤粺姣� 60 绉掕嚜鍔ㄦ鏌ヤ竴娆℃柊鎶ヨ锛屽彂鐜版湭澶勭悊鎶ヨ浼氬脊绐楁彁閱掞紙绔欏唴鎺ㄩ�侊級" />
+      <el-table :data="alarmList" border v-loading="alarmLoading" height="calc(100vh - 16em)">
+        <el-table-column align="center" label="搴忓彿" type="index" width="60" />
+        <el-table-column label="璁惧鍚嶇О" prop="deviceName" show-overflow-tooltip width="220">
+          <template #default="scope">{{ scope.row.deviceName || '-' }}</template>
+        </el-table-column>
+        <el-table-column label="鏁呴殰鎻忚堪" prop="defectDescription" show-overflow-tooltip />
+        <el-table-column label="璁惧鐘舵��" prop="status" width="120" />
+        <el-table-column label="鏄惁澶勭悊" width="110" align="center">
+          <template #default="scope">
+            <el-tag :type="scope.row.handled ? 'success' : 'danger'">{{ scope.row.handled ? '宸叉秷闄�' : '鏈鐞�' }}</el-tag>
+          </template>
+        </el-table-column>
+        <el-table-column label="鍙戠敓鏃堕棿" prop="createTime" width="170" />
+        <el-table-column label="娑堥櫎鏃堕棿" prop="eliminateTime" width="170" />
+      </el-table>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref, onMounted, onUnmounted, computed } from "vue";
+import { ElNotification, ElMessageBox, ElMessage } from "element-plus";
+import pagination from "@/components/PIMTable/Pagination.vue";
+import LedgerPage from "@/views/equipmentManagement/ledger/index.vue";
+import { getDeviceList, getAlarmList, getCommandPage, sendCommand } from "@/api/environmentAccess/deviceCommand.js";
+
+defineOptions({ name: "璁惧杩滅▼鐩戞帶" });
+
+const activeTab = ref("ledger");
+const deviceList = ref([]);
+const deviceLoading = ref(false);
+const commandList = ref([]);
+const commandLoading = ref(false);
+const commandPage = ref({ current: 1, size: 10, total: 0 });
+const alarmList = ref([]);
+const alarmLoading = ref(false);
+
+const unhandledCount = computed(() => alarmList.value.filter((a) => !a.handled).length);
+
+/* ---------- 杩滅▼鎺у埗 ---------- */
+const loadDevices = () => {
+  deviceLoading.value = true;
+  getDeviceList().then((res) => {
+    deviceList.value = res.data || [];
+  }).finally(() => { deviceLoading.value = false; });
+};
+
+const loadCommands = () => {
+  commandLoading.value = true;
+  getCommandPage({ current: commandPage.value.current, size: commandPage.value.size }).then((res) => {
+    commandList.value = (res.data && res.data.records) || [];
+    commandPage.value.total = (res.data && res.data.total) || 0;
+  }).finally(() => { commandLoading.value = false; });
+};
+
+const commandPageChange = (obj) => {
+  commandPage.value.current = obj.page;
+  commandPage.value.size = obj.limit;
+  loadCommands();
+};
+
+const handleSend = (row, type) => {
+  const label = type === "start" ? "鍚姩" : "鍋滄";
+  ElMessageBox.confirm(`纭瀵广��${row.deviceName || '璇ヨ澶�'}銆嶄笅鍙�${label}鎸囦护锛焋, "杩滅▼鎺у埗", { type: "warning" })
+    .then(() => {
+      sendCommand({ deviceLedgerId: row.id, deviceName: row.deviceName, commandType: type }).then((res) => {
+        ElMessage.success(res.msg || `${label}鎸囦护宸蹭笅鍙慲);
+        commandPage.value.current = 1;
+        loadCommands();
+      });
+    })
+    .catch(() => {});
+};
+
+/* ---------- 寮傚父鎶ヨ锛堝惈绔欏唴寮圭獥鎻愰啋锛� ---------- */
+let alarmTimer = null;
+let lastMaxAlarmId = null;
+
+const loadAlarms = (notify) => {
+  alarmLoading.value = true;
+  return getAlarmList().then((res) => {
+    const list = res.data || [];
+    alarmList.value = list;
+    const maxId = list.reduce((m, a) => Math.max(m, Number(a.id) || 0), 0);
+    if (notify && lastMaxAlarmId !== null && maxId > lastMaxAlarmId) {
+      const fresh = list.filter((a) => Number(a.id) > lastMaxAlarmId && !a.handled);
+      fresh.slice(0, 3).forEach((a) => {
+        ElNotification({
+          title: "璁惧寮傚父鎶ヨ",
+          message: `銆�${a.deviceName || '鏈煡璁惧'}銆�${a.defectDescription || '鍙戠敓璁惧鏁呴殰'}锛岃鍙婃椂澶勭悊`,
+          type: "error",
+          duration: 15000,
+          position: "bottom-right",
+        });
+      });
+    }
+    lastMaxAlarmId = maxId;
+  }).finally(() => { alarmLoading.value = false; });
+};
+
+const startAlarmPolling = () => {
+  loadAlarms(false);
+  alarmTimer = setInterval(() => loadAlarms(true), 60000);
+};
+
+onMounted(() => {
+  loadDevices();
+  loadCommands();
+  startAlarmPolling();
+});
+
+onUnmounted(() => {
+  if (alarmTimer) {
+    clearInterval(alarmTimer);
+    alarmTimer = null;
+  }
+});
+</script>
+
+<style scoped lang="scss">
+.section-title {
+  font-size: 14px;
+  font-weight: 600;
+  color: #303133;
+  margin-bottom: 8px;
+}
+</style>
diff --git a/src/views/environmentAccess/vehicleInfoAudit/index.vue b/src/views/environmentAccess/vehicleInfoAudit/index.vue
index 924ca55..337f6bd 100644
--- a/src/views/environmentAccess/vehicleInfoAudit/index.vue
+++ b/src/views/environmentAccess/vehicleInfoAudit/index.vue
@@ -367,8 +367,8 @@
 function loadTableData() {
   tableLoading.value = true;
   listVehicleInfo({
-    pageNum: page.current,
-    pageSize: page.size,
+    current: page.current,
+    size: page.size,
     ...searchForm,
   })
     .then((res) => {
@@ -419,6 +419,7 @@
       .then(() => {
         ElMessage.success(operationType.value === "add" ? "鏂板鎴愬姛" : "缂栬緫鎴愬姛");
         dialogVisible.value = false;
+        if (operationType.value === "add") page.current = 1;
         loadTableData();
       })
       .catch(() => {});
diff --git a/src/views/environmentAccess/vehicleInfoCenter/index.vue b/src/views/environmentAccess/vehicleInfoCenter/index.vue
new file mode 100644
index 0000000..2c50e29
--- /dev/null
+++ b/src/views/environmentAccess/vehicleInfoCenter/index.vue
@@ -0,0 +1,43 @@
+<template>
+  <div class="vehicle-center">
+    <el-tabs v-model="activeTab" class="center-tabs">
+      <el-tab-pane label="閲囬泦瀹℃牳" name="audit" />
+      <el-tab-pane label="鎵嬫満绔噰闆�" name="collect" />
+    </el-tabs>
+    <div class="center-body">
+      <keep-alive>
+        <component :is="currentComponent" />
+      </keep-alive>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref, computed } from "vue";
+import AuditPage from "../vehicleInfoAudit/index.vue";
+import CollectPage from "../vehicleInfoCollect/index.vue";
+
+defineOptions({ name: "杞﹁締淇℃伅閲囬泦瀹℃牳" });
+
+const activeTab = ref("audit");
+
+const tabMap = {
+  audit: AuditPage,
+  collect: CollectPage,
+};
+
+const currentComponent = computed(() => tabMap[activeTab.value] || AuditPage);
+</script>
+
+<style scoped lang="scss">
+.vehicle-center {
+  padding: 10px 12px;
+}
+.center-tabs {
+  margin-bottom: 6px;
+}
+/* 瀛愰〉闈㈣嚜甯︾殑 app-container 浼氬涓�灞傚唴杈硅窛 */
+.center-body :deep(.app-container) {
+  padding: 0;
+}
+</style>
diff --git a/src/views/environmentAccess/vehicleInfoCollect/index.vue b/src/views/environmentAccess/vehicleInfoCollect/index.vue
new file mode 100644
index 0000000..c37475c
--- /dev/null
+++ b/src/views/environmentAccess/vehicleInfoCollect/index.vue
@@ -0,0 +1,189 @@
+<template>
+  <div class="collect-page">
+    <div class="collect-header">
+      <h2>杞﹁締淇℃伅閲囬泦</h2>
+      <p>璇峰瀹炲~鍐欒溅杈嗕俊鎭紝鎻愪氦鍚庣敱浼佷笟瀹℃牳</p>
+    </div>
+
+    <el-form ref="formRef" :model="form" :rules="rules" label-position="top" class="collect-form">
+      <el-form-item label="杞︾墝鍙风爜" prop="plateNo">
+        <el-input v-model="form.plateNo" size="large" placeholder="濡傦細鑻廇12345" clearable />
+      </el-form-item>
+
+      <el-form-item label="鍙风墝棰滆壊" prop="plateColor">
+        <el-select v-model="form.plateColor" size="large" placeholder="璇烽�夋嫨" style="width: 100%">
+          <el-option v-for="i in plateColorOptions" :key="i" :label="i" :value="i" />
+        </el-select>
+      </el-form-item>
+
+      <el-form-item label="杞﹁締绫诲瀷" prop="carType">
+        <el-select v-model="form.carType" size="large" placeholder="璇烽�夋嫨" style="width: 100%">
+          <el-option v-for="i in carTypeOptions" :key="i" :label="i" :value="i" />
+        </el-select>
+      </el-form-item>
+
+      <el-form-item label="杞﹁締璇嗗埆浠g爜锛圴IN锛�" prop="carVin">
+        <el-input v-model="form.carVin" size="large" placeholder="17 浣� VIN 鐮�" clearable />
+      </el-form-item>
+
+      <el-form-item label="杞﹁締鍨嬪彿" prop="carModel">
+        <el-input v-model="form.carModel" size="large" placeholder="璇疯緭鍏ヨ溅杈嗗瀷鍙�" clearable />
+      </el-form-item>
+
+      <el-form-item label="鍙戝姩鏈哄瀷鍙�" prop="engineModel">
+        <el-input v-model="form.engineModel" size="large" placeholder="璇疯緭鍏ュ彂鍔ㄦ満鍨嬪彿" clearable />
+      </el-form-item>
+
+      <el-form-item label="鍙戝姩鏈虹敓浜у巶" prop="engineProductFactory">
+        <el-input v-model="form.engineProductFactory" size="large" placeholder="璇疯緭鍏ュ彂鍔ㄦ満鐢熶骇鍘�" clearable />
+      </el-form-item>
+
+      <el-form-item label="鍙戝姩鏈虹紪鍙�" prop="engineNo">
+        <el-input v-model="form.engineNo" size="large" placeholder="璇疯緭鍏ュ彂鍔ㄦ満缂栧彿" clearable />
+      </el-form-item>
+
+      <el-form-item label="鎺掓斁鏍囧噯" prop="emissionStandard">
+        <el-select v-model="form.emissionStandard" size="large" placeholder="璇烽�夋嫨" style="width: 100%">
+          <el-option v-for="i in emissionOptions" :key="i" :label="i" :value="i" />
+        </el-select>
+      </el-form-item>
+
+      <el-form-item label="娉ㄥ唽鐧昏鏃ユ湡" prop="registeDate">
+        <el-date-picker
+          v-model="form.registeDate"
+          size="large"
+          type="date"
+          value-format="YYYY-MM-DD"
+          placeholder="璇烽�夋嫨娉ㄥ唽鐧昏鏃ユ湡"
+          style="width: 100%"
+        />
+      </el-form-item>
+
+      <el-form-item label="浣跨敤鎬ц川" prop="natureOfUse">
+        <el-select v-model="form.natureOfUse" size="large" placeholder="璇烽�夋嫨" style="width: 100%">
+          <el-option v-for="i in natureOptions" :key="i" :label="i" :value="i" />
+        </el-select>
+      </el-form-item>
+
+      <el-form-item label="鐕冩枡绫诲瀷" prop="fuelType">
+        <el-select v-model="form.fuelType" size="large" placeholder="璇烽�夋嫨" style="width: 100%">
+          <el-option v-for="i in fuelOptions" :key="i" :label="i" :value="i" />
+        </el-select>
+      </el-form-item>
+
+      <div class="collect-actions">
+        <el-button type="primary" size="large" :loading="submitting" style="width: 100%" @click="submit">
+          鎻愪氦閲囬泦
+        </el-button>
+        <el-button size="large" style="width: 100%; margin: 10px 0 0 0" @click="reset">閲嶆柊濉啓</el-button>
+      </div>
+    </el-form>
+  </div>
+</template>
+
+<script setup>
+import { ref, reactive } from "vue";
+import { ElMessage } from "element-plus";
+import { addVehicleInfo } from "@/api/environmentAccess/vehicleInfo.js";
+
+defineOptions({ name: "杞﹁締淇℃伅閲囬泦" });
+
+const formRef = ref();
+const submitting = ref(false);
+
+const plateColorOptions = ["钃濊壊", "榛勮壊", "缁胯壊", "鐧借壊", "榛戣壊", "鍏朵粬"];
+const carTypeOptions = ["灏忓瀷姹借溅", "澶у瀷姹借溅", "鏂拌兘婧愭苯杞�", "鎸傝溅", "鎽╂墭杞�", "鍏朵粬"];
+const emissionOptions = ["鍥戒笁", "鍥藉洓", "鍥戒簲", "鍥藉叚", "绾數鍔�", "鍏朵粬"];
+const natureOptions = ["钀ヨ繍", "闈炶惀杩�", "璐ц繍", "瀹㈣繍", "鍏朵粬"];
+const fuelOptions = ["姹芥补", "鏌存补", "澶╃劧姘�", "鐢�", "娣峰悎鍔ㄥ姏", "鍏朵粬"];
+
+const emptyForm = () => ({
+  plateNo: "",
+  plateColor: "",
+  carType: "",
+  carVin: "",
+  carModel: "",
+  engineModel: "",
+  engineProductFactory: "",
+  engineNo: "",
+  emissionStandard: "",
+  registeDate: "",
+  natureOfUse: "",
+  fuelType: "",
+});
+
+const form = reactive(emptyForm());
+
+const rules = {
+  plateNo: [{ required: true, message: "璇疯緭鍏ヨ溅鐗屽彿鐮�", trigger: "blur" }],
+  plateColor: [{ required: true, message: "璇烽�夋嫨鍙风墝棰滆壊", trigger: "change" }],
+  carType: [{ required: true, message: "璇烽�夋嫨杞﹁締绫诲瀷", trigger: "change" }],
+};
+
+const submit = () => {
+  formRef.value?.validate((valid) => {
+    if (!valid) return;
+    submitting.value = true;
+    addVehicleInfo({ ...form, reviewStatus: "pending" })
+      .then(() => {
+        ElMessage.success("鎻愪氦鎴愬姛锛岀瓑寰呬紒涓氬鏍�");
+        Object.assign(form, emptyForm());
+        formRef.value?.clearValidate();
+      })
+      .catch(() => ElMessage.error("鎻愪氦澶辫触锛岃绋嶅悗閲嶈瘯"))
+      .finally(() => {
+        submitting.value = false;
+      });
+  });
+};
+
+const reset = () => {
+  Object.assign(form, emptyForm());
+  formRef.value?.clearValidate();
+};
+</script>
+
+<style scoped lang="scss">
+.collect-page {
+  max-width: 640px;
+  margin: 0 auto;
+  padding: 16px 14px 40px;
+  background: #fff;
+  min-height: 100vh;
+  box-sizing: border-box;
+}
+
+.collect-header {
+  padding: 8px 0 16px;
+  border-bottom: 1px solid #ebeef5;
+  margin-bottom: 18px;
+
+  h2 {
+    margin: 0 0 6px;
+    font-size: 20px;
+    color: #303133;
+  }
+
+  p {
+    margin: 0;
+    font-size: 13px;
+    color: #909399;
+  }
+}
+
+.collect-form {
+  :deep(.el-form-item__label) {
+    font-size: 15px;
+    padding-bottom: 4px;
+  }
+
+  :deep(.el-input__inner),
+  :deep(.el-select__placeholder) {
+    font-size: 15px;
+  }
+}
+
+.collect-actions {
+  margin-top: 22px;
+}
+</style>

--
Gitblit v1.9.3