4.6 KiB
4.6 KiB
| name | description |
|---|---|
| entity | 实体管理模块(W-03)——实体表(entity)CRUD、列表查询、实体文件导入(entity_import 记录),通过 load_entity() 挂载。 |
entity 实体管理模块
概述
元景项目 W-03 实体管理:管理实体(entity)数据。实体归属于场景(scene_id→scene.id,逻辑关联,不加外键)与世界(world_id→world.id)。提供实体表 CRUD、分页列表查询、CSV/JSON 文件导入(两阶段校验+批量插入+失败回滚)。
数据模型
| 表 | 说明 |
|---|---|
entity |
实体表。entity_code 唯一索引;entity_type/status 引用 appcodes_kv 字典;scene_id/world_id 为逻辑外键(codes 段,无物理外键);import_id 标记导入批次;org_id 机构隔离 |
entity_import |
导入批次记录(系统生成,只读)。import_no 唯一;status ∈ importing/success/fail |
entity_import_log |
导入逐行明细(系统生成,只读)。result 1=成功 0=失败 |
编码字典(init/data.json 幂等落库 appcodes/appcodes_kv):
entity_type:character/prop/vehicle/building/faction/othercommon_status:1=启用 / 0=停用import_status:importing/success/fail
关键接口(REST 统一前缀 /api/*)
| 接口 | 方法 | 说明 | 返回 |
|---|---|---|---|
/entity/api/entity_list.dspy |
GET/POST | 分页列表(keyword/entity_type/status/scene_id 过滤) | {list, total, page, rows} |
/entity/api/entity_create.dspy |
POST | 新增实体(校验失败 100% 拦截不落库) | {success, data:{id}} |
/entity/api/entity_update.dspy |
POST | 更新实体(校验+存在性检查) | {success, data:{id}} |
/entity/api/entity_delete.dspy |
POST | 删除实体 | {success, data:{id}} |
/entity/api/entity_get.dspy |
GET/POST | 实体详情 | {success, data} |
/entity/api/entity_import.dspy |
POST | 文件导入(file 域 / file_content) | {success, data:{import_id,total,success,fail}} |
/entity/api/entity_import_guard.dspy |
POST | 导入预校验(干跑,只校验不落库) | {valid, errors, total} |
/entity/api/entity_import_list.dspy |
GET/POST | 导入记录只读分页 | {list, total, page, rows} |
错误结构统一:{code, message, field, detail}。分页结构统一:{list, total}。
导入处理逻辑
- 解析:CSV(首行表头,字段 entity_code/entity_name/entity_type/scene_id/world_id/description/status/sort_no)或 JSON 数组。
- 全量校验(第一阶段,不落库):编码必填/长度/文件内唯一/库内唯一;名称必填;类型/状态字典白名单;scene_id/world_id 存在性。任一行非法 → 整批拦截,只写失败批次+逐行日志,不导入任何实体。
- 批量插入(第二阶段):同批实体以同一
import_id标记插入;任一行异常 → 按import_id补偿 DELETE 已插入实体,保证失败回滚无脏数据。 - 成功/失败均写
entity_import批次与entity_import_log明细。
陷阱
- sor.I() 只用于表结构:插入用
sor.C(table, ns),不要sor.I(table, data)(I 只收 1 参)。 - sor.U() 只收 2 参:
sor.U('entity', {**upd, 'id': id}),id 必须在 data 内;仅主键字段时先校验非空字段。 - dspy 中禁 import:全部函数经
load_entity()注册为全局(create_entity/update_entity/delete_entity/get_entity/list_entities/import_entities/entity_import_guard/reject_import_write),dspy 直接调用;__init__.py必须导出 init.py 的 async 函数,否则 NameError。 - 取库名不硬编码:.py 用
get_sor_context(ServerEnv(), 'entity')(内部解析get_module_dbname('entity'));.dspy 用get_sor_context(request._run_ns, 'entity')。禁止写DBNAME='...'。 - 请求上下文:.py 内取用户/机构用
request._run_ns(get_user/get_userorgid),不要用ServerEnv()(进程级单例)。 _text后缀字段:表格提交会带xxx_text,_clean_ns会剔除后再写库。- curDateString():sqlor 不自动写时间戳,插入必须显式
created_at,否则记录静默丢失。 - 删除校验:entity 可能被 world_snapshot 等引用,删除前可扩展引用检查(当前实现仅校验存在性)。
依赖
- 基础:sqlor、ahserver、appPublic
- 数据依赖(逻辑关联,不物理外键):
scene(scene.id)、world(world.id)——codes 段引用,表缺失时仅下拉不渲染,不影响 CRUD - 字典:appbase 的 appcodes / appcodes_kv
- 被
world_snapshot(W-03 快照)聚合读取