From af8d4d90fa64ab6eea81af99ca77fa26272c3fe9 Mon Sep 17 00:00:00 2001 From: wuzilong <704541015@qq.com> Date: Sat, 7 Nov 2026 17:51:57 +0800 Subject: [PATCH] =?UTF-8?q?feat(pl):=20=E8=B0=83=E6=95=B4=E5=8A=A0?= =?UTF-8?q?=E6=B2=B9=E7=99=BB=E8=AE=B0=E5=88=97=E8=A1=A8=E6=8E=92=E5=BA=8F?= =?UTF-8?q?=E3=80=81=E5=BF=85=E5=A1=AB=E9=A1=B9=E5=92=8C=E9=A1=B6=E9=83=A8?= =?UTF-8?q?=E6=B1=87=E6=80=BB=E5=8C=BA=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 按登记日期倒序列表并增加列统计,期初公里数改为必填,车辆统计卡片改为待开发。 Co-authored-by: Cursor --- backend/app/schemas/pl/vehicle_fuel.py | 8 +- .../app/services/pl_vehicle_fuel_service.py | 15 +- .../test_pl_vehicle_fuel_list_filters.py | 8 + backend/tests/test_vehicle_fuel_schema.py | 27 ++++ miniprogram/pages/pl/fuel-register/form.vue | 20 ++- .../FuelRegisterListPage.vue | 149 ++++++++++-------- 6 files changed, 155 insertions(+), 72 deletions(-) diff --git a/backend/app/schemas/pl/vehicle_fuel.py b/backend/app/schemas/pl/vehicle_fuel.py index 36f56b21b..092a6078b 100644 --- a/backend/app/schemas/pl/vehicle_fuel.py +++ b/backend/app/schemas/pl/vehicle_fuel.py @@ -22,7 +22,7 @@ class VehicleFuelRegisterCreate(BaseModel): register_date: date = Field(..., alias="registerDate") registrant_id: Optional[str] = Field(default=None, alias="registrantId") license_plate: str = Field(..., alias="licensePlate") - odometer_km: Optional[Decimal] = Field(default=None, alias="odometerKm") + odometer_km: Decimal = Field(..., alias="odometerKm") fuel_liters: Decimal = Field(..., alias="fuelLiters") attachment_urls: Optional[str] = Field(default=None, alias="attachmentUrls") remark: Optional[str] = None @@ -45,8 +45,10 @@ class VehicleFuelRegisterCreate(BaseModel): @field_validator("odometer_km") @classmethod - def validate_odometer_km(cls, v: Optional[Decimal]) -> Optional[Decimal]: - if v is not None and v < 0: + def validate_odometer_km(cls, v: Decimal) -> Decimal: + if v is None: + raise ValueError("期初公里数不能为空") + if v < 0: raise ValueError("期初公里数不能为负数") return v diff --git a/backend/app/services/pl_vehicle_fuel_service.py b/backend/app/services/pl_vehicle_fuel_service.py index 059a51145..3378633f4 100644 --- a/backend/app/services/pl_vehicle_fuel_service.py +++ b/backend/app/services/pl_vehicle_fuel_service.py @@ -168,6 +168,15 @@ def to_read( ) +def fuel_register_list_order(): + """列表与导出:按加油日期倒序;同一天再按创建时间、主键倒序。""" + return ( + PlVehicleFuelRegister.register_date.desc(), + PlVehicleFuelRegister.create_time.desc(), + PlVehicleFuelRegister.id.desc(), + ) + + def list_registers( db: Session, tenant_no: str, @@ -260,11 +269,7 @@ def list_registers( cap = int(max_page_size) if max_page_size else 500 page_size = min(max(1, page_size), cap) rows = ( - # 与 seqNo 倒序一致:序号大的在前(create_time ASC,id ASC → seqNo;列表取反) - query.order_by( - PlVehicleFuelRegister.create_time.desc(), - PlVehicleFuelRegister.id.desc(), - ) + query.order_by(*fuel_register_list_order()) .offset((page - 1) * page_size) .limit(page_size) .all() diff --git a/backend/tests/test_pl_vehicle_fuel_list_filters.py b/backend/tests/test_pl_vehicle_fuel_list_filters.py index a0f8e07bf..22024c912 100644 --- a/backend/tests/test_pl_vehicle_fuel_list_filters.py +++ b/backend/tests/test_pl_vehicle_fuel_list_filters.py @@ -47,3 +47,11 @@ def test_fuel_register_filters(): def test_empty(): assert build_fuel_register_column_filters() == [] + + +def test_fuel_register_list_order_by_register_date_desc(): + from app.services.pl_vehicle_fuel_service import fuel_register_list_order + + compiled = " ".join(_compile(clause) for clause in fuel_register_list_order()) + assert compiled.index("register_date desc") < compiled.index("create_time desc") + assert compiled.index("create_time desc") < compiled.index("pl_vehicle_fuel_register.id desc") diff --git a/backend/tests/test_vehicle_fuel_schema.py b/backend/tests/test_vehicle_fuel_schema.py index 6408b58bf..c0d04dbbd 100644 --- a/backend/tests/test_vehicle_fuel_schema.py +++ b/backend/tests/test_vehicle_fuel_schema.py @@ -54,9 +54,36 @@ def test_create_accepts_shanxia_factory(): "registerDate": "2026-09-12", "licensePlate": "皖A12345", "fuelLiters": "1176", + "odometerKm": "0", } ) assert body.fuel_category == "shanxia_factory" + assert body.odometer_km == Decimal("0") + + +def test_create_rejects_missing_odometer(): + with pytest.raises(ValidationError): + VehicleFuelRegisterCreate.model_validate( + { + "fuelCategory": "bailian", + "registerDate": "2026-09-12", + "licensePlate": "皖A12345", + "fuelLiters": "10", + } + ) + + +def test_create_rejects_negative_odometer(): + with pytest.raises(ValidationError): + VehicleFuelRegisterCreate.model_validate( + { + "fuelCategory": "bailian", + "registerDate": "2026-09-12", + "licensePlate": "皖A12345", + "fuelLiters": "10", + "odometerKm": "-1", + } + ) def test_calc_fuel_tons(): diff --git a/miniprogram/pages/pl/fuel-register/form.vue b/miniprogram/pages/pl/fuel-register/form.vue index dfe37afbd..e69016e18 100644 --- a/miniprogram/pages/pl/fuel-register/form.vue +++ b/miniprogram/pages/pl/fuel-register/form.vue @@ -80,13 +80,14 @@ - 期初公里数/KM + 期初公里数/KM* @@ -267,6 +268,7 @@ const form = reactive({ const fieldErr = reactive({ registerDate: false, licensePlate: false, + odometerKm: false, fuelLiters: false }) @@ -334,6 +336,7 @@ function onDateChange(e) { function onOdometerInput(e) { form.odometerKm = e.detail.value + fieldErr.odometerKm = false } function onLitersInput(e) { @@ -439,6 +442,7 @@ function previewAt(idx) { function validate() { fieldErr.registerDate = false fieldErr.licensePlate = false + fieldErr.odometerKm = false fieldErr.fuelLiters = false if (!form.fuelCategory) { uni.showToast({ title: '请选择加油类别', icon: 'none' }) @@ -454,6 +458,18 @@ function validate() { uni.showToast({ title: '请选择车牌号', icon: 'none' }) return false } + const odoRaw = String(form.odometerKm ?? '').trim() + if (!odoRaw) { + fieldErr.odometerKm = true + uni.showToast({ title: '请输入期初公里数', icon: 'none' }) + return false + } + const odo = Number(odoRaw) + if (Number.isNaN(odo) || odo < 0) { + fieldErr.odometerKm = true + uni.showToast({ title: '期初公里数须为非负数字', icon: 'none' }) + return false + } const litersRaw = String(form.fuelLiters ?? '').trim() if (!litersRaw) { fieldErr.fuelLiters = true diff --git a/web-admin/src/views/pl/vehicle-fuel-register/FuelRegisterListPage.vue b/web-admin/src/views/pl/vehicle-fuel-register/FuelRegisterListPage.vue index 9959903aa..8e94a7c16 100644 --- a/web-admin/src/views/pl/vehicle-fuel-register/FuelRegisterListPage.vue +++ b/web-admin/src/views/pl/vehicle-fuel-register/FuelRegisterListPage.vue @@ -2,16 +2,7 @@