# 营商助手 · 栏目使用手册 **面向日常使用** —— 查数据、写数据、做集成时看这份。 > 与 [`DMS_MAPPING.md`](DMS_MAPPING.md) 的分工: > 那份是**迁移视角**(源表→栏目怎么映射、建栏目踩了什么坑); > 这份是**使用视角**(这五个栏目怎么用,字段叫什么)。 > 接口本身的通用约定见 [`DMS_API.md`](DMS_API.md)。 **服务**:`http://121.43.55.7:10081/dms` **父栏目**:营商助手 `columnId=1883`(分级栏目,`tag=yszs`) **最后核对**:2026-09-16 > 📍 **本文引用的 artifacts / RUNBOOK 不在本仓库**,属于另一个项目 > `F:\yysk\AI_zhaoshang\DMS_Data_Migration\`(本文从它的 `harness/docs/` 复制而来)。 > 链接已改为**绝对路径**指向那边。 --- ## ⚠️ 先读这段:栏目建好了,但**数据还没迁** | 栏目 | columnId | 当前内容数 | |------|----------|-----------| | 助手页面浏览 | 1885 | **0** | | 企业荣誉信息 | 1886 | **0** | | 助手会话 | 1887 | **0** | | 企业基础信息 | 1888 | **0** | | 助手问答记录 | 1889 | **0** | 实测 `selectContentList` 五个栏目全部返回 `code=202 数据不存在`。 **五张表的结构(栏目 + 字段)已就绪,但业务数据尚未写入。** 数据迁移(`F4-*`)还没开始。所以现在查任何栏目都只会得到 202。 --- ## 1. 速查表 | 栏目 | columnId | tag(权限名) | 栏目模型 modelId | 字段数 | 源表 | 源行数 | |------|----------|---------------|------------------|--------|------|--------| | 助手页面浏览 | **1885** | `yszs_page_view` | **2030** | 4 | `assistant_page_view` | 39,723 | | 企业荣誉信息 | **1886** | `yszs_qcc_honor` | **2032** | 11 | `qcc_honor` | 7,118 | | 助手会话 | **1887** | `yszs_chat_session` | **2034** | 7 | `chat_session` | 3,133 | | 企业基础信息 | **1888** | `yszs_qcc_enterprise` | **2036** | 41 | `qcc_enterprise` | 81,980 | | 助手问答记录 | **1889** | `yszs_chat_record` | **2038** | 13 | `chat_record` | 15,542 | **调 content 接口时用 `columnId`。** 权限用 `tag`(已同步 OAuth `permissionName`)。 **业务主线**:`c_credit_code`(统一社会信用代码)串起 `企业基础信息` ↔ `企业荣誉信息` ↔ `助手会话` ↔ `助手问答记录`。 --- ## 2. 字段全表 > 字段名以 `c_` 开头。`type` 是 DMS 存储类型,`前端控件` 是 DMS 界面渲染用的控件名。 > 类型为 `text` 的字段**用模糊查询**(`searchType=2`),其余用精确(`searchType=1`)。 ### 2.1 助手页面浏览 `columnId=1885` 埋点数据。**无企业关联**(没有 `credit_code`),只有访客维度。 | 字段 | 别名 | 类型 | 前端控件 | 必填 | |------|------|------|----------|------| | `c_id` | ID | integer | int_num | ✓ | | `c_business_code` | 业务编码 | text | varchar | | | `c_visitor_id` | 访客ID | text | varchar | | | `c_created_at` | 创建时间 | **timestamp** | date_time | | ### 2.2 企业荣誉信息 `columnId=1886` | 字段 | 别名 | 类型 | 前端控件 | 必填 | |------|------|------|----------|------| | `c_id` | ID | integer | int_num | ✓ | | `c_credit_code` | 统一社会信用代码 | text | varchar | ✓ | | `c_name` | 企业名称 | text | varchar | | | `c_level` | 级别 | text | varchar | | | `c_source` | 来源 | text | varchar | | | `c_publish_office` | 发布机构 | text | varchar | | | `c_publish_date` | 发布日期 | **text** | varchar | | | `c_beging_date` | 起始日期 | **text** | varchar | | | `c_dead_line` | 截止日期 | **text** | varchar | | | `c_certificate_code` | 证书编号 | text | varchar | | | `c_created_at` | 创建时间 | **timestamp** | date_time | | | `c_tag_name` | 荣誉 | text | text | | > `c_tag_name` 由**前端的企业信息分类同步**写入(2026-09-18 DMS 侧新增,12 字段): > 一行 = 一个资质荣誉标签,同时写 `c_credit_code` / `c_name`, > 并用 `c_source = company_info_sync` 标记「这行是前端同步写的」—— > 同步只增删带这个标记的行,迁移数据一律不碰。 > 见 [`../exec-plans/active/company-classify-dms-sync.md`](../exec-plans/active/company-classify-dms-sync.md)。 ### 2.3 助手会话 `columnId=1887` | 字段 | 别名 | 类型 | 前端控件 | 必填 | |------|------|------|----------|------| | `c_id` | ID | integer | int_num | ✓ | | `c_credit_code` | 统一社会信用代码 | text | varchar | ✓ | | `c_session_id` | 会话ID | text | varchar | | | `c_title` | 标题 | text | varchar | | | `c_source` | 来源 | text | varchar | | | `c_created_at` | 创建时间 | **timestamp** | date_time | | | `c_updated_at` | 更新时间 | **timestamp** | date_time | | ### 2.4 企业基础信息 `columnId=1888` 47 字段(原 41 + 2026-09-18 新增的 6 个 `c_tag_*`)。 **主键 `c_credit_code`**(注意:没有 `c_id`);**must 字段只有 `c_credit_code`**(实测自 `getModelById`)。 **分类标签字段**(前端的企业信息分类同步写入;值是 JSON 数组字符串,空集存 `"[]"`) | 字段 | 别名 | 类型 | 前端控件 | 必填 | |------|------|------|----------|------| | `c_tag_basic` | 基本信息 | text | text | | | `c_tag_honor` | 资质荣誉 | text | **content(富文本)** | | | `c_tag_sector` | 产业信息 | text | text | | | `c_tag_operation` | 经营活动 | text | text | | | `c_tag_industry` | 行业信息 | text | text | | | `c_tag_license` | 许可认证 | text | text | | > 六个字段与分类接口的六个角度一一对应(字段名映射见 > `src/network/api/dms/classification-sync-utils.ts` 的 `ANGLE_TO_FIELD`)。 > ⚠️ **行业信息用 `c_tag_industry`**,别和原有的 `c_industry`(源库行业分类 JSON)混了。 > ⚠️ `c_tag_honor` 的控件类型是 `content`(富文本),其余是 text——2026-09-18 实测 > JSON 字符串**逐字往返正常**(见 `verify-company-classify-dms.mjs` 的专项断言)。 **主体字段** | 字段 | 别名 | 类型 | |------|------|------| | `c_credit_code` | 统一社会信用代码 | text | | `c_name` | 企业名称 | text | | `c_belong_org` | 所属机构 | text | | `c_oper_id` | 经营者ID | text | | `c_oper_name` | 经营者名称 | text | | `c_ent_type` | 企业类型 | text | | `c_econ_kind` | 经济类型 | text | | `c_status` | 经营状态 | text | | `c_province` | 省份 | text | | `c_area_code` | 行政区划代码 | text | | `c_address` | 注册地址 | text | | `c_phone_number` | 联系电话 | text | | `c_email` | 邮箱 | text | **经营期限与资本** | 字段 | 别名 | 类型 | |------|------|------| | `c_start_date` | 成立日期 | text | | `c_end_date` | 结束日期 | text | | `c_term_start` | 营业期限起 | text | | `c_term_end` | 营业期限止 | text | | `c_check_date` | 核准日期 | text | | `c_updated_date` | 更新日期 | text | | `c_regist_capi` | 注册资本 | text | | `c_registered_capital` | 注册资本数值 | text | | `c_registered_capital_unit` | 注册资本单位 | text | | `c_registered_capital_ccy` | 注册资本币种 | text | | `c_rec_cap` | 实收资本 | text | | `c_paid_up_capital` | 实缴资本 | text | | `c_paid_up_capital_unit` | 实缴资本单位 | text | | `c_paid_up_capital_ccy` | 实缴资本币种 | text | **上市与编码** | 字段 | 别名 | 类型 | |------|------|------| | `c_is_on_stock` | 是否上市 | text | | `c_stock_number` | 股票代码 | text | | `c_stock_type` | 股票类型 | text | | `c_org_no` | 组织机构代码 | text | | `c_no` | 编号 | text | | `c_image_url` | 图片地址 | text | **长文本** | 字段 | 别名 | 类型 | |------|------|------| | `c_scope` | 经营范围 | **text** | | `c_scope_brief` | 经营范围简述 | text | **JSON 存成 text 的字段**(⚠️ 内容不可被 DMS search 检索,见 §5.3) | 字段 | 别名 | 源 jsonb 内容 | |------|------|---------------| | `c_designated_representative_list` | 法定代表人列表 | 法定代表人数组 | | `c_original_name` | 曾用名 | 曾用名数组 | | `c_revoke_info` | 撤销信息 | 撤销记录 | | `c_area` | 行政区划 | 行政区划对象 | | `c_industry` | 行业 | 行业分类对象 | **时间** | 字段 | 别名 | 类型 | |------|------|------| | `c_created_at` | 创建时间 | **timestamp** | ### 2.5 助手问答记录 `columnId=1889` | 字段 | 别名 | 类型 | 前端控件 | 必填 | |------|------|------|----------|------| | `c_id` | ID | integer | int_num | ✓ | | `c_credit_code` | 统一社会信用代码 | text | varchar | ✓ | | `c_session_id` | 会话ID | text | varchar | | | `c_record_id` | 记录ID | text | varchar | | | `c_question` | 问题 | **text** | text | | | `c_answer` | 回答 | **text** | text | | | `c_reason` | 原因 | **text** | text | | | `c_source` | 来源 | text | varchar | | | `c_feedback_status` | 反馈状态 | integer | int_num | | | `c_feedback_option` | 反馈选项 | text | varchar | | | `c_feedback_remark` | 反馈备注 | **text** | text | | | `c_created_at` | 创建时间 | **timestamp** | date_time | | | `c_feedback_at` | 反馈时间 | **timestamp** | date_time | | --- ## 3. 查询示例 所有查询共用: ```bash export DMS_HOST=121.43.55.7:10081 export DMS_TOKEN='...' ``` ### 3.1 通用模板 ```bash curl -s -X POST "http://${DMS_HOST}/dms/content/selectContentList" \ -H "token: ${DMS_TOKEN}" \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "columnId=1888" \ -d "page=0" \ -d "pageSize=20" \ -d "search=[{\"field\":\"c_name\",\"searchType\":2,\"content\":{\"value\":\"科技\"}}]" \ -d "orderBy=[{\"field\":\"c_created_at\",\"orderByType\":2}]" ``` 返回 `content.data`(数组)+ `content.count`(总数)。 `page` **从 0 开始**。 ### 3.2 按企业名模糊查(企业基础信息 1888) ```bash -d 'search=[{"field":"c_name","searchType":2,"content":{"value":"上海某某"}}]' ``` ### 3.3 按信用代码精确查(跨栏目都能用) ```bash -d 'search=[{"field":"c_credit_code","searchType":1,"content":{"value":"91310118MA1JLXXXXX"}}]' ``` ### 3.4 查某企业的荣誉(企业荣誉信息 1886) ```bash curl -s -X POST "http://${DMS_HOST}/dms/content/selectContentList" \ -H "token: ${DMS_TOKEN}" \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "columnId=1886" \ -d 'search=[{"field":"c_credit_code","searchType":1,"content":{"value":"91310118MA1JLXXXXX"}}]' \ -d "page=0&pageSize=50" ``` ### 3.5 查某企业的问答记录(助手问答记录 1889) ```bash -d "columnId=1889" -d 'search=[{"field":"c_credit_code","searchType":1,"content":{"value":"91310118MA1JLXXXXX"}}]' ``` ### 3.6 时间区间查(`searchType=3`) ```bash -d 'search=[{"field":"c_created_at","searchType":3,"content":{"start":"2026-01-01 00:00:00","end":"2026-12-31 23:59:59"}}]' ``` ### 3.7 多条件(数组里放多个对象 = AND) ```bash -d 'search=[ {"field":"c_credit_code","searchType":1,"content":{"value":"91310118MA1JLXXXXX"}}, {"field":"c_level","searchType":2,"content":{"value":"市级"}} ]' ``` ### 3.8 searchType 速查 | 值 | 含义 | content 写法 | |----|------|--------------| | `1` | 精确 | `{"value":"..."}` | | `2` | 模糊 | `{"value":"..."}` | | `3` | 区间 | `{"start":"...","end":"..."}` | | `4` | in 数组 | `{"value":["a","b"]}` | | `5` | between | `{"start":..,"end":..}` | ### 3.9 取单条详情 ```bash # columnId + contentId(contentId 是 UUID 字符串) curl -s -X POST "http://${DMS_HOST}/dms/content/selectContentById" \ -H "token: ${DMS_TOKEN}" \ -d "columnId=1888&contentId={uuid}" ``` **需要字典解析**(把码值翻成文本)时用 `selectContentListInfo`,参数相同。 ### 3.10 用 Python 查(推荐,避免 shell 转义地狱) ```python import sys; sys.path.insert(0, 'harness/tools') from dms import Dms import json d = Dms() r = d.call("POST", "/content/selectContentList", { "columnId": 1888, "page": 0, "pageSize": 20, "search": json.dumps([{"field": "c_name", "searchType": 2, "content": {"value": "科技"}}], ensure_ascii=False), "orderBy": json.dumps([{"field": "c_created_at", "orderByType": 2}]), }, expect=None) print(r["content"]["count"], "条") for row in r["content"]["data"]: print(row.get("c_credit_code"), row.get("c_name")) ``` --- ## 4. 写入示例 **写入前先读 §5.1(时间换算)和 §5.2(幂等)** —— 这两条不注意会产生脏数据。 ### 4.1 新增 ```bash curl -s -X POST "http://${DMS_HOST}/dms/content/addContent" \ -H "token: ${DMS_TOKEN}" \ -d "columnId=1886" \ -d "modelId=2032" \ -d 'content={"c_id":1,"c_credit_code":"91310118MA1JLXXXXX","c_name":"某某公司","c_level":"市级"}' ``` `content` 是 **JSON 字符串**,字段名带 `c_` 前缀。 `modelId` 用**栏目模型 id**(速查表里的那个)。 ### 4.2 修改 同 `addContent`,但 `content` 里**必须带 `id`**(记录 UUID,不是业务 id): ```bash -d 'content={"id":"{记录uuid}","c_level":"国家级"}' ``` > ⚠️ 注意区分两个「id」:`c_id` 是**业务 id**(来自源库),`id` 是 **DMS 记录 UUID**。 > 修改时要用后者。 ### 4.3 批量 `POST /content/importJSON` —— 服务端确认存在,但**参数未文档化、本项目未实测**。 大批量写入前先在测试栏目验证(见 [`DMS_API.md`](DMS_API.md) §4.7)。 --- ## 5. 使用注意 ### 5.1 ⏱ 时间是 **epoch 秒**,查询和写入都要注意 源库的 `created_at` / `updated_at` / `feedback_at` 是 **epoch 秒**(不是毫秒), 栏目里存为 `timestamp`。 **查询时**用正常的时间字符串(DMS 已转好): ```bash -d 'search=[{"field":"c_created_at","searchType":3,"content":{"start":"2026-09-01 00:00:00","end":"2026-09-30 23:59:59"}}]' ``` **写入/换算时**:`datetime.fromtimestamp(v)`,**不要除以 1000**。 ```python from datetime import datetime datetime.fromtimestamp(1789450583) # 2026-09-15 13:36 ✅ datetime.fromtimestamp(1789450583/1000) # 1970-01-22 ❌ ``` ### 5.2 🔁 幂等键(重跑不产生重复) | 栏目 | 幂等键 | 说明 | |------|--------|------| | 企业基础信息 1888 | `c_credit_code` | 源表主键,天然唯一 | | 企业荣誉信息 1886 | `c_id` | 源表主键 | | 助手会话 1887 | `c_id` | 源表主键 | | 助手问答记录 1889 | `c_id` | 源表主键 | | 助手页面浏览 1885 | `c_id` | 源表主键 | **写入前先按幂等键查一次**:不存在则 `addContent`,已存在则 `updateContent`。 ### 5.3 🔍 jsonb 字段存成 text,**搜不了内部** 企业基础信息里这 5 个字段是 JSON 文本,**DMS 的 search 无法检索其内部值**: `c_designated_representative_list`(法定代表人)、`c_industry`(行业)、 `c_area`(行政区划)、`c_original_name`(曾用名)、`c_revoke_info`(撤销信息) > 例如「查法定代表人是张三的企业」**做不到** —— 除非把 JSON 反序列化后另建字段/栏目。 > 如果这类查询有需求,需要单独提出来做。 ### 5.4 🕳 空值 - `c_credit_code` 在企业基础信息里是主键;但在荣誉/会话/问答里**可空** - 关联查询时注意 `c_credit_code` 为空的行会被漏掉 ### 5.5 🔐 权限 栏目 `tag` 已同步 OAuth `permissionName`: | 栏目 | tag | |------|-----| | 助手页面浏览 | `yszs_page_view` | | 企业荣誉信息 | `yszs_qcc_honor` | | 助手会话 | `yszs_chat_session` | | 企业基础信息 | `yszs_qcc_enterprise` | | 助手问答记录 | `yszs_chat_record` | 无权限访问返回 `code=201`,token 失效返回 `212`。 > ⚠️ **权限边界尚未验证**(未用测试账号确认「有权限能读 / 没权限返回 201」)。 --- ## 6. 已知问题 | 问题 | 影响 | 处置 | |------|------|------| | ~~`c_updated_at`(1887)显示名为 `updated_at`~~ | — | ✅ **已修复**(2026-09-16),现显示「更新时间」。根因是建栏目脚本别名表漏配 `updated_at`,已同步修正 | | 数据尚未迁移 | 5 个栏目全部 `code=202 数据不存在` | 等 `F4-*` | | 权限边界未验证 | 不知道无权限用户能否读到 | 等 `F6-01` | **改字段别名的方法**(实测可用): ```bash python harness/tools/fix_field_alias.py --model 2034 --field c_updated_at --alias 更新时间 --apply ``` > ⚠️ 更新模型要用 `POST /model/updateProperty`。 > `updateFields` 返回 HTTP 400、`updateFieldList` 返回 HTTP 500 —— 名字最像的恰好不能用。 --- ## 7. 错误码 | code | 含义 | 排查 | |------|------|------| | `200` | 成功 | | | `201` | 无权限 | 检查栏目 `tag` 与用户 OAuth 权限 | | `202` | **数据不存在** | 栏目是空的 —— 当前 5 个栏目都会返回这个 | | `205` | 无数据 / 模型不存在 | 查询条件无匹配;或 `getModelList` 没传 `type` | | `212` | token 无效/过期 | 重新获取 | --- ## 8. 相关文档 | 文档 | 用途 | |------|------| | [`DMS_API.md`](DMS_API.md) | DMS 接口通用约定与全部端点 | | [`DMS_MAPPING.md`](DMS_MAPPING.md) | 源表→栏目映射、建栏目实测契约 | | [`RUNBOOK.md`](F:/yysk/AI_zhaoshang/DMS_Data_Migration/harness/docs/RUNBOOK.md) | 操作手册 | | [`dms_column_fields.json`](F:/yysk/AI_zhaoshang/DMS_Data_Migration/harness/artifacts/dms_column_fields.json) | 本文档字段表的机器可读版(从 DMS 实时拉取) |