22 KiB
22 KiB
flux-web 功能说明文档
项目简介
flux-web 是薇钱包 H5 前端项目,提供用户借款申请、信息填写和授权流程的完整业务功能。
一、业务流程总览
1.1 完整用户旅程
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ index.html │───>│ basic-info.html │───>│ 授权流程 │
│ 借款申请页面 │ │ 基本信息填写 │ │ (可选) │
└─────────────────┘ └─────────────────┘ └─────────────────┘
1.2 核心业务流程图
用户进入页面
│
├─> 输入/修改借款金额
├─> 选择还款期数
├─> 选择借款用途
│
├─> [已有登录态?] ──是──> 显示脱敏手机号
│ │
│ └─> 勾选协议 → 跳转基本信息页
│
└─> 否 ──> 选择登录方式
│
├─> 方式A: 极光一键登录
│ └─> 成功 → 注册/登录 → 跳转
│ └─> 失败 → 降级到方式B
│
└─> 方式B: 短信验证码登录
├─> 输入手机号
├─> 发送验证码 (60s倒计时)
├─> 验证码校验
└─> 注册/登录 → 跳转
二、index.html - 借款申请页面
2.1 页面元素与交互
| 元素 | DOM ID | 交互行为 | 数据流向 |
|---|---|---|---|
| 借款金额输入 | loanAmount |
input 事件触发 | loanData.amount |
| 全部借出按钮 | maxLoan |
点击设为最大值 | loanData.amount = 200000 |
| 还款期数 | repaymentTerm |
点击打开选择器 | loanData.period |
| 还款计划 | repaymentPlan |
自动计算更新 | calculateRepaymentPlan() |
| 借款用途 | loanPurpose |
点击打开选择器 | loanData.purpose |
| 手机号输入 | phoneNumber |
输入 + 验证 | → 验证码弹窗 |
| 一键登录 | oneClickLoginWrapper |
极光SDK | → 成功后自动填手机号 |
| 立即申请按钮 | applyBtn |
点击触发申请 | → 验证码/跳转 |
| 协议勾选 | agreementCheck |
必选 | 未勾选弹窗提示 |
2.2 借款数据结构
loanData = {
amount: 50000, // 借款金额 (1000-200000)
period: 12, // 还款期数 (3,6,9,12,18,24,36)
purpose: '个人日常消费' // 借款用途
}
2.3 还款计划计算逻辑
接口: LoanService.calculateRepaymentPlan(amount, period, interestRate)
计算公式:
月均本金 = 借款金额 / 期数
月利息 = 借款金额 × (年化利率 / 100) / 12
首期还款 = 月均本金 + 月利息
首期日期 = 当前日期 + 30天
年化利率范围: 10.8% - 24%(单利)
显示格式: 首期02月05日 应还 4916.67元
三、用户认证流程
3.1 极光一键登录
初始化条件:
- 配置了
jVerifyAppId - 用户未登录
流程:
加载极光SDK
│
├─> 成功获取手机号
│ └─> AuthService.registerOrLogin(phone, loanData)
│ └─> 成功 → 跳转基本信息页
│ └─> 失败 → 显示手机号输入框
│
└─> 失败/不支持
└─> 自动降级到短信验证码登录
关键接口: AuthService.registerOrLogin(phone, loanData)
3.2 短信验证码登录
流程图:
输入手机号
│
├─> 验证手机号格式
│ └─> 无效 → 显示错误提示
│
├─> 有效 → 点击"立即申请"
│ │
│ ├─> 勾选协议?
│ │ └─> 否 → 弹协议确认窗
│ │
│ └─> 是 → 打开验证码弹窗
│ │
│ ├─> 发送验证码
│ │ ├─> SMSService.send(phone)
│ │ ├─> 成功 → 启动60s倒计时
│ │ └─> 失败 → 显示错误,可重新发送
│ │
│ ├─> 输入验证码
│ │ └─> SMSService.verify(phone, code)
│ │ └─> 成功 → 注册/登录
│ │ └─> 失败 → 显示错误
│ │
│ └─> 验证通过
│ └─> 跳转基本信息页
倒计时逻辑:
- 60秒倒计时
- 倒计时结束显示"重新发送"
- 可点击重新发送
3.3 接口数据说明
发送短信验证码
接口: POST /zcore/sms/send
请求格式: application/json
{
"phone": "13800138000"
}
响应:
{
"retcode": 0,
"retinfo": "发送成功"
}
验证短信验证码
接口: POST /zcore/sms/verify
请求格式: application/json
{
"phone": "13800138000",
"code": "123456"
}
响应:
{
"retcode": 0,
"retinfo": "验证成功"
}
用户注册/登录
接口: POST /api/partnerh5/login
请求格式: application/x-www-form-urlencoded
bean={"phone":"13800138000","loanamount":50000,"repaymentperiod":12,"loanpurpose":"个人日常消费"}
响应:
{
"retcode": 0,
"result": {
"customerid": "12345",
"sessionid": "abc123xyz",
"loginPhone": "13800138000"
}
}
本地存储:
UserCache.saveUserSession({
customerid: "12345",
sessionid: "abc123xyz",
loginPhone: "13800138000",
formData: { loanamount: 50000, ... }
})
后续请求自动添加请求头:
jsessionid: abc123xyz
四、basic-info.html - 基本信息填写页面
4.1 页面结构
┌─────────────────────────────────┐
│ 顶部进度卡片 │
│ - 预期额度: 35000 → 50000 │
│ - 进度条: 0% → 100% │
│ - 已完成: 0/8 │
└─────────────────────────────────┘
│
├─> 选择一项,进度+12.5%
│ 预期额度增加1875元
│
┌─────────────────────────────────┐
│ 资产信息区域 (渐进式显示) │
│ 1. 房产: 有房产/无房产 │
│ 2. 车辆: 有车辆/无车辆 │
│ 3. 公积金: 有/无 │
│ 4. 社保: 有/无 │
│ 5. 信用卡: 有/无 │
│ 6. 银行流水: 有/无 │
│ 7. 职业: 4个选项 │
│ 8. 芝麻分: 4个选项 │
└─────────────────────────────────┘
│
└─> 8项全部完成后
↓
┌─────────────────────────────────┐
│ 基本信息区域 (自动展开) │
│ 1. 真实姓名 (输入) │
│ 2. 身份证号 (输入) │
│ 3. 所属城市 (选择器) │
└─────────────────────────────────┘
│
↓
┌─────────────────────────────────┐
│ 提交按钮 (基本信息完成时可用) │
└─────────────────────────────────┘
4.2 资产选项配置
ASSET_CONFIG.ITEMS = [
{ id: 'house', name: '房产', options: ['有房产', '无房产'] },
{ id: 'car', name: '车辆', options: ['有车辆', '无车辆'] },
{ id: 'fund', name: '公积金', options: ['有公积金', '无公积金'] },
{ id: 'social', name: '社保', options: ['有社保', '无社保'] },
{ id: 'credit', name: '信用卡', options: ['有信用卡', '无信用卡'] },
{ id: 'bank', name: '银行流水', options: ['有银行流水', '无银行流水'] },
{ id: 'job', name: '职业', options: ['上班族', '自由职业', '企业主', '公务员/国企'] },
{ id: 'zhima', name: '芝麻分', options: ['700以上', '650-700', '600-650', '无'] }
]
4.3 数据映射关系
前端中文 → 后端数字:
VALUE_MAPPING = {
'有房产': 1, '无房产': 2,
'有车辆': 1, '无车辆': 2,
// ... 其他类似
'上班族': 1, '自由职业': 2, '企业主': 3, '公务员/国企': 4,
'700以上': 1, '650-700': 2, '600-650': 3, '无': 4
}
4.4 渐进式显示逻辑
selectAssetOption(itemId, value) {
// 1. 保存选择
this.selectedValues[itemId] = value;
// 2. 更新进度
const completed = Object.keys(this.selectedValues).length;
const progress = (completed / 8) * 100;
const money = 35000 + (50000 - 35000) * (progress / 100);
// 3. 检查是否是当前步骤
const currentIndex = ASSET_CONFIG.ITEMS.findIndex(item => item.id === itemId);
if (currentIndex === this.currentStep && this.currentStep < 7) {
// 延迟400ms后显示下一项
setTimeout(() => this.revealNextItem(), 400);
}
// 4. 自动保存草稿(2秒后)
this.autoSaveDraft();
}
4.5 城市选择逻辑
IP定位自动填充:
页面加载
│
├─> 调用 IP定位接口
│ └─> /api/partnerh5/ip_location
│ └─> 返回 { province: "广东省", city: "深圳市" }
│
├─> 查询城市代码
│ └─> AreaService.findCityCode(province, city)
│ └─> 返回 { provinceCode: "440000", cityCode: "440300" }
│
└─> 自动填充城市字段
省市区数据结构:
PROVINCE_CITY_DATA = {
'广东省': ['广州市', '深圳市', '珠海市', ...],
'江西省': ['南昌市', '九江市', ...],
...
}
五、表单提交与草稿管理
5.1 草稿自动保存
触发条件:
- 选择任一资产选项
- 修改任一基本信息
延迟机制: 2秒防抖
保存接口: POST /api/partnerh5/save_draft
请求数据:
{
shortcode: "I3fMzX", // URL参数或默认值
formid: "uuid-xxx", // 唯一表单ID
draftstatus: 1, // 1=草稿,0=正式提交
// 资产信息(映射为数字)
house: 1, car: 2, fund: 1, ...,
// 基本信息
name: "张三",
idCard: "110101199001011234",
city: "深圳市"
}
5.2 表单正式提交
提交接口: POST /api/partnerh5/submit
请求数据结构:
{
shortcode: "I3fMzX",
formid: "uuid-xxx",
draftstatus: 0, // 0=正式提交
// 资产信息
house: 1, car: 2, fund: 1, social: 1,
credit: 1, bank: 1, job: 1, zhima: 2,
// 基本信息
name: "张三",
idCard: "110101199001011234",
city: "深圳市"
}
响应数据:
{
"retcode": 0,
"retinfo": "提交成功",
"result": {
"formdataid": 12345, // 表单数据ID(用于授权流程)
"h5Urls": [ // 需要授权的H5列表(可能为空)
{
"apicode": "TAOBAA",
"apiname": "淘宝授权",
"h5url": "https://..."
},
{
"apicode": "JD",
"apiname": "京东授权",
"h5url": "https://..."
}
],
"redirectUrl": "https://..." // 最终跳转URL(H5直推地址)
}
}
5.3 表单验证规则
| 字段 | 验证规则 | 错误提示 |
|---|---|---|
| 手机号 | /^1[3-9]\d{9}$/ |
"请输入有效的11位手机号" |
| 姓名 | /^[\u4e00-\u9fa5]{2,20}/ |
"请输入2-20位中文姓名" |
| 身份证 | 18位身份证校验 | "请输入有效的身份证号码" |
| 验证码 | 6位数字 | "请输入6位验证码" |
六、授权流程(AuthFlow)
6.1 流程触发条件
表单提交成功且 h5Urls 不为空时触发。
6.2 授权状态枚举
AUTH_STATUS = {
WAITING: 1, // 等待授权
CALLBACK: 2, // 已回调
APPLY_OK: 3, // 进件成功
APPLY_FAIL: 4 // 进件失败
}
6.3 授权流程图
表单提交成功,返回 h5Urls
│
↓
┌─────────────────────────────────┐
│ 显示授权进度列表 │
│ - 当前产品: 1/3 │
│ - 状态: ● 淘宝授权 授权中... │
│ - iframe 加载 h5url │
└─────────────────────────────────┘
│
↓
开始轮询授权状态
│
├─> 每3秒查询一次
│ └─> POST /api/partnerh5/check_auth_status
│ └─> { formdataid: 12345, apicode: "TAOBAO" }
│
├─> 状态判断
│ ├─> status = 1 (WAITING) → 继续轮询
│ ├─> status = 2 (CALLBACK) → 成功,下一个
│ ├─> status = 3 (APPLY_OK) → 成功,下一个
│ └─> status = 4 (APPLY_FAIL) → 失败,下一个
│
├─> 超时判断
│ └─> 超过10分钟 → 标记超时,下一个
│
└─> 全部完成
↓
┌─────────────────────────────────┐
│ 显示完成页面 │
│ - 全部授权完成 ✓ │
│ - 5秒后自动跳转... │
│ - [立即跳转] 按钮 │
└─────────────────────────────────┘
│
├─> 有 redirectUrl → 跳转到指定页面
└─> 无 redirectUrl → 返回首页
6.4 授权状态查询接口
接口: POST /api/partnerh5/check_auth_status
请求格式: application/x-www-form-urlencoded
bean={"formdataid":12345,"apicode":"TAOBAO"}
响应:
{
"retcode": 0,
"result": {
"apicode": "TAOBAO",
"apiname": "淘宝授权",
"status": 2,
"h5url": "https://..."
}
}
6.5 轮询配置
POLL_INTERVAL = 3000 // 轮询间隔:3秒
POLL_TIMEOUT = 10 * 60 * 1000 // 超时时间:10分钟
COUNTDOWN_SECONDS = 5 // 完成后倒计时:5秒
6.6 Mixed Content 处理
当 HTTPS 页面需要加载 HTTP 的 iframe 时:
if (window.location.protocol === 'https:' && h5url.startsWith('http://')) {
// 检测到 Mixed Content,使用新窗口打开
window.open(h5url, '_blank');
}
七、页面间数据传递
7.1 URL 参数传递
// 从 index.html 跳转到 basic-info.html,保留当前页的查询串
window.location.href = 'basic-info.html' + window.location.search;
// 跳转后 URL 参数保持不变,例如:
// basic-info.html?shortcode=I3fMzX&channel=toutiao
// 其中 shortcode 为短链编码(与后端 shortcode 对应),;channel 等其它参数一并保留。
7.2 本地存储传递
// 保存用户会话
UserCache.saveUserSession({
customerid: "12345",
sessionid: "abc123",
loginPhone: "13800138000",
formData: {
loanamount: 50000,
repaymentperiod: 12,
loanpurpose: "个人日常消费"
}
});
// 读取用户会话
const session = UserCache.getUserSession();
7.3 表单ID管理
// 生成或获取表单ID
const formId = FormIdGenerator.getOrCreate(); // uuid
// 提交成功后清除
FormIdGenerator.clear();
八、API 接口汇总
8.1 接口列表
| 接口 | 方法 | 用途 | Content-Type |
|---|---|---|---|
| /zcore/sms/send | POST | 发送短信验证码 | application/json |
| /zcore/sms/verify | POST | 验证短信验证码 | application/json |
| /zcore/jpush/login | POST | 极光一键登录 | application/json |
| /api/partnerh5/login | POST | 用户注册/登录 | x-www-form-urlencoded |
| /api/partnerh5/submit | POST | 提交表单 | x-www-form-urlencoded |
| /api/partnerh5/save_draft | POST | 保存草稿 | x-www-form-urlencoded |
| /api/partnerh5/get_draft | POST | 获取草稿 | x-www-form-urlencoded |
| /api/partnerh5/check_auth_status | POST | 检查授权状态 | x-www-form-urlencoded |
| /api/partnerh5/area_list | GET | 获取区域列表 | - |
| /api/partnerh5/ip_location | GET | IP定位 | - |
8.2 请求头规范
// 所有请求自动添加
headers: {
'Content-Type': 'application/json' 或 'application/x-www-form-urlencoded',
'jsessionid': '从 UserCache 获取' // 用户登录后自动添加
}
8.3 响应格式规范
{
"retcode": 0, // 0=成功,其他=失败
"retinfo": "操作成功", // 提示信息
"result": { ... } // 返回数据(可选)
}
九、配置说明
9.1 API 配置
// src/js/config/api.config.js
BASE_URL: '' // 空字符串表示同源部署
TIMEOUT: 30000 // 请求超时30秒
9.2 应用配置
// src/js/config/app.config.js
DEBUG_CONFIG: {
ENABLED: false, // 生产环境设为 false
SMS_CODE: '123456', // 调试模式固定验证码
DEFAULT_SHORTCODE: 'I3fMzX', // 默认短链代码
VERBOSE_LOGGING: true // 详细日志
}
LOAN_CONFIG: {
AMOUNT: { MIN: 1000, MAX: 200000, DEFAULT: 50000 },
INTEREST_RATE: { MIN: 10.8, MAX: 24 },
PERIOD_OPTIONS: [3, 6, 9, 12, 18, 24, 36]
}
ASSET_CONFIG: {
PROGRESS_MONEY: {
INITIAL: 35000, // 初始预期额度
FINAL: 50000 // 最终预期额度
}
}
十、关键业务逻辑
10.1 一键登录降级机制
极光一键登录初始化
│
├─> 成功获取手机号
│ └─> 调用注册接口
│ ├─> 成功 → 跳转
│ └─> 失败 → 显示手机号输入框
│
└─> 失败/不支持
└─> 隐藏一键登录按钮
└─> 显示手机号输入框
└─> 显示"立即申请"按钮
10.2 已登录用户处理
// 页面加载时检查登录态
restoreUserData() {
const session = UserCache.getUserSession();
if (session && session.loginPhone) {
// 显示脱敏手机号
this.elements.phoneNumber.value = Formatter.maskPhone(session.loginPhone);
this.elements.phoneNumber.readOnly = true;
// 恢复表单数据
if (session.formData) {
this.elements.loanAmount.value = session.formData.loanamount;
// ...
}
}
}
10.3 协议确认逻辑
点击"立即申请"
│
├─> 已登录
│ └─> 勾选协议? ──否──> 弹协议确认窗
│ └─> 是 → 跳转基本信息页
│
└─> 未登录
└─> 验证手机号
└─> 勾选协议? ──否──> 弹协议确认窗
└─> 是 → 显示验证码弹窗
10.4 表单提交锁机制
// 防止重复提交
this.isSubmitting = false;
async handleSubmit() {
if (this.isSubmitting) return; // 已在提交中
this.elements.submitBtn.disabled = true;
this.elements.submitBtn.textContent = '提交中...';
this.isSubmitting = true;
try {
const response = await DraftManager.submitForm(...);
if (response.success) {
// 处理成功
} else {
throw new Error(response.message);
}
} catch (error) {
// 恢复按钮状态
this.elements.submitBtn.disabled = false;
this.elements.submitBtn.textContent = '下一步';
this.isSubmitting = false;
}
}
十一、错误处理
11.1 短信发送失败
发送短信
│
└─> 失败
├─> 显示错误信息
├─> 倒计时显示"重新发送"
└─> 可点击重新发送
11.2 验证码错误
输入验证码点击确定
│
└─> 验证失败
├─> 显示错误提示
├─> 输入框标红
├─> 保持弹窗打开
└─> 可重新输入
11.3 表单提交失败
提交表单
│
└─> 失败
├─> Toast 提示错误信息
├─> 恢复提交按钮
├─> 不清除表单数据
└─> 可重新提交
十二、版本信息
- 当前版本: 2.0.0
- 最后更新: 2025-01-21
- 版权所有: 北京百雅科技有限公司