SFT/docs/superpowers/specs/2026-07-21-enterprise-custo...

21 KiB

企业客户新增/编辑表单增强设计(基础信息必填订正 + 更多信息 + 股东高管信息重构 + 对外投资关系信息)

  • 状态: 已与用户完成澄清问答,用户确认设计方向,直接进入 writing-plans
  • 上级文档: 2026-07-09-phase3-customer-management-design.md(阶段3客户管理原始设计,本文档是对其"企业客户"部分的增补/局部覆盖)
  • 触发来源: 用户提供"客户管理 > 企业客户管理 > 新增企业客户"页面最新原型截图,要求:①订正基础字段必填属性;②基础信息下新增"更多信息"折叠区块;③"公司股东与高管信息"交互与字段按截图重做;④新增"对外投资关系信息"区块
  • 直接对应文件: src/views/customer/enterprise/EnterpriseForm.vue(唯一改动的表单组件)、src/api/customer.js、新增 src/constants/enterpriseEnums.js、新增 src/components/RegionCascader.vue缺失的后端接口.md

0. 与既有设计的关系/参考先例

个人客户表单在 2026-07-20 已经做过同类改造(《缺失的后端接口.md》Part 7/8):产品截图要求的新字段在后端 swagger 里完全不存在时,前端策略是——按截图完整实现 UI 和交互,新字段用前端占位枚举,随 create/update 请求一并提交(后端会忽略未声明字段,不报错也不落库),同时把所有缺口逐条记录进《缺失的后端接口.md》,不因后端能力不足阻塞前端交付。本次企业客户表单改造延续同一策略,不再逐条与用户确认"要不要做",直接照此模式实现。

经与用户澄清确认的关键决策(详见下文各节引用):

  1. 省市区级联选择:引入静态省市区数据包(china-division,仅取其 dist/pca-code.json 省市区三级数据),封装通用组件,不依赖后端。
  2. "公司股东与高管信息""对外投资关系信息"均支持新增多条记录,每条一张可删除的卡片。
  3. 股东高管卡片里国籍/性别/职业类型/联系电话/地址信息/客户编号,选中个人客户后只读回填,不可编辑覆盖。
  4. "是否法定代表人"改为按股东逐行勾选,同一时间最多一位,互斥。
  5. "对外投资关系信息"的"客户名称"只能选企业客户(不支持个人客户)。

1. 范围

包含:

  • EnterpriseForm.vue 基础信息区必填属性订正、证件地址改为省市区级联+详细地址
  • 新增"更多信息"可折叠区块(公司级标量字段 + 联系信息表格 + 地址信息表格 + 若干是否布尔 + 备注)
  • "股东与高管信息"由"只读表格+行内下拉"重构为"卡片列表"(可新增多条/单条删除),字段按截图扩展
  • 新增"对外投资关系信息"卡片列表区块(全新概念,与股东高管信息平级)
  • 新增枚举字典 src/constants/enterpriseEnums.js
  • 新增通用组件 src/components/RegionCascader.vue(省市区级联,供"证件地址"与"地址信息"表格复用)
  • 依赖新增:china-division(仅用其静态 JSON 数据,不引入运行时逻辑)
  • 《缺失的后端接口.md》新增一节记录所有新增/扩展字段(编号从 79 开始,章节标题为 Part 9)

不包含:

  • 不改动企业客户列表页 EnterpriseList.vue(用户需求未提及列表页)
  • 不新建"个人+企业通用选择器"——对外投资关系信息按用户确认只需企业客户选择,复用/扩展现有企业客户选择弹窗即可
  • 不改动股东高管信息/对外投资关系信息在编辑/详情模式下的可用性限制原则:两者继续仅新增模式可编辑,编辑/详情模式沿用"仅支持新增时登记"提示文案(原因见第7节)
  • 不引入省市区之外的国际地区数据(国家地区字段仅提供"中国/其他"二选,选"其他"时行政区划退化为自由文本,见 4.1 节)

2. 组件与文件清单

src/
  components/
    RegionCascader.vue          # 新增:省市区级联选择器,基于 china-division 的 pca-code.json
  constants/
    enterpriseEnums.js          # 新增:企业客户"更多信息"+股东高管+对外投资关系 涉及的全部占位/复用枚举
  views/customer/enterprise/
    EnterpriseForm.vue          # 改造:基础信息必填订正、更多信息区块、股东高管信息重构、对外投资关系信息新增
  api/customer.js               # 不新增接口方法(仍是同一个 create/update),仅在 payload 组装处扩展字段
