SFT/项目要点总结.md

50 KiB

凡荣e链管理后台前端 —— 项目要点总结

本文档基于代码现状(部分文件存在尚未提交的工作区改动)与 缺失的后端接口.md(接口契约权威来源)整理,用于帮助后续开发/维护人员快速理解项目整体架构、路由组织方式、各页面业务逻辑与后端接口对接情况。不以 mock-server/ 作为接口设计依据,该目录仅为真实后端不可用时的本地应急演示后端。


目录

  1. 项目概述
  2. 技术栈与项目结构
  3. 整体架构
  4. 公共组件与工具函数
  5. 登录页与错误页
  6. 系统管理模块
  7. 基础配置模块
  8. 客户管理模块
  9. 钱包管理模块
  10. 授信管理模块
  11. 商户中心模块
  12. 支付管理模块
  13. 订单管理模块
  14. 已知问题与待确认事项汇总
  15. 本地 Mock Server 说明
  16. 维护建议

1. 项目概述

凡荣e链管理后台前端是一套面向供应链金融/产业互联网场景的管理后台 SPA,覆盖系统管理、授信管理、支付管理、订单管理、客户管理、钱包管理、商户中心、基础配置等核心业务域。项目没有 Node 服务端,mock-server/ 仅用于本地演示,构建产物为纯静态前端资源,真实业务数据依赖已接入的独立后端服务。

项目范围以 docs/superpowers/specs/2026-07-08-fryl-frontend-overall-design.md 为权威依据,明确包含 9 个一级模块(系统管理、授信管理、支付管理、订单管理、客户管理、钱包管理、商户中心、基础配置、登录),并明确排除原型库中的非银专区、分账专区、税筹专区、农都专区、驾驶舱、首页仪表盘等模块,以及各模块下需求说明书未提及的原型子页面。website_detail/ 目录是从已上线的稠州银行商业平台完整抓取的原型参考(84 个页面),覆盖面远大于本项目实际范围,不能当作"待实现清单",仅用于查阅交互细节。

2. 技术栈与项目结构

2.1 技术栈

分类 选型
框架 Vue 3(<script setup> 组合式 API)+ Vite
语言 纯 JavaScript,无 TypeScript
UI 组件库 Ant Design Vue
状态管理 Pinia
路由 Vue Router 4(动态路由,见下文)
HTTP Axios(单例封装,withCredentials: true)
日期处理 dayjs
表格导出 xlsx
省市区数据 china-division
本地演示后端 express / cors / cookie-parser(仅 mock-server/,devDependencies)

无 lint / prettier / 单元测试脚本配置,不要假设它们存在。

2.2 常用命令

npm run dev       # 启动开发服务器,端口 5173
npm run build     # 构建
npm run preview   # 预览构建产物
npm run mock      # 启动本地 mock 后端(express),默认端口 8888,可用 MOCK_PORT 覆盖

2.3 目录速览

src/
├── api/                各模块 axios 请求封装(request.js 为唯一 axios 实例)
├── components/         通用业务组件(ProTable、上传组件、选择器等)
├── constants/           各模块枚举字典(*Enums.js),来源必须是 swagger/缺失的后端接口.md
├── directives/          自定义指令(v-permission)
├── layouts/             MainLayout(主布局)/ BlankLayout(登录页布局)
├── router/              index.js(静态路由+守卫)/ dynamic.js(动态路由生成)/ componentRegistry.js(组件映射表)
├── stores/               Pinia:auth.js(鉴权与权限)/ tabs.js(多标签页)
├── utils/                traceHeaders/orgScope/loopDelete/permissionTreeBuilder/formFocus/errorModal/mask/download/validators/lastActive/ocrMapping/batchDeleteResult
└── views/                页面,按模块/子模块分文件夹:
    base-config/ credit/ customer/ error/ login/ merchant/ order/ payment/ system/ wallet/

关键文档索引:

  • AGENTS.md:项目开发规范与范围说明入口(本仓库的权威开发约定)。
  • 缺失的后端接口.md(936 行):接口契约权威来源。Part 1(1~234 行)是"已对接契约速查表",按模块列出接口的方法/路径/请求/响应;Part 2~11(235~936 行)是后续补充与变更记录(如机构数据隔离、字段调整、字段核对等),优先级高于 Part 1,如有冲突以 Part 2 及以后的记录为准。
  • swagger_project_scfs_2026-07-09_14-15-23.json:后端真实接口定义源文件。
  • docs/superpowers/specs/2026-07-08-fryl-frontend-overall-design.md:总体架构与范围划分设计文档。
  • docs/superpowers/specs/2026-07-08-module-requirements-mapping.md:需求条款与原型页面映射。
  • docs/superpowers/specs/2026-07-16-org-data-isolation-design.md:机构数据隔离设计说明。
  • mock-server/README.md:本地演示后端说明,列出了"已知简化点/未文档化项",这些恰恰是真实后端接口设计不完整、需要额外注意的地方。
  • website_detail/:70+ 页面的原型截图(png)+ HTML + summary.md,仅用于查阅本项目范围内页面的交互细节参考,不代表待实现范围。

2.4 已实现的一级视图目录

src/views 下已存在 10 个一级目录:base-configcreditcustomererrorloginmerchantorderpaymentsystemwallet

3. 整体架构

3.1 全局布局

  • BlankLayout.vue:无侧边栏/导航栏的空白布局,仅用于登录页,符合"登录页必须不含任何导航元素"的规范。
  • MainLayout.vue:深色水平主菜单 + 可关闭的多标签页(状态由 src/stores/tabs.js 管理)+ 右上角用户下拉(含退出登录)。所有业务页面均挂载在此布局下。

3.2 路由机制(动态路由,新增页面必须两处登记)

