# company_info ↔ DMS 企业两栏目 · 字段对应关系 > **这份文档回答一个问题**:对话里拿到的 `company_info`(企查查原始结构)的每个字段, > 最终落到 DMS 的哪一列;哪些没落、为什么。 > > - **面向**:接手的开发、DMS 侧维护者 > - **由脚本生成**:`node harness/tools/gen-company-info-mapping-doc.mjs` > (读代码里的映射表 + 实时拉 DMS 模型定义)——**改了字段请重跑,不要手改本文件** > - **覆盖**:对话 `result` 事件 → `company_info` → DMS **1888 企业基础信息** / **1886 企业荣誉信息** > - 相关:实现见 `src/network/api/dms/classification-sync-utils.ts` 与 `company-info-sync.ts`; > 字段覆盖审计见 `harness/tools/audit-company-info-coverage.mjs` ## 1. 总览 | company_info 里的段 | 落到哪 | 粒度 | 匹配/幂等键 | |---|---|---|---| | `profile.data`(38 个字段) | **1888 企业基础信息** | 一行一家企业 | `c_credit_code` | | 分类接口六角度(不是 company_info,由它调出) | **1888** 的 `c_tag_*` | 同上 | 同上 | | `honors.records[].data`(8 个字段) | **1886 企业荣誉信息** | **一条荣誉一行** | 荣誉名 + 级别 + 来源 | | `company` / `profile.source` / `honors.sources` 等 | **不落库** | — | 见 §5 | 触发:对话 `result` 事件的 `company_info` 非空 → 回答完成后后台同步(fire-and-forget,失败只 warn)。 三类数据(工商信息 / 荣誉 / 分类标签)**互不依赖**:分类接口挂了,前两者照常同步。 ## 2. 1888 企业基础信息(columnId 1888 / modelId 2036) ### 2.1 身份与工商信息:`profile.data` → 列(36 项) | company_info 字段 | DMS 列 | 列的中文别名与控件 | |---|---|---| | `profile.data.CreditCode` | `c_credit_code` | 「统一社会信用代码」`varchar` | | `profile.data.Name` | `c_name` | 「企业名称」`varchar` | | `profile.data.BelongOrg` | `c_belong_org` | 「所属机构」`varchar` | | `profile.data.OperId` | `c_oper_id` | 「经营者ID」`varchar` | | `profile.data.OperName` | `c_oper_name` | 「经营者名称」`varchar` | | `profile.data.DesignatedRepresentativeList` | `c_designated_representative_list` | 「法定代表人列表」`text` | | `profile.data.StartDate` | `c_start_date` | 「成立日期」`varchar` | | `profile.data.EndDate` | `c_end_date` | 「结束日期」`varchar` | | `profile.data.Status` | `c_status` | 「经营状态」`varchar` | | `profile.data.Province` | `c_province` | 「省份」`varchar` | | `profile.data.UpdatedDate` | `c_updated_date` | 「更新日期」`varchar` | | `profile.data.RegistCapi` | `c_regist_capi` | 「注册资本」`varchar` | | `profile.data.RegisteredCapital` | `c_registered_capital` | 「注册资本数值」`varchar` | | `profile.data.RegisteredCapitalUnit` | `c_registered_capital_unit` | 「注册资本单位」`varchar` | | `profile.data.RegisteredCapitalCCY` | `c_registered_capital_ccy` | 「注册资本币种」`varchar` | | `profile.data.EconKind` | `c_econ_kind` | 「经济类型」`varchar` | | `profile.data.Address` | `c_address` | 「注册地址」`varchar` | | `profile.data.Scope` | `c_scope` | 「经营范围」`text` | | `profile.data.TermStart` | `c_term_start` | 「营业期限起」`varchar` | | `profile.data.TermEnd` | `c_term_end` | 「营业期限止」`varchar` | | `profile.data.CheckDate` | `c_check_date` | 「核准日期」`varchar` | | `profile.data.OrgNo` | `c_org_no` | 「组织机构代码」`varchar` | | `profile.data.IsOnStock` | `c_is_on_stock` | 「是否上市」`varchar` | | `profile.data.StockNumber` | `c_stock_number` | 「股票代码」`varchar` | | `profile.data.StockType` | `c_stock_type` | 「股票类型」`varchar` | | `profile.data.OriginalName` | `c_original_name` | 「曾用名」`text` | | `profile.data.ImageUrl` | `c_image_url` | 「图片地址」`varchar` | | `profile.data.EntType` | `c_ent_type` | 「企业类型」`varchar` | | `profile.data.RecCap` | `c_rec_cap` | 「实收资本」`varchar` | | `profile.data.PaidUpCapital` | `c_paid_up_capital` | 「实缴资本」`varchar` | | `profile.data.PaidUpCapitalUnit` | `c_paid_up_capital_unit` | 「实缴资本单位」`varchar` | | `profile.data.PaidUpCapitalCCY` | `c_paid_up_capital_ccy` | 「实缴资本币种」`varchar` | | `profile.data.RevokeInfo` | `c_revoke_info` | 「撤销信息」`text` | | `profile.data.Area` | `c_area` | 「行政区划」`text` | | `profile.data.AreaCode` | `c_area_code` | 「行政区划代码」`varchar` | | `profile.data.No` | `c_no` | 「编号」`varchar` | > `profile.data` 共 38 个字段,上表覆盖 36 个;其余 2 个(`KeyNo`、`TeamEnd`) > DMS 侧**没有对应列**,见 §5。 > `company` 段里的 `Name` / `CreditCode` / `OperName` 等与 `profile.data` 同名字段重复, > **只作为回退**(profile 缺失时才用),不单独落列。 ### 2.2 分类标签:分类接口六角度 → `c_tag_*` | 分类角度 | DMS 列 | 列的中文别名与控件 | 取值形态 | |---|---|---|---| | 基本信息 | `c_tag_basic` | 「基本信息标签」`text` | JSON 数组字符串,如 `["第一产业","现代农业"]`;空集**不落库** | | 资质荣誉 | `c_tag_honor` | 「资质荣誉标签」`content` | JSON 数组字符串,如 `["第一产业","现代农业"]`;空集**不落库** | | 产业信息 | `c_tag_sector` | 「产业信息标签」`text` | JSON 数组字符串,如 `["第一产业","现代农业"]`;空集**不落库** | | 经营活动 | `c_tag_operation` | 「经营活动标签」`text` | JSON 数组字符串,如 `["第一产业","现代农业"]`;空集**不落库** | | 行业信息 | `c_tag_industry` | 「行业信息标签」`text` | JSON 数组字符串,如 `["第一产业","现代农业"]`;空集**不落库** | | 许可认证 | `c_tag_license` | 「许可认证标签」`text` | JSON 数组字符串,如 `["第一产业","现代农业"]`;空集**不落库** | > 数据**不是**来自 `company_info`,而是把 `company_info` 整个对象发给分类接口 > `POST /api/company/classify` 后的返回(契约见 [`company-classification.md`](./company-classification.md))。 ### 2.3 系统字段 `title` | 来源 | DMS 字段 | 说明 | |---|---|---| | `profile.data.Name`(或回退 `company.Name`) | `title`(**不在模型 fieldList 里**,是 DMS 的列表显示列) | 取企业名称。不写的话 DMS 会落成**字符串 `"null"`**——`title` 只在创建那一刻初始化,之后改 `c_*` 不带动它 | ### 2.4 其余列(前端同步不写,4 列) | DMS 列 | 别名与控件 | 为什么不写 | |---|---|---| | `c_scope_brief` | 「经营范围简述」`varchar` | 见 §5:`company_info` 里没有对应数据源 | | `c_phone_number` | 「联系电话」`varchar` | 见 §5:`company_info` 里没有对应数据源 | | `c_email` | 「邮箱」`varchar` | 见 §5:`company_info` 里没有对应数据源 | | `c_industry` | 「行业」`text` | 见 §5:`company_info` 里没有对应数据源 | ## 3. 1886 企业荣誉信息(columnId 1886 / modelId 2032) ### 3.1 `honors.records[].data` → 列(7 项,**一条荣誉一行**) | company_info 字段 | DMS 列 | 列的中文别名与控件 | |---|---|---| | `honors.records[].data.Level` | `c_level` | 「级别」`varchar` | | `honors.records[].data.Source` | `c_source` | 「来源」`varchar` | | `honors.records[].data.PublishOffice` | `c_publish_office` | 「发布机构」`varchar` | | `honors.records[].data.PublishDate` | `c_publish_date` | 「发布日期」`varchar` | | `honors.records[].data.BegingDate` | `c_beging_date` | 「起始日期」`varchar` | | `honors.records[].data.DeadLine` | `c_dead_line` | 「截止日期」`varchar` | | `honors.records[].data.CertificateCode` | `c_certificate_code` | 「证书编号」`varchar` | ### 3.2 另外写入的列 | 值 | DMS 列 | 说明 | |---|---|---| | `records[].data.Name` | `c_honor` 与系统字段 `title` | 荣誉名**两处都写**:自有列 + 列表显示列 | | 归属企业 | `c_credit_code` / `c_name` | 来自身份(`company_info.profile.data`) | | — | `c_id` | 必填字段,前端传 `0`(DMS 自动填) | | — | `c_created_at` | 新增时写 `YYYY-MM-DD HH:mm:ss`(该列在 1888 里写了读不回,1886 正常) | ### 3.3 不写的列(1 列) | DMS 列 | 别名与控件 | 说明 | |---|---|---| | `c_tag_name` | 「荣誉标签」`text` | 用户 2026-09-18 确认:不承担语义、也不清理(早期版本曾把荣誉名写在这里) | ## 4. 荣誉的「全量对齐」语义 1886 不是简单地「有则更新」,而是**与后端这份荣誉列表对齐**: | 情况 | 动作 | |---|---| | 后端有、库里没有 | 新增一行 | | 两边都有(荣誉名+级别+来源 相同),但某列值不同 | 只更新有差异的列 | | 库里多出来的 | **删除**(`updateAudit state=4`)——**仅当 `honors.complete === true`**;不完整时只增改不删 | | 完全一致 | 零写入 | ## 5. 不落库的字段 | 字段 | 为什么不落 | |---|---| | `profile.source.*`(provider / api_code / document_url / fetched_at / page_index / total_records / company_key) | 溯源元信息,1888 没有对应列 | | `profile.data.KeyNo`、`company.KeyNo` | 企查查主体键,DMS 侧没有对应列 | | `profile.data.TeamEnd` | 企查查的拼写错误字段(正确拼法是 `TermEnd`),**值恒为空串** | | `honors.complete` / `honors.error` / `honors.sources[].*` | 只用于判断「能不能删」与溯源,不落库 | | 1888 的 `c_scope_brief` / `c_phone_number` / `c_email` / `c_industry` | **DMS 有列,但 `company_info` 里没有这些字段**(企查查 410 接口未返回)——要存需后端先补数据源 | ## 6. 三条影响「对应关系」的写入规则 1. **空值一律不写**(`null` / 空串 / 空数组 / 空对象)——**不清存量**: 库里已有的值不会被「本次没带」的字段抹掉 2. **JSON 列按语义比较**(`c_area` / `c_original_name` / `c_revoke_info` / `c_designated_representative_list`):DMS 里是 Python/jsonb 序列化的(带空格、键按字母序), 与 JS 的 `JSON.stringify` 字节不同——语义相同就不写,避免每轮无谓改写 3. **无差异零写入**:字段级 diff,patch 为空则完全不发请求(幂等,重复同步不改数据) ## 7. 当前覆盖率 | 栏目 | 在写 | 未写 | 未写的原因 | |---|---|---|---| | 1888(47 列) | **43 列** | 4 列 | 载荷里没有数据源(§5) | | 1886(13 列) | **12 列** | 1 列 | 用户确认不用(§3.3) | > 复核命令:`node harness/tools/audit-company-info-coverage.mjs ` > (实时拉模型 + 从代码派生写入列,输出同样可比对的清单)