浅念
|
c2143e1f94
|
feat(app): album banner picker in edit form — show current banner, pick & upload on save
- api_client:uploadAlbumAssetFromFile 泛化(cover 为薄壳)+ fetchAlbumAssetUrl
(GET /albums/{id}/assets → 指定 kind 全局行 URL)
- 编辑页 Details:封面下方新增「宣传图」3:1 选择器——编辑模式异步加载现有
banner 预览(失败静默);保存成功后上传(同封面:失败不阻塞表单结果)
- 未保存变更判断纳入 banner;l10n zh/en
- 测试适配:编辑用例 pumpForm 后清空 banner 现状预检请求(397/397 全绿)
Co-Authored-By: Claude Code <noreply@anthropic.com>
|
2026-09-23 11:07:54 +08:00 |
|
浅念
|
8e674a902e
|
feat(albums): soft-delete albums (admin+owner, hidden & irreversible, both app entries)
契约 deleteAlbum(DELETE /albums/{albumId} → 204 幂等)+ status enum 'deleted':
- 服务端:softDelete(canView 404→canManage 403 防枚举;乐观锁 claim +
outbox album.updated priority=high + audit album.delete);列表/详情/更新/
成员/资产/分类/水印/照片/展示位绑定全部 deleted→404;公开端 cn
(status!=='active')与 ov(isAlbumVisibleOv)天然屏蔽;ov 副本经
album.updated 载荷 status 直投自动下线
- Admin:列表表格操作「删除」+ 详情页头「删除相册」(确认含不可恢复说明)
- App:操作面板「删除相册」(红字、二次确认、成功退回列表并刷新)
- 验证:API 56/56、App 397/397(analyze 0)、admin typecheck/lint/test/build 绿
Co-Authored-By: Claude Code <noreply@anthropic.com>
|
2026-09-23 10:13:08 +08:00 |
|
浅念
|
b353a3de06
|
fix(viewer): replace text arrow share icon with SVG share glyph
Co-Authored-By: Claude Code <noreply@anthropic.com>
|
2026-09-22 13:55:37 +08:00 |
|
浅念
|
f6929ae18f
|
feat(mobile): UI-01 album cards, photo grid and full viewer
Co-Authored-By: Claude Code <noreply@anthropic.com>
|
2026-09-21 15:55:44 +08:00 |
|
浅念
|
8be21b856b
|
feat(mobile): login, password change and logout screens
P3 Task 3 移动端(对接 Task 2 api client + 本任务新增的后端契约):
- 登录页实装:账号/密码表单(空值客户端校验)→ api.login(会话自动
持久化)→ pushReplacement /home;错误码本地化(AUTH_INVALID_
CREDENTIALS / AUTH_RATE_LIMITED(含稍后再试文案)/ 网络 / 校验);
提交加载态防重复提交。
- 修改密码页(设置页入口):当前/新/确认三字段,客户端校验(≥8 位、
两次一致)→ api.changePassword → toast + pop;成功后本地会话不变
(服务端保留当前会话);旧密码错误(401 AUTH_INVALID_CREDENTIALS)
显示「当前密码错误」且不触发 401 驱逐。
- 退出登录:设置页按钮 → api.logout 尽力而为 → 清会话 → 清栈回
/login;App 壳 initState 注册 onUnauthorized(业务 401 → 清栈 /login),
根 navigatorKey 接线;password-change 的 401 豁免会话驱逐(拦截器
豁免集合与令牌附加分离)。
- l10n:新增 16 组 zh/en 文案;错误码 → 文案解析扩展
(core/error_l10n.dart,errorCode→AppLocalizations)。
- 测试:ApiClient.changePassword 单测 ×2(Bearer+请求体;旧密码 401
不驱逐);widget 测试 ×12(登录 5:空值/成功跳转/凭据错误/限速文案/
加载禁用;改密 4:过短/不一致/旧密码错误文案+会话保留/成功 toast+pop
且令牌不变;设置 2:改密入口跳转/登出清会话回登录;App 壳 1:401
清栈回 /login)。flutter analyze 0 issue;flutter test 81/81。
Co-Authored-By: Claude Code <noreply@anthropic.com>
|
2026-09-19 01:19:57 +08:00 |
|
浅念
|
f975321b67
|
feat(mobile): api client, session storage and contract-aligned models
P3 计划 Task 2(apps/mobile):
- core/config.dart:API_BASE/VIEWER_BASE 经 --dart-define 覆盖,缺省
10.0.2.2 模拟器宿主回环;viewer 相册链接构造 {VIEWER_BASE}/a/{token}。
- core/error_codes.dart:errors.ts 17 码 1:1 镜像(含注释),另设 4 个
客户端本地伪码(NETWORK_ERROR/NETWORK_TIMEOUT/CANCELLED/HTTP_ERROR)。
- core/api_client.dart:dio 封装——Bearer 注入(登录端点豁免)、401
驱逐(清会话 + onUnauthorized 回调去重,App 壳注册跳 /login)、
DioException/错误体 {code,message,requestId} 归一 AppException、
通用游标分页助手;auth/albums/members/categories/admin/uploads/photos
全端点方法;riverpod provider 出口。
- core/session_store.dart:SessionStore 抽象 + flutter_secure_storage
实现(token/expiresAt/account 三键,encode/decode 纯函数可测)。
- features/{auth,albums,uploads,photos}/models.dart:手写 fromJson/
toJson,逐字段对齐 openapi.yaml(类注释标注契约 schema/operationId);
locale 按字符串透传(zh-CN 标识符不兼容),业务枚举 Dart 化并在
未知值 fail-fast。
- 测试 66 项:17 码表驱动 + 网络/超时/取消 + 兜底映射、游标边界
(含 CursorPageMeta 不变式违约容错)、模型往返(fixture 转写自
openapi.yaml schema 与 api e2e 断言,来源在测试头注释)、拦截器
行为(手写 FakeAdapter:Bearer 注入/401 驱逐/登录豁免/并发去重/
尽力而为 logout/refresh 滑动续期)。flutter analyze 零告警。
Co-Authored-By: Claude Code <noreply@anthropic.com>
|
2026-09-19 00:40:02 +08:00 |
|