路由不是静态声明的,而是登录后根据后端返回的菜单权限树动态生成:

  1. src/router/index.js:仅静态声明 /login/403、404 通配符路由,并挂载全局前置守卫 router.beforeEach:
    • accessToken(除白名单路由) → 跳转 /login;
    • 有 token 但路由尚未就绪(routesReady 为 false)→ 先调用 fetchCurrentUserrebuildPermissions 拉取权限树,再调用 installDynamicRoutes 挂载动态路由,然后重新 next(to.fullPath) 完成一次"replay"跳转;
    • 登录成功后默认落地页为菜单权限列表中第一个可访问页面(或用户登录前尝试访问的原始目标页面)。
  2. src/router/dynamic.js(installDynamicRoutes):遍历后端菜单树,为每个菜单节点生成一条挂载在 MainLayout 下的子路由记录,组件通过 import.meta.glob('@/views/**/*.vue') 懒加载。
  3. src/router/componentRegistry.js:手工维护的路径 → 组件映射表,是新增页面最容易漏掉的一步:
    • routePathComponentMap:后端菜单 path → 组件相对路径的映射,用于侧边栏可见的列表页。
    • extraChildRoutes:新增/编辑/详情等不出现在侧边栏菜单里的表单页路由(通常以 create/edit/detail 作为路径后缀,组件内部据此推导表单模式:新建/编辑/只读查看)。

已注册的 routePathComponentMap 完整映射:

菜单 path 组件
/system/user system/user/UserList.vue
/system/role system/role/RoleList.vue
/system/org system/org/OrgList.vue
/system/permission system/permission/PermissionList.vue
/base-config/channel base-config/channel/ChannelList.vue
/base-config/manager base-config/manager/ManagerList.vue
/customer/personal customer/personal/PersonalList.vue
/customer/enterprise customer/enterprise/EnterpriseList.vue
/wallet/account wallet/account/AccountList.vue
/wallet/personal-open wallet/personal-open/PersonalOpenList.vue
/wallet/enterprise-open wallet/enterprise-open/EnterpriseOpenList.vue
/credit/loan-application credit/loan-application/LoanApplicationList.vue
/merchant/management merchant/management/MerchantList.vue
/merchant/invoice merchant/invoice/InvoiceList.vue
/payment/order-payment payment/order-payment/PaymentRecordList.vue
/order/summary order/summary/SummaryOrderList.vue
/order/original order/original/OriginalOrderList.vue

说明:/system/permission(权限字典管理)虽然在 2026-07-08 总体设计文档明确的"实施范围"清单中未被单列,但代码中已实际注册路由并有完整组件实现,属于代码现状与早期设计文档之间的差异,维护时应以代码现状为准,如需收窄范围需与产品确认。

extraChildRoutes 中登记了各业务模块的新增/编辑/详情隐藏路由(如 customer/personal/createwallet/enterprise-open/edit 等),具体见各模块章节。

3.3 鉴权与权限流程

核心文件:src/stores/auth.js + src/api/request.js + src/utils/permissionTreeBuilder.js

  • accessToken 持久化存储在 localStorage;userInfo/menuTree/buttonCodes 仅保存在内存态(Pinia store,不持久化,符合"用户信息不得持久化存储"的规范)。
  • 判定登录态的唯一依据:本地是否存在 accessToken,不做后端二次校验(直到某次请求触发 401)。
  • 登录后 / 刷新页面后调用 rebuildPermissions(内部请求 /api/auth/user/permission-detail 获取扁平权限列表),经 permissionTreeBuilder.js 构建菜单树并提取按钮权限码集合。
  • 请求拦截器(src/api/request.js):
    • 自动注入 Authorization: Bearer {accessToken};
    • 自动注入 buildTraceHeaders() 生成的追踪头(见下文 3.4);
    • 统一按响应体 code !== 200 判定业务失败,提示 message
  • 401 静默刷新:响应拦截器检测到 401 时,通过 httpOnly Cookie 中的 refresh_token 调用 /api/auth/refresh-token(该请求本身不带 Authorization 头),并用请求队列防止刷新期间的并发请求重复触发刷新;刷新失败则清空登录态并跳转 /login
  • 403:展示"无权限访问该资源"的明确提示(全局统一处理,不需要业务页面单独处理)。
  • 按钮级权限:v-permission 自定义指令(src/directives/permission.js),未授权按钮会被直接从 DOM 移除(而非仅置灰/隐藏)。
  • 机构数据隔离:src/utils/orgScope.jsgetCurrentOrganizationId() 用于查询/新增表单默认填充当前用户所属机构,机构可选范围的裁剪职责在后端,前端不做二次过滤(部分模块后端尚未按此实现,见第 14 章已知问题)。

3.4 请求追踪头(Trace Headers)

每次请求必须附带以下 5 个 header(字段名大小写固定,首字母大写、其余小写):

Header 说明
Appno 随机值
Channelno 渠道 ID,来自页面上用户选择的渠道(非固定值,不能硬编码);页面无渠道上下文时不传
Serialno 流水号,随机值
Transdate yyyy-MM-dd 格式日期
Transtradetime yyyy-MM-dd HH:mm:ss 格式时间

实现位于 src/utils/traceHeaders.jsbuildTraceHeaders()