缺失的后端接口.md                # 新增 Part 9
package.json                    # 新增依赖 china-division

RegionCascader.vue 设计:

  • Props: v-model:value(省市区 code 三元数组,如 ['330000','330100','330102'])、v-model:text(对应中文名以 / 连接的展示字符串,如"浙江省/杭州市/上城区",用于提交给后端的可读地址,因为后端目前是自由文本字段,不是 code)
  • 内部:import pcaCode from 'china-division/dist/pca-code.json',转换为 a-cascader 所需的 {value, label, children} 结构(一次性转换,computed 缓存)
  • a-cascader :options="options" v-model:value="innerValue" change-on-select="false" />,change 时同步计算 text

3. 基础信息区改造

3.1 必填订正(对照截图逐项核对)

字段 现状 改为
证件照片(营业执照) 无 required 维持不必填(截图只有识别提示,无红星)
所属机构 已必填 维持
企业名称 已必填 维持
营业执照号 仅格式校验,非必填 改为必填(格式校验规则保留)
证件生效日期 无校验 改为必填
证件失效日期 无校验 改为必填,但勾选"长期"后可不填(复用个人客户 CERTIFICATE_LONG_TERM_DATE 哨兵日期方案,新增"长期"勾选框,交互与 PersonalForm.vuecertificateExpiryDate 校验规则完全一致)
手机号码 仅格式校验,非必填 改为必填
证件地址 无校验,纯文本 改为必填,且改为"省市区级联 + 详细地址"两部分(见3.2)
经营范围 无校验 改为必填
法定代表人 独立选择字段,非必填 删除该字段,改为股东高管卡片内"是否法定代表人"勾选(见5.4)

3.2 证件地址结构调整

  • 表单字段拆分为 certificateRegionCode(数组,不提交,仅本地级联控件绑定)、certificateRegionText(省市区文本)、certificateAddress(详细地址,复用现有字段名)
  • 提交时按后端现有字段 certificateAddress 的自由文本约定,拼接为 ${certificateRegionText}${certificateAddress}(与现有个人客户/企业客户"证件地址"是单一自由文本字段的既有约定保持兼容,不新增后端字段;若后端后续拆分省市区结构化字段,见 Part 9 建议)

4. 更多信息区块(新增,<a-collapse>,默认展开,风格与 PersonalForm.vue 一致)

4.1 标量字段(挂载在企业主表单 form 上,提交时随 create/update 一起发送)

分组 字段(前端命名) 类型/组件 枚举来源
单位性质 unitNature select enterpriseEnums.UNIT_NATURE_OPTIONS(占位)
经济成分 economicComposition select ECONOMIC_COMPOSITION_OPTIONS(占位)
机构类别 institutionCategory select INSTITUTION_CATEGORY_OPTIONS(占位,对应"登记注册类型")
经济性质经营类型 economicNature select ECONOMIC_NATURE_OPTIONS(占位)
国民经济门类 nationalEconomyCategory select NATIONAL_ECONOMY_CATEGORY_OPTIONS(采用 GB/T 4754 标准20门类真实分类,非占位)
注册资本 + 币种 registeredCapital + registeredCapitalCurrency input-number + select 币种复用现有 CURRENCY_OPTIONS(如项目已有则复用,否则新增,默认"人民币")
企业成立日期 establishmentDate date-picker -
实收资本 + 币种 paidInCapital + paidInCapitalCurrency input-number + select 同上
上年末企业从业人员 lastYearEmployeeCount input-number(单位:人次) -
上年末资产总额 lastYearTotalAssets input-number -
上年营业收入 lastYearRevenue input-number -
净资产 netAssets input-number -
基本账户信息 basicAccountBankName + basicAccountNumber input + input -
开户信息 accountLicenseNumber + accountLicenseDate input + date-picker -
缴款卡号 paymentCardNumber input -
企业规模 enterpriseScale select ENTERPRISE_SCALE_OPTIONS(采用工信部四级标准:大型/中型/小型/微型,非占位)
外汇企业类型 foreignExchangeEnterpriseType select FOREIGN_EXCHANGE_ENTERPRISE_TYPE_OPTIONS(占位)
人行金融机构编码 pbocFinancialInstitutionCode input -
金融机构行业分类 financialInstitutionIndustryType select FINANCIAL_INSTITUTION_INDUSTRY_OPTIONS(占位)
同业客户类型 interbankCustomerType select INTERBANK_CUSTOMER_TYPE_OPTIONS(占位)
经营状态 businessStatus select BUSINESS_STATUS_OPTIONS(占位)
客户状态 customerStatus select,截图当前为空("暂无客户") 复用个人客户 CUSTOMER_STATUS_OPTIONS(FORMAL/POTENTIAL)
是否冰点客户 + 冰冻类型 isFrozenCustomer(布尔) + frozenType(冰点=true时才可选) radio + select FROZEN_TYPE_OPTIONS(占位)
境内境外 residencyArea radio 复用 DOMESTIC/OVERSEAS(与个人客户一致命名)
是否绿色企业 isGreenEnterprise radio(布尔) -
是否集团客户 isGroupCustomer radio(布尔) -
是否个体工商户 isIndividualBusiness radio(布尔) -
是否上市公司 isListedCompany radio(布尔) -
是否小微企业 isSmallMicroEnterprise radio(布尔) -
是否科技企业 isTechEnterprise radio(布尔) -
备注 remark textarea -

