# OneOS 与 ln-asset-management 系统分析 更新时间:2026-07-14 分析方式:源码静态分析、生产数据库只读元数据与聚合核验 修改边界:本报告未修改 `/Users/lingniu/project/ai-coding/oneos`。用户已明确要求不修改 `ln-asset-management` 任何逻辑;所有建议均需另行同步和批准。 ## 1. 结论先行 `ln-asset-management` 不是单一车辆档案服务,而是 OneOS 的资产和车辆业务单体,覆盖车辆主档、租赁合同、交车、还车、换车、应收、结算、保险、证照、异常异动、维修故障、加氢、备件、培训、消息与工作台等领域。车辆数据中台不能把它当作实时遥测服务,也不能直接把它的现有 REST/Dubbo 接口公开给客户。 推荐的系统职责是: - OneOS:车辆业务身份、客户、合同、交还车、业务状态的权威来源; - 车辆数据中台:TDengine/Redis/Kafka 中遥测、轨迹、在线状态、告警和分析的权威来源; - 两者之间:使用最小权限只读快照,不在客户请求链路上实时查询 OneOS,不信任客户端传入的客户 ID; - 当前客户车辆生命周期:以完成的 `delivery_vehicle` 和 `return_vehicle_task` 事务事实判断,`vehicle_lease_order_record` 仅用于客户归属交叉校验。 当前不能安全公开 OneOS 接口,主要原因包括: 1. `RemoteVehicleService.listByCustomerId` 当前忽略客户 ID,存在返回全量车辆风险; 2. 网关能证明“已登录”,但 93 个业务 Controller 中只有 1 个检出细粒度权限注解,不能证明接口级或客户级授权完整; 3. 全局 API 日志拦截器会记录请求头、请求体和响应体,且未像注解切面一样脱敏 Authorization、Token 和 Cookie; 4. 注解接口同时被全局拦截器与 `@ApiLog` 切面记录,存在重复日志;两个月日志表约占生产库数据体积 83%; 5. 租赁聚合表会被合同保存和还车草稿等非最终业务动作影响,不能单独作为授权真值; 6. 核心交车、还车和合同类达到 2,700~6,000 行,自动化测试没有覆盖核心生命周期; 7. 24 个定时任务未发现分布式锁,服务多副本部署存在重复执行风险。 ## 2. 仓库与运行架构 `/Users/lingniu/project/ai-coding/oneos` 下是四个独立 Git 仓库,而不是一个单仓: | 仓库 | 主要职责 | 与车辆数据中台关系 | | --- | --- | --- | | `ln-cloud` | RuoYi Cloud 网关、认证、用户、组织、字典、资源、工作流、Nacos 等 | 身份和组织来源;外部客户身份尚未建立 | | `ln-asset-management` | 车辆和资产全生命周期业务 | 车辆业务主档和客户 Scope 来源 | | `ln-energy-v2` | 能源及财务类远程能力 | OneOS 内部依赖,不作为遥测主源 | | `ln-ocr` | OCR 能力及共享 API | 保险、证照等业务依赖 | `ln-asset-management` 技术基线: - Java 21;Spring Boot 3.5.10;Spring Cloud 2025.0.0; - MyBatis-Plus 3.5.15,MySQL Connector/J 9.5; - Nacos 配置与注册、Dubbo 服务、Sa-Token、RabbitMQ、异步和定时任务; - 主服务端口 8701,网关路由 `/asset/**` 后去除一层前缀; - Dockerfile 默认 `test` profile,生产实际配置依赖 Nacos 覆盖; - Maven 依赖公司私有 SNAPSHOT 包,本机缺少仓库凭证时构建会在依赖解析阶段收到 401; - 仓库没有发现 Maven Wrapper、CI 工作流、docker-compose 或完整生产运行手册。 源码规模基线: | 指标 | 数量 | | --- | ---: | | Java 代码 | 约 181,425 行 | | 业务 Controller | 93 个(按源码注解统计;命名扫描为 95 个) | | 显式 HTTP 方法 | 约 815 个 | | Mapper | 约 161 个 | | `@TableName` 实体映射 | 158 个 | | Dubbo 服务实现 | 20 个 | | 含 Dubbo 引用的文件 | 85 个 | | 定时任务文件 | 24 个 | | 测试文件 | 30 个、约 4,372 行 | ## 3. 业务领域清单 ### 3.1 车辆主档与运营状态 模块路径存在历史拼写 `modules/vihicle`,但它是车辆核心模块,共 11 个 Controller、约 107 个 HTTP 方法。 主要能力: - `VehicleInfoController`:车辆档案、查询、导入导出; - `VehicleModelController`:车型; - `VehicleRealtimeLocationController`:OneOS 内部实时位置投影; - `PrepareCarController`:备车; - `VehicleLicenseController`、批量上牌:证照和上牌; - `VehicleTransferController`:调拨; - `AftermarketDeviceController`:后装设备; - `AccidentInfoController`:事故; - `VehicleCheckItemController`、`VehicleMaintenanceItemController`:检查和维保配置。 主要表:`vehicle_info`、`vehicle_model`、`vehicle_status`、`vehicle_realtime_location`、`prepare_car`、`vehicle_transfer`、`vehicle_license`、`aftermarket_device`、`accident_info`、`tab_data_attachment` 等 19 张显式映射表。 权威性判断: - 车辆身份以 `vehicle_info.id` 和标准化 VIN 为主; - 车牌会变化,不能作为跨系统唯一键; - `vehicle_status` 是 OneOS 业务运营状态,不等于车联网在线状态; - `vehicle_realtime_location` 和地图同步表是 OneOS 的展示投影,实时遥测仍应以车辆数据中台 Redis/TDengine 为准; - `vehicle_info.customer_id` 不是可靠客户归属来源,客户关系需通过合同和交还车事实确定。 ### 3.2 租赁合同、交车、还车和换车 `contract` 是最大领域:21 个 Controller、约 237 个 HTTP 方法、46 张显式映射表。 主要链路: ```text 客户/合同 -> vehicle_lease_contract_info -> vehicle_lease_order / vehicle_lease_order_detail -> delivery_task_subject / delivery_vehicle -> 正式交车完成 -> 客户当前持有车辆 -> return_vehicle_task 或 vehicle_replacement -> 正式还车/换车完成 -> 应收、还车付款、还车结算、发票 ``` 关键事实表: - 合同:`vehicle_lease_contract_info`、`vehicle_lease_contract_log`; - 合同车辆:`vehicle_lease_order`、`vehicle_lease_order_detail`; - 交车:`delivery_task_subject`、`delivery_vehicle`、`delivery_vehicle_check_item`; - 还车:`return_vehicle_task`、`return_vehicle_check_item`; - 换车:`vehicle_replacement`; - 当前聚合与历史:`vehicle_lease_order_record`、`vehicle_lease_order_record_log`; - 财务:`receivable_*`、`return_payment*`、`return_settlement*`、`rental_invoice`。 当前客户车辆的安全口径: ```text 最新有效 delivery_vehicle.delivery_status IN (2, 3) AND delivery_time IS NOT NULL AND 不存在该交车单对应的有效 return_vehicle_task.status IN (2, 3, 5) AND vehicle_info 有效且 VIN 非空 AND customer_info 有效 AND vehicle_lease_contract_info 有效 AND vehicle_lease_order_record.customer_id = COALESCE(contract.other_customer_id, contract.customer_id) AND 同一车辆和标准化 VIN 不存在多个当前关系 ``` 不能仅使用 `vehicle_lease_order_record.last_delivery_time/last_return_time`:还车草稿保存会提前写 `last_return_time`;合同保存也可能覆盖交还车聚合字段;部分聚合更新失败只记录日志。用户已要求不修改这些 OneOS 逻辑,因此车辆数据中台必须在读取侧绕开并失败关闭。 ### 3.3 客户、司机与身份 - `customer_info`:业务客户档案; - `driver_info`:司机档案、黑名单、手机号和证件; - `ln-cloud/ry-cloud.sys_user`:登录账号; - 业务客户 ID 与 `sys_user.user_id` 没有稳定映射,生产只读审计未发现可直接使用的客户账号体系; - 手机号只能作为人工核对线索,不能自动建立授权关系; - 合同有甲方和丙方客户,当前有效客户规则为 `COALESCE(other_customer_id, customer_id)`。 结论:车辆数据中台内部管理员可以继续使用独立平台令牌;外部客户入口在可信身份映射建立前不能开放。 ### 3.4 地图与外部定位 `map` 模块有 5 个 Controller:字典、组织、站点、车辆和地理编码。 数据和依赖: - `tab_truck_remote_sync_realtime_info`:车辆地图投影; - `tab_outside_hydrogen_site`:站点投影; - Hasp、远程实际车辆接口和高德 REST API; - `MapSyncTask` 定期同步车辆与站点。 结论:OneOS 地图适合内部业务展示,不适合作为车辆数据中台遥测源。两套地图需要统一 WGS-84 到 GCJ-02 的显示转换,但原始存储坐标必须保留来源和坐标系标识。 ### 3.5 资产后市场与合规 覆盖领域包括: - 保险采购、保单、OCR:14 张表、约 69 个 HTTP 方法; - 车辆异常异动:`vehicle_abnormal_move*`; - 故障:`vehicle_fault_manage`; - 年检、年审、车辆证书、交通违章; - 维修站、救援队、检查站; - 备件、出入库和仓库; - 培训材料与培训记录。 这些业务可以消费车辆中台的里程、位置、在线、告警证据,但车辆中台不能反向改写合同、保险、证照、结算或事故事实。涉及锁车、控车的能力不在本分析和实施范围。 ### 3.6 能源与工作流 - 加氢站、加氢台账、加氢场站、充电站; - 消息、通知规则、待办任务和工作台; - 通过 `RemoteWorkflowService`、`RemoteUserService`、`RemoteDictService`、`RemoteFileService` 等 Dubbo 服务依赖 `ln-cloud`; - 定时生成账单、合同到期提醒、证照到期提醒、台账状态同步等。 ## 4. 接口与安全边界 ### 4.1 已有安全机制 - 网关 `AuthFilter` 对非白名单请求执行 `StpUtil.checkLogin()`; - 微服务 `SecurityConfiguration` 可通过 Same-Token 验证请求是否由网关转发; - actuator 使用 Basic Auth; - 网关把 `/asset/**` 转发到 `ln-asset-management`。 这些机制只能证明请求已登录或来自网关,不能自动证明用户有某个业务动作权限,更不能证明客户只能访问自己的车辆。 ### 4.2 接口级授权缺口 静态扫描 93 个业务 Controller,只有 1 个文件出现 `@SaCheckPermission` 等细粒度权限注解;另有 3 个 Controller/回调路径使用 `@SaIgnore`。部分数据权限由 Mapper/DataPermission 处理,但没有形成覆盖所有车辆、合同、地图和导出入口的统一客户 Scope。 因此: - OneOS 现有 REST API 只能作为内部业务接口; - 不能直接公网开放 8701; - 不能把 `customerId` 查询参数或 `X-Customer-Id` 请求头当作授权身份; - 车辆数据中台应在自身底层查询统一注入 VIN Scope,并对详情返回 404,避免泄漏对象存在性。 ### 4.3 Dubbo 接口评估 `ln-asset-api` 暴露 20 个远程服务,包括车辆、客户、合同匹配、充电/加氢站、异常异动、保险、结算和任务等。 车辆数据中台当前不应直接调用 `RemoteVehicleService.listByCustomerId`:实现忽略客户 ID,并按有效车辆返回全量结果。可复用的 Dubbo 接口必须逐个做参数、范围、分页、超时和失败策略审计;RPC 不等于安全边界。 ## 5. 数据库现状 生产只读元数据基线: | 指标 | 结果 | | --- | ---: | | 基础表 | 448 | | 数据体积 | 约 2.63 GB | | 索引体积 | 约 381 MB | | 有效车辆 | 1,209 | | 当前事务事实候选车辆 | 639 | | 可安全发布 Scope | 613 | | 隔离关系 | 26 | 448 张表明显多于 158 个实体映射,因为数据库还包含历史表、BI 表、手工迁移表、备份表和动态月表。迁移、备份和运行表混放在同一业务库,增加容量、权限和误操作风险。 ### 5.1 API 请求日志容量与隐私风险 `api_request_log_202606` 和 `api_request_log_202607` 合计约 2.19 GB,约占全库数据体积 83%。源码证据: - `ApiLogWebConfig` 把全局拦截器挂到几乎所有业务路径; - `ApiLogConfig` 默认记录参数、请求体、响应体和请求头; - `ApiLogInterceptor.getRequestHeaders()` 不脱敏任何请求头; - `ApiLogAspect.getRequestHeaders()` 会脱敏 Authorization/Token/Cookie,但仅用于 `@ApiLog` 切面; - 带 `@ApiLog` 的接口同时被拦截器和切面保存,可能生成两条日志; - 清理接口只删除“当前时间减保留天数所在月份”一张表内的旧行,并不会遍历或删除所有更早月表;异常被吞掉; - `/api-request-log/clean` 没有细粒度权限注解。 这是 P0 安全和运维风险:日志可能包含登录凭证、身份证、手机号、合同、签章、附件地址和完整业务响应,并持续快速增长。 ### 5.2 关键索引和约束 已确认: - `vehicle_info` 有车牌索引,但 VIN 没有索引或唯一约束; - `vehicle_lease_order_record.vehicle_id`、`vehicle_status.vehicle_id` 只有普通索引,没有唯一约束; - `vehicle_lease_order_record.customer_id` 缺少 Scope 查询索引; - `delivery_vehicle.vehicle_id` 和 `return_vehicle_task.delivery_vehicle_id` 已有普通/组合索引; - 生产数据存在 1 组“一车多聚合记录”和大量聚合/历史差异,不能直接添加唯一约束。 任何清理、唯一约束或索引 DDL 都必须单独审批,不属于当前只读分析。 ## 6. 可靠性与可维护性 ### 6.1 超大类热点 | 文件 | 行数(约) | 风险 | | --- | ---: | --- | | `VehicleLeaseContractFullServiceImpl` | 6,082 | 合同、工作流、附件和聚合职责耦合 | | `ReturnTaskServiceImpl` | 4,015 | 草稿、完成、签章、结算与聚合边界混合 | | `ReturnSettlementServiceImpl` | 3,902 | 财务聚合复杂、回滚边界难验证 | | `InsuranceProcurement2ServiceImpl` | 3,626 | OCR、任务、保单、附件和状态混合 | | `HydrogenFuelLedgerServiceImpl` | 3,322 | 导入、匹配、财务状态耦合 | | `VehicleTransferServiceImpl` | 3,268 | 调拨、车辆状态、工作流耦合 | | `DeliveryTaskServiceImpl` | 2,715 | 交车事实和下游副作用耦合 | 测试集中在加氢、保险辅助逻辑、证照和少量 Mapper;没有覆盖合同保存、交车完成、还车草稿、还车完成、再次交车、丙方客户、换车等 Scope 核心用例。 ### 6.2 事务和错误处理 106 个 `service/impl` 文件中约 63 个文件出现 `@Transactional`,但“存在注解”不代表跨 Dubbo、工作流、签章、文件和本地数据库具备原子性。核心链路存在捕获异常后只记日志、继续返回成功的模式,导致任务状态与聚合表可能不一致。 ### 6.3 定时任务 源码有 24 个 `@Scheduled` 文件,应用主类全局启用调度,未发现 ShedLock 或等价分布式锁。若生产运行多个实例,账单生成、到期提醒、地图同步、证照状态同步等任务可能重复执行。部署前必须确认生产实例数和任务幂等性。 ### 6.4 配置和交付 - `application.yml` 是 Git 跟踪文件,包含邮件、短信和第三方服务的凭证型配置项;部分值看起来不是纯占位符,必须在不打印原值的前提下轮换并迁到密钥管理/Nacos; - README 只给出 Swagger 地址,没有依赖、构建、配置、迁移、部署、回滚、健康检查和故障处置说明; - Dockerfile 默认测试环境,若生产变量遗漏可能连入错误命名空间; - 私有 Maven 仓库凭证缺失会阻断可重复构建; - 未发现 CI 门禁,无法证明每次发布都执行测试、依赖扫描和镜像校验。 ### 6.5 可从源码推导的运维顺序 仓库没有 OneOS 专用生产运维手册,`ln-cloud/README.md` 基本是上游 RuoYi 框架说明,Nacos README 只有“复制配置”的一句提示。以下只能作为源码推导,不能替代生产值班手册: 1. 先启动 MySQL、Redis、Nacos,以及文件存储/资源服务所需基础设施; 2. 在对应 namespace/group 中准备 `application-common.yml`、`datasource.yml`、`ln-asset-management.yaml`; 3. 启动 `ruoyi-system`、`ruoyi-resource`、`ruoyi-workflow` 等被 Dubbo 引用的服务; 4. 启动 `ruoyi-auth` 和 `ruoyi-gateway`; 5. 最后启动 `ln-asset-management`,核验 Nacos 注册、Dubbo 引用、数据库、Redis、RabbitMQ、文件服务和 actuator; 6. 确认只有一个实例执行非幂等 `@Scheduled`,或先证明所有定时任务具备分布式幂等; 7. 再开放 `/asset/**` 流量,并检查错误率、Dubbo 超时、数据库连接池、API 日志增速和任务重复执行。 构建时应显式选择 profile,并避免 Maven package 阶段意外连接 Docker daemon: ```text mvn -Pprod -Ddocker.skip=true clean package ``` 该命令当前仍依赖公司私有 Maven 仓库凭证。Dockerfile 自带的 `SPRING_PROFILE_ACTIVE=test` 和 `NAMESPACE=test` 必须由生产环境显式覆盖;否则不能视为生产可部署制品。 生产运维说明仍缺少:真实部署拓扑、实例数、镜像仓库流程、Nacos 配置版本、SQL 迁移账本、备份恢复、发布回滚、健康检查阈值、告警接收人、日志保留和密钥轮换。未补齐前,不建议自动化改动或独立部署 OneOS。 ## 7. 风险矩阵 | 等级 | 风险 | 当前处置 | | --- | --- | --- | | P0 | API 日志可能保存未脱敏认证头和大量敏感请求/响应 | 不改 OneOS;立即限制日志查询/清理接口访问,制定脱敏、保留和轮换方案后另行审批 | | P0 | `listByCustomerId` 返回全量车辆 | 数据中台禁用该接口,使用只读事务事实快照 | | P0 | 登录校验不等于业务/客户数据权限 | OneOS 不公开;数据中台统一执行 VIN Scope | | P0 | 客户账号与业务客户没有可信映射 | 外部客户入口保持关闭 | | P1 | 聚合生命周期被草稿/合同保存影响 | 读取交还车事务事实,聚合仅作交叉校验 | | P1 | 关键业务异常被吞掉,状态可能不一致 | 快照失败关闭并隔离;上游修复需重新同步批准 | | P1 | 多副本定时任务可能重复 | 上线前确认单实例或任务幂等/分布式锁 | | P1 | VIN、聚合和状态缺少唯一约束 | 不直接 DDL;先清理异常并做影子验证 | | P1 | 核心生命周期测试缺失 | 将合同/交还车/换车作为未来修改的强制回归门禁 | | P1 | 凭证型配置进入源码 | 安全轮换和密钥迁移需单独紧急流程 | | P2 | 超大类、命名和 URL 漂移 | 分领域抽取应用服务,保持兼容接口 | | P2 | 运维文档与 CI 缺失 | 补齐构建、发布、回滚、监控和演练说明 | ## 8. 对车辆数据中台的可复用与禁止清单 ### 可只读复用 - `vehicle_info`:VIN、车牌、车型和主档; - `vehicle_model`:车型能力和显示配置; - `vehicle_status`:OneOS 业务运营状态; - `customer_info`、`vehicle_lease_contract_info`:客户和合同; - `delivery_vehicle`、`return_vehicle_task`:当前持有生命周期; - 停车场、站点、司机等低频主数据; - 所有读取都通过专用表级 SELECT 账号和周期快照。 ### 不作为权威来源 - OneOS 地图投影中的在线状态、位置和里程; - `vehicle_info.customer_id`; - 单独的 `vehicle_lease_order_record.last_return_time`; - `vehicle_lease_order_record_log` 最大 ID; - 客户手机号与系统用户手机号的自动匹配; - 客户请求参数中的客户 ID。 ### 禁止回写 - 合同、交车、还车、换车; - 锁车、控车; - 保险、事故、违章、证照、结算和发票; - OneOS 用户和客户归属; - 任何生产数据修复或 DDL,除非用户另行明确批准。 ## 9. 分阶段建议 ### 阶段 A:只读基线(已完成) - 仓库和模块清单; - 生产表规模、车辆/客户/Scope 数据质量; - 生命周期和权限风险; - OneOS 保持零修改。 ### 阶段 B:车辆数据中台只读投影(代码已准备,尚未部署) - 专用只读账号只授予 7 张必要表 SELECT; - 两分钟一次读取交还车事务事实; - 613 条安全关系发布,26 条隔离; - 内容寻址版本、事务整体切换、异常比例门禁; - ECS 当前仍缺 `ONEOS_MYSQL_DSN`、平台迁移 012 和同步 timer。 ### 阶段 C:客户身份与 API Scope(未完成) - 明确可信客户身份来源; - 平台 Principal 增加主体类型和客户 ID; - 对监控、车辆、轨迹、历史、统计、告警、导出和地图统一注入 Scope; - 完成双客户越权测试后才允许灰度。 ### 阶段 D:OneOS 风险治理(未获授权) 如用户未来批准,应优先按独立批次处理: 1. API 日志脱敏、去重、保留策略和访问权限; 2. 客户车辆 RPC 失败关闭; 3. 聚合写入的事务与生命周期边界; 4. 定时任务幂等或分布式锁; 5. 凭证轮换、构建和运维门禁。 每个批次都必须先同步文件、行为变化、数据库影响、测试和回滚方案,不与数据修复或 DDL 混合发布。 ## 10. 证据索引 - 系统集成与 Scope:`docs/oneos-integration-analysis.md`; - 生产只读审计:`docs/oneos-production-audit-report.md`; - 业务影响:`docs/oneos-business-impact-matrix.md`; - 客户 API 覆盖:`docs/customer-scope-api-enforcement-matrix.md`; - Scope 契约:`docs/oneos-customer-vehicle-scope-contract.md`; - OneOS 网关认证:`ln-cloud/ruoyi-gateway/.../AuthFilter.java`; - 微服务 Same-Token:`ln-cloud/ruoyi-common/ruoyi-common-security/.../SecurityConfiguration.java`; - 全局 API 日志:`ln-asset-management/src/main/java/com/ln/asset/common/log/`; - 租赁生命周期:`ln-asset-management/src/main/java/com/ln/asset/modules/contract/`; - 车辆主档:`ln-asset-management/src/main/java/com/ln/asset/modules/vihicle/`; - 远程接口:`ln-asset-management/ln-asset-api/src/main/java/com/ln/asset/api/`。