| | |
| | | <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 class="search_form" > |
| | | <div style="flex: 1; padding-right: 20px;"> |
| | | <el-row :gutter="16"> |
| | | <el-col :span="6" style="display: flex; align-items: center;"> |
| | | <span class="search_title" style="white-space: nowrap;">车牌号码:</span> |
| | | <el-input v-model="queryParams.plateNumber" placeholder="请输入车牌号码" clearable style="flex: 1;" @keyup.enter.native="handleQuery" /> |
| | | </el-col> |
| | | <el-col :span="6" style="display: flex; align-items: center;"> |
| | | <span class="search_title" style="white-space: nowrap;">所属部门:</span> |
| | | <el-tree-select v-model="queryParams.deptId" :data="deptOptions" :props="{ value: 'id', label: 'label', children: 'children' }" value-key="id" placeholder="请选择部门" check-strictly clearable filterable style="flex: 1;" /> |
| | | </el-col> |
| | | <el-col :span="6" style="display: flex; align-items: center;"> |
| | | <span class="search_title" style="white-space: nowrap;">状态:</span> |
| | | <el-select v-model="queryParams.vehicleStatus" placeholder="请选择状态" clearable style="flex: 1;"> |
| | | <el-option label="在用" value="NORMAL" /> |
| | | <el-option label="闲置" value="IDLE" /> |
| | | <el-option label="维修" value="REPAIR" /> |
| | | </el-select> |
| | | </el-col> |
| | | <el-col :span="6" style="display: flex; align-items: center;"> |
| | | <el-button type="primary" @click="handleQuery">搜索</el-button> |
| | | <el-button @click="resetQuery">重置</el-button> |
| | | </el-col> |
| | | </el-row> |
| | | </div> |
| | | <div> |
| | | <el-button type="primary" icon="Plus" @click="openAdd">新增车辆</el-button> |
| | | <el-button type="primary" icon="Plus" @click="handleAdd">新增车辆</el-button> |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- 表格 --> |
| | | <div class="table_list"> |
| | | <el-table |
| | | v-loading="loading" |
| | | :data="tableData" |
| | | border |
| | | style="width: 100%" |
| | | height="calc(100vh - 18.5em)" |
| | | height="calc(100vh - 22em)" |
| | | :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"> |
| | | <el-table-column prop="plateNumber" label="车牌号码" min-width="120" show-overflow-tooltip /> |
| | | <el-table-column prop="deptName" label="所属部门" min-width="150" show-overflow-tooltip /> |
| | | <el-table-column prop="userName" label="责任人" min-width="120" /> |
| | | <el-table-column prop="propertyOwnership" label="产权所有" min-width="120" show-overflow-tooltip /> |
| | | <el-table-column label="年检到期日期" min-width="140"> |
| | | <template #default="scope"> |
| | | <el-tag :type="statusTagType(scope.row.status)"> |
| | | {{ scope.row.status }} |
| | | <span>{{ scope.row.inspectionExpireDate }}</span> |
| | | <el-tag v-if="isExpired(scope.row.inspectionExpireDate)" type="danger" size="small" style="margin-left:5px;">已超期</el-tag> |
| | | <el-tag v-else-if="isExpiringSoon(scope.row.inspectionExpireDate)" type="warning" size="small" style="margin-left:5px;">即将到期</el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="保险到期日期" min-width="140"> |
| | | <template #default="scope"> |
| | | <span>{{ scope.row.insuranceExpireDate }}</span> |
| | | <el-tag v-if="isExpired(scope.row.insuranceExpireDate)" type="danger" size="small" style="margin-left:5px;">已超期</el-tag> |
| | | <el-tag v-else-if="isExpiringSoon(scope.row.insuranceExpireDate)" type="warning" size="small" style="margin-left:5px;">即将到期</el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="状态" min-width="100" align="center"> |
| | | <template #default="scope"> |
| | | <el-tag :type="statusTagType(scope.row.vehicleStatus)"> |
| | | {{ statusLabel(scope.row.vehicleStatus) }} |
| | | </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 prop="remark" label="备注" min-width="150" show-overflow-tooltip /> |
| | | <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> |
| | | <el-button type="success" link size="small" @click="handleCost(scope.row)">费用管理</el-button> |
| | | <el-button type="primary" link size="small" @click="handleUpdate(scope.row)">编辑</el-button> |
| | | <el-button type="danger" link size="small" @click="handleDelete(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" |
| | | > |
| | | <!-- 分页 --> |
| | | <pagination |
| | | v-show="total > 0" |
| | | :total="total" |
| | | v-model:page="queryParams.current" |
| | | v-model:limit="queryParams.size" |
| | | @pagination="getList" |
| | | /> |
| | | </div> |
| | | <!-- 新增/编辑车辆弹窗 --> |
| | | <el-dialog :title="title" v-model="open" width="600px" append-to-body> |
| | | <el-form ref="formRef" :model="form" :rules="rules" label-width="110px"> |
| | | <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-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 label="产权所有" prop="propertyOwnership"> |
| | | <el-input v-model="form.propertyOwnership" placeholder="如:自有,租赁等" /> |
| | | </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="请选择购置日期" |
| | | <el-form-item label="所属部门" prop="deptId"> |
| | | <el-tree-select |
| | | v-model="form.deptId" |
| | | :data="deptOptions" |
| | | :props="{ value: 'id', label: 'label', children: 'children' }" |
| | | value-key="id" |
| | | placeholder="请选择部门" |
| | | check-strictly |
| | | clearable |
| | | filterable |
| | | 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-form-item label="责任人" prop="userId"> |
| | | <el-select v-model="form.userId" placeholder="请选择责任人" style="width: 100%" filterable> |
| | | <el-option |
| | | v-for="item in statusOptions" |
| | | :key="item.value" |
| | | :label="item.label" |
| | | :value="item.value" |
| | | v-for="item in userList" |
| | | :key="item.userId" |
| | | :label="item.userId + ' - ' + (item.nickName || item.userName)" |
| | | :value="item.userId" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | |
| | | </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 label="状态" prop="vehicleStatus"> |
| | | <el-select v-model="form.vehicleStatus" placeholder="请选择状态" style="width: 100%"> |
| | | <el-option label="在用" value="NORMAL" /> |
| | | <el-option label="闲置" value="IDLE" /> |
| | | <el-option label="维修" value="REPAIR" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="到期日期:" prop="licenseExpireDate"> |
| | | <el-form-item label="年检到期" prop="inspectionExpireDate"> |
| | | <el-date-picker |
| | | v-model="form.licenseExpireDate" |
| | | v-model="form.inspectionExpireDate" |
| | | 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="insuranceExpireDate"> |
| | | <el-date-picker |
| | | v-model="form.insuranceExpireDate" |
| | | type="date" |
| | | value-format="YYYY-MM-DD" |
| | | placeholder="请选择到期日期" |
| | | style="width: 100%" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-form-item label="备注" prop="remark"> |
| | | <el-input v-model="form.remark" type="textarea" placeholder="请输入内容" /> |
| | | </el-form-item> |
| | | </el-form> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button @click="handleCancel">取 消</el-button> |
| | | <el-button type="primary" @click="handleSubmit">保 存</el-button> |
| | | <el-button type="primary" @click="submitForm">确 定</el-button> |
| | | <el-button @click="cancel">取 消</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | |
| | | <!-- 费用管理抽屉 --> |
| | | <el-drawer v-model="costDrawer" :title="'费用管理 - ' + currentVehiclePlate" size="50%"> |
| | | <div style="padding: 20px;"> |
| | | <div style="margin-bottom: 20px;"> |
| | | <el-button type="primary" @click="handleAddCost">新增记录</el-button> |
| | | </div> |
| | | <el-table v-loading="costLoading" :data="costList" border> |
| | | <el-table-column label="费用类型" prop="costType"> |
| | | <template #default="scope"> |
| | | {{ costTypeLabel(scope.row.costType) }} |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="金额(元)" prop="amount" align="right" /> |
| | | <el-table-column label="发生日期" prop="costDate" /> |
| | | <el-table-column label="备注" prop="remark" show-overflow-tooltip /> |
| | | <el-table-column label="操作" width="100" align="center"> |
| | | <template #default="scope"> |
| | | <el-button type="danger" link size="small" @click="handleDeleteCost(scope.row)"> |
| | | 删除 |
| | | </el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | <pagination |
| | | v-show="costTotal > 0" |
| | | :total="costTotal" |
| | | v-model:page="costQuery.current" |
| | | v-model:limit="costQuery.size" |
| | | @pagination="getCostList" |
| | | /> |
| | | </div> |
| | | </el-drawer> |
| | | |
| | | <!-- 新增费用弹窗 --> |
| | | <el-dialog title="新增费用" v-model="costOpen" width="400px" append-to-body> |
| | | <el-form ref="costFormRef" :model="costForm" :rules="costRules" label-width="100px"> |
| | | <el-form-item label="费用类型" prop="costType"> |
| | | <el-select v-model="costForm.costType" placeholder="请选择" style="width:100%"> |
| | | <el-option label="保养" value="MAINTENANCE" /> |
| | | <el-option label="年检" value="INSPECTION" /> |
| | | <el-option label="保险" value="INSURANCE" /> |
| | | <el-option label="维修" value="REPAIR" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="金额(元)" prop="amount"> |
| | | <el-input-number v-model="costForm.amount" :precision="2" :min="0" style="width:100%" /> |
| | | </el-form-item> |
| | | <el-form-item label="发生日期" prop="costDate"> |
| | | <el-date-picker v-model="costForm.costDate" type="date" value-format="YYYY-MM-DD" style="width:100%" /> |
| | | </el-form-item> |
| | | <el-form-item label="备注" prop="remark"> |
| | | <el-input v-model="costForm.remark" type="textarea" /> |
| | | </el-form-item> |
| | | </el-form> |
| | | <template #footer> |
| | | <el-button type="primary" @click="submitCostForm">确 定</el-button> |
| | | <el-button @click="costOpen = false">取 消</el-button> |
| | | </template> |
| | | </el-dialog> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, reactive } from "vue"; |
| | | import { ElMessage, ElMessageBox } from "element-plus"; |
| | | import { ref, reactive, onMounted } from 'vue'; |
| | | import { ElMessage, ElMessageBox } from 'element-plus'; |
| | | import { listVehicleInfo, getWarningList, addVehicleInfo, updateVehicleInfo, delVehicleInfo } from '@/api/inventoryManagement/vehicle'; |
| | | import request from '@/utils/request'; |
| | | |
| | | // 模拟车辆基础数据 |
| | | const allVehicles = ref([ |
| | | { |
| | | id: 1, |
| | | vehicleCode: "CL-202401", |
| | | plateNumber: "粤A12345", |
| | | 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: "粤B67890", |
| | | 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: "粤C11223", |
| | | 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: "粤D33445", |
| | | vehicleType: "厢式货车", |
| | | department: "资产管理部", |
| | | purchaseDate: "2019-11-11", |
| | | licenseNumber: "4401-2019-0789", |
| | | licenseIssueDate: "2019-11-08", |
| | | licenseExpireDate: "2023-11-08", |
| | | status: "在用", |
| | | archived: true, |
| | | }, |
| | | ]); |
| | | const loading = ref(true); |
| | | const tableData = ref([]); |
| | | const total = ref(0); |
| | | const open = ref(false); |
| | | const title = ref(""); |
| | | const formRef = ref(null); |
| | | |
| | | // 下拉枚举 |
| | | const vehicleTypeOptions = [ |
| | | { label: "厢式货车", value: "厢式货车" }, |
| | | { label: "冷藏车", value: "冷藏车" }, |
| | | { label: "牵引车", value: "牵引车" }, |
| | | { label: "其他", value: "其他" }, |
| | | ]; |
| | | const deptOptions = ref([]); |
| | | const userList = ref([]); |
| | | |
| | | 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 queryParams = reactive({ |
| | | current: 1, |
| | | size: 10, |
| | | plateNumber: undefined, |
| | | deptId: undefined, |
| | | vehicleStatus: undefined |
| | | }); |
| | | |
| | | // 表格数据 |
| | | 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, |
| | | id: undefined, |
| | | plateNumber: undefined, |
| | | propertyOwnership: undefined, |
| | | deptId: undefined, |
| | | userId: undefined, |
| | | vehicleStatus: 'NORMAL', |
| | | inspectionExpireDate: undefined, |
| | | insuranceExpireDate: undefined, |
| | | remark: undefined |
| | | }); |
| | | |
| | | 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" }], |
| | | plateNumber: [{ required: true, message: "车牌号码不能为空", trigger: "blur" }], |
| | | deptId: [{ required: true, message: "所属部门不能为空", trigger: "change" }], |
| | | vehicleStatus: [{ 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; |
| | | // 字典获取 |
| | | function getDicts() { |
| | | request({url: '/system/user/deptTree', method: 'get'}).then(res => { |
| | | deptOptions.value = res.data || []; |
| | | }); |
| | | }; |
| | | request({url: '/system/user/list', method: 'get'}).then(res => { |
| | | userList.value = res.rows || res.data || []; |
| | | }); |
| | | } |
| | | |
| | | const resetSearch = () => { |
| | | searchForm.plateNumber = ""; |
| | | searchForm.vehicleType = ""; |
| | | searchForm.department = ""; |
| | | searchForm.status = ""; |
| | | searchForm.archived = ""; |
| | | |
| | | const statTotal = ref(0); |
| | | const statNormal = ref(0); |
| | | const statIdle = ref(0); |
| | | const statRepair = ref(0); |
| | | |
| | | function getStats() { |
| | | listVehicleInfo({ current: 1, size: 10000 }).then(res => { |
| | | const arr = res.data.records || []; |
| | | statTotal.value = arr.length; |
| | | statNormal.value = arr.filter(i => i.vehicleStatus === 'NORMAL').length; |
| | | statIdle.value = arr.filter(i => i.vehicleStatus === 'IDLE').length; |
| | | statRepair.value = arr.filter(i => i.vehicleStatus === 'REPAIR').length; |
| | | }); |
| | | } |
| | | |
| | | function getList() { |
| | | loading.value = true; |
| | | listVehicleInfo(queryParams).then(response => { |
| | | tableData.value = response.data.records; |
| | | total.value = response.data.total; |
| | | loading.value = false; |
| | | }).catch(() => { |
| | | loading.value = false; |
| | | }); |
| | | } |
| | | |
| | | function handleWarningList() { |
| | | loading.value = true; |
| | | getWarningList().then(response => { |
| | | tableData.value = response.data; |
| | | total.value = response.data.length; |
| | | loading.value = false; |
| | | ElMessage.info("已展示30天内到期的预警车辆"); |
| | | }).catch(() => { |
| | | loading.value = false; |
| | | }); |
| | | } |
| | | |
| | | function handleQuery() { |
| | | queryParams.current = 1; |
| | | getList(); |
| | | getStats(); |
| | | } |
| | | |
| | | function resetQuery() { |
| | | queryParams.plateNumber = undefined; |
| | | queryParams.deptId = undefined; |
| | | queryParams.vehicleStatus = undefined; |
| | | handleQuery(); |
| | | }; |
| | | } |
| | | |
| | | // 新增 |
| | | const openAdd = () => { |
| | | dialogTitle.value = "新增车辆"; |
| | | isEdit.value = false; |
| | | function reset() { |
| | | Object.assign(form, { |
| | | id: null, |
| | | vehicleCode: "", |
| | | plateNumber: "", |
| | | vehicleType: "", |
| | | department: "", |
| | | purchaseDate: "", |
| | | licenseInfo: "", |
| | | status: "在用", |
| | | archived: false, |
| | | id: undefined, |
| | | plateNumber: undefined, |
| | | propertyOwnership: undefined, |
| | | deptId: undefined, |
| | | userId: undefined, |
| | | vehicleStatus: 'NORMAL', |
| | | inspectionExpireDate: undefined, |
| | | insuranceExpireDate: undefined, |
| | | remark: undefined |
| | | }); |
| | | dialogVisible.value = true; |
| | | }; |
| | | if (formRef.value) formRef.value.resetFields(); |
| | | } |
| | | |
| | | // 编辑 |
| | | const openEdit = (row) => { |
| | | dialogTitle.value = "编辑车辆"; |
| | | isEdit.value = true; |
| | | function handleAdd() { |
| | | reset(); |
| | | open.value = true; |
| | | title.value = "新增车辆"; |
| | | } |
| | | |
| | | function handleUpdate(row) { |
| | | reset(); |
| | | Object.assign(form, row); |
| | | dialogVisible.value = true; |
| | | }; |
| | | open.value = true; |
| | | title.value = "修改车辆"; |
| | | } |
| | | |
| | | // 保存 |
| | | 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 }; |
| | | function submitForm() { |
| | | formRef.value.validate(valid => { |
| | | if (valid) { |
| | | if (form.id != null) { |
| | | updateVehicleInfo(form).then(response => { |
| | | ElMessage.success("修改成功"); |
| | | open.value = false; |
| | | getList(); |
| | | getStats(); |
| | | }); |
| | | } else { |
| | | addVehicleInfo(form).then(response => { |
| | | ElMessage.success("新增成功"); |
| | | open.value = false; |
| | | getList(); |
| | | getStats(); |
| | | }); |
| | | } |
| | | 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( |
| | | "是否确认将该车辆归档?归档后仅保留查询,不再参与运输任务分配。", |
| | | "归档提示", |
| | | { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "取消", |
| | | type: "warning", |
| | | } |
| | | ) |
| | | .then(() => { |
| | | row.archived = true; |
| | | if (row.status === "在用") { |
| | | row.status = "闲置"; |
| | | } |
| | | ElMessage.success("车辆已归档"); |
| | | handleQuery(); |
| | | }) |
| | | .catch(() => {}); |
| | | }; |
| | | |
| | | // 删除 |
| | | const removeRow = (row) => { |
| | | ElMessageBox.confirm("是否确认删除该车辆基础信息?", "删除提示", { |
| | | confirmButtonText: "确认", |
| | | function handleDelete(row) { |
| | | ElMessageBox.confirm('是否确认删除该车辆数据?', "警告", { |
| | | confirmButtonText: "确定", |
| | | cancelButtonText: "取消", |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | allVehicles.value = allVehicles.value.filter((v) => v.id !== row.id); |
| | | handleQuery(); |
| | | ElMessage.success("删除成功"); |
| | | }) |
| | | .catch(() => {}); |
| | | }; |
| | | type: "warning" |
| | | }).then(function() { |
| | | return delVehicleInfo(row.id); |
| | | }).then(() => { |
| | | getList(); |
| | | getStats(); |
| | | ElMessage.success("删除成功"); |
| | | }); |
| | | } |
| | | |
| | | // 状态样式 |
| | | function cancel() { |
| | | open.value = false; |
| | | reset(); |
| | | } |
| | | |
| | | |
| | | function isExpired(dateStr) { |
| | | if (!dateStr) return false; |
| | | const targetDate = new Date(dateStr).getTime(); |
| | | const now = new Date().getTime(); |
| | | return targetDate < now; |
| | | } |
| | | |
| | | function isExpiringSoon(dateStr) { |
| | | if (!dateStr) return false; |
| | | const targetDate = new Date(dateStr).getTime(); |
| | | const now = new Date().getTime(); |
| | | const diffDays = (targetDate - now) / (1000 * 3600 * 24); |
| | | return diffDays >= 0 && diffDays <= 30; |
| | | } |
| | | const statusTagType = (status) => { |
| | | if (status === "在用") return "success"; |
| | | if (status === "闲置") return "info"; |
| | | if (status === "维修") return "warning"; |
| | | if (status === "NORMAL") return "success"; |
| | | if (status === "IDLE") return "info"; |
| | | if (status === "REPAIR") return "warning"; |
| | | return "default"; |
| | | }; |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | .dialog-footer { |
| | | text-align: right; |
| | | const statusLabel = (status) => { |
| | | if (status === "NORMAL") return "在用"; |
| | | if (status === "IDLE") return "闲置"; |
| | | if (status === "REPAIR") return "维修"; |
| | | return status; |
| | | }; |
| | | |
| | | // 费用管理逻辑 |
| | | const costDrawer = ref(false); |
| | | const currentVehicleId = ref(null); |
| | | const currentVehiclePlate = ref(""); |
| | | const costLoading = ref(false); |
| | | const costList = ref([]); |
| | | const costTotal = ref(0); |
| | | const costQuery = reactive({ current: 1, size: 10, vehicleId: null }); |
| | | |
| | | function costTypeLabel(type) { |
| | | const map = { MAINTENANCE: '保养', INSPECTION: '年检', INSURANCE: '保险', REPAIR: '维修' }; |
| | | return map[type] || type; |
| | | } |
| | | </style> |
| | | |
| | | function handleCost(row) { |
| | | currentVehicleId.value = row.id; |
| | | currentVehiclePlate.value = row.plateNumber; |
| | | costQuery.vehicleId = row.id; |
| | | costDrawer.value = true; |
| | | getCostList(); |
| | | } |
| | | |
| | | function getCostList() { |
| | | costLoading.value = true; |
| | | request({ url: '/vehicle/cost/listPage', method: 'get', params: costQuery }).then(res => { |
| | | costList.value = res.data.records; |
| | | costTotal.value = res.data.total; |
| | | costLoading.value = false; |
| | | }); |
| | | } |
| | | |
| | | const costOpen = ref(false); |
| | | const costFormRef = ref(null); |
| | | const costForm = reactive({ vehicleId: null, costType: undefined, amount: undefined, costDate: undefined, remark: undefined }); |
| | | const costRules = { |
| | | costType: [{ required: true, message: "费用类型不能为空", trigger: "change" }], |
| | | amount: [{ required: true, message: "金额不能为空", trigger: "blur" }], |
| | | costDate: [{ required: true, message: "日期不能为空", trigger: "change" }] |
| | | }; |
| | | |
| | | function handleAddCost() { |
| | | costForm.vehicleId = currentVehicleId.value; |
| | | costForm.costType = undefined; |
| | | costForm.amount = undefined; |
| | | costForm.costDate = undefined; |
| | | costForm.remark = undefined; |
| | | if(costFormRef.value) costFormRef.value.resetFields(); |
| | | costOpen.value = true; |
| | | } |
| | | |
| | | function submitCostForm() { |
| | | costFormRef.value.validate(valid => { |
| | | if (valid) { |
| | | request({ url: '/vehicle/cost', method: 'post', data: costForm }).then(res => { |
| | | ElMessage.success("添加成功"); |
| | | costOpen.value = false; |
| | | getCostList(); |
| | | }); |
| | | } |
| | | }); |
| | | } |
| | | |
| | | function handleDeleteCost(row) { |
| | | ElMessageBox.confirm('确定删除该费用记录?', '提示', { type: 'warning' }).then(() => { |
| | | request({ url: '/vehicle/cost/' + row.id, method: 'delete' }).then(() => { |
| | | ElMessage.success("删除成功"); |
| | | getCostList(); |
| | | }); |
| | | }); |
| | | } |
| | | |
| | | onMounted(() => { |
| | | getDicts(); |
| | | getList(); |
| | | getStats(); |
| | | }); |
| | | </script> |