全部标量字段均为非必填(截图无红星),默认值均为 undefined/false,不做前端强制校验。

4.2 联系信息表格(可增删行,交互模式复用现有"股东高管信息"表格的增删行写法)

  • 数据模型 contactInfoList = ref([{ contactType: 'MOBILE', contactValue: '', isPrimary: true }])(默认一行,截图默认展示"移动电话")
  • 列:联系类型(select,CONTACT_TYPE_OPTIONS:移动电话/固定电话/传真/电子邮箱/其他)、联系信息(input)、主要标志(select 是/否)、操作(删除链接,至少保留一行不可删空)
  • 提交字段名:contactInfoBtoList

4.3 地址信息表格(可增删行)

  • 数据模型 addressInfoList = ref([{ addressType: 'CERTIFICATE', country: 'CN', regionCode: [], regionText: '', detailAddress: '', isPrimary: true }])(默认一行"证件地址",国家默认中国)
  • 列:地址类型(select,ADDRESS_TYPE_OPTIONS:证件地址/联系地址/注册地址/经营地址/其他)、国家地区(select:中国/其他,选"其他"时行政区划列切换为自由文本输入)、行政区划(复用 RegionCascader.vue,仅当国家=中国时可用)、详细地址(input)、主要标志(select 是/否)、操作(删除)
  • 提交字段名:addressInfoBtoList

5. 公司股东与高管信息(卡片列表重构)

5.1 交互变化

  • 由"a-table 只读表格 + 行内 select"改为"卡片列表":每条已添加的关联人渲染为一张 <a-card>,卡片内是完整字段表单;区块标题右侧"+"按钮点击后打开 PersonalCustomerPicker 选人,选中后在列表末尾追加一张新卡片;每张卡片右上角"删除"按钮移除该卡片(relatedPersonList.value.splice(index,1))
  • 沿用现状:仅新增模式(isCreate)展示且可编辑;编辑/详情模式展示提示文案(原因:后端 enterpriseRelatedPersonBtoList 只存在于 CreateEnterpriseCustomerBto,Update/Detail 均无此字段,见现有设计文档第7节能力缺口8,本次不改变这一限制)

5.2 卡片字段(选中个人客户后只读回填 vs 可编辑,严格按截图区分)

只读回填字段(选中个人客户后从其详情快照,不可编辑,与现状"证件类型/号码/生效日/到期日"一致处理):

  • 证件类型、证件号码、证件生效日期、证件失效日期(现状已有,保持不变)
  • 国籍(nationality)、性别(gender)、职业类型(occupationType,展示时用个人客户模块 OCCUPATION_TYPE_OPTIONS 反查中文标签)、联系电话(mobilePhone)、地址信息(certificateAddress)、客户编号(customerCode)——均来自选中个人客户的 detail 接口返回(个人客户 2026-07-20 已扩展这些字段,若后端尚未实现则显示为空,不是缺陷)