3.5 通用接口约定(来自《缺失的后端接口.md》)

  • 响应体统一 { code, message, data },业务成功判定为 code === 200;非 200 时使用 message 提示,不做具体错误码分支(除 401/403 的全局统一处理外)。
  • 除登录 / 刷新令牌 / 发短信外,所有请求必须带 Authorization: Bearer {token}
  • 日期时间字段统一格式 yyyy-MM-dd HH:mm:ss
  • 分页接口:请求 Body 含 page(从 1 开始)/ pageSize;响应 data 统一为 { total, page, pageSize, records } —— 字段是 records,不是 list
  • 绝大多数模块没有批量删除接口,批量操作使用 src/utils/loopDelete.js 循环调用单条删除接口并汇总结果,再配合 src/utils/batchDeleteResult.js 展示成功/失败明细。
  • 文件(身份证、营业执照等)以 Base64 字符串放在 JSON body 中传输,不使用 multipart/form-data
  • 枚举值必须来自 swagger / 《缺失的后端接口.md》,已整理在 src/constants/*Enums.js,不得臆造。

3.6 BASE_URL 可配置入口

登录页右上角齿轮图标可打开"接口地址设置"弹窗,运行时切换后端地址,存储于 localStorage.base_url_override;实现见 src/api/request.jsgetBaseUrl() / setBaseUrlOverride().env.development 默认 VITE_API_BASE_URL=http://localhost:8888(即本地 mock server),.env.production 为空(走相对路径/运行时配置)。本地联调真实后端遇到 CORS 时,通过 .env.development.local(已 gitignore)配置 DEV_API_PROXY_TARGET,走 vite.config.js 中的同源代理方案,不应为此改动生产构建逻辑。

4. 公共组件与工具函数

4.1 ProTable.vue

通用"查询表单 + 操作栏 + 分页表格"封装,绝大多数列表页优先复用它而不是重写查询/分页逻辑,支持 checkbox/radio 行选择模式(配合批量操作/单选联动场景)。

4.2 图片/证件上传组件规范

所有"图片上传卡片"(身份证、营业执照、人脸照片等 list-type="picture-card"a-upload 封装组件),一旦已选中图片,必须支持鼠标 hover 缩略图时显示半透明遮罩 + 预览/重新上传/删除三个操作按钮,不允许只放一张裸 <img>。标准实现参照 src/components/IdCardUpload.vue(LicenseUpload.vue 已按此模式改造):

  • 缩略图外层 .thumb-wrapper(position: relative)包裹 <img> + .hover-mask(position:absolute; inset:0,rgba(0,0,0,0.5) 背景,默认 opacity:0,hover 时 opacity:1,transition:opacity 0.2s)。
  • 遮罩内横向排列三个图标:EyeOutlined(预览)/ EditOutlined(重新上传)/ DeleteOutlined(删除),之间用 1px 竖线 .mask-divider 分隔,图标颜色 #fff,hover 变 #1677ff
  • 预览:图标加 @click.stop,打开 a-modal(:footer="null")放大展示图片。
  • 删除:图标加 @click.stop,清空本地预览态并 emit('update:fileNo', '')
  • 重新上传:图标不加 @click.stop,让点击事件冒泡到外层 a-upload 容器,复用其原生文件选择流程。
  • 支持 readonly prop(默认 false),为 true 时只保留预览图标,隐藏重新上传/删除,用于只读详情表单;调用处需将页面自身的 isDetail 等只读态标记正确传给该 prop。
  • 当前项目没有抽出通用的图片上传基础组件,IdCardUpload.vue / LicenseUpload.vue / FacePhotoUpload.vue 各自独立实现(结构相似但不复用)。FacePhotoUpload.vue 尚未按此规范改造,涉及时需一并补上。

4.3 耗时操作统一等待态规范

图片/文件上传、"提交"/"创建"/"保存"等触发接口调用的按钮及其他明显耗时的异步操作,必须统一展示等待态,期间禁止用户对页面做其他操作。标准参照 src/views/customer/enterprise/EnterpriseForm.vue(及 PersonalForm.vue):

  • 页面级遮罩:最外层用 <a-spin :spinning="busy" :tip="busyTip"> 包裹表单内容。
  • busy 用一个 computed 统一收敛所有"进行中"状态(如 submitting.value || xxxUploading.value)。
  • busyTip 按当前处于哪个耗时状态给出对应提示文案,无耗时状态时留空。
  • 触发按钮加 :loading="submitting" 双重防止重复点击。
  • 图片上传组件通过 update:uploading 事件把自身上传中状态回传给父表单,父表单纳入 busy 统一遮罩,并在提交前校验各 xxxUploading 状态,阻止文件未上传完成时提交表单。

4.4 其他通用业务组件

组件 说明
OrgTreeSelect.vue 机构树选择器
PermissionTree.vue 权限树勾选组件,用于角色分配权限
ChannelSelect.vue 渠道(核心企业)下拉选择,内部调用 fetchCoreEnterprisePageApi 拉取选项,下拉展示"渠道编号 - 渠道名称";兼容新旧字段名(channelName/channelNo 与历史字段 enterpriseName/enterpriseCode)
RegionCascader.vue 省市区级联选择(基于 china-division 数据)
StatusTag.vue 状态徽标展示,内置默认映射(ACTIVE→绿色"正常"、LOCKED→红色"已锁定"、INACTIVE→灰色"停用"),支持 map prop 覆盖/扩展
SmsCodeInput.vue 短信验证码输入框(含倒计时发送按钮)
IdCardUpload.vue / LicenseUpload.vue / FacePhotoUpload.vue 身份证/营业执照/人脸照片上传,见 4.2
WalletAccountPicker.vue / WalletCustomerPicker.vue / PersonalCustomerPicker.vue / EnterpriseCustomerPicker.vue 钱包账户/客户选择器(弹窗选人场景)
EnterpriseRelatedPersonCard.vue / EnterpriseInvestmentCard.vue 企业客户股东高管/对外投资信息卡片
WithdrawModal.vue / MarginModal.vue / BindCardModal.vue 钱包提现/保证金/绑卡弹窗

4.5 工具函数

文件 作用
src/utils/loopDelete.js 无批量删除接口时,循环调用单条删除接口并汇总结果
src/utils/batchDeleteResult.js 展示批量操作的成功/失败明细
src/utils/formFocus.js focusFirstInvalidField():表单校验失败后定位并聚焦第一个带 .ant-form-item-has-error 的字段,滚动到视口居中;已知局限:字段位于折叠面板隐藏区域(display:none)时聚焦不生效,当前项目所有必填字段均在展开区域,暂不处理该场景
src/utils/errorModal.js showErrorModal(content, title):统一错误提醒弹窗,内部维护队列,同一时刻只展示一个 Modal.error,多个错误依次排队,用户必须点击"我知道了"才能看到下一个/继续操作;用于替代原先分散的 message.error 调用
src/utils/mask.js 敏感信息脱敏展示(不影响提交给后端的真实值):maskIdCard() 保留前 6 位/后 4 位,中间替换为 4 个 *(长度 ≤10 原样返回);maskMobile() 保留前 3 位/后 4 位(长度 ≤7 原样返回)
src/utils/download.js downloadBase64File(base64, filename, mimeType):将后端返回的 base64 文件内容(如回单/对账单 PDF)解码为 Blob 并触发浏览器下载,不依赖第三方库
src/utils/validators.js 常用校验规则:手机号(/^1\d{10}$/)、密码强度(8 位以上且含大小写字母+数字)、身份证号(18 位,末位允许 X/x,不做校验码算术级校验)、统一社会信用代码/营业执照号(15-20 位数字+大写字母)
src/utils/lastActive.js startIdleWatcher(onTimeout, timeoutMs):监听 mousemove/mousedown/keydown/scroll/click 事件,空闲超时(默认 5 分钟)触发回调,在 App.vue 中启用实现自动登出
src/utils/orgScope.js getCurrentOrganizationId():获取当前用户所属机构 ID,用于表单默认值;机构范围裁剪职责在后端
src/utils/permissionTreeBuilder.js 将后端返回的扁平权限列表构建为菜单树,并提取按钮权限码集合
src/utils/traceHeaders.js buildTraceHeaders():生成请求追踪头,见 3.4
src/utils/ocrMapping.js OCR 识别结果字段到表单字段的映射

5. 登录页与错误页

5.1 登录页(/login,src/views/login/Login.vue)

  • 使用 BlankLayout,页面不含任何侧边栏/导航栏,只有登录表单。
  • 支持两种登录方式(Tab 切换):账号密码登录、手机验证码登录。
  • 右上角齿轮图标可打开"接口地址设置"弹窗,配置 BASE_URL(见 3.6)。
  • 登录成功后:accessToken 写入 localStorage,拉取当前用户信息与权限树后跳转到用户原本想访问的页面,或菜单权限列表中第一个可访问页面。
  • 严禁 mock/硬编码当前用户信息或 AuthToken/登录验证令牌,均为真实接口交互结果。

5.2 错误页

路由 组件 说明
/403 src/views/error/Forbidden.vue 极简 a-result 403 页面
*(通配) src/views/error/NotFound.vue 极简 a-result 404 页面

6. 系统管理模块

侧边栏一级菜单"系统管理"下含用户管理、角色管理、机构管理、权限管理 4 个子页面,均只有列表页(部分含新增/编辑弹窗或子路由),无独立详情页。

6.1 用户管理(/system/user)

  • 组件:src/views/system/user/UserList.vue

  • 功能:用户账号的分页查询、新增、编辑、启用/停用、密码重置、角色分配、机构归属维护。

  • 业务逻辑要点:

    • 列表支持按用户名/手机号/所属机构/状态筛选,分页查询。
    • 新增/编辑通过弹窗(a-modal)完成,不跳独立路由。
    • 密码修改限制:后端不存在"管理员直接修改用户密码"的接口,因此列表操作栏的"密码修改"按钮永久置灰,只能通过"密码重置并发送短信"按钮触发重置流程(生成新密码后以短信方式通知用户)。
    • 状态切换(启用/锁定)通过状态更新接口完成,不是删除。
    • 用户与角色为多对多关系,分配角色通过独立弹窗多选完成。
  • 调用接口(以《缺失的后端接口.md》Part 1.2 用户管理章节为准):

接口说明 Method + Path 关键请求参数 关键响应字段
用户分页查询 POST /api/system/user/page page,pageSize,username,mobile,organizationId,status data.records[]:id,username,realName,mobile,organizationName,roleNames,status,createTime
新增用户 POST /api/system/user/create username,realName,mobile,organizationId,roleIds[] data:新建用户 id
编辑用户 POST /api/system/user/update id + 同新增字段 code=200
启用/停用用户 POST /api/system/user/update-status id,status code=200
密码重置并发送短信 POST /api/system/user/reset-password id code=200
分配角色 POST /api/system/user/assign-role id,roleIds[] code=200

6.2 角色管理(/system/role)

  • 组件:src/views/system/role/RoleList.vue
  • 功能:角色的分页查询、新增、编辑、删除、权限分配(勾选 PermissionTree 组件)。
  • 业务逻辑要点:角色与权限为多对多,权限分配通过独立弹窗内嵌 PermissionTree 树形勾选组件完成;无批量删除接口,如需批量操作走 loopDelete.js
接口说明 Method + Path 关键请求参数 关键响应字段
角色分页查询 POST /api/system/role/page page,pageSize,roleName data.records[]:id,roleName,roleCode,remark,createTime
新增角色 POST /api/system/role/create roleName,roleCode,remark,permissionIds[] data:新建角色 id
编辑角色 POST /api/system/role/update id + 同新增字段 code=200
删除角色 POST /api/system/role/delete id code=200
分配权限 POST /api/system/role/assign-permission id,permissionIds[] code=200

6.3 机构管理(/system/org)

  • 组件:src/views/system/org/OrgList.vue
  • 功能:机构树形结构的查询、新增下级机构、编辑、删除(叶子节点)。
  • 业务逻辑要点:机构以树形结构展示(OrgTreeSelect 同源数据),新增机构需选择上级机构节点;机构数据隔离(不同角色可见的机构范围裁剪)由后端负责,前端不做二次过滤。
接口说明 Method + Path 关键请求参数 关键响应字段
机构树查询 GET /api/system/org/tree data[]:id,orgName,parentId,children[]
新增机构 POST /api/system/org/create orgName,parentId data:新建机构 id
编辑机构 POST /api/system/org/update id,orgName code=200
删除机构 POST /api/system/org/delete id code=200

6.4 权限管理(/system/permission)

  • 组件:src/views/system/permission/PermissionList.vue
  • 功能:权限字典(菜单权限/按钮权限)的树形维护。
  • 说明:该页面未在 2026-07-08 总体设计文档明确列出的实施范围清单中单独出现,但代码已实际实现并注册路由,属代码现状与设计文档的差异点,维护/评审时需注意。
接口说明 Method + Path 关键请求参数 关键响应字段
权限树查询 GET /api/system/permission/tree data[]:id,permissionName,permissionCode,type(菜单/按钮),parentId,path,children[]
新增权限 POST /api/system/permission/create permissionName,permissionCode,type,parentId,path data:新建权限 id
编辑权限 POST /api/system/permission/update id + 同新增字段 code=200
删除权限 POST /api/system/permission/delete id code=200

注:系统管理模块接口字段以子 agent 调研摘要整理,如需精确核对逐字段类型/是否必填,请以《缺失的后端接口.md》Part 1.2~1.5 原文及 src/api/system.js 实际调用代码为准。

7. 基础配置模块

7.1 核心企业(渠道)管理(/base-config/channel)

  • 组件:src/views/base-config/channel/ChannelList.vue
  • 功能:维护渠道(核心企业)基础信息,供其他模块(客户、钱包开户、支付等)下拉选择。
  • 业务逻辑要点:
    • 列表分页查询,支持按渠道名称/编号筛选。
    • 新增/编辑通过弹窗完成。
    • 无前端唯一性校验:渠道编号/名称是否重复完全依赖后端返回错误提示,前端未做提交前查重。
    • 字段兼容:ChannelSelect.vue 组件内部对 channelName/channelNo 与历史字段名 enterpriseName/enterpriseCode 做了兼容读取,提交时以 enterpriseName 字段名兜底(历史字段名残留,新代码统一使用 channelXxx 命名)。
    • 机构过滤:前端表单已预留机构关联字段传参,但后端尚未按机构范围过滤渠道列表(见第 14 章)。
接口说明 Method + Path 关键请求参数 关键响应字段
渠道分页查询 POST /api/base-config/channel/page(即 fetchCoreEnterprisePageApi) page,pageSize,channelName/enterpriseName data.records[]:channelNo/enterpriseCode,channelName/enterpriseName,status,createTime
新增渠道 POST /api/base-config/channel/create channelName,channelNo 等基础信息字段 data:新建记录标识
编辑渠道 POST /api/base-config/channel/update 同新增 + 主键 code=200
删除渠道 POST /api/base-config/channel/delete 主键 code=200

7.2 客户经理管理(/base-config/manager)

  • 组件:src/views/base-config/manager/ManagerList.vue
  • 功能:维护客户经理基础信息(姓名、工号、联系方式、所属机构),供客户/授信等模块关联展示。
  • 业务逻辑要点:分页查询 + 新增/编辑弹窗,常规 CRUD,无特殊校验规则。
接口说明 Method + Path 关键请求参数 关键响应字段
客户经理分页查询 POST /api/base-config/manager/page page,pageSize,managerName,mobile data.records[]:id,managerName,managerNo,mobile,organizationName
新增客户经理 POST /api/base-config/manager/create managerName,managerNo,mobile,organizationId data:新建记录 id
编辑客户经理 POST /api/base-config/manager/update 同新增 + id code=200
删除客户经理 POST /api/base-config/manager/delete id code=200

8. 客户管理模块

8.1 个人客户(/customer/personal)

  • 列表组件:src/views/customer/personal/PersonalList.vue
  • 表单组件:src/views/customer/personal/PersonalForm.vue(新增/编辑/查看共用,查看态字段只读)
  • 隐藏路由(extraChildRoutes):customer/personal/createcustomer/personal/editcustomer/personal/detail
  • 业务逻辑要点:
    • 列表支持按姓名/手机号/证件号/所属渠道筛选,分页查询;无删除入口
    • 表单字段含身份证正反面 OCR 识别上传(IdCardUpload.vue)、人脸照片上传(FacePhotoUpload.vue,尚未按 4.2 规范改造)、联系信息(地址/紧急联系人等,来自 Part 7 补充说明)。
    • 身份证号/手机号仅做前端正则格式校验(validators.js),未实现证件联网核查(如公安网/运营商核验),提交即视为通过。
    • 列表页"性别/创建人/创建时间"等列,若后端接口未返回对应字段则前端展示为空白,不做兜底伪造数据。
    • OCR 识别结果通过 src/utils/ocrMapping.js 映射填充到表单对应字段,用户仍可手动修改后再提交。
接口说明 Method + Path 关键请求参数 关键响应字段
个人客户分页查询 POST /api/customer/personal/page page,pageSize,customerName,mobile,certificateNumber,channelNo data.records[]:id,customerName,mobile,certificateNumber,channelName,createTime
个人客户详情 GET /api/customer/personal/detail id data:客户完整信息(基础信息+联系信息)
新增个人客户 POST /api/customer/personal/create customerName,certificateNumber,mobile,idCardFrontFile(Base64),idCardBackFile(Base64),facePhotoFile(Base64),联系信息字段等 data:新建客户 id
编辑个人客户 POST /api/customer/personal/update id + 同新增字段 code=200
身份证 OCR 识别 POST /api/customer/ocr/id-card imageBase64 data:识别出的姓名/证件号/地址等字段

8.2 企业客户(/customer/enterprise)

  • 列表组件:src/views/customer/enterprise/EnterpriseList.vue
  • 表单组件:src/views/customer/enterprise/EnterpriseForm.vue(新增/编辑/查看共用)
  • 隐藏路由:customer/enterprise/createcustomer/enterprise/editcustomer/enterprise/detail
  • 业务逻辑要点:
    • 表单含营业执照 OCR 上传(LicenseUpload.vue)、企业基础信息、法人信息、联系信息(Part 7/8 补充)、股东高管信息(EnterpriseRelatedPersonCard.vue 多条动态表单卡片)、对外投资关系(EnterpriseInvestmentCard.vue 多条动态表单卡片,来自 Part 9 补充说明)。
    • 提交前统一走 busy 遮罩(见 4.3),校验各上传组件的 uploading 状态,防止文件未上传完成时提交。
    • 营业执照号格式校验:15-20 位数字+大写字母(validators.js),同样未做工商联网核验
接口说明 Method + Path 关键请求参数 关键响应字段
企业客户分页查询 POST /api/customer/enterprise/page page,pageSize,enterpriseName,businessLicenseNo,channelNo data.records[]:id,enterpriseName,businessLicenseNo,legalPersonName,channelName,createTime
企业客户详情 GET /api/customer/enterprise/detail id data:企业完整信息(基础信息+法人信息+联系信息+股东高管列表+对外投资列表)
新增企业客户 POST /api/customer/enterprise/create enterpriseName,businessLicenseNo,legalPersonName,businessLicenseFile(Base64),股东高管列表 relatedPersons[],对外投资列表 investments[] data:新建企业 id
编辑企业客户 POST /api/customer/enterprise/update id + 同新增字段 code=200
营业执照 OCR 识别 POST /api/customer/ocr/business-license imageBase64 data:识别出的企业名称/统一社会信用代码/法人姓名等字段

客户管理模块字段/接口以《缺失的后端接口.md》Part 1.7、1.8 及 Part 7~9 补充说明为准,股东高管/对外投资列表的具体字段结构请对照 Part 9 原文逐项核对。

9. 钱包管理模块

特别提示:调研时工作区存在大量尚未提交的 Git 改动(PersonalOpenList.vueFacePhotoUpload.vue 等为新增未跟踪文件;AccountList.vue/AccountDetail.vue/PersonalOpenForm.vue/EnterpriseOpenForm.vue/BindCardModal.vue/WithdrawModal.vue/MarginModal.vue/wallet.js 等为已修改未提交)。本节内容基于当前工作区最新代码整理,而非最后一次 commit,与早期设计文档(2026-07-09 phase4 设计)相比字段/流程已经过多轮变更,如发现与旧文档不一致,以本节及当前代码为准。

9.1 钱包账户列表(/wallet/account)

  • 组件:src/views/wallet/account/AccountList.vue
  • 功能:查询个人/企业钱包账户列表,支持进入账户详情页,支持提现/保证金操作弹窗入口。
  • 业务逻辑要点:列表区分个人/企业账户类型;账户状态用 StatusTag 展示;提现/保证金操作通过 WithdrawModal.vue/MarginModal.vue 弹窗完成,提交后刷新列表余额。
接口说明 Method + Path 关键请求参数 关键响应字段
钱包账户分页查询 POST /api/wallet/account/page page,pageSize,accountName,accountType,channelNo data.records[]:accountNo,accountName,accountType,balance,availableBalance,status
账户提现 POST /api/wallet/account/withdraw accountNo,amount,bankCardNo code=200
保证金存入/支取 POST /api/wallet/account/margin accountNo,amount,type(存入/支取) code=200

9.2 账户详情页(/wallet/account/detail,隐藏路由)

  • 组件:src/views/wallet/account/AccountDetail.vue
  • 功能:展示账户基础信息、余额明细、交易流水、绑卡信息;支持绑卡(BindCardModal.vue)、下载回单等操作。
  • 业务逻辑要点:交易流水分页查询;回单下载走 src/utils/download.js 的 base64 转 Blob 下载方案。
接口说明 Method + Path 关键请求参数 关键响应字段
账户详情查询 GET /api/wallet/account/detail accountNo data:账户基础信息+绑卡列表
交易流水分页查询 POST /api/wallet/account/transaction/page accountNo,page,pageSize,startDate,endDate data.records[]:transactionNo,amount,type,balance,transactionTime
绑卡 POST /api/wallet/account/bind-card accountNo,bankCardNo,bankName,短信验证码等 code=200
回单下载 GET /api/wallet/account/receipt transactionNo data.fileData:Base64 编码的 PDF 内容

9.3 个人开户(/wallet/personal-open)

  • 列表组件:src/views/wallet/personal-open/PersonalOpenList.vue
  • 表单组件:src/views/wallet/personal-open/PersonalOpenForm.vue
  • 业务逻辑要点:选择已有个人客户(PersonalCustomerPicker.vue)发起钱包开户申请,填写渠道、联系方式等开户信息,提交后走短信验证码确认(SmsCodeInput.vue),开户状态需轮询/查询确认。字段结构经 Part 5、Part 6、Part 10 多次调整,当前以代码实现为准。
接口说明 Method + Path 关键请求参数 关键响应字段
个人开户申请分页查询 POST /api/wallet/personal-open/page page,pageSize,customerName,status data.records[]:id,customerName,mobile,channelName,status,createTime
提交个人开户申请 POST /api/wallet/personal-open/apply customerId,channelNo,mobile data:申请单 id
开户短信验证确认 POST /api/wallet/personal-open/confirm id,smsCode code=200

9.4 企业开户(/wallet/enterprise-open)

  • 列表组件:src/views/wallet/enterprise-open/EnterpriseOpenList.vue
  • 表单组件:src/views/wallet/enterprise-open/EnterpriseOpenForm.vue
  • 业务逻辑要点:选择已有企业客户(EnterpriseCustomerPicker.vue)发起企业钱包开户申请,流程与个人开户类似但字段更多(经办人信息、企业联系信息等),列表页字段结构见 Part 11 补充说明。
接口说明 Method + Path 关键请求参数 关键响应字段
企业开户申请分页查询 POST /api/wallet/enterprise-open/page page,pageSize,enterpriseName,status data.records[]:id,enterpriseName,channelName,status,createTime
提交企业开户申请 POST /api/wallet/enterprise-open/apply enterpriseId,channelNo,经办人信息等 data:申请单 id
开户短信验证确认 POST /api/wallet/enterprise-open/confirm id,smsCode code=200

钱包管理模块接口字段变动较为频繁(Part 5/6/9/10/11 均有相关补充调整),涉及改动前务必先重新核对《缺失的后端接口.md》对应最新章节以及 src/api/wallet.js 实际调用代码,不要照抄早期设计文档字段。

10. 授信管理模块

10.1 贷款申请列表(/credit/loan-application)

  • 列表组件:src/views/credit/loan-application/LoanApplicationList.vue
  • 表单组件:个人贷款申请表单 / 企业贷款申请表单(新增/编辑/查看共用)
  • 枚举字典:src/constants/creditEnums.js(完整枚举表,贷款状态、贷款类型等均来源于 swagger)
  • 业务逻辑要点:
    • 列表按申请人/渠道/状态/申请时间筛选分页查询,可查看申请详情。
    • 个人贷款申请表单字段相对完整,均有对应 swagger 枚举约束。
    • 企业贷款申请表单部分字段(如 legalPersonGender 等)在 swagger 中无枚举约束,前端为保证 UI 一致性,推断性地复用了个人贷款枚举,该做法未经后端明确确认,存在语义风险。
    • 实际调用的接口前缀为 /api/credit-apply/*
接口说明 Method + Path 关键请求参数 关键响应字段
贷款申请分页查询 POST /api/credit-apply/page page,pageSize,applicantName,applicantType(个人/企业),status,channelNo data.records[]:id,applicantName,applicantType,loanAmount,status,createTime
贷款申请详情 GET /api/credit-apply/detail id data:申请完整信息
提交个人贷款申请 POST /api/credit-apply/personal/create customerId,loanAmount,loanPurpose,loanTerm data:申请单 id
提交企业贷款申请 POST /api/credit-apply/enterprise/create enterpriseId,loanAmount,legalPersonName,legalPersonGender(推断枚举)等 data:申请单 id
编辑贷款申请 POST /api/credit-apply/update id + 对应字段 code=200

已知问题:后端 swagger 中存在另一组语义存疑的 /api/loan-application/* 接口,与实际前端使用的 /api/credit-apply/* 并存,两组接口的关系(是否为废弃/重复/不同业务场景)未经后端确认,涉及授信模块改动时需留意不要混用这两组接口。

11. 商户中心模块

11.1 商户管理(/merchant/management)

  • 组件:src/views/merchant/management/MerchantList.vue
  • 业务逻辑要点:
    • 无详情接口:查看/编辑商户信息时,依赖路由 query 参数回填表单数据,刷新页面会丢失数据(需重新从列表页跳转进入)。
    • 无审批接口:商户"审批"流程实际通过状态字段 ACTIVE/INACTIVE 的切换接口替代,不是独立的审批工作流。
    • 机构过滤筛选字段前端已实现,但后端未按机构范围过滤商户列表(见第 14 章)。
接口说明 Method + Path 关键请求参数 关键响应字段
商户分页查询 POST /api/merchant/page page,pageSize,merchantName,status,organizationId(未生效) data.records[]:id,merchantName,merchantNo,status,channelName,createTime
新增商户 POST /api/merchant/create merchantName,merchantNo,channelNo data:新建商户 id
编辑商户 POST /api/merchant/update id + 同新增字段(通过 query 回填) code=200
状态切换(代替审批) POST /api/merchant/update-status id,status(ACTIVE/INACTIVE) code=200

11.2 发票管理(/merchant/invoice)

  • 组件:src/views/merchant/invoice/InvoiceList.vue + 5 个功能弹窗组件(开票申请、发票详情、匹配、结算、驳回等,具体命名以代码为准)
  • 业务逻辑要点:发票状态流转(申请→审核→匹配→结算)通过状态更新接口驱动,列表按状态筛选;发票金额与订单匹配逻辑依赖后端返回的匹配结果字段展示,前端不做金额校验计算。
接口说明 Method + Path 关键请求参数 关键响应字段
发票分页查询 POST /api/merchant/invoice/page page,pageSize,merchantName,status,invoiceNo data.records[]:id,invoiceNo,merchantName,amount,status,createTime
发票申请详情 GET /api/merchant/invoice/detail id data:发票完整信息(含匹配订单/结算记录)
发票状态更新 POST /api/merchant/invoice/update-status id,status code=200
发票匹配 POST /api/merchant/invoice/match id,orderIds[] code=200
发票结算 POST /api/merchant/invoice/settle id,settleAmount code=200

商户中心模块字段以《缺失的后端接口.md》Part 1.13、1.14 及 src/api/merchant.js/src/api/invoice.js 为准;5 个弹窗组件的具体接口调用请对照组件文件逐一核对。

12. 支付管理模块

12.1 订单支付(/payment/order-payment)

  • 组件:src/views/payment/order-payment/PaymentRecordList.vue + 发起支付弹窗 + 支付详情弹窗
  • 业务逻辑要点:
    • 列表查询支付记录,支持发起新支付(选择订单+融资额度查询后确认支付)。
    • 融资额度查询接口 queryCreditQuotaApi(POST /api/payment/query-credit-quota)响应结构完全未在 swagger 中文档化,前端目前采取"原样展示返回 JSON"的保守处理方式,未做强类型字段映射(mock-server 假设其结构为 { accountNo, creditLimit, usedAmount, availableAmount },但该假设未经真实后端确认)。
    • 机构过滤字段前端已实现但后端不支持按机构过滤支付记录(见第 14 章)。
接口说明 Method + Path 关键请求参数 关键响应字段
支付记录分页查询 POST /api/payment/order-payment/page page,pageSize,orderNo,status,organizationId(未生效) data.records[]:id,orderNo,amount,status,payTime
融资额度查询 POST /api/payment/query-credit-quota accountNoenterpriseId(响应结构未文档化) data:结构未文档化,前端原样展示
发起支付 POST /api/payment/order-payment/create orderNo,amount,accountNo data:支付记录 id
支付详情查询 GET /api/payment/order-payment/detail id data:支付记录完整信息

13. 订单管理模块

13.1 汇总订单(/order/summary)

  • 组件:src/views/order/summary/SummaryOrderList.vue
  • 业务逻辑要点:
    • "汇总订单"页面本身在原型库中缺失对应设计,由前端团队自行设计该列表页的字段与交互结构。
    • 列表中的"剩余额度"列为前端本地计算字段(financeQuota - accumulatedLoanAmount),不是后端返回字段,维护时需注意不要误以为它来自接口响应。
    • 机构筛选未生效:前端提供了机构筛选下拉,但后端汇总订单接口无 organizationId 关联路径,筛选不产生实际效果。
    • 详情弹窗无法展示关联的原始订单明细,因为后端不支持"汇总订单→原始订单"的关联查询接口。
接口说明 Method + Path 关键请求参数 关键响应字段
汇总订单分页查询 POST /api/order/summary/page page,pageSize,enterpriseName,channelNo data.records[]:id,enterpriseName,financeQuota,accumulatedLoanAmount,channelName,createTime(前端另计算 remainingQuota = financeQuota - accumulatedLoanAmount)
汇总订单详情 GET /api/order/summary/detail id data:汇总订单完整信息(不含关联原始订单明细)

13.2 原始订单(/order/original)

  • 组件:src/views/order/original/OriginalOrderList.vue
  • 业务逻辑要点:展示原始交易订单明细,支持按订单号/企业名称/渠道/时间范围筛选分页查询,无新增/编辑操作(数据来源为上游业务系统同步)。
接口说明 Method + Path 关键请求参数 关键响应字段
原始订单分页查询 POST /api/order/original/page page,pageSize,orderNo,enterpriseName,channelNo,startDate,endDate data.records[]:id,orderNo,enterpriseName,amount,orderTime
原始订单详情 GET /api/order/original/detail id data:订单完整信息

14. 已知问题与待确认事项汇总

模块 问题描述
用户管理 管理员直接修改用户密码的接口不存在,"密码修改"按钮永久置灰,只能走"密码重置并发送短信"流程
核心企业(渠道)管理 无渠道名称/编号唯一性前端校验,依赖后端报错提示;字段名历史遗留 enterpriseName 与新命名 channelName 并存兼容
客户管理 未实现身份证号/统一社会信用代码的联网核查,仅做前端正则格式校验;个人客户列表"性别/创建人/创建时间"等列在后端未返回时展示为空白;无删除入口
商户中心 无商户详情接口,查看/编辑靠路由 query 回填,刷新会丢数据;无独立审批接口,用状态 ACTIVE/INACTIVE 切换代替审批;机构过滤筛选未生效
支付管理 queryCreditQuotaApi 融资额度查询接口响应结构完全未文档化,前端原样展示返回 JSON;机构过滤字段后端不支持
订单管理 汇总订单"剩余额度"为前端本地计算字段,非后端返回;机构筛选未生效(无 organizationId 关联路径);汇总订单详情无法关联展示原始订单明细
授信管理 存在另一组语义存疑的 /api/loan-application/* 接口与实际使用的 /api/credit-apply/* 并存,关系未经后端确认;企业贷款表单部分字段(如 legalPersonGender)无 swagger 枚举约束,前端推断性复用个人贷款枚举
权限管理 /system/permission 页面未在总体设计文档的实施范围清单中单独列出,但代码已实现并注册路由,属代码现状与文档的差异
全局 src/utils/formFocus.js 的聚焦逻辑对隐藏在折叠面板(display:none)内的报错字段不生效,当前项目暂无该场景但后续新增折叠式表单时需注意
图片上传组件 FacePhotoUpload.vue 尚未按 IdCardUpload.vue/LicenseUpload.vue 的 hover 遮罩+预览/重新上传/删除三按钮规范改造
钱包管理 调研时工作区存在大量未提交改动,字段/流程相比早期设计文档(2026-07-09 phase4)已多轮变更,任何改动前务必核对当前代码而非早期设计文档

15. 本地 Mock Server 说明

mock-server/(npm run mock,默认端口 8888)是真实后端不可用时的应急本地演示后端,所有接口路径/字段力求对齐 swagger_project_scfs_2026-07-09_14-15-23.json 及前端实际调用代码,核心业务规则(登录锁定、状态流转、余额扣减、发票匹配/结算等)为真实本地状态维护,而非纯占位透传。但其契约已知与真实接口不完全一致,不能作为接口设计依据,仅用于本地演示/无后端环境时的联调。

  • 目录结构:index.js(入口,装配路由/CORS/Cookie/全局错误处理)、state.js(内存态)、middleware/requireAuth.js(鉴权中间件)、utils/(统一响应封装/分页/ID 生成)、db/(各模块种子数据,进程重启后重置)、routes/(各模块 Express Router)。
  • 测试账号:admin / Admin@123(系统管理员全权限);短信验证码场景万能验证码 123456,真实生成的验证码打印在 Mock Server 控制台。
  • "已知简化点/未文档化项"(mock-server/README.md 已列出,例如 POST /api/payment/query-credit-quota 响应结构完全未文档化,Mock 自行假设为 { accountNo, creditLimit, usedAmount, availableAmount })恰恰标记出真实后端接口设计不完整、需要额外与后端确认的地方,阅读该文件有助于快速定位待确认接口清单。

16. 维护建议

  1. 新增菜单页面:必须同时完成 (a) src/views/** 下新建组件、(b) src/router/componentRegistry.js 中登记 routePathComponentMap(侧边栏菜单页)或 extraChildRoutes(新增/编辑/详情等隐藏子路由),否则会 404;权限字典由权限管理页面动态维护,但组件映射永远需要前端手工登记,后端加菜单不会自动出现页面。
  2. 对接/修改后端接口前,先查阅《缺失的后端接口.md》Part 1 速查表确认基础契约,再检查 Part 2~11 是否有该接口的后续补充/变更记录(优先级更高);如用户告知接口有变更,应通过 MCP 工具重新获取最新 swagger(前提是 .toco/CONFIG 补充了 PROJECT_ID,目前该文件仅有 ORG_ID/ORG_NAME)。
  3. 请求 Header:涉及请求 header 改动前务必先核对/修复 src/utils/traceHeaders.jsbuildTraceHeaders(),不要照抄旧的字段实现(历史实现字段名大小写不规范,已在 3.4 节更新为规范写法)。
  4. 枚举值统一从 src/constants/*Enums.js 引用,来源必须是 swagger/《缺失的后端接口.md》,不得编造;如遇后端未明确约束的字段(如授信模块企业贷款表单部分字段),需在代码注释中明确标注"推断性实现,未经后端确认"。
  5. 批量操作统一使用 src/utils/loopDelete.js + batchDeleteResult.js 模式,不要假设后端存在批量接口。
  6. 图片上传组件新增/修改时统一参照 IdCardUpload.vue 的 hover 遮罩+三按钮规范(4.2 节),并记得补齐 FacePhotoUpload.vue 的改造欠账。
  7. 耗时操作统一接入 busy/busyTip 遮罩模式(4.3 节),不要各自维护互不关联的 loading 变量。
  8. 机构数据隔离类问题(多个模块的机构筛选未生效)本质是后端未按机构范围过滤数据,前端不应通过本地二次过滤"解决",应推动后端补齐 organizationId 关联查询能力。
  9. website_detail/ 原型库覆盖面远大于本项目范围,新增功能前先核对 docs/superpowers/specs/2026-07-08-fryl-frontend-overall-design.md 明确的范围划分,避免误将排除模块的原型页面当作待实现需求。