hailin
|
149cf7ea77
|
fix(auth): 修复找回密码流程的三个 bug
Backend:
- password.service.ts: resetPassword 补齐验证码暴力破解防护,
输错时累计 attempts,超过 5 次拒绝,与 loginBySms 逻辑一致
Frontend (forgot_password_page.dart):
- 发送验证码错误消息改为提取真实 message,不再显示原始异常类名
- 重置密码错误消息同上处理
- 新增 _sendingSms 标志,发送请求期间禁用按钮,防止重复发短信
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
2026-03-10 19:56:34 -07:00 |
hailin
|
761dcb1115
|
fix(auth): resetPassword 解除锁定 + 登录错误提示优化
Backend:
- password.service.ts: resetPassword 成功后调用 user.unlock(),
清除 loginFailCount 和 lockedUntil,避免用户改密后仍无法登录
Frontend:
- api_client.dart: 401 响应提取后端真实错误消息,不再丢弃
- auth_remote_datasource.dart: loginWithPassword 直接 rethrow
已知异常类型,避免二次包装导致消息格式混乱
- login_page.dart: 登录失败按错误类型分类提示:
· 账户锁定 → AlertDialog + "找回密码"按钮
· 还有尝试机会 → SnackBar(橙色) + "找回密码"Action
· 其他错误 → 普通 SnackBar
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
2026-03-10 19:46:06 -07:00 |
hailin
|
ff82bddbc6
|
fix(mining-admin): 审计日志 keyword 搜索、管理员列、详情中文化
1. keyword 搜索实际生效:按 resourceId 和管理员用户名模糊匹配
2. LOGIN_FAILED 无账号时管理员列显示尝试的用户名(而非 unknown)
3. 详情列对 LOGIN_FAILED reason 做中文映射
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
2026-03-10 01:27:31 -07:00 |
hailin
|
a72be1bbf3
|
fix(mining-admin): 修正 migration SQL 列名为驼峰式 adminId
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
2026-03-10 00:49:20 -07:00 |
hailin
|
ad1c889848
|
feat(mining-admin): 审计日志记录登录失败事件
- audit_logs.adminId 改为可选字段,支持用户名不存在时的失败记录
- 登录失败时记录 LOGIN_FAILED 操作,resourceId 存储尝试的用户名,newValue 记录失败原因
- 前端审计日志页新增 LOGIN_FAILED 标签(红色)及筛选选项
- 新增 migration: 20260310_audit_log_nullable_admin
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
2026-03-10 00:42:57 -07:00 |
hailin
|
e7d852e25e
|
fix(mining-admin-web): 移除 Google Fonts 依赖,改用系统字体
服务器构建时无法访问 fonts.googleapis.com(ETIMEDOUT),
导致 next build 失败。移除 next/font/google 的 Inter 引入,
直接使用 Tailwind 默认系统字体栈(-apple-system, BlinkMacSystemFont,
Segoe UI, Roboto 等),无需网络请求,离线构建完全可用。
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
2026-03-09 23:25:20 -07:00 |
hailin
|
d6e4dd58c7
|
fix(mining-admin-web): 禁用 configs 页矿池充值对话框中的中心化充值入口
将 100亿销毁池 和 200万挖矿池 充值对话框中的「中心化充值」TabsTrigger
设为 disabled,并将默认选中项改为「区块链充值」。
与 market-maker 页面的处理方式一致(硬编码禁用),
待中心化充值功能完善后再重新启用。
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
2026-03-09 23:13:45 -07:00 |
hailin
|
5050d5cacd
|
fix(mining-admin-web): 暂时禁用做市商管理中的中心化充值入口
现金(积分值)和积分股两个充值 Dialog 的「中心化充值」Tab
均设为 disabled,默认展示「区块链充值」Tab。
中心化充值的表单内容保留,待功能就绪后只需移除 disabled 即可恢复。
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
2026-03-09 23:07:41 -07:00 |
hailin
|
9f73adc999
|
feat(mining-admin-web): 审计日志页面补全操作类型标签和资源名称中文映射
新增缺失的操作类型 label(含颜色区分):
- LOGOUT 登出(灰色)
- ENABLE 启用(翠绿)
- DISABLE 禁用(橙色)
- UNLOCK 解锁(黄色)
- ACTIVATE 激活挖矿(蓝绿)
- DEACTIVATE 停用挖矿(玫红)
- INIT 初始化(浅灰)
新增 resourceLabels 映射,resource 列改为显示中文:
AUTH→认证 / CONFIG→系统配置 / MINING→挖矿 /
CAPABILITY→用户能力 / PRE_PLANTING_SELL_RESTRICTION→预种卖出限制 /
MANUAL_MINING→手工补发 / BATCH_MINING→批量补发
过滤下拉框补全所有操作类型选项,与后端实际写入的 action 值对齐。
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
2026-03-09 23:03:31 -07:00 |
hailin
|
991bc77db8
|
fix(mining-admin): Dockerfile builder 阶段补充 python3/make/g++ 以支持 bcrypt 编译
缓存失效后 npm ci 会从源码编译 bcrypt,但 node:20-alpine 的 builder 阶段
缺少 python3/make/g++,导致构建失败。runner 阶段已有这些工具,
现在 builder 阶段同步补上,确保镜像可稳定重建。
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
2026-03-09 22:37:47 -07:00 |
hailin
|
510a890b33
|
fix(mining-admin): 修复审计日志 IP 地址记录为内网 IP 的问题,补全全操作的 IP 审计
【根本原因】
- main.ts 缺少 `app.set('trust proxy', 1)`,Express 在 Nginx/Kong 代理后 req.ip
返回的是代理服务器内网 IP(127.0.0.1),而非真实客户端 IP。
- Nginx 已正确设置 X-Forwarded-For / X-Real-IP,但后端从未读取这些 header。
【修复内容】
1. main.ts
- 新增 `app.set('trust proxy', 1)`,使 Express 信任 Nginx 第一跳的
X-Forwarded-For,req.ip 从此返回真实客户端 IP。
2. shared/utils/get-client-ip.ts(新建工具函数)
- 优先读取 X-Forwarded-For(取逗号分隔的第一个 IP,支持多跳代理)
- 其次读取 X-Real-IP
- 兜底使用 req.ip
- 全服务统一使用此函数,避免各处重复逻辑。
3. auth.controller.ts / auth.service.ts
- LOGIN:将 req.ip 改为 getClientIp(req)(已记录 IP,修正来源)
- LOGOUT:之前完全不记录 IP/UA,现在补全传入并存入审计日志。
4. config.service.ts / config.controller.ts
- setConfig / deleteConfig 新增 ipAddress / userAgent 可选参数。
- 新增 recordAuditLog 通用方法,供 Controller 记录任意审计事件。
- 所有写操作(setTransferEnabled、setP2pTransferFee、setConfig、
deleteConfig)均传入真实 IP 和 UA。
- activateMining / deactivateMining 之前完全无审计日志,
现补录 ACTIVATE / DEACTIVATE 类型的 MINING 审计条目。
5. capability-admin.service.ts / capability.controller.ts
- setCapability / setCapabilities / writeAuditLog 均新增
ipAddress / userAgent 参数,Controller 层传入真实 IP。
6. pre-planting-restriction.service.ts / controller
- unlockRestriction 新增 ipAddress / userAgent 参数并写入审计日志。
7. manual-mining.service.ts / controller
- execute 新增 ipAddress / userAgent 参数并写入审计日志。
8. batch-mining.service.ts / controller
- execute 新增 ipAddress / userAgent 参数并写入审计日志
(upload-execute 和 execute 两个入口均已更新)。
【影响范围】
- 仅 mining-admin-service,无数据库 Schema 变更(ipAddress/userAgent 字段已存在)。
- 所有现有接口签名向后兼容(新增参数均为可选)。
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
2026-03-09 22:32:29 -07:00 |
hailin
|
92c71b5e97
|
fix(presence): 在线判定窗口从 3 分钟调整为 5 分钟(行业标准)
心跳间隔 60s 不变,窗口从 180s → 300s(5x 容差),
对网络抖动、Android ROM 限制、WiFi/4G 切换更友好。
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
2026-03-05 21:48:09 -08:00 |
hailin
|
c9217a85a9
|
fix(presence-service): JWT guard 用 sub 兼容旧 token 的 userId/accountSequence
旧 token 只有 sub 字段,新 token 有 userId/accountSequence。
用 payload.userId ?? payload.sub 兼容两种格式,
确保旧 token 心跳能正确写入在线状态。
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
2026-03-05 21:24:12 -08:00 |
hailin
|
a01355aecc
|
fix(presence-service): JWT guard 向后兼容无 type 字段的旧 token
新 token 含 type:'access',旧 token 无 type 字段。
改为:只有 type 字段存在且不为 'access' 时才拒绝,
避免已登录用户因旧 token 格式导致心跳永久 401。
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
2026-03-05 21:16:01 -08:00 |
hailin
|
330f8c7681
|
fix(auth-service): JWT access token 加入 type/userId/accountSequence 字段
presence-service 的 JwtAuthGuard 校验 payload.type === 'access',
但之前 token 只有 sub/phone/source,导致心跳接口一直 401。
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
2026-03-05 21:09:24 -08:00 |
hailin
|
38423e7bf0
|
fix(mining-app): 删除 heartbeat_service 中未声明的 _apiBaseUrl 赋值
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
2026-03-05 20:36:36 -08:00 |
hailin
|
7aa81bc5ab
|
fix(mobile-app): 初始化遥测时传入已登录用户ID,避免session_start丢失userId
从SecureStorage读取已存储的userSerialNum,在TelemetryService初始化时
传入,确保老token登录用户的session事件携带正确的user_id。
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
2026-03-05 20:19:57 -08:00 |
hailin
|
5e6ab25199
|
fix(mining-app): 前台回来时也上传遥测队列(大厂标准做法)
- 进入后台(paused)时立即 flush:session_end + 设备信息不丢失
- 回到前台(resumed)时立即 flush:上传被强杀遗留事件 + 新 session_start
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
2026-03-05 20:07:11 -08:00 |
hailin
|
893513ad78
|
feat(presence): 添加设备档案表,实现事件流水+设备快照分离
大厂标准架构(Amplitude/Mixpanel):
- analytics_event_log: 事件流水(append-only,每条事件一行)
- analytics_device_profile: 设备快照(每台设备一行,upsert 更新)
设备分布查询从 O(events) 降为 O(devices):
- SELECT COUNT(*), device_brand FROM analytics_device_profile GROUP BY device_brand
不再需要 COUNT(DISTINCT install_id) 扫描全量事件表
ON CONFLICT (install_id) DO UPDATE:
- COALESCE 保留已有字段(不被 NULL 覆盖)
- last_seen_at 每次上报更新
- event_count 累加(可用于活跃度分析)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
2026-03-05 19:31:33 -08:00 |
hailin
|
be415c1eb6
|
fix(mobile-app): 前台回来时也上传遥测队列(大厂标准做法)
进入前台时 flush 覆盖两种场景:
1. 上次 paused flush 因网络失败未上传的事件
2. 上次被强杀(force-kill)遗留在本地队列的事件
app_session_start 事件(含设备信息)也在此时立即上传,
无需等待10条阈值或30秒定时器。
参考:Amplitude/Mixpanel 均在 session start 时触发 flush。
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
2026-03-05 19:14:16 -08:00 |
hailin
|
9e90294d0e
|
fix(mobile-app): App进入后台时立即上传遥测队列
问题:TelemetryService.dispose()从未被调用,导致forceUploadAll()
永远不执行;uploadIfNeeded()有10条最小阈值,单次会话只有2-3条
事件无法触发上传,设备信息永远留在本地队列。
修复:进入后台(paused)结束session后,立即调用uploadBatch()
绕过10条阈值,确保每次App切换到后台时都能上报事件。
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
2026-03-05 19:11:25 -08:00 |
hailin
|
2c312a850b
|
fix(2.0): presence-service-2 使用 APP_PORT 指定监听端口
presence-service 的 main.ts 读取 APP_PORT 而非 PORT,
添加 APP_PORT: 3027 确保服务监听在正确端口。
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
2026-03-05 18:53:28 -08:00 |
hailin
|
b06f1272e2
|
feat(deploy): 注册 presence-service-2 到 deploy-mining.sh
- MINING_SERVICES 追加 presence-service-2 (port 3027)
- SERVICE_ALIASES 追加 presence / presence2 快捷名
- MINING_DATABASES 追加 rwa_mining_presence
- SERVICE_DB / SERVICE_PORTS 映射表同步更新
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
2026-03-05 18:46:27 -08:00 |
hailin
|
5eb4afa2f9
|
feat(2.0): 为 2.0 部署独立的 presence-service-2
- 在 docker-compose.2.0.yml 添加 presence-service-2 (port 3027)
- 使用独立数据库 rwa_mining_presence,隔离 2.0 用户 DAU/在线数据
- Redis DB 17(2.0 其他服务已用 8,10,12,13,14,15,16)
- postgres-2 POSTGRES_MULTIPLE_DATABASES 追加 rwa_mining_presence
- 复用 presence-service 代码,与 auth-service 共享 JWT_SECRET
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
2026-03-05 18:39:44 -08:00 |
hailin
|
b9cfa67835
|
docs(telemetry): 补充事件上报格式设计决策(Amplitude 风格顶层设备字段)
新增第三部分说明设备字段为何放顶层而非 JSONB properties:
- 对比 JSONB 与独立列在亿级数据下的查询性能差异
- 说明 toServerJson() 的提取原理(本地存储与服务端格式分离)
- 列出对应的数据库列定义和索引
- 各部分编号顺延
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
2026-03-05 09:52:02 -08:00 |
hailin
|
6bca65e434
|
feat(telemetry): 设备字段提升为顶层结构化列(Amplitude 风格)
将 device_brand/device_model/device_os/app_version/locale 从 JSONB properties
提升为 analytics_event_log 表的独立列,并建立索引,支持亿级数据量下的高效
按设备维度查询和分组统计。
前端 (mining-app + mobile-app):
- toServerJson() 从 properties 中提取设备字段,以顶层字段发送给服务端
- 本地存储格式不变(properties 仍保留设备字段,便于离线队列完整性)
后端 (presence-service):
- Prisma schema: EventLog 新增 deviceBrand/deviceModel/deviceOs/appVersion/locale 列
- Migration: ALTER TABLE 添加 5 列 + 2 个索引
- DTO/Command: EventItemDto 接收顶层设备字段
- Entity: EventLog 新增 5 个字段及 getter
- Mapper: toDomain/toPersistence 映射新字段
- Handler: toEventLog 从 DTO 读取设备字段;SessionStartedEvent 优先使用顶层字段
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
2026-03-05 09:50:48 -08:00 |
hailin
|
482df12f91
|
fix(telemetry): 将设备信息合并到每个事件的 properties 中上报服务端
设备信息(品牌/型号/OS/版本/语言)此前只存储在本地,对服务端分析毫无价值。
现在在 logEvent() 中将 deviceProps 合并到每个事件的 properties 字段,
使服务端 analytics 表能按设备维度进行统计分析。同时修复 _deviceContext 为
null 时的空指针异常(deviceContextId 使用 ?? '' 安全降级)。
适用于 mining-app 和 mobile-app 两端。
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
2026-03-05 09:42:14 -08:00 |
hailin
|
033d1cde42
|
feat(mining-app): 完善 telemetry 埋点 - 页面访问 + 用户行为
- 新增 TelemetryRouteObserver,挂载到 GoRouter 自动追踪全部页面访问
无需每个页面手动调用 logPageView(),覆盖 27 个路由
- user_providers: login_success/login_failed(区分密码/短信)、logout
- trading_page: buy_shares、sell_shares(含价格/数量/结果)、transfer_shares(含方向/金额/结果)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
2026-03-05 09:36:04 -08:00 |
hailin
|
a2a318e24c
|
feat(mining-app): 集成 telemetry 遥测功能
- TelemetryService 添加 _accessToken 字段和 setAccessToken() 方法
- _getAuthHeaders() 现在返回 Bearer token 供心跳上报使用
- splash_page.dart: 启动时初始化 TelemetryService,已登录用户自动注入 userId 和 token
- user_providers.dart: 登录成功后注入 userId/token 并恢复上报;退出时暂停上报并清除 token;token 刷新时同步更新 telemetry token
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
2026-03-05 09:29:06 -08:00 |
hailin
|
34603aac8e
|
fix(security): 修复修改登录密码页面加载失败时静默降级的 bug
与 change_payment_password_page 同款问题:加载失败时原本默默设为
hasPassword=true(注册时必须设置的假设),改为显示错误状态+重试按钮。
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
2026-03-05 09:17:53 -08:00 |
hailin
|
9c84be72bc
|
chore(presence-service): 更新 package-lock.json 以包含 @nestjs/jwt
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
2026-03-05 08:59:34 -08:00 |
hailin
|
e8d9cb72a9
|
feat(presence-service): 修复鉴权——用户JWT验证心跳,管理员JWT查询在线/DAU数据
- 添加 @nestjs/jwt 依赖,AppModule 注册全局 JwtModule
- 重写 JwtAuthGuard:使用 JwtService.verifyAsync 解析用户 token (type=access)
- 新建 AdminGuard:验证管理员 token (type=admin),与 identity-service 共享 JWT_SECRET
- heartbeat 接口:保持 JwtAuthGuard(用户 JWT)
- online-count / online-history / dau:改用 AdminGuard(管理员 JWT)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
2026-03-05 08:52:39 -08:00 |
hailin
|
5df9c97794
|
fix(account): 修复 verifyLoginPassword/verifyPaymentPassword 未读取 TransformInterceptor 包装层的 bug
后端 TransformInterceptor 将所有响应包装为 { success, data: <实际数据> },
但两个 verify 方法直接读 response.data['valid'],导致始终得到 null == true → false,
用户输入正确密码也显示"密码错误"。修复为读取 response.data['data']['valid']。
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
2026-03-05 08:47:17 -08:00 |
hailin
|
405e7e407e
|
fix(security): 修复支付密码页面加载失败时静默降级为设置模式的 bug
加载状态失败时改为显示错误提示和重试按钮,避免误导用户认为未设置支付密码。
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
2026-03-05 08:19:44 -08:00 |
hailin
|
a1d284b6b5
|
fix(password): 统一登录密码和支付密码状态查询为服务端 API
问题:
- isPasswordSet() 读 SecureStorage,重装/换设备后丢失 → 页面误判未设密码
- isPaymentPasswordSet() 读 response.data['isSet'],但实际格式为
{ success, data: { isSet } },取到 null → 始终返回 false
修复:
- 后端新增 GET /user/password-status 接口(isLoginPasswordSet 方法)
- 前端 isPasswordSet() 改为调用服务端 API
- 两个方法均使用正确的 response.data['data']['isSet'] 解包
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
2026-03-05 08:14:24 -08:00 |
hailin
|
728b11c2aa
|
fix(payment-password): 修复 isPaymentPasswordSet 响应解析错误
API 返回 { success: true, data: { isSet: true } },
但代码读的是 response.data['isSet'](顶层),
实际应该读 response.data['data']['isSet'](嵌套在 data 下)。
导致 isSet 永远为 null == true → false,
支付密码页面始终显示「设置」模式而非「修改」模式。
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
2026-03-05 08:12:46 -08:00 |
hailin
|
5752f7b545
|
fix(telemetry): 冷启动会话恢复时注入 access token 到 TelemetryService
checkAuthStatus() 从 SecureStorage 读取 token 后,只设置了 userId
而未调用 setAccessToken,导致 App 冷启动后心跳一直返回 401。
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
2026-03-05 07:43:19 -08:00 |
hailin
|
37b11a3db6
|
feat(telemetry): 接通心跳服务的 JWT 认证,启用实时在线统计
- TelemetryService: 添加 _accessToken 缓存字段,实现 setAccessToken/clearAccessToken
- _getAuthHeaders(): 返回 Bearer token(原为空 {},导致心跳 401)
- AccountService: 3 处登录成功后同步调用 setAccessToken(response.accessToken)
- MultiAccountService: 账号切换后从 SecureStorage 读取恢复的 token 并注入;
账号删除时同步调用 clearAccessToken()
presence-service 后端待部署后,心跳将开始正常工作,实时在线数和 DAU 数据可用。
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
2026-03-05 07:20:05 -08:00 |
hailin
|
3aa2856770
|
fix(payment-password): 修复 isActive 字段名错误(应为 status !== ACTIVE)
Prisma schema 中 UserAccount 无 isActive 字段,实际为 status VARCHAR(20)。
两处 select 改为 { phoneNumber, status },检查改为 status !== 'ACTIVE'。
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
2026-03-05 07:05:42 -08:00 |
hailin
|
6f912b1232
|
feat(payment-password): 添加忘记支付密码功能(全栈)
后端(identity-service,纯新增):
- user-application.service 添加 2 个方法:
sendResetPaymentPasswordSmsCode(userId) —— 发送验证码到已绑定手机(Redis key 独立)
resetPaymentPassword(userId, smsCode, newPassword) —— 验证码校验 + 格式校验 + bcrypt 更新
- user-account.controller 新增 2 个端点(均为 @ApiBearerAuth):
POST /user/send-reset-payment-password-sms
POST /user/reset-payment-password
前端(mobile-app,纯新增):
- account_service 新增 sendResetPaymentPasswordSmsCode / resetPaymentPassword 两个方法
- 新建 reset_payment_password_page.dart:验证码 + 新6位PIN,重置成功后自动返回
- 路由:RoutePaths / RouteNames / AppRouter 各新增 resetPaymentPassword 条目
- change_payment_password_page:旧密码输入框下方添加「忘记支付密码?」入口链接
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
2026-03-05 07:04:20 -08:00 |
hailin
|
71774f301d
|
fix(payment-password): 优化未设置支付密码时的错误提示
- 识别后端"尚未设置支付密码"异常,显示明确引导语
"请先前往「我的」→「支付密码」完成设置",替代误导性的"请检查网络"
- 简化空输入提示逻辑(直接使用 widget.hint)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
2026-03-05 06:21:25 -08:00 |
hailin
|
cad7ebe832
|
feat(payment-password): 添加支付密码功能(全栈)
后端(identity-service):
- Prisma schema 新增 paymentPasswordHash 字段及手动迁移脚本
- user-application.service 添加 4 个方法:isPaymentPasswordSet / setPaymentPassword /
changePaymentPassword / verifyPaymentPassword(纯新增,不修改已有逻辑)
- user-account.controller 新增 4 个端点:
GET /user/payment-password-status
POST /user/set-payment-password
POST /user/change-payment-password
POST /user/verify-payment-password → { valid: bool }
前端(mobile-app):
- account_service 新增 4 个方法对应后端 4 个接口
- 新建 change_payment_password_page.dart:6 位数字支付密码设置/修改页面
- 路由:RoutePaths / RouteNames / AppRouter 注册 /security/payment-password
- profile_page:'修改登录密码' 改为 '修改密码',下方新增 '支付密码' 入口
- PasswordVerifyDialog:新增 title / subtitle / hint 可选参数,支持登录/支付双模式
- planting_location_page:认种确认改为验证支付密码(verifyPaymentPassword)
- pre_planting_purchase_page:预种确认后追加支付密码验证步骤
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
2026-03-05 06:18:40 -08:00 |
hailin
|
d91ff7b83a
|
docs(mobile-app): 完善认种密码校验相关代码注释
- PasswordVerifyDialog: 补充类级文档、onVerify 字段说明、_handleConfirm 流程注释
- account_service.verifyLoginPassword: 补充参数、响应格式、行为说明
- planting_location_page._verifyPasswordThenSubmit: 说明在认种流程中的插入位置与作用
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
2026-03-05 05:55:07 -08:00 |
hailin
|
3a84315b64
|
fix(mobile-app): verifyLoginPassword 读取响应体 valid 字段
后端 POST /user/verify-password 返回 { valid: bool },不用 HTTP 状态码区分,
修正响应解析逻辑。
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
2026-03-05 05:53:16 -08:00 |
hailin
|
41fa6349bd
|
feat(mobile-app): 认种确认前新增登录密码校验弹窗
- 新增 PasswordVerifyDialog 弹窗,风格与主体 App 一致
- account_service 新增 verifyLoginPassword() 调用 POST /user/verify-password
- planting_location_page 在 PlantingConfirmDialog 确认后插入密码校验步骤
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
2026-03-05 05:51:47 -08:00 |
hailin
|
8de92f2511
|
fix(mining-app): 已解锁上 null 时显示 0
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
2026-03-05 05:41:00 -08:00 |
hailin
|
98c898769f
|
fix(mining-app): 已解锁上层数 = unlockedBonusTiers × 5
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
2026-03-05 05:40:00 -08:00 |
hailin
|
353299fd75
|
fix(mining-app): 已解锁上层数改为动态数据,替换硬编码的 15
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
2026-03-05 05:13:10 -08:00 |
hailin
|
b67dfa0f4c
|
fix(planting-service+app): 合并列表补充 totalPortions,前端显示实际份数而非订单数
- getMerges 批量查来源订单 portionCount,按合并分组求和后返回 totalPortions
- 预种明细合并卡片改用 totalPortions 显示份数,fallback 才用订单数
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
2026-03-04 08:58:45 -08:00 |
hailin
|
1f5bb62805
|
fix(contribution-service): 合并完成后写入 synced_adoptions 记录以解除卖出限制
swapContributionForMerge 在事务内新增步骤 9f:
- 写入 synced_adoptions(original_adoption_id = 20B + mergeId)
- 供 SellRestrictionService.isRestricted 的 has_real_tree 判断使用
- upsert 保证幂等,contributionDistributed 由调用方置 true
Bug: 合并已完成(contribution_records 正确),但 isRestricted 始终
返回 true,因为 synced_adoptions 中没有 20B+ 记录(virtualAdoption
仅用于计算,未持久化)。
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
2026-03-04 08:25:15 -08:00 |