<template>
|
<div class="app-container">
|
|
<!-- 查询条件 -->
|
<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="handleAdd">新增车辆</el-button>
|
</div>
|
</div>
|
<!-- 表格 -->
|
<div class="table_list">
|
<el-table
|
v-loading="loading"
|
:data="tableData"
|
border
|
style="width: 100%"
|
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="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">
|
<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 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="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>
|
|
<!-- 分页 -->
|
<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="plateNumber">
|
<el-input v-model="form.plateNumber" placeholder="请输入车牌号码" />
|
</el-form-item>
|
</el-col>
|
<el-col :span="12">
|
<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="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="userId">
|
<el-select v-model="form.userId" placeholder="请选择责任人" style="width: 100%" filterable>
|
<el-option
|
v-for="item in userList"
|
:key="item.userId"
|
:label="item.userId + ' - ' + (item.nickName || item.userName)"
|
:value="item.userId"
|
/>
|
</el-select>
|
</el-form-item>
|
</el-col>
|
</el-row>
|
<el-row :gutter="20">
|
<el-col :span="12">
|
<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="inspectionExpireDate">
|
<el-date-picker
|
v-model="form.inspectionExpireDate"
|
type="date"
|
value-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 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, 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 loading = ref(true);
|
const tableData = ref([]);
|
const total = ref(0);
|
const open = ref(false);
|
const title = ref("");
|
const formRef = ref(null);
|
|
const deptOptions = ref([]);
|
const userList = ref([]);
|
|
const queryParams = reactive({
|
current: 1,
|
size: 10,
|
plateNumber: undefined,
|
deptId: undefined,
|
vehicleStatus: undefined
|
});
|
|
const form = reactive({
|
id: undefined,
|
plateNumber: undefined,
|
propertyOwnership: undefined,
|
deptId: undefined,
|
userId: undefined,
|
vehicleStatus: 'NORMAL',
|
inspectionExpireDate: undefined,
|
insuranceExpireDate: undefined,
|
remark: undefined
|
});
|
|
const rules = {
|
plateNumber: [{ required: true, message: "车牌号码不能为空", trigger: "blur" }],
|
deptId: [{ required: true, message: "所属部门不能为空", trigger: "change" }],
|
vehicleStatus: [{ required: true, message: "状态不能为空", trigger: "change" }]
|
};
|
|
// 字典获取
|
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 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();
|
}
|
|
function reset() {
|
Object.assign(form, {
|
id: undefined,
|
plateNumber: undefined,
|
propertyOwnership: undefined,
|
deptId: undefined,
|
userId: undefined,
|
vehicleStatus: 'NORMAL',
|
inspectionExpireDate: undefined,
|
insuranceExpireDate: undefined,
|
remark: undefined
|
});
|
if (formRef.value) formRef.value.resetFields();
|
}
|
|
function handleAdd() {
|
reset();
|
open.value = true;
|
title.value = "新增车辆";
|
}
|
|
function handleUpdate(row) {
|
reset();
|
Object.assign(form, row);
|
open.value = true;
|
title.value = "修改车辆";
|
}
|
|
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();
|
});
|
}
|
}
|
});
|
}
|
|
function handleDelete(row) {
|
ElMessageBox.confirm('是否确认删除该车辆数据?', "警告", {
|
confirmButtonText: "确定",
|
cancelButtonText: "取消",
|
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 === "NORMAL") return "success";
|
if (status === "IDLE") return "info";
|
if (status === "REPAIR") return "warning";
|
return "default";
|
};
|
|
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;
|
}
|
|
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>
|