From 5a1d88618f2009cee5e0b8b77f7dad1b4c5a494f Mon Sep 17 00:00:00 2001 From: halo Date: Wed, 12 Aug 2026 21:22:13 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E4=B8=AA=E4=BA=BA/=E4=BC=81?= =?UTF-8?q?=E4=B8=9A=E8=B4=B7=E6=AC=BE=E7=94=B3=E8=AF=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AGENTS.md | 38 +- mock-server/routes/credit.js | 4 +- src/api/customer.js | 2 + src/components/FacePhotoUpload.vue | 44 +- src/constants/creditEnums.js | 22 +- .../loan-application/EnterpriseLoanForm.vue | 1260 ++++++++--------- .../loan-application/LoanApplicationList.vue | 4 + .../loan-application/PersonalLoanForm.vue | 328 ++--- .../enterprise-open/EnterpriseOpenForm.vue | 417 +++--- .../wallet/personal-open/PersonalOpenForm.vue | 11 +- 缺失的后端接口.md | 111 ++ 11 files changed, 1090 insertions(+), 1151 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index d0c8247..6d13273 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,9 +1,14 @@ # AGENTS.md -凡荣e链管理后台前端。Vue 3 + Vite,**纯 JavaScript(无 TypeScript)**,Ant Design Vue + Pinia + Vue Router + Axios。无 Node 服务端(mock-server 仅本地演示用),构建产物是纯静态 SPA。 +**本仓库包含两个独立的 npm 工程,各自 `package.json`/`node_modules`/`dist`,不是 monorepo/workspaces:** + +- **根目录**:凡荣e链**管理后台**前端(PC 端,银行内部人员用)。Vue 3 + Vite,**纯 JavaScript(无 TypeScript)**,Ant Design Vue + Pinia + Vue Router + Axios。无 Node 服务端(mock-server 仅本地演示用),构建产物是纯静态 SPA。 +- **`fryl_h5/`**:凡荣e链**移动端 H5**(手机端,未登录终端客户扫码后访问,用于开户/贷款申请信息核对)。Vue 3 + Vite + **Vant**(不是 Ant Design Vue)+ Vue Router + Axios,**无 Pinia/任何状态管理库**,纯静态路由(无动态菜单)。它没有自己的 README/AGENTS.md,本文件下方"H5 子工程"一节即是它的说明来源;不是 git submodule,是根仓库直接纳管的目录,有自己独立的 commit 历史(`git log -- fryl_h5`)。 +- 两者**共享同一个真实后端**,接口契约统一记录在根目录《缺失的后端接口.md》和 `docs/superpowers/specs/`(`fryl_h5` 自己没有这些文档)。改动前先确认改的是哪一个工程,不要把两者的依赖/组件/约定搞混。 ## 常用命令 +根目录(管理后台): ```bash npm run dev # 启动开发服务器,端口 5173 npm run build # 构建 @@ -11,7 +16,15 @@ npm run preview # 预览构建产物 npm run mock # 启动本地 mock 后端(express),默认端口 8888,可用 MOCK_PORT 覆盖 ``` -没有配置 lint / prettier / 单元测试脚本,不要假设它们存在,也不要臆造 `npm run lint`/`npm test`。 +`fryl_h5/`(H5,命令要在该目录下跑): +```bash +npm run dev # 端口 5174(特意与根项目 5173 区分,可同时开两个工程调试) +npm run build +npm run preview +``` +`fryl_h5` **没有自己的 mock 命令**,本地联调依赖根目录的 `npm run mock`(默认端口 8888,`fryl_h5/.env.development` 的 `VITE_API_BASE_URL` 也指向它)。 + +两个工程都没有配置 lint / prettier / 单元测试脚本,不要假设它们存在,也不要臆造 `npm run lint`/`npm test`。 ## 后端接口对接(最重要,容易出错) @@ -22,7 +35,7 @@ npm run mock # 启动本地 mock 后端(express),默认端口 8888,可用 M - 分页接口 Body 含 `page`(从1开始)/`pageSize`,响应 `data` 为 `{ total, page, pageSize, records }`——字段是 **records**,不是 `list`。 - 绝大多数模块**没有批量删除接口**,批量操作需用 `src/utils/loopDelete.js` 循环调单条删除并汇总结果(配合 `batchDeleteResult.js` 展示成功/失败)。 - 文件(身份证/营业执照等)以 **Base64 字符串**放在 JSON body 传输,不用 `multipart/form-data`。 -- `.toco/CONFIG` 目前只有 `ORG_ID`/`ORG_NAME`,**没有 `PROJECT_ID`**。若需要用 MCP 工具(`getApiList`/`getApiSwaggerByUris`)读取最新 swagger,先确认该文件是否已补上 `PROJECT_ID`;否则以仓库根目录的 `swagger_project_scfs_2026-07-09_14-15-23.json` 和《缺失的后端接口.md》为准。 +- `.toco/CONFIG` 目前只有 `ORG_ID`/`ORG_NAME`,**没有 `PROJECT_ID`**。若需要用 MCP 工具(`getApiList`/`getApiSwaggerByUris`)读取最新 swagger,先确认该文件是否已补上 `PROJECT_ID`;否则以仓库根目录**最新日期**的 `swagger_project_scfs_*.json`(目前有 `2026-07-09`/`2026-07-31`/`2026-08-05` 三份快照,取文件名日期最大的)和《缺失的后端接口.md》为准,不要默认用最早那份。 - `mock-server/`(`npm run mock`,端口 8888)是真实后端不可用时的应急本地演示后端,**契约已知与真实接口不完全一致**(见 `mock-server/README.md` “已知简化点”),不要把它当作接口设计依据。真实后端已接入,`.env.development` 默认 `VITE_API_BASE_URL=http://localhost:8888`,登录页齿轮图标可在运行时切换到真实后端地址(存 `localStorage.base_url_override`,见 `src/api/request.js` 的 `getBaseUrl`/`setBaseUrlOverride`)。 - 本地联调真实后端遇 CORS 时,用 `.env.development.local`(已 gitignore)配 `DEV_API_PROXY_TARGET`,走 `vite.config.js` 里的同源代理方案;别改生产构建逻辑去“解决” CORS。 - 每次请求必须附带以下 5 个 header(**字段名大小写固定为下列形式**,首字母大写、其余小写): @@ -31,8 +44,8 @@ npm run mock # 启动本地 mock 后端(express),默认端口 8888,可用 M - `serialNo`:流水号,随机值 - `transDate`:`yyyy-MM-dd` 格式日期 - `transTradeTime`:`yyyy-MM-dd HH:mm:ss` 格式时间 - - ⚠️ 现状:`src/utils/traceHeaders.js` 的 `buildTraceHeaders()` 目前只生成 `serialNo`/`transDate`/`transTradeTime` 三个小写驼峰字段,**缺少 `Appno`/`Channelno`**,尚未按最新要求改造;涉及请求 header 的改动前务必先核对/修复这里,不要照抄旧的三字段实现。 - `channelNo` 如果页面没有渠道信息,则不需要传值 + - `src/utils/traceHeaders.js` 的 `buildTraceHeaders(channelNo)` 已正确实现上述 5 个字段(含固定大小写、`channelNo` 按需可选),**不需要再改造**;`fryl_h5/src/utils/traceHeaders.js` 是同一实现的独立拷贝(H5 端匿名接口,永远不传 `Channelno`)。 - 枚举值必须来自 swagger/《缺失的后端接口.md》,已整理在 `src/constants/*Enums.js`,不要编造新枚举。 ## 路由架构(新增页面容易漏配置) @@ -56,13 +69,13 @@ npm run mock # 启动本地 mock 后端(express),默认端口 8888,可用 M ## 目录速览 - `src/api/*.js`:按后端模块拆分的请求封装,`src/api/request.js` 是唯一的 axios 实例(含鉴权/刷新/trace header/错误提示拦截器)。 -- `src/components/ProTable.vue`:通用查询表单+分页表格封装,列表页优先复用它而不是重写查询/分页逻辑。 +- `src/components/ProTable.vue`:通用查询表单+分页表格封装,列表页优先复用它而不是重写查询/分页逻辑。传给它的 `fetch-data` 函数必须返回 `{ list, total }`(**注意**:后端分页字段是 `records`,列表页自己的 `loadList`/`fetchData` 函数里要做 `records → list` 的映射,不要指望 `ProTable` 或 api 封装层自动转换)。 - `src/constants/*Enums.js`:各模块枚举字典(状态/类型等),来源必须是 swagger。 - `src/views///`:页面按模块/子模块分文件夹,列表页与新增/编辑/查看表单通常拆成 `XxxList.vue` + 共用的 `XxxForm.vue`(查看态字段只读,不是单独组件)。 ## 图片/证件照片上传交互规范 -所有"图片上传卡片"(身份证、营业执照、人脸照片等 `list-type="picture-card"` 的 `a-upload` 封装组件)一旦已选中图片,**必须**支持鼠标 hover 缩略图时显示半透明遮罩 + 预览/重新上传/删除三个操作按钮,不允许只放一张裸 ``。以 `src/components/IdCardUpload.vue` 为标准实现参照,新增或修改任何图片上传组件都要照此模式实现(`src/components/LicenseUpload.vue` 已按此模式改造): +所有"图片上传卡片"(身份证、营业执照、人脸照片等 `list-type="picture-card"` 的 `a-upload` 封装组件)一旦已选中图片,**必须**支持鼠标 hover 缩略图时显示半透明遮罩 + 预览/重新上传/删除三个操作按钮,不允许只放一张裸 ``。以 `src/components/IdCardUpload.vue` 为标准实现参照,新增或修改任何图片上传组件都要照此模式实现(`LicenseUpload.vue`/`FacePhotoUpload.vue` 均已按此模式改造): - 缩略图外层包 `.thumb-wrapper`(`position: relative`),内部 `` + 一个 `position:absolute; inset:0` 的 `.hover-mask`(`rgba(0,0,0,0.5)` 背景,默认 `opacity:0`,`:hover` 时 `opacity:1`,`transition:opacity 0.2s`)。 - 遮罩内横向排列三个图标(`EyeOutlined` 预览 / `EditOutlined` 重新上传 / `DeleteOutlined` 删除),之间用 1px 竖线 `.mask-divider` 分隔,图标颜色 `#fff`,hover 变 `#1677ff`。 @@ -70,7 +83,7 @@ npm run mock # 启动本地 mock 后端(express),默认端口 8888,可用 M - **删除**:图标加 `@click.stop`,清空本地预览态并 `emit('update:fileNo', '')`,让父组件感知已清空。 - **重新上传**:图标**不加** `@click.stop`,让点击事件自然冒泡到外层 `a-upload` 容器,复用其原生文件选择流程触发重新选图(不要单独写一套"重新上传"逻辑)。 - 组件需支持 `readonly` prop(默认 `false`):为 `true` 时只保留预览图标,隐藏"重新上传/删除"——用于查看详情等只读表单场景。调用处如果页面本身有 `isDetail` 之类的只读态标记,必须把它传给上传组件的 `readonly`,不要漏传(否则只读页面会出现可用的删除按钮)。 -- 当前项目**没有抽出通用的图片上传基础组件**,`IdCardUpload.vue`/`LicenseUpload.vue`/`FacePhotoUpload.vue` 是各自独立实现(结构相似但不复用)。`FacePhotoUpload.vue` 目前还没有按此规范改造,后续涉及到它时要一并补上。 +- 当前项目**没有抽出通用的图片上传基础组件**,`IdCardUpload.vue`/`LicenseUpload.vue`/`FacePhotoUpload.vue` 是各自独立实现(结构相似但不复用)。新增同类组件时照抄这三个的模式,不要指望后续会抽公共组件。 ## 耗时操作统一等待态规范 @@ -83,6 +96,17 @@ npm run mock # 启动本地 mock 后端(express),默认端口 8888,可用 M - 图片上传组件(见上一节规范)通过 `update:uploading` 事件把自身上传中状态回传给父表单,父表单纳入 `busy` 统一遮罩,并在提交前校验各 `xxxUploading` 状态、阻止在文件尚未上传完成时提交表单。 - 新增页面/表单时按此模式补齐,不需要抽公共 hook/组件,保持和现有页面一致的写法即可。 +## H5 子工程(`fryl_h5/`)特殊约定 + +- 路由**是纯静态声明**(`fryl_h5/src/router/index.js`),没有根项目那套动态菜单机制;向导式流程(信息核对→协议/人脸→短验→完成)的步骤切换靠页面内部 `currentStep` ref 维护,**不为每个步骤单独设路由**,避免用户分享/刷新中间步骤 URL 导致状态错乱。新增步骤直接加 `views/steps/**` 组件即可,不用碰路由文件。 +- `fryl_h5/src/api/request.js` 是独立的精简版 axios 实例,**不注入 `Authorization`、不做 401 刷新**(面向未登录终端客户的匿名接口),不要照抄根项目 `src/api/request.js` 的鉴权逻辑。 +- **无 Pinia**,所有状态用组件内 `ref` 管理,不要为这个子工程引入状态管理库。 +- Trace header 同样用 `buildTraceHeaders()`,但**永远不传 `channelNo`**(二维码链接不带渠道上下文)。 +- 与根项目**复用同一批后端接口**:例如协议模板接口 `GET /api/customer-info/bank-agreement/base64` 根项目在 `src/api/customer.js` 封装,`fryl_h5` 在 `src/api/personalOpen.js` 里对同一接口重新封装了一份(两处各自维护,改接口字段要两边一起改)。 +- 生成二维码指向 `fryl_h5` 哪个页面的环境变量(`VITE_H5_QRCODE_BASE_URL`/`VITE_H5_QRCODE_PATH*`)配置在**根项目**的 `.env.development`/`.env.production` 里,由根项目 `src/utils/qrCode.js` 拼出完整链接,不在 `fryl_h5` 自己的 env 文件中。 +- 相关设计文档在根目录 `docs/superpowers/specs/`,文件名含 `mobile-h5`/`loan-application-mobile` 关键字(如 `2026-07-27-personal-open-mobile-h5-design.md`、`2026-08-11-loan-application-mobile-confirm-design.md`),改动前先查。 +- 企业开户 H5 的提交接口本地 `mock-server` 未实现,只能连真实后端联调验证;涉及企业开户 H5 时先看《缺失的后端接口.md》里标注"前端假设"的段落,不要假定 mock 能跑通。 + ## 其他约定 - BASE_URL 必须保留界面可配置入口(已实现,见上文),不要改成硬编码。 diff --git a/mock-server/routes/credit.js b/mock-server/routes/credit.js index 208f41f..1c21e60 100644 --- a/mock-server/routes/credit.js +++ b/mock-server/routes/credit.js @@ -45,7 +45,7 @@ router.post('/loan-application/detail', (req, res) => { // ---------------- 个人贷款申请 ---------------- router.post('/personal-loan-application/create', (req, res) => { const body = req.body || {} - if (!body.channel) return sendFail(res, '所属渠道不能为空', 400) + if (!body.channelNo) return sendFail(res, '所属渠道不能为空', 400) if (!body.loanProductCode) return sendFail(res, '贷款产品编号不能为空', 400) if (!body.goodsCategory) return sendFail(res, '商品类目不能为空', 400) if (!body.paymentCycle) return sendFail(res, '回款周期不能为空', 400) @@ -85,7 +85,7 @@ router.post('/personal-loan-application/update', (req, res) => { // ---------------- 企业贷款申请 ---------------- router.post('/enterprise-loan-application/create', (req, res) => { const body = req.body || {} - if (!body.channel) return sendFail(res, '所属渠道不能为空', 400) + if (!body.channelNo) return sendFail(res, '所属渠道不能为空', 400) if (!body.loanProductCode) return sendFail(res, '贷款产品编号不能为空', 400) if (!body.enterpriseName) return sendFail(res, '企业客户不能为空', 400) if (!body.goodsCategory) return sendFail(res, '商品类目不能为空', 400) diff --git a/src/api/customer.js b/src/api/customer.js index 05ef4bb..a52c4cc 100644 --- a/src/api/customer.js +++ b/src/api/customer.js @@ -18,6 +18,8 @@ export const uploadCustomerFileApi = (data, channelNo) => // 入参 {fileData(人脸照片base64,字段名含"zip"但实际直传图片base64即可)/idNo/name/channelNo}; // 响应 {fileNo(识别通过后可直接用于个人开户提交的人脸照片文件编号)/recode/recodeInfo(识别结果码/说明, // 具体取值枚举后端未文档化,前端仅按"fileNo 是否返回"判断识别是否成功,recodeInfo 仅作提示展示)} +// 产品要求暂时不调用此接口(个人开户/个人贷款申请/企业贷款申请的"正面免冠照"上传项改为直接调用 +// 上面的 uploadCustomerFileApi 只拿 fileNo),此导出暂无调用方,保留以便后续恢复识别校验。 export const faceRecognizeApi = (data, channelNo) => request.post('/api/customer-info/personal/face-recognize', data, { channelNo }) diff --git a/src/components/FacePhotoUpload.vue b/src/components/FacePhotoUpload.vue index dbcb75c..b188ebc 100644 --- a/src/components/FacePhotoUpload.vue +++ b/src/components/FacePhotoUpload.vue @@ -1,10 +1,12 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 长期 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + 长期 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {{ opt.label }} + + + + + + + + {{ opt.label }} + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - {{ opt.label }} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - {{ opt.label }} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -635,7 +479,7 @@
营业执照:
- +
@@ -643,15 +487,15 @@
- +
身份证人像面
- +
身份证国徽面
下载模板 (form.businessLicenseExpiry ? dayjs(form.businessLicenseExpiry) : undefined), set: (val) => (form.businessLicenseExpiry = val ? val.format('YYYY-MM-DD') : '') }) +const businessLicenseEffectiveDateModel = computed({ + get: () => (form.businessLicenseEffectiveDate ? dayjs(form.businessLicenseEffectiveDate) : undefined), + set: (val) => (form.businessLicenseEffectiveDate = val ? val.format('YYYY-MM-DD') : '') +}) +const enterpriseEstablishDateModel = computed({ + get: () => (form.enterpriseEstablishDate ? dayjs(form.enterpriseEstablishDate) : undefined), + set: (val) => (form.enterpriseEstablishDate = val ? val.format('YYYY-MM-DD') : '') +}) +const enterpriseOfficeAddressUpdateDateModel = computed({ + get: () => (form.enterpriseOfficeAddressUpdateDate ? dayjs(form.enterpriseOfficeAddressUpdateDate) : undefined), + set: (val) => (form.enterpriseOfficeAddressUpdateDate = val ? val.format('YYYY-MM-DD') : '') +}) +const firstAccountOpenDateModel = computed({ + get: () => (form.firstAccountOpenDate ? dayjs(form.firstAccountOpenDate) : undefined), + set: (val) => (form.firstAccountOpenDate = val ? val.format('YYYY-MM-DD') : '') +}) +const enterpriseFirstLoanDateModel = computed({ + get: () => (form.enterpriseFirstLoanDate ? dayjs(form.enterpriseFirstLoanDate) : undefined), + set: (val) => (form.enterpriseFirstLoanDate = val ? val.format('YYYY-MM-DD') : '') +}) +const creditRelationshipDateModel = computed({ + get: () => (form.creditRelationshipDate ? dayjs(form.creditRelationshipDate) : undefined), + set: (val) => (form.creditRelationshipDate = val ? val.format('YYYY-MM-DD') : '') +}) +const legalPersonEmploymentDateModel = computed({ + get: () => (form.legalPersonEmploymentDate ? dayjs(form.legalPersonEmploymentDate) : undefined), + set: (val) => (form.legalPersonEmploymentDate = val ? val.format('YYYY-MM-DD') : '') +}) +const legalPersonFirstLoanDateModel = computed({ + get: () => (form.legalPersonFirstLoanDate ? dayjs(form.legalPersonFirstLoanDate) : undefined), + set: (val) => (form.legalPersonFirstLoanDate = val ? val.format('YYYY-MM-DD') : '') +}) function handleLegalPersonCertExpiryLongTermChange(e) { if (e.target.checked) { @@ -1071,7 +943,6 @@ async function autoFillFromEnterpriseCustomer(customerId) { if (res.data.code !== 200) return const detail = res.data.data || {} form.businessLicenseNo = detail.businessLicense || form.businessLicenseNo - form.enterpriseCode = detail.enterpriseCode || form.enterpriseCode form.businessScope = detail.businessScope || form.businessScope form.businessLicenseRegisteredAddress = detail.certificateAddress || form.businessLicenseRegisteredAddress form.businessLicenseExpiry = detail.certificateExpiryDate ? detail.certificateExpiryDate.slice(0, 10) : form.businessLicenseExpiry @@ -1119,9 +990,18 @@ async function loadDetail() { if (res.data.code !== 200) return const data = res.data.data Object.assign(form, data, { + channelNo: data.channel, legalPersonBirthday: data.legalPersonBirthday ? data.legalPersonBirthday.slice(0, 10) : '', legalPersonCertExpiry: data.legalPersonCertExpiry ? data.legalPersonCertExpiry.slice(0, 10) : '', - businessLicenseExpiry: data.businessLicenseExpiry ? data.businessLicenseExpiry.slice(0, 10) : '' + legalPersonEmploymentDate: data.legalPersonEmploymentDate ? data.legalPersonEmploymentDate.slice(0, 10) : '', + legalPersonFirstLoanDate: data.legalPersonFirstLoanDate ? data.legalPersonFirstLoanDate.slice(0, 10) : '', + businessLicenseExpiry: data.businessLicenseExpiry ? data.businessLicenseExpiry.slice(0, 10) : '', + businessLicenseEffectiveDate: data.businessLicenseEffectiveDate ? data.businessLicenseEffectiveDate.slice(0, 10) : '', + enterpriseEstablishDate: data.enterpriseEstablishDate ? data.enterpriseEstablishDate.slice(0, 10) : '', + enterpriseOfficeAddressUpdateDate: data.enterpriseOfficeAddressUpdateDate ? data.enterpriseOfficeAddressUpdateDate.slice(0, 10) : '', + firstAccountOpenDate: data.firstAccountOpenDate ? data.firstAccountOpenDate.slice(0, 10) : '', + enterpriseFirstLoanDate: data.enterpriseFirstLoanDate ? data.enterpriseFirstLoanDate.slice(0, 10) : '', + creditRelationshipDate: data.creditRelationshipDate ? data.creditRelationshipDate.slice(0, 10) : '' }) legalPersonCertExpiryLongTerm.value = form.legalPersonCertExpiry === CERTIFICATE_LONG_TERM_DATE_ONLY businessLicenseExpiryLongTerm.value = form.businessLicenseExpiry === CERTIFICATE_LONG_TERM_DATE_ONLY @@ -1151,7 +1031,7 @@ function buildImageList() { // 提交前校验通过后弹出二次确认弹窗(保存/取消/扫码确认),与 PersonalLoanForm.vue 同一模式, // 原 handleSubmit 的前置校验逻辑保留在此,真正提交动作下沉到 submitApplication()。 function handleConfirmButtonClick() { - if (!form.channel) { + if (!form.channelNo) { showErrorModal('请先选择所属渠道') return } @@ -1192,19 +1072,16 @@ async function submitApplication() { submitting.value = true try { const payload = { - organizationId: form.organizationId, - channel: form.channel, + channelNo: form.channelNo, loanProductCode: form.loanProductCode, customerType: form.customerType, customerId: form.customerId, customerName: form.enterpriseName, enterpriseName: form.enterpriseName, accountNo: form.accountNo, - phoneNo: form.phoneNo, loanAmount: form.loanAmount, applicationInterestRate: form.applicationInterestRate, loanPurpose: form.loanPurpose, - creditCategory: form.creditCategory, legalPersonCertType: form.legalPersonCertType, legalPersonCertId: form.legalPersonCertId, @@ -1219,31 +1096,33 @@ async function submitApplication() { legalPersonAnnualIncome: form.legalPersonAnnualIncome, legalPersonMobile: form.legalPersonMobile, legalPersonEmail: form.legalPersonEmail, - emergencyContactName: form.emergencyContactName, - emergencyContactPhone: form.emergencyContactPhone, + legalPersonResidenceCity: form.legalPersonResidenceCity, legalPersonMailAddress: form.legalPersonMailAddress, isLocalPropertyOwner: form.isLocalPropertyOwner, isChildLocalSchool: form.isChildLocalSchool, - legalPersonAccountType: form.legalPersonAccountType, + legalPersonCustomerType: form.legalPersonCustomerType, legalPersonLocalHousehold: form.legalPersonLocalHousehold, - legalPersonHasSocialInsurance: form.legalPersonHasSocialInsurance, + legalPersonMarketOperator: form.legalPersonMarketOperator, legalPersonBusinessCompanyName: form.legalPersonBusinessCompanyName, - legalPersonBusinessNature: form.legalPersonBusinessNature, + legalPersonBusinessLicenseNo: form.legalPersonBusinessLicenseNo, legalPersonBusinessAddress: form.legalPersonBusinessAddress, - legalPersonBusinessZipCode: form.legalPersonBusinessZipCode, - legalPersonResidenceZipCode: form.legalPersonResidenceZipCode, - legalPersonCreditBusiness: form.legalPersonCreditBusiness, + legalPersonBusinessType: form.legalPersonBusinessType, + legalPersonBusinessPhone: form.legalPersonBusinessPhone, + legalPersonResidenceStatus: form.legalPersonResidenceStatus, legalPersonMailZipCode: form.legalPersonMailZipCode, - legalPersonBasicAccountOpened: form.legalPersonBasicAccountOpened, + legalPersonFamilyMonthlyIncome: form.legalPersonFamilyMonthlyIncome, + legalPersonEmploymentDate: toFullDate(form.legalPersonEmploymentDate), legalPersonBankType: form.legalPersonBankType, - legalPersonBasicAccountName: form.legalPersonBasicAccountName, legalPersonBasicAccountNo: form.legalPersonBasicAccountNo, - legalPersonStockCode: form.legalPersonStockCode, + legalPersonFirstLoanDate: toFullDate(form.legalPersonFirstLoanDate), legalPersonRemark: form.legalPersonRemark, businessScope: form.businessScope, enterpriseOrgType: form.enterpriseOrgType, + enterpriseEconomyType: form.enterpriseEconomyType, businessLicenseExpiry: toFullDate(form.businessLicenseExpiry), + businessLicenseEffectiveDate: toFullDate(form.businessLicenseEffectiveDate), + enterpriseEstablishDate: toFullDate(form.enterpriseEstablishDate), annualEmployeeCount: form.annualEmployeeCount, annualRevenue: form.annualRevenue, annualTotalAssets: form.annualTotalAssets, @@ -1253,48 +1132,48 @@ async function submitApplication() { isListedCompany: form.isListedCompany, isPrivateControlled: form.isPrivateControlled, businessLicenseNo: form.businessLicenseNo, - enterpriseEconomicOwnership: form.enterpriseEconomicOwnership, businessLicenseRegisteredAddress: form.businessLicenseRegisteredAddress, - enterpriseEconomicZone: form.enterpriseEconomicZone, - enterpriseMailAddress: form.enterpriseMailAddress, - enterpriseCode: form.enterpriseCode, - withdrawalTypeFlag: form.withdrawalTypeFlag, - isLocalStockParticipated: form.isLocalStockParticipated, + enterpriseRegisteredRegion: form.enterpriseRegisteredRegion, + enterpriseCreditReferenceCode: form.enterpriseCreditReferenceCode, + loanCardPassword: form.loanCardPassword, + isLoanNumberValid: form.isLoanNumberValid, paidInCapital: form.paidInCapital, - enterpriseLocationAddress: form.enterpriseLocationAddress, - enterpriseLocationZipCode: form.enterpriseLocationZipCode, + paidInCapitalCurrency: form.paidInCapitalCurrency, + enterpriseContactPhone: form.enterpriseContactPhone, + enterpriseFinanceContactPhone: form.enterpriseFinanceContactPhone, enterpriseBasicAccountLocalBank: form.enterpriseBasicAccountLocalBank, enterpriseBasicAccountBank: form.enterpriseBasicAccountBank, enterpriseBasicAccountNo: form.enterpriseBasicAccountNo, - enterprisePrimaryShareholder: form.enterprisePrimaryShareholder, enterpriseOfficeAddress: form.enterpriseOfficeAddress, - enterpriseOfficeZipCode: form.enterpriseOfficeZipCode, - hasStorefront: form.hasStorefront, - enterprisePerformance: form.enterprisePerformance, - listedStockCode: form.listedStockCode, - enterpriseRemitAccountName: form.enterpriseRemitAccountName, - enterpriseRemitAccountNo: form.enterpriseRemitAccountNo, - enterpriseRemitBankBranch: form.enterpriseRemitBankBranch, - enterpriseLoanPaymentAccountName: form.enterpriseLoanPaymentAccountName, - enterpriseOtherBankCreditRelation: form.enterpriseOtherBankCreditRelation, - financialStatementNo: form.financialStatementNo, - enterpriseMarketingRegion: form.enterpriseMarketingRegion, - hasExternalGuarantee: form.hasExternalGuarantee, - isSmeEnterprise: form.isSmeEnterprise, - isLocalEcological: form.isLocalEcological, - isEquitySystem: form.isEquitySystem, - highTechIndustryFlag: form.highTechIndustryFlag, - companyCodeAndAffiliates: form.companyCodeAndAffiliates, + enterpriseOfficeRegion: form.enterpriseOfficeRegion, + enterpriseOfficeAddressUpdateDate: toFullDate(form.enterpriseOfficeAddressUpdateDate), + isMarketOperator: form.isMarketOperator, + enterpriseAffiliation: form.enterpriseAffiliation, + listedStatus: form.listedStatus, + enterpriseZipCode: form.enterpriseZipCode, + enterpriseOtherBankName: form.enterpriseOtherBankName, + enterpriseOtherBankAccountNo: form.enterpriseOtherBankAccountNo, + firstAccountOpenDate: toFullDate(form.firstAccountOpenDate), + enterpriseFirstLoanDate: toFullDate(form.enterpriseFirstLoanDate), + creditRelationshipDate: toFullDate(form.creditRelationshipDate), + financialStatementType: form.financialStatementType, + taxRefundRegistrationCert: form.taxRefundRegistrationCert, + hasImportExportRight: form.hasImportExportRight, + isKeySmeEnterprise: form.isKeySmeEnterprise, + isGroupCustomer: form.isGroupCustomer, + isGovernmentPlatform: form.isGovernmentPlatform, + governmentPlatformCategory: form.governmentPlatformCategory, + enterpriseRiskType: form.enterpriseRiskType, enterpriseEmail: form.enterpriseEmail, enterpriseWebsite: form.enterpriseWebsite, - enterpriseBusinessWebsite: form.enterpriseBusinessWebsite, - enterpriseAccountOpeningMethod: form.enterpriseAccountOpeningMethod, + enterpriseFaxPhone: form.enterpriseFaxPhone, + enterpriseHistoryManagementIntro: form.enterpriseHistoryManagementIntro, enterpriseMainProductsServices: form.enterpriseMainProductsServices, - enterpriseBusinessAddressScope: form.enterpriseBusinessAddressScope, - enterpriseEquityOtherType: form.enterpriseEquityOtherType, + businessPremisesArea: form.businessPremisesArea, + businessPremisesOwnership: form.businessPremisesOwnership, parentCompanyName: form.parentCompanyName, - parentCompanyAddress: form.parentCompanyAddress, - parentCompanyShareRatio: form.parentCompanyShareRatio, + parentCompanyOrgCode: form.parentCompanyOrgCode, + parentCompanyLoanCardNo: form.parentCompanyLoanCardNo, enterpriseRemark: form.enterpriseRemark, loanApplicationImageBtoList: buildImageList() @@ -1359,6 +1238,9 @@ function goBack() {