可编辑字段(卡片内表单项):

  • 是否法定代表人:isLegalRepresentative(radio 是/否)。互斥规则:任一卡片勾选"是"时,其余所有卡片自动置为"否"(前端本地维护,提交时取值为 true 的那一条的 individualId 作为顶层 legalRepresentativeId 提交,若无人勾选则 legalRepresentativeId 为空)
  • 关联人类型:relatedType(现状已有:股东/高管/受益所有人)
  • 职务:position(select,enterpriseEnums.POSITION_OPTIONS,复用后端真实已有字段 position)
  • 任职时间:positionStartDate(date-picker,新增)
  • 相关行业从业年限:industryYears(input-number,新增)
  • 持股状况:shareholdingRatio(input-number + %,复用后端真实已有字段 shareholdingRatio)
  • 出资相关:出资方式 contributionMethod(select,CONTRIBUTION_METHOD_OPTIONS:货币/实物/知识产权/土地使用权/其他)+ 币种 contributionCurrency(默认人民币)+ 应出资金额 subscribedAmount + 实际出资金额 paidAmount + 出资比例 contributionRatio(%,与"持股状况"含义不同——持股比例是最终股权占比,出资比例是本次出资占应出资总额的比例,两个字段都保留)+ 出资日期 contributionDate
  • 备注:remark(新增)

只读展示,不可编辑,不提交:

  • 关联客户编号:固定展示"暂无关联客户编号"(新增卡片时后端尚未生成该关系记录的编号,无实际数据来源,纯展示占位,不对应任何提交字段)

5.3 数据模型与提交字段扩展

relatedPersonList 每项字段从现状 {individualId, customerName, relatedType, certificateType, certificateNumber, certificateEffectiveDate, certificateExpiryDate} 扩展为新增:nationality, gender, occupationType, mobilePhone, certificateAddress, customerCode(以上6项均为选人后只读快照,来自个人客户 detail 接口返回值,取不到则留空)+ isLegalRepresentative, position, positionStartDate, industryYears, shareholdingRatio, contributionMethod, contributionCurrency, subscribedAmount, paidAmount, contributionRatio, contributionDate, remark(以上均为用户可编辑项)

提交时 enterpriseRelatedPersonBtoList 逐项组装,在现有5个字段基础上追加:position, shareholdingRatio, nationality, contactPhone(取mobilePhone), positionStartDate, industryYears, contributionMethod, contributionCurrency, subscribedAmount, paidAmount, contributionRatio, contributionDate, remark(nationality/contactPhone/position/shareholdingRatio 是后端 swagger 已声明的真实字段,其余是新增待后端确认的字段,见 Part 9)。gender/occupationType/certificateAddress/customerCode 仅用于页面展示,不重复提交(它们是个人客户自身的属性,不属于"企业-关联人关系"这层数据,提交这些字段没有业务意义)。

6. 对外投资关系信息(全新区块,卡片列表)

6.1 交互

  • 与"股东与高管信息"完全相同的卡片列表交互:标题右侧"+"打开企业客户选择弹窗 → 选中后追加卡片 → 每卡片可删除
  • 选择器:企业客户选择只能选企业客户(用户已确认),复用现有企业客户列表查询能力封装一个 EnterpriseCustomerPicker.vue(仿照 PersonalCustomerPicker.vue 的结构,内部用 mini ProTable 查询 fetchEnterpriseCustomerPageApi,查询条件:企业名称/营业执照号/手机号,与 EnterpriseList.vue 现有查询字段一致)
  • 仅新增模式(isCreate)展示且可编辑;编辑/详情模式展示提示文案"对外投资关系信息仅支持新增时登记,当前接口不支持查询或修改,如需变更请联系技术支持核实数据"(与股东高管信息保持一致的处理原则,理由:该结构在后端 swagger 中完全不存在,无法验证 update/detail 是否可回显,为避免"编辑时列表总是空"造成用户误以为数据丢失,统一按"仅新增可编辑"处理,与已有股东高管信息处理原则保持一致)

6.2 卡片字段

选中企业客户后只读回填:

  • 证件类型(固定"营业执照")、证件号码(企业营业执照号)、失效时间(证件到期日)

可编辑字段:

  • 持股状况:shareholdingRatio(%,本企业持有被投资企业的股权比例)
  • 出资相关:出资方式 contributionMethod + 币种 contributionCurrency(默认人民币)+ 应出资金额 subscribedAmount + 实际出资金额 paidAmount + 出资比例 contributionRatio(%)+ 出资日期 contributionDate
  • 出资人经济成分:investorEconomicComposition(select,复用 4.1 节 ECONOMIC_COMPOSITION_OPTIONS)
  • 关系类型:relationType(select,INVESTMENT_RELATION_TYPE_OPTIONS:控股/参股/联营/合营/其他)
  • 是否有效:isValid(radio 是/否,默认是)
  • 关系到期时间:relationExpiryDate(date-picker)
  • 备注:remark

只读展示,不提交:

  • 关联客户编号:固定展示"暂无关联客户编号"(同 5.2 节说明)

6.3 数据模型与提交字段

新增 investmentList = ref([]),每项:{investeeEnterpriseId, investeeName, certificateType, certificateNumber, certificateExpiryDate, shareholdingRatio, contributionMethod, contributionCurrency, subscribedAmount, paidAmount, contributionRatio, contributionDate, investorEconomicComposition, relationType, isValid, relationExpiryDate, remark}

提交字段名:enterpriseInvestmentBtoList(全新数组,后端完全没有对应结构,见 Part 9 建议)

7. 编辑/详情模式统一处理原则

relatedPersonList(股东高管信息)与新增的 investmentList(对外投资关系信息)在编辑/详情模式下均替换为提示文案,不渲染卡片列表与"+"按钮,理由统一为:

  1. 股东高管信息:已确认的既有限制,Update/Detail Bto/Vo 均无该数组字段
  2. 对外投资关系信息:后端完全没有此结构,无法确认 update/detail 是否支持,为避免行为不一致与用户误解,统一按同一限制处理

"更多信息"区块的标量字段(单位性质、经济成分……备注)以及联系信息/地址信息表格,在编辑模式下仍可编辑并随 update 提交(与股东高管/对外投资关系不同处理),理由:这些是挂载在企业主体 Bto/Vo 上的字段/子结构,一旦后端补充,天然会随 detail/update 一起生效,不存在"仅 Create Bto 独有数组字段"这种结构性限制,处理方式与个人客户 2026-07-20 改造的"更多信息"标量字段完全一致。

8. 表单校验补充

新增必填规则(3.1节已列出字段),证件失效日期沿用个人客户 certificateLongTerm 校验模式(勾选长期后不强制填日期,否则必填)。"更多信息"、联系信息/地址信息表格、股东高管卡片扩展字段、对外投资关系信息全部字段均不做前端必填校验(截图均无红星标注)。

9. 《缺失的后端接口.md》记录内容(Part 9,编号从79开始)

新增章节 ## Part 9:企业客户新增表单"更多信息"/股东高管信息扩展/对外投资关系信息 —— 2026-07-21 补充,按 Part 7 的行文格式,分条记录:

  1. CreateEnterpriseCustomerBto/UpdateEnterpriseCustomerBto/EnterpriseCustomerDetailVo 需扩展 4.1 节列出的约30个标量字段(逐项列出字段名/类型/枚举来源,标注哪些是真实标准分类[国民经济门类/企业规模]、哪些是前端占位)
  2. 建议新增 contactInfoBtoList(联系信息)、addressInfoBtoList(地址信息)两个子数组结构
  3. EnterpriseRelatedPersonBto 需在已有 position/shareholdingRatio/nationality/contactPhone 基础上补充 positionStartDate/industryYears/contributionMethod/contributionCurrency/subscribedAmount/paidAmount/contributionRatio/contributionDate/remark 等新字段,并说明 gender/occupationType/certificateAddress/customerCode 属于个人客户自身字段、前端不重复提交
  4. 全新结构建议:enterpriseInvestmentBtoList(对外投资关系),列出完整字段清单,并说明当前无法确认 update/detail 是否可回显,前端按"仅新增模式可用"处理
  5. "证件地址"由自由文本拆分省市区+详细地址是纯前端展示层拼接(省市区数据来自静态npm包 china-division,不依赖后端),建议后端后续可考虑拆分省市区结构化字段,但非阻塞项
  6. "是否法定代表人"由股东逐行勾选互斥决定,提交时仍复用已有的顶层 legalRepresentativeId 字段,后端无需改动

10. 自查(占位符/矛盾/歧义/范围)

  • 全文无 "TBD/待定" 类占位符;标注"占位枚举/待确认"的字段均已给出前端拟定的具体可用值,不是留白
  • 第7节明确区分了"标量字段随 update 提交"与"数组字段仅新增可用"两类字段的不同处理原则,与第5/6节的处理方式一致,无矛盾
  • 范围严格对应用户截图与4个明确诉求(必填订正/更多信息/股东高管信息/对外投资关系信息),未扩展到列表页或其它模块
  • 与用户澄清问答的5个决策结论均已在对应章节体现(0节已汇总引用),无冲突

设计自查通过,进入 writing-plans 生成实施计划。