输入文件:
- 租赁任务考核_2026年{1,2,3}月.xlsx (考核源数据)
- {1,2}月.xlsx (客户盈亏表)
- 车辆里程考核与奖金发放规则(V.1.2).docx
输出文件:
- 里程任务考核_{1,2,3}月核算.xlsx (月度核算结果)
- 里程任务考核_Q1汇总.xlsx (含车辆台账)
- 3月客户盈亏表(待填写).xlsx (模版)
.claude_memory: 项目记忆(规则/偏好/架构/测试车辆)
.claude_plans: 历次计划文件
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
28 KiB
Phase 2 ETC 模块完成计划(Controller + API Client + 前端)
Context
Phase 1 基础设施层(FeeType 枚举、DeductionRequest、IDeductionService 重构、ContractMatchService、ReviewConfig 扩展)已完成并编译通过。 Phase 2 ETC 模块后端核心(Entity/Mapper/Service/Event/Listener)已完成并编译通过。
本次任务: 完成 Phase 2 剩余部分:
- ETC 后端 Controller 层(3 个 Controller)
- EtczjApiClient(etczj.com HTTP 客户端 + OCR 验证码)
- 前端 ETC 配置页面 + ETC 账单查询页面
用户决策:
- 账户结构:共用一个能源账户(三种费用从同一余额扣款)
- 账单模式:各费用类型独立账单
- 业务流程:ETC/电费与氢费完全一致(合同匹配 → 审核 → 扣款)
- 数据源:先设计通用框架,具体 API/Excel 格式后续对接
架构方案:独立明细表 + 共享账户层
modules/
station/ ← 已有:氢费数据源(不动)
etc/ ← 新增:ETC 数据源
electricity/ ← 新增:电费数据源
energy/ ← 已有:共享结算层(小幅扩展)
payment/ ← 已有:款项管理(小幅扩展)
核心原则: 三种费用的明细/账单各自独立(字段差异大),但扣款引擎、账户、流水、充值、款项管理完全共享。
Phase 1: 基础设施层改造(energy 域)
1.1 新增 FeeType 枚举
文件: modules/energy/enums/FeeType.java(新建)
public enum FeeType {
HYDROGEN(1, "氢费"),
ETC(2, "高速通行费"),
ELECTRICITY(3, "电费");
private final int code;
private final String label;
}
1.2 重构 IDeductionService → 接受通用扣款请求
改动文件:
modules/energy/service/IDeductionService.javamodules/energy/service/impl/DeductionServiceImpl.java
改动内容:
新增通用 DTO DeductionRequest:
@Data @Builder
public class DeductionRequest {
private FeeType feeType;
private Long detailId; // 明细ID(在各自的明细表中)
private Long customerId;
private String customerName;
private Long contractId;
private BigDecimal amount; // 扣款金额
private Integer paymentMode; // 1-预充值 2-月结 3-自行结算
private Integer deductionStatus; // 当前扣款状态(幂等守卫用)
}
接口签名变更:
// 原:DeductionResult deduct(EnergyHydrogenDetail detail);
// 新:
DeductionResult deduct(DeductionRequest request);
void reDeduct(DeductionRequest request, BigDecimal newAmount);
DeductionServiceImpl 改动点:
deduct()方法参数从EnergyHydrogenDetail改为DeductionRequest,逻辑不变(读 customerId/amount/contractId/paymentMode)- 移除
detailMapper.updateById(detail)—— 扣款服务不再直接更新明细表,改为返回DeductionResult,由调用方负责更新各自的明细表扣款状态 - 流水 description 加入
feeType.getLabel()(如 "ETC扣款" / "电费扣款") reDeduct()同理,不再直接操作detailMapper
向后兼容: 在 EnergyDetailImportListener(氢费监听器)中构造 DeductionRequest.fromHydrogenDetail(detail),调用新接口后手动更新氢费明细扣款状态。
1.3 energy_account_transaction 表加 fee_type 列
DDL 迁移脚本: db/energy/V2__add_fee_type_to_transaction.sql
ALTER TABLE energy_account_transaction
ADD COLUMN fee_type TINYINT NOT NULL DEFAULT 1 COMMENT '费用类型:1-氢费 2-ETC 3-电费';
ALTER TABLE energy_account_transaction
ADD INDEX idx_eat_fee_type (fee_type);
EnergyAccountTransaction.java 新增 feeType 字段。
1.4 customer_payment_item 款项解构扩展
fee_type 枚举扩展(已有字段):
- 现有:1-租赁费 2-氢费充值 3-押金 4-违约金 5-其他
- 新增:6-ETC充值 7-电费充值
PaymentFlowService 的流转逻辑需根据新 fee_type 创建对应充值单。
1.5 通用合同匹配抽取
现有合同匹配逻辑在 EnergyDetailImportListener 中(车牌+时间→合同)。
抽取为共享服务:
新建: modules/energy/service/IContractMatchService.java
public interface IContractMatchService {
ContractMatchResult matchContract(String plateNumber, Date eventTime);
}
返回 ContractMatchResult(customerId, customerName, contractId, contractCode, costType, paymentMode)。
ETC/电费/氢费三个监听器共用此服务。
1.6 审核配置扩展
energy_review_config 表加 fee_type 列:
ALTER TABLE energy_review_config
ADD COLUMN fee_type TINYINT NOT NULL DEFAULT 1 COMMENT '费用类型:1-氢费 2-ETC 3-电费';
DROP INDEX uk_erc_level_customer ON energy_review_config;
CREATE UNIQUE INDEX uk_erc_level_customer_fee ON energy_review_config (config_level, customer_id, fee_type);
每种费用类型可独立配置"是否需要审核后才扣款"。
Phase 2: ETC 模块(modules/etc/)
2.0 ETC 数据源逆向分析(etczj.com - 浙江货车ETC)
平台信息: https://www.etczj.com (Nuxt.js + Element UI 前端,nginx/1.27.2 后端)
认证流程:
1. GET /createCaptcha?verifyCodeSize=null&tmp={random}&secret={guid} → 图形验证码图片
2. POST /member/toLogin?secret={guid}
Body: { acctId: "手机号", password: "Base64编码密码", checkCode: "验证码", msgCode: "", secret: guid }
Response: { state: "1", payload: { randomVal: "xxx", signState: "1" } }
3. 后续请求 Header: Randomval: {randomVal}(存 localStorage)
核心业务 API:
| API | 方法 | 说明 | 关键参数 |
|---|---|---|---|
/vehicleManage/queryVehicleConsumptionDetailPage |
POST | 通行记录分页 | transTimeBegin/End, postingTimeBegin/End, vehicleCode, licenseColor, vcEnStation, vcExStation, currPage, pageSize |
/vehicleManage/sumVehicleToll |
POST | 通行费汇总 | 同上(返回 totalPassAmount, totalServiceAmount) |
/vehicleManage/viewVehiclePage |
POST | 车辆列表 | vehicleCode, currPage, pageSize |
/largeFileExport/billDetails |
POST | 通行记录导出 | postingTimeBegin/End, transTimeBegin/End, vehicleCode |
/member/flowList |
POST | 账单流水 | - |
/member/viewMember |
POST | 用户信息 | - |
通行记录响应字段映射 → etc_toll_record 表:
| etczj 字段 | 含义 | → 表字段 |
|---|---|---|
| vehicleCode | 车牌号码 | plate_number |
| licenseColor | 车牌颜色(0-6) | license_color |
| cardType | 卡类型 | card_type |
| cardCode | 通行卡号 | etc_card_number |
| postingTimeStr | 记账日期 | posting_time |
| transDate + transTime | 通行日期+时间 | trans_time |
| enStation | 入口站 | entry_station_name |
| exStation | 出口站 | exit_station_name |
| dToll | 通行费用(元) | toll_amount |
| serviceFee | 服务费(元) | service_fee |
| appealStatus | 申诉状态 | appeal_status |
同步策略设计要点:
- 登录需图形验证码 → 需 OCR 或人工介入。建议:首次登录获取 session 后缓存
randomVal,session 过期时告警人工重新登录 - 增量同步:按
postingTimeBegin/End(记账日期)拉取,每次从lastSyncTime开始 - 去重键:
vehicleCode + transDate + transTime + enStation + exStation(平台无唯一订单号) - 分页:
currPage+pageSize,默认 pageSize=5,建议调大到 100 - 日期限制:时间范围最多 31 天
2.1 数据库表
etc_toll_record(ETC通行记录表):
| 字段 | 类型 | 说明 |
|---|---|---|
| id | BIGINT | 主键 |
| record_code | VARCHAR(32) | 记录编码(系统生成,唯一) |
| etc_card_number | VARCHAR(64) | 通行卡号(cardCode) |
| card_type | VARCHAR(32) | 卡类型(cardType) |
| plate_number | VARCHAR(16) | 车牌号 |
| license_color | TINYINT | 车牌颜色(0-6) |
| vehicle_id | BIGINT | 车辆ID(匹配后) |
| contract_id | BIGINT | 合同ID(匹配后) |
| customer_id | BIGINT | 客户ID(匹配后) |
| customer_name | VARCHAR(128) | 客户名称 |
| entry_station_name | VARCHAR(128) | 入口站 |
| exit_station_name | VARCHAR(128) | 出口站 |
| trans_time | DATETIME | 通行时间(transDate+transTime) |
| posting_time | DATETIME | 记账日期(postingTimeStr) |
| toll_amount | DECIMAL(10,2) | 通行费(元)(dToll) |
| service_fee | DECIMAL(10,2) | 服务费(元)(serviceFee) |
| total_amount | DECIMAL(10,2) | 合计金额(toll+service) |
| appeal_status | TINYINT | 申诉状态 |
| cost_type | TINYINT | 费用承担方 |
| payment_mode | TINYINT | 付款模式 |
| contract_matched | TINYINT | 合同匹配状态 |
| review_status | TINYINT | 审核状态 |
| deduction_status | TINYINT | 扣款状态 |
| bill_id | BIGINT | 关联账单ID |
| source_type | TINYINT | 来源:1-API同步 |
| source_dedup_key | VARCHAR(128) | 去重键(车牌+通行时间+入口+出口) |
| is_oneos_vehicle | TINYINT | 是否OneOS车辆 |
| + BaseEntity 审计字段 |
etc_sync_config 和 etc_sync_log:复用 station 的 sync_config/sync_log 结构,provider_type 固定为 ETCZJ。额外字段:acct_id(手机号)、password(加密存储)。
energy_etc_bill(ETC账单表):
| 字段 | 类型 | 说明 |
|---|---|---|
| id | BIGINT | 主键 |
| bill_code | VARCHAR(32) | 账单编码 |
| customer_id | BIGINT | 客户ID |
| bill_period_start/end | DATE | 账单周期 |
| total_toll_count | INT | 通行笔数 |
| total_toll_amount | DECIMAL(12,2) | 通行总金额 |
| total_service_fee | DECIMAL(12,2) | 服务费总额 |
| receivable_amount | DECIMAL(12,2) | 应收金额 |
| actual_amount | DECIMAL(12,2) | 实收金额 |
| adjustment_amount | DECIMAL(12,2) | 调整额 |
| payment_status | TINYINT | 支付状态 |
| review_status | TINYINT | 审核状态 |
| + 审核/财务/审计字段 |
2.2 代码结构
modules/etc/
entity/
record/po/EtcTollRecord.java
record/vo/EtcTollRecordVO.java
record/query/EtcTollRecordQuery.java
record/req/UpdateEtcRecordReq.java
sync/po/EtcSyncConfig.java
sync/po/EtcSyncLog.java
bill/po/EnergyEtcBill.java
bill/vo/EtcBillVO.java
bill/req/EtcBillGenerateReq.java
mapper/
EtcTollRecordMapper.java
EtcSyncConfigMapper.java
EtcSyncLogMapper.java
EnergyEtcBillMapper.java
service/
IEtcTollRecordService.java
IEtcSyncConfigService.java
IEtcBillService.java
impl/EtcTollRecordServiceImpl.java
impl/EtcSyncConfigServiceImpl.java
impl/EtcBillServiceImpl.java
sync/EtcSyncStrategy.java ← 策略接口
sync/EtczjSyncStrategy.java ← etczj.com 具体实现(登录+分页拉取+字段映射)
sync/EtczjApiClient.java ← HTTP 客户端(登录/session管理/通行记录查询)
sync/EtczjApiResponse.java ← 响应 DTO
ingest/EtcIngestTemplate.java ← 模板方法(extract→validate→dedup→match→persist→event)
controller/
EtcTollRecordController.java
EtcSyncConfigController.java
EtcBillController.java
event/
EtcRecordImportedEvent.java
listener/
EtcDetailImportListener.java ← 监听 EtcRecordImportedEvent,执行合同匹配+扣款
validation/
EtcValidationChain.java
2.3 数据流
EtczjSyncStrategy 定时/手动同步:
1. EtczjApiClient.login(acctId, password) → 获取 randomVal session
2. 按日期范围分页调用 /vehicleManage/queryVehicleConsumptionDetailPage
- 从 lastSyncTime 开始,每次最多31天
- pageSize=100,循环翻页直到无更多数据
3. 字段映射:etczj 响应 → EtcTollRecordDTO
4. → EtcIngestTemplate.ingest()
→ extract → validate → dedup(source_dedup_key) → matchVehicle → persist(etc_toll_record)
→ publishEvent(EtcRecordImportedEvent)
5. → EtcDetailImportListener
→ 筛选 is_oneos_vehicle=1
→ contractMatchService.matchContract(plateNumber, transTime)
→ 审核配置检查(FeeType.ETC)
→ deductionService.deduct(DeductionRequest)
→ 更新 etc_toll_record.deduction_status
Session 管理:
- randomVal 缓存在 Redis,key: `etc:session:{configId}`,过期后自动重新登录
- 图形验证码处理:OCR 自动识别(Tesseract/百度OCR)
- GET /createCaptcha?secret={guid} → 图片
- OCR 识别 → 4位数字
- 识别失败重试(刷新验证码重试,最多3次)
- 3次均失败 → 告警通知人工介入
- 去重策略:vehicleCode + transTime + enStation + exStation 组合键
2.4 API 接口(约 20 个)
| 模块 | 接口数 |
|---|---|
| ETC 通行记录 CRUD + 审核 + 导出 | 8 |
| ETC 同步配置 + 手动触发 + 日志 | 7 |
| ETC 账单生成 + 审核 + 调整项 | 8 |
Phase 3: 电费模块(modules/electricity/)
3.1 数据库表
electricity_charge_record(充电记录表):
| 字段 | 类型 | 说明 |
|---|---|---|
| id | BIGINT | 主键 |
| record_code | VARCHAR(32) | 记录编码 |
| charging_station_id | BIGINT | 充电站ID(关联已有 charging_station 表) |
| charging_station_name | VARCHAR(128) | 充电站名称 |
| plate_number | VARCHAR(16) | 车牌号 |
| vehicle_id / contract_id / customer_id | BIGINT | 匹配后填充 |
| charging_start_time | DATETIME | 充电开始 |
| charging_end_time | DATETIME | 充电结束 |
| charging_duration | INT | 时长(分钟) |
| kwh | DECIMAL(10,4) | 充电量(度) |
| unit_price | DECIMAL(10,4) | 单价(元/度) |
| charge_amount | DECIMAL(10,2) | 电费(元) |
| service_fee | DECIMAL(10,2) | 服务费(元) |
| total_amount | DECIMAL(10,2) | 合计金额 |
| cost_type / payment_mode / contract_matched / review_status / deduction_status / bill_id | 与氢费/ETC 一致 | |
| source_type | TINYINT | 来源:1-Excel导入 2-RPA导入 |
| source_row_key | VARCHAR(64) | 源Excel行唯一键(去重) |
| is_oneos_vehicle | TINYINT | 是否OneOS车辆 |
| + BaseEntity 审计字段 |
energy_electricity_bill(电费账单表): 结构类似 ETC 账单,特有字段:total_kwh, total_charge_amount, total_service_fee。
3.2 代码结构
与 ETC 模块镜像,核心差异:
- 无 API 同步(暂时),数据入口为 Excel 导入(手动上传 / RPA 落盘后系统扫描)
ElectricityExcelIngestStrategy实现ElectricityIngestTemplate- 关联已有
chargingstation/模块的充电站主数据 - 校验链包含:电量/金额一致性校验、充电站匹配校验
3.3 数据流
Excel 手动导入 / RPA 定期落盘
→ ElectricityIngestTemplate.ingest()
→ extract(解析Excel) → validate → dedup(source_row_key) → matchVehicle → persist
→ publishEvent(ElectricityRecordImportedEvent)
→ ElectricityDetailImportListener
→ 合同匹配 → 审核配置检查(FeeType.ELECTRICITY)→ 扣款 → 更新状态
3.4 API 接口(约 15 个)
| 模块 | 接口数 |
|---|---|
| 充电记录 CRUD + 审核 + 导入/导出 | 8 |
| 电费账单生成 + 审核 + 调整项 | 7 |
Phase 4: 账户层统一视图
4.1 流水查询增加 fee_type 过滤
改动文件:
TransactionQuery.java— 新增feeType可选参数EnergyAccountController.java— 流水分页接口支持按费用类型筛选
4.2 账户汇总接口
新增接口: GET /energy/account/{id}/fee-summary
返回各费用类型的扣款/充值汇总:
{
"hydrogen": { "totalDeducted": 50000, "count": 320 },
"etc": { "totalDeducted": 12000, "count": 580 },
"electricity": { "totalDeducted": 8000, "count": 150 }
}
Phase 5: 前端菜单与页面
5.1 菜单结构
能源管理
├── 加氢明细(已有)
├── ETC 通行记录(新增)
├── 充电记录(新增)
├── 能源账户(已有,增加 fee_type 筛选)
├── 充值单管理(已有)
├── 氢费账单(已有)
├── ETC 账单(新增)
├── 电费账单(新增)
└── 审核配置(已有,增加 fee_type 维度)
加氢站管理(已有,不动)
ETC 管理(新增)
├── ETC 同步配置
└── ETC 同步日志
款项管理(已有)
└── fee_type 解构类型新增 ETC充值/电费充值
实施顺序
| 步骤 | 内容 | 依赖 |
|---|---|---|
| 1 | Phase 1 基础设施(FeeType枚举、DeductionRequest、IDeductionService重构、DB迁移、ContractMatchService抽取、ReviewConfig扩展) | 无 |
| 2 | Phase 1 向后兼容(更新氢费监听器/服务适配新接口) | Step 1 |
| 3 | Phase 2 ETC 模块(实体→Mapper→Service→Controller→事件→监听器→测试) | Step 2 |
| 4 | Phase 3 电费模块(同上) | Step 2,可与 Step 3 并行 |
| 5 | Phase 4 账户层统一视图 | Step 3 & 4 |
| 6 | Phase 5 前端页面 | Step 3 & 4 |
| 7 | Payment 域扩展(fee_type 解构+流转) | Step 1 |
关键改动文件清单
修改已有文件
| 文件 | 改动 |
|---|---|
energy/service/IDeductionService.java |
接口签名改为 DeductionRequest |
energy/service/impl/DeductionServiceImpl.java |
实现适配,移除 detailMapper 直接操作 |
energy/entity/account/po/EnergyAccountTransaction.java |
新增 feeType 字段 |
energy/listener/EnergyDetailImportListener.java |
适配新 DeductionRequest,抽取合同匹配逻辑 |
energy/entity/review/po/EnergyReviewConfig.java |
新增 feeType 字段 |
energy/service/impl/ReviewConfigServiceImpl.java |
查询时加 feeType 条件 |
energy/controller/EnergyAccountController.java |
流水查询加 feeType 过滤 |
energy/entity/account/query/TransactionQuery.java |
新增 feeType 参数 |
payment/entity/po/CustomerPaymentItem.java |
fee_type 枚举扩展文档 |
payment/service/impl/PaymentFlowServiceImpl.java |
支持 ETC/电费充值流转 |
新建文件(按 Phase)
- Phase 1: ~5 文件(FeeType, DeductionRequest, ContractMatchService 接口+实现, V2迁移脚本)
- Phase 2: ~20 文件(ETC 全套 entity/mapper/service/controller/event/listener)+ 3 张表 DDL
- Phase 3: ~18 文件(电费全套)+ 2 张表 DDL
- Phase 4: ~2 文件改动
验证方案
单元测试
DeductionServiceTest—— 验证新接口支持三种 FeeTypeEtcIngestTemplateTest—— ETC 数据导入全流程ElectricityIngestTemplateTest—— 电费 Excel 导入全流程ContractMatchServiceTest—— 合同匹配逻辑
集成测试
EtcModuleIntegrationTest—— ETC 同步 → 导入 → 合同匹配 → 审核 → 扣款 → 账单生成ElectricityModuleIntegrationTest—— Excel 导入 → 合同匹配 → 审核 → 扣款 → 账单生成MultiFeeBillingIntegrationTest—— 三种费用共享账户扣款 → 流水 fee_type 正确 → 各自独立出账单
回归验证
- 现有氢费全链路测试通过(
EnergyModuleIntegrationTest) - 现有款项管理测试通过(
PaymentModuleIntegrationTest)
Phase 2 剩余实施计划(本次任务)
已完成
- Phase 1 基础设施层(FeeType/DeductionRequest/IDeductionService/ContractMatchService/ReviewConfig)
- Phase 2 DDL(
db/etc/V1__create_etc_tables.sql- 4 张表) - Phase 2 Entity PO(EtcTollRecord/EtcSyncConfig/EtcSyncLog/EnergyEtcBill)
- Phase 2 DTO(EtcTollRecordVO/EtcTollRecordQuery/EtcBillVO/EtcBillGenerateReq)
- Phase 2 Mapper(4 个)
- Phase 2 Service 接口 + 实现(IEtcTollRecordService/IEtcSyncConfigService/IEtcBillService)
- Phase 2 Event(EtcRecordImportedEvent)
- Phase 2 Listener(EtcDetailImportListener)
- 编译通过
Step 1: ETC 后端 Controller 层
3 个 Controller,沿用 EnergyBillController 的精确模式:
1.1 EtcTollRecordController.java
路径: modules/etc/controller/EtcTollRecordController.java
前缀: @RequestMapping("/etc/record")
Tag: @Tag(name = "ETC通行记录管理")
| 方法 | 路径 | 说明 | 调用 |
|---|---|---|---|
| GET | /page | 分页查询 | service.pageList(query) |
| GET | /detail/{id} | 详情 | service.getDetail(id) |
| PUT | /review | 单条审核 | service.review(id, approved, remark) |
| PUT | /batch-review | 批量审核 | service.batchReview(ids, approved) |
| PUT | /manual-match | 手动匹配合同 | service.manualMatch(detailId, contractId) |
| POST | /export | 导出 | TODO |
| GET | /statistics | 统计数据 | service.getStatistics() |
1.2 EtcSyncConfigController.java
路径: modules/etc/controller/EtcSyncConfigController.java
前缀: @RequestMapping("/etc/sync-config")
Tag: @Tag(name = "ETC同步配置")
| 方法 | 路径 | 说明 |
|---|---|---|
| GET | /page | 分页查询 |
| GET | /detail/{id} | 详情 |
| POST | / | 新增 |
| PUT | / | 编辑 |
| DELETE | /{id} | 删除 |
| PUT | /toggle/{id} | 启用/停用 |
| POST | /trigger/{id} | 手动触发同步 |
| GET | /log/{configId} | 同步日志 |
1.3 EtcBillController.java
路径: modules/etc/controller/EtcBillController.java
前缀: @RequestMapping("/etc/bill")
Tag: @Tag(name = "ETC账单管理")
| 方法 | 路径 | 说明 |
|---|---|---|
| GET | /page | 分页查询 |
| GET | /detail/{id} | 详情 |
| POST | /generate/preview | 生成预览 |
| POST | /generate | 确认生成 |
| PUT | /review | 审核 |
| PUT | /submit-finance/{id} | 提交财务 |
| DELETE | /{id} | 删除 |
| POST | /export | 导出 |
| GET | /statistics | 统计 |
| GET | /record/page/{billId} | 关联通行记录分页 |
参考文件:
ln-asset-management/src/main/java/com/ln/asset/modules/energy/controller/EnergyBillController.javaln-asset-management/src/main/java/com/ln/asset/modules/station/controller/SyncConfigController.java
Step 2: EtczjApiClient(etczj.com HTTP 客户端)
新建文件:
modules/etc/service/sync/EtczjApiClient.java— HTTP 客户端modules/etc/service/sync/EtczjApiResponse.java— 响应 DTOmodules/etc/service/sync/EtczjTollRecordDTO.java— 通行记录 DTOmodules/etc/service/sync/EtczjSyncStrategy.java— 同步策略实现
EtczjApiClient 核心方法:
@Slf4j
@Component
public class EtczjApiClient {
private final RestTemplate restTemplate;
private final ObjectMapper objectMapper;
// 登录(获取 randomVal session)
public String login(String baseUrl, String acctId, String password) {
// 1. GET /createCaptcha?secret={guid} → 验证码图片
// 2. OCR 识别验证码(Tesseract)
// 3. POST /member/toLogin?secret={guid}
// Body: { acctId, password: Base64(password), checkCode, secret }
// 4. 返回 randomVal
}
// 查询通行记录
public EtczjApiResponse<List<EtczjTollRecordDTO>> queryTollRecords(
String baseUrl, String randomVal,
String transTimeBegin, String transTimeEnd,
int currPage, int pageSize) {
// POST /vehicleManage/queryVehicleConsumptionDetailPage
// Header: Randomval: {randomVal}
}
// 查询通行费汇总
public EtczjApiResponse<Map<String, Object>> sumToll(
String baseUrl, String randomVal,
String transTimeBegin, String transTimeEnd) {
// POST /vehicleManage/sumVehicleToll
}
}
参考文件:
ln-asset-management/src/main/java/com/ln/asset/modules/station/feign/HecriApiClient.java(RestTemplate + ObjectMapper 模式)
Step 3: 前端 ETC 页面
技术栈: Vben Admin (Vue 3 + TypeScript + Ant Design Vue + VxeTable)
模式参考:
- 路由:
playground/src/router/routes/modules/system.ts - API:
playground/src/api/system/role.ts - 列表页:
playground/src/views/system/role/list.vue - 列定义:
playground/src/views/system/role/data.ts
3.1 API 层
新建文件: playground/src/api/etc/index.ts
export namespace EtcApi {
export interface EtcSyncConfig { id: string; providerType: string; acctId: string; syncEnabled: 0|1; syncCron: string; lastSyncTime: string; lastSyncStatus: 0|1; }
export interface EtcTollRecord { id: string; recordCode: string; plateNumber: string; entryStationName: string; exitStationName: string; transTime: string; tollAmount: number; serviceFee: number; totalAmount: number; reviewStatus: number; deductionStatus: number; }
export interface EtcBill { id: string; billCode: string; customerName: string; billPeriodStart: string; billPeriodEnd: string; totalTollCount: number; totalTollAmount: number; receivableAmount: number; actualAmount: number; reviewStatus: number; paymentStatus: number; }
}
// ETC 同步配置 API
async function getEtcSyncConfigPage(params) { return requestClient.get('/etc/sync-config/page', { params }); }
async function addEtcSyncConfig(data) { return requestClient.post('/etc/sync-config', data); }
async function updateEtcSyncConfig(data) { return requestClient.put('/etc/sync-config', data); }
async function deleteEtcSyncConfig(id) { return requestClient.delete(`/etc/sync-config/${id}`); }
async function toggleEtcSync(id) { return requestClient.put(`/etc/sync-config/toggle/${id}`); }
async function triggerEtcSync(id) { return requestClient.post(`/etc/sync-config/trigger/${id}`); }
async function getEtcSyncLog(configId, params) { return requestClient.get(`/etc/sync-config/log/${configId}`, { params }); }
// ETC 账单 API
async function getEtcBillPage(params) { return requestClient.get('/etc/bill/page', { params }); }
async function getEtcBillDetail(id) { return requestClient.get(`/etc/bill/detail/${id}`); }
async function reviewEtcBill(data) { return requestClient.put('/etc/bill/review', data); }
// ... 其他
3.2 ETC 同步配置页面
新建文件:
playground/src/views/etc/sync-config/list.vue— 配置列表(useVbenVxeGrid)playground/src/views/etc/sync-config/data.ts— 列定义 + 表单 schemaplayground/src/views/etc/sync-config/modules/form.vue— 新增/编辑表单(useVbenDrawer)
页面功能:
- 表格列:供应商类型、登录账号、API地址、同步频率、上次同步时间/状态、启用状态
- 操作:编辑、删除、启用/停用切换、手动触发同步
- 新增/编辑抽屉:账号、密码、API地址、同步 cron 表达式
3.3 ETC 账单查询页面
新建文件:
playground/src/views/etc/bill/list.vue— 账单列表playground/src/views/etc/bill/data.ts— 列定义 + 搜索表单playground/src/views/etc/bill/modules/detail.vue— 账单详情抽屉
页面功能:
- 搜索条件:客户名称、账单周期、审核状态、支付状态
- 表格列:账单编码、客户名称、账期、通行笔数、通行费总额、服务费总额、应收、实收、审核状态、支付状态
- 操作:查看详情、审核、提交财务、删除
- 详情抽屉:账单信息 + 关联通行记录分页列表
3.4 路由配置
新建文件: playground/src/router/routes/modules/etc.ts
const routes: RouteRecordRaw[] = [{
meta: { icon: 'mdi:highway', order: 30, title: 'ETC管理' },
name: 'Etc',
path: '/etc',
children: [
{ path: '/etc/sync-config', name: 'EtcSyncConfig', meta: { icon: 'mdi:sync', title: 'ETC同步配置' }, component: () => import('#/views/etc/sync-config/list.vue') },
{ path: '/etc/bill', name: 'EtcBill', meta: { icon: 'mdi:file-document-outline', title: 'ETC账单' }, component: () => import('#/views/etc/bill/list.vue') },
],
}];
实施顺序
| 步骤 | 内容 | 文件数 |
|---|---|---|
| 1 | 3 个 ETC Controller | 3 |
| 2 | EtczjApiClient + DTO + SyncStrategy | 4 |
| 3 | 前端 API 层 | 1 |
| 4 | 前端 ETC 同步配置页面 | 3 |
| 5 | 前端 ETC 账单查询页面 | 3 |
| 6 | 前端路由配置 | 1 |
| 合计 | 15 个文件 |
验证方案
- 后端:
mvn compile编译通过 - 前端:
cd ln-one-os-web/playground && pnpm dev启动无报错 - ETC 同步配置页面:可访问 /etc/sync-config,表格加载正常
- ETC 账单页面:可访问 /etc/bill,表格加载正常
- Swagger:
/swagger-ui.html可看到 ETC 相关 3 组 API