From 60dd86ab88d75f320fd7d0da14ba1af488989dd7 Mon Sep 17 00:00:00 2001 From: ouyangxq <775153912@qq.com> Date: Sat, 3 Oct 2026 19:41:55 +0800 Subject: [PATCH] fix(fleet): leave unknown vehicle fuel consumption empty --- .../pages/VehiclesQueryRace.test.ts | 18 ++++++++++++++++++ .../pages/VehiclesView.vue | 6 +++--- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/src/modules/overseas-master-data/pages/VehiclesQueryRace.test.ts b/src/modules/overseas-master-data/pages/VehiclesQueryRace.test.ts index 3e802ea6..be8e6507 100644 --- a/src/modules/overseas-master-data/pages/VehiclesQueryRace.test.ts +++ b/src/modules/overseas-master-data/pages/VehiclesQueryRace.test.ts @@ -52,3 +52,21 @@ it('keeps loading until the currently selected query finishes', async () => { expect(wrapper.findComponent({ name: 'DataTable' }).props('loading')).toBe(false) expect(api.listVehicles).toHaveBeenCalledTimes(2) }) + +it('opens a new vehicle with unknown fuel consumption blank instead of clamping it to 0.01', async () => { + vi.mocked(api.listVehicles).mockResolvedValue({ records: [], total: 0, page: 1, size: 20, pages: 0 }) + const wrapper = shallowMount(VehiclesView, { global: { stubs: { + AdminPage: layout, ListPageLayout: layout, QueryToolbar: true, LoadErrorState: true, + DataTable: { ...table, template: '
' }, + AppDialog: { name: 'AppDialog', props: ['modelValue'], emits: ['confirm'], template: '
' }, + ElButton: { template: '' }, ElForm: layout, ElFormItem: layout, + ElInputNumber: { name: 'ElInputNumber', props: ['modelValue'], template: '' }, ElInput: true, ElSelect: true, ElOption: true, ElTag: true, + } } }) + wrappers.push(wrapper); await flushPromises() + await wrapper.findAll('button').find(button => button.text() === '添加车辆')!.trigger('click') + await flushPromises() + expect(wrapper.findAllComponents({ name: 'ElInputNumber' })[0]!.get('input').element.value).toBe('') + await wrapper.findAll('button').find(button => button.text() === '保存')!.trigger('click') + await flushPromises() + expect(api.createVehicle).not.toHaveBeenCalled() +}) diff --git a/src/modules/overseas-master-data/pages/VehiclesView.vue b/src/modules/overseas-master-data/pages/VehiclesView.vue index 45e41606..97952a1e 100644 --- a/src/modules/overseas-master-data/pages/VehiclesView.vue +++ b/src/modules/overseas-master-data/pages/VehiclesView.vue @@ -13,7 +13,7 @@ const router=useRouter(),access=useAccessPreviewStore(),rows=ref('OWNED'),tabs:[string,VehicleOwnership][]=[['自有车辆','OWNED'],['外派车辆','DISPATCHED']] const filters=ref({keyword:'',region:'',status:''});const fields:QueryField[]=[{key:'keyword',type:'input',label:'车辆关键词',placeholder:'车牌 / 司机 / 车型',width:220},{key:'region',type:'select',label:'区域',placeholder:'全部区域',width:140,options:[{label:'国内',value:'DOMESTIC'},{label:'海外',value:'OVERSEAS'}]},{key:'status',type:'select',label:'状态',placeholder:'全部状态',width:140,options:Object.entries(vehicleStatusLabels).map(([value,label])=>({label,value}))}] const columns:DataTableColumn[]=[{key:'actions',label:'操作',width:250,fixed:'left',slotName:'actions'},{key:'plateNumber',prop:'plateNumber',label:'车牌',minWidth:130},{key:'model',prop:'model',label:'车型',minWidth:180},{key:'fuelConsumptionPer100Km',prop:'fuelConsumptionPer100Km',label:'油耗(L/100km)',minWidth:130,align:'right'},{key:'mileageKm',prop:'mileageKm',label:'当前公里码(km)',minWidth:140,align:'right'},{key:'driverOrDispatchCompany',prop:'driverOrDispatchCompany',label:'司机 / 外派单位',minWidth:160},{key:'phone',prop:'phone',label:'联系电话',minWidth:145},{key:'maxPalletSpaces',prop:'maxPalletSpaces',label:'最大托位',minWidth:100,align:'right'},{key:'maxLoadKg',prop:'maxLoadKg',label:'最大载重(kg)',minWidth:130,align:'right'},{key:'maxVolumeCbm',prop:'maxVolumeCbm',label:'可用容积(m³)',minWidth:130,align:'right'},{key:'status',label:'状态',width:100,slotName:'status'},{key:'region',label:'区域',width:100,slotName:'region'}] -const form=reactive({plateNumber:'',model:'',fuelConsumptionPer100Km:0,mileageKm:0,driverOrDispatchCompany:'',phone:'',region:'OVERSEAS' as VehicleRegion,ownership:'OWNED' as VehicleOwnership,status:'IN_SERVICE' as VehicleStatus,remark:'',recordVersion:0,maxPalletSpaces:null as number|null,maxLoadKg:null as number|null,maxVolumeCbm:null as number|null}) +const form=reactive({plateNumber:'',model:'',fuelConsumptionPer100Km:null as number|null,mileageKm:0,driverOrDispatchCompany:'',phone:'',region:'OVERSEAS' as VehicleRegion,ownership:'OWNED' as VehicleOwnership,status:'IN_SERVICE' as VehicleStatus,remark:'',recordVersion:0,maxPalletSpaces:null as number|null,maxLoadKg:null as number|null,maxVolumeCbm:null as number|null}) function params(){return{page:page.value,size:pageSize.value,keyword:String(filters.value.keyword||'')||undefined,ownership:ownership.value,region:(filters.value.region||undefined) as VehicleRegion|undefined,status:(filters.value.status||undefined) as VehicleStatus|undefined}} let querySequence = 0 async function load() { @@ -28,9 +28,9 @@ async function load() { } onBeforeUnmount(() => { querySequence++ }) function search(){if(page.value===1)void load();else page.value=1} function selectOwnership(v:VehicleOwnership){if(ownership.value===v)return;ownership.value=v;search()} -function reset(){Object.assign(form,{plateNumber:'',model:'',fuelConsumptionPer100Km:0,mileageKm:0,driverOrDispatchCompany:'',phone:'',region:'OVERSEAS',ownership:ownership.value,status:'IN_SERVICE',remark:'',recordVersion:0,maxPalletSpaces:null,maxLoadKg:null,maxVolumeCbm:null})} +function reset(){Object.assign(form,{plateNumber:'',model:'',fuelConsumptionPer100Km:null,mileageKm:0,driverOrDispatchCompany:'',phone:'',region:'OVERSEAS',ownership:ownership.value,status:'IN_SERVICE',remark:'',recordVersion:0,maxPalletSpaces:null,maxLoadKg:null,maxVolumeCbm:null})} function openCreate(){editingId.value='';reset();editorOpen.value=true} async function openEdit(row:VehicleDetail){try{const d=await getVehicle(row.id);editingId.value=d.id;Object.assign(form,{...d,driverOrDispatchCompany:d.driverOrDispatchCompany||'',phone:d.phone||'',remark:d.remark||''});editorOpen.value=true}catch(e){ElMessage.error(masterDataErrorMessage(e,'车辆详情加载失败'))}} -async function save(){if(!form.plateNumber||!form.model||form.fuelConsumptionPer100Km<=0){ElMessage.warning('请完整填写车辆必填信息');return}const capacity=[form.maxPalletSpaces,form.maxLoadKg,form.maxVolumeCbm];if(capacity.some(v=>v!=null)&&capacity.some(v=>v==null||v<=0)){ElMessage.warning('托位、载重和容积须同时填写正数,或全部留空');return}saving.value=true;try{const base={plateNumber:form.plateNumber,model:form.model,fuelConsumptionPer100Km:form.fuelConsumptionPer100Km,mileageKm:form.mileageKm,driverOrDispatchCompany:form.driverOrDispatchCompany||null,phone:form.phone||null,region:form.region,ownership:form.ownership,remark:form.remark||null,maxPalletSpaces:form.maxPalletSpaces??null,maxLoadKg:form.maxLoadKg??null,maxVolumeCbm:form.maxVolumeCbm??null};if(editingId.value)await updateVehicle(editingId.value,{...base,recordVersion:form.recordVersion});else await createVehicle({...base,status:form.status});ElMessage.success(editingId.value?'车辆已更新':'车辆已创建');editorOpen.value=false;await load()}catch(e){ElMessage.error(masterDataErrorMessage(e,'车辆保存失败'))}finally{saving.value=false}} +async function save(){if(!form.plateNumber||!form.model||form.fuelConsumptionPer100Km==null||form.fuelConsumptionPer100Km<=0){ElMessage.warning('请完整填写车辆必填信息');return}const capacity=[form.maxPalletSpaces,form.maxLoadKg,form.maxVolumeCbm];if(capacity.some(v=>v!=null)&&capacity.some(v=>v==null||v<=0)){ElMessage.warning('托位、载重和容积须同时填写正数,或全部留空');return}saving.value=true;try{const base={plateNumber:form.plateNumber,model:form.model,fuelConsumptionPer100Km:form.fuelConsumptionPer100Km,mileageKm:form.mileageKm,driverOrDispatchCompany:form.driverOrDispatchCompany||null,phone:form.phone||null,region:form.region,ownership:form.ownership,remark:form.remark||null,maxPalletSpaces:form.maxPalletSpaces??null,maxLoadKg:form.maxLoadKg??null,maxVolumeCbm:form.maxVolumeCbm??null};if(editingId.value)await updateVehicle(editingId.value,{...base,recordVersion:form.recordVersion});else await createVehicle({...base,status:form.status});ElMessage.success(editingId.value?'车辆已更新':'车辆已创建');editorOpen.value=false;await load()}catch(e){ElMessage.error(masterDataErrorMessage(e,'车辆保存失败'))}finally{saving.value=false}} function openStatus(row:VehicleDetail){statusRow.value=row;statusTarget.value=row.status;statusOpen.value=true} async function submitStatus(){const row=statusRow.value;if(!row)return;saving.value=true;try{await changeVehicleStatus(row.id,statusTarget.value,row.recordVersion);ElMessage.success('车辆状态已更新');statusOpen.value=false;await load()}catch(e){ElMessage.error(masterDataErrorMessage(e,'车辆状态更新失败'))}finally{saving.value=false}} async function exportCsv(){exporting.value=true;try{const{page:_,size:__,...q}=params();saveCsv(await exportVehicles(q),'vehicles.csv')}catch(e){ElMessage.error(masterDataErrorMessage(e,'车辆导出失败'))}finally{exporting.value=false}} watch([page,pageSize],load);onMounted(load)