fix(viewer): replace text arrow share icon with SVG share glyph
Co-Authored-By: Claude Code <noreply@anthropic.com>
@@ -0,0 +1 @@
|
||||
<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover"><title>PhotoLive · Login</title><link rel="stylesheet" href="styles.css"></head><body data-page="1"><main id="app" class="app"></main><script src="app.js"></script></body></html>
|
||||
@@ -0,0 +1 @@
|
||||
<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover"><title>PhotoLive · Settings</title><link rel="stylesheet" href="styles.css"></head><body data-page="2"><main id="app" class="app"></main><script src="app.js"></script></body></html>
|
||||
@@ -0,0 +1 @@
|
||||
<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover"><title>PhotoLive · Change password</title><link rel="stylesheet" href="styles.css"></head><body data-page="3"><main id="app" class="app"></main><script src="app.js"></script></body></html>
|
||||
@@ -0,0 +1 @@
|
||||
<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover"><title>PhotoLive · App language</title><link rel="stylesheet" href="styles.css"></head><body data-page="4"><main id="app" class="app"></main><script src="app.js"></script></body></html>
|
||||
@@ -0,0 +1 @@
|
||||
<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover"><title>PhotoLive · Albums</title><link rel="stylesheet" href="styles.css"></head><body data-page="5"><main id="app" class="app"></main><script src="app.js"></script></body></html>
|
||||
@@ -0,0 +1 @@
|
||||
<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover"><title>PhotoLive · Album overview</title><link rel="stylesheet" href="styles.css"></head><body data-page="6"><main id="app" class="app"></main><script src="app.js"></script></body></html>
|
||||
@@ -0,0 +1 @@
|
||||
<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover"><title>PhotoLive · Album actions</title><link rel="stylesheet" href="styles.css"></head><body data-page="7"><main id="app" class="app"></main><script src="app.js"></script></body></html>
|
||||
@@ -0,0 +1 @@
|
||||
<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover"><title>PhotoLive · Empty album</title><link rel="stylesheet" href="styles.css"></head><body data-page="8"><main id="app" class="app"></main><script src="app.js"></script></body></html>
|
||||
@@ -0,0 +1 @@
|
||||
<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover"><title>PhotoLive · New album</title><link rel="stylesheet" href="styles.css"></head><body data-page="9"><main id="app" class="app"></main><script src="app.js"></script></body></html>
|
||||
@@ -0,0 +1 @@
|
||||
<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover"><title>PhotoLive · Edit album</title><link rel="stylesheet" href="styles.css"></head><body data-page="10"><main id="app" class="app"></main><script src="app.js"></script></body></html>
|
||||
@@ -0,0 +1 @@
|
||||
<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover"><title>PhotoLive · Members</title><link rel="stylesheet" href="styles.css"></head><body data-page="11"><main id="app" class="app"></main><script src="app.js"></script></body></html>
|
||||
@@ -0,0 +1 @@
|
||||
<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover"><title>PhotoLive · Categories</title><link rel="stylesheet" href="styles.css"></head><body data-page="12"><main id="app" class="app"></main><script src="app.js"></script></body></html>
|
||||
@@ -0,0 +1 @@
|
||||
<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover"><title>PhotoLive · Camera</title><link rel="stylesheet" href="styles.css"></head><body data-page="13"><main id="app" class="app"></main><script src="app.js"></script></body></html>
|
||||
@@ -0,0 +1 @@
|
||||
<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover"><title>PhotoLive · Uploads</title><link rel="stylesheet" href="styles.css"></head><body data-page="14"><main id="app" class="app"></main><script src="app.js"></script></body></html>
|
||||
@@ -0,0 +1 @@
|
||||
<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover"><title>PhotoLive · Needs attention</title><link rel="stylesheet" href="styles.css"></head><body data-page="15"><main id="app" class="app"></main><script src="app.js"></script></body></html>
|
||||
@@ -0,0 +1 @@
|
||||
<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover"><title>PhotoLive · Upload history</title><link rel="stylesheet" href="styles.css"></head><body data-page="16"><main id="app" class="app"></main><script src="app.js"></script></body></html>
|
||||
@@ -0,0 +1 @@
|
||||
<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover"><title>PhotoLive · Manage photos</title><link rel="stylesheet" href="styles.css"></head><body data-page="17"><main id="app" class="app"></main><script src="app.js"></script></body></html>
|
||||
@@ -0,0 +1 @@
|
||||
<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover"><title>PhotoLive · Photo details</title><link rel="stylesheet" href="styles.css"></head><body data-page="18"><main id="app" class="app"></main><script src="app.js"></script></body></html>
|
||||
@@ -0,0 +1 @@
|
||||
<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover"><title>PhotoLive · Share album</title><link rel="stylesheet" href="styles.css"></head><body data-page="19"><main id="app" class="app"></main><script src="app.js"></script></body></html>
|
||||
@@ -0,0 +1 @@
|
||||
<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover"><title>PhotoLive · Hide photo</title><link rel="stylesheet" href="styles.css"></head><body data-page="20"><main id="app" class="app"></main><script src="app.js"></script></body></html>
|
||||
@@ -0,0 +1,72 @@
|
||||
# PhotoLive App 全页面 HTML 交互原型
|
||||
|
||||
日期:2026-09-22。打开 **index.html** 查看页面目录和交互预览,点击“全部页面总览”查看全部20页的实际渲染截图。也可以直接打开 `01-login.html` 等独立入口。无须启动服务、安装依赖或访问网络。
|
||||
|
||||
## 设计依据
|
||||
|
||||
- `../../plans/2026-09-21-UI03-App全页面新版效果图落地实施方案.md`
|
||||
- `../../plans/2026-09-22-UI03R-App高保真还原完整实施方案.md`
|
||||
- `../app-redesign-2026-09-21/` 下五张设计板。
|
||||
|
||||
本目录为独立 HTML 设计原型,未修改 Flutter、API、观众页或嵌入组件业务代码。各页面是 HTML/CSS 控件,不是把整张设计板作为界面。摄影素材通过 CSS 显示已有生成设计图中的摄影区域,来源为本项目 `viewer-mobile-concept-2026-09-21.png`;`assets/reference.png` 为离线副本。摄影主题接近参考图,但并非五张板中的每张原始照片;低分辨率局部素材仅用于预览,不作为生产图片素材。
|
||||
|
||||
## 页面清单
|
||||
|
||||
| 编号 | 独立文件 | 内容 |
|
||||
|---|---|---|
|
||||
| 01 | 01-login.html | 摄影拼贴、示例账号登录 |
|
||||
| 02 | 02-settings.html | 账号摘要、设置、退出 |
|
||||
| 03 | 03-password.html | 密码校验演示 |
|
||||
| 04 | 04-language.html | 语言选择与 Done 提交 |
|
||||
| 05 | 05-albums.html | 三张摄影封面相册卡 |
|
||||
| 06 | 06-album-detail.html | 相册详情、九宫格、拍摄/选图 |
|
||||
| 07 | 07-album-actions.html | 相册操作面板 |
|
||||
| 08 | 08-empty-album.html | 空相册与上传入口 |
|
||||
| 09 | 09-create-album.html | 创建表单、日期、时区、地点、语言 |
|
||||
| 10 | 10-edit-album.html | 详情/权限页签,草稿统一保存 |
|
||||
| 11 | 11-members.html | 所有者、协作者、内部账号选择 |
|
||||
| 12 | 12-categories.html | 分类列表、新建与编辑面板 |
|
||||
| 13 | 13-camera.html | 深色相机取景演示、模拟入队 |
|
||||
| 14 | 14-uploads.html | 本机摘要、进度与状态 |
|
||||
| 15 | 15-upload-errors.html | 可重试与需重新选择的异常任务 |
|
||||
| 16 | 16-upload-history.html | 服务端跨设备历史示例 |
|
||||
| 17 | 17-photos.html | 三列照片网格与公开/隐藏筛选 |
|
||||
| 18 | 18-photo-detail.html | 管理大图、元信息、隐藏/删除 |
|
||||
| 19 | 19-share.html | 分享卡、演示二维码、预览链接 |
|
||||
| 20 | 20-hide-photo.html | 隐藏确认面板 |
|
||||
|
||||
## 可操作的演示路径
|
||||
|
||||
1. 登录(不用真实密码)→相册→详情→拍摄→快门模拟入队→上传中心。
|
||||
2. 相册详情→更多→编辑→切换 Details/Access→保存,预览会话中的标题/权限更新。
|
||||
3. 成员→邀请同事→搜索示例内部账号→添加;成员菜单可模拟移除。
|
||||
4. 分类→填写名称→保存;点击分类铅笔编辑。
|
||||
5. 照片网格→大图→隐藏→确认→Hidden 筛选;大图可重新公开及模拟删除。
|
||||
6. 设置→语言→选择 English/中文/跟随系统→Done。关闭面板不提交选择。
|
||||
7. 上传→Needs attention→重试;不可恢复的源文件项进入示例选图面板。
|
||||
8. 分享→打开此前的观众页原型,或复制本地文件预览地址。
|
||||
|
||||
状态仅保存在当前文档内存,刷新/从目录重新打开某页会恢复示例。直接在预览内跳转保留当前会话变更。账号密码不发送、不持久化;请勿输入真实凭证。
|
||||
|
||||
## 边界说明
|
||||
|
||||
- 相机是示例图片,快门仅增加示例队列数;不请求设备摄像头权限。
|
||||
- 上传进度、服务端记录、账号、角色与时间为视觉样本,不接入 OSS/网络/原生后台上传。
|
||||
- 浏览器HTML不能验证 Flutter 的系统相机、后台/锁屏、原生手势、iOS/Android 安全区或性能。
|
||||
- 二维码是真实编码的演示 URL `https://example.com/photolive-preview`,不是公开相册,不能用于活动分发。正式 QR 必须由真实公开相册链接生成。
|
||||
- 分享中的“打开观众页预览”依赖本目录上一层 `viewer-preview-2026-09-22.html`;单独搬运本目录时,App 本身可离线打开,但此跨原型链接会失效。
|
||||
- 所有管理写操作仅在原型内模拟,不构成权限、接口或生产功能验收。
|
||||
- 参考板是英文浅色,本套以该基准制作;中文可切换,未提供全套系统深色主题、双指缩放和原生键盘还原。
|
||||
|
||||
## 文件结构
|
||||
|
||||
- `index.html`:目录、固定尺寸预览、截图总览。
|
||||
- `01-*.html` 至 `20-*.html`:20个独立页面入口。
|
||||
- `app.js` / `styles.css`:公共界面和交互实现。
|
||||
- `pages.js`:页面索引。
|
||||
- `assets/`:离线摄影素材与演示二维码。
|
||||
- `screenshots/`:实际 HTML 渲染截图。
|
||||
- `validation.json`:自动检查结果,不能替代原生 App 验收。
|
||||
- `build-preview.cjs`:本仓库环境中重新生成入口与二维码;浏览原型无需运行。
|
||||
|
||||
在本目录使用 `node build-preview.cjs` 可以重新生成入口,所需 qrcode 使用仓库已有依赖。不要通过此脚本修改原生 App 或线上配置。
|
||||
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 33 33" shape-rendering="crispEdges"><path fill="#ffffff" d="M0 0h33v33H0z"/><path stroke="#172033" d="M2 2.5h7m2 0h4m1 0h1m1 0h5m1 0h7M2 3.5h1m5 0h1m2 0h3m1 0h5m4 0h1m5 0h1M2 4.5h1m1 0h3m1 0h1m1 0h3m3 0h3m5 0h1m1 0h3m1 0h1M2 5.5h1m1 0h3m1 0h1m1 0h5m2 0h1m1 0h1m1 0h1m2 0h1m1 0h3m1 0h1M2 6.5h1m1 0h3m1 0h1m1 0h2m3 0h1m2 0h1m2 0h2m1 0h1m1 0h3m1 0h1M2 7.5h1m5 0h1m1 0h1m1 0h1m2 0h4m5 0h1m5 0h1M2 8.5h7m1 0h1m1 0h1m1 0h1m1 0h1m1 0h1m1 0h1m1 0h1m1 0h7M10 9.5h2m1 0h1m1 0h1m1 0h1m2 0h1M2 10.5h1m1 0h5m2 0h1m1 0h1m2 0h1m2 0h1m2 0h1m1 0h5M3 11.5h1m5 0h2m3 0h1m3 0h5m1 0h3m3 0h1M4 12.5h3m1 0h2m2 0h2m3 0h1m1 0h1m2 0h2m1 0h2M2 13.5h5m2 0h1m1 0h1m4 0h1m1 0h1m2 0h3m1 0h1m1 0h1m1 0h1M2 14.5h1m2 0h1m2 0h1m1 0h1m6 0h3m1 0h1m5 0h2M2 15.5h2m3 0h1m1 0h1m1 0h2m2 0h2m1 0h4m1 0h4m3 0h1M3 16.5h3m1 0h2m1 0h2m3 0h4m3 0h1m1 0h5M6 17.5h2m1 0h1m2 0h1m2 0h1m1 0h2m1 0h1m1 0h2m2 0h1m2 0h1M2 18.5h2m2 0h1m1 0h5m1 0h1m1 0h2m1 0h1m1 0h1m5 0h2M2 19.5h1m1 0h1m1 0h2m1 0h1m1 0h4m3 0h9m1 0h1m1 0h1M2 20.5h1m1 0h1m2 0h2m8 0h1m2 0h1m1 0h1m3 0h1m1 0h1M2 21.5h1m1 0h1m6 0h2m1 0h1m1 0h1m4 0h2m6 0h1M2 22.5h1m2 0h4m3 0h2m3 0h3m1 0h6m1 0h3M10 23.5h2m1 0h1m1 0h2m1 0h1m3 0h1m3 0h5M2 24.5h7m3 0h6m1 0h1m1 0h2m1 0h1m1 0h3M2 25.5h1m5 0h1m1 0h1m1 0h2m1 0h1m1 0h1m2 0h3m3 0h1M2 26.5h1m1 0h3m1 0h1m1 0h5m1 0h4m2 0h5m1 0h1M2 27.5h1m1 0h3m1 0h1m1 0h3m1 0h2m2 0h1m1 0h4m1 0h1m1 0h4M2 28.5h1m1 0h3m1 0h1m1 0h1m1 0h4m1 0h2m4 0h7M2 29.5h1m5 0h1m2 0h2m3 0h3m3 0h1m1 0h4m1 0h1M2 30.5h7m1 0h3m1 0h2m3 0h3m1 0h4m1 0h1"/></svg>
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 1.7 MiB |
@@ -0,0 +1,10 @@
|
||||
const fs=require('fs'),path=require('path');
|
||||
const root=__dirname;
|
||||
const pages=[['login','登录','Login'],['settings','设置','Settings'],['password','修改密码','Change password'],['language','语言选择','App language'],['albums','相册列表','Albums'],['album-detail','相册详情','Album overview'],['album-actions','相册操作','Album actions'],['empty-album','空相册','Empty album'],['create-album','创建相册','New album'],['edit-album','编辑相册','Edit album'],['members','协作成员','Members'],['categories','分类管理','Categories'],['camera','拍摄','Camera'],['uploads','上传中心','Uploads'],['upload-errors','异常任务','Needs attention'],['upload-history','上传历史','Upload history'],['photos','照片管理','Manage photos'],['photo-detail','管理大图','Photo details'],['share','相册分享','Share album'],['hide-photo','隐藏确认','Hide photo']].map(([slug,zh,en],i)=>({id:i+1,file:`${String(i+1).padStart(2,'0')}-${slug}.html`,zh,en}));
|
||||
fs.mkdirSync(path.join(root,'assets'),{recursive:true});
|
||||
fs.copyFileSync(path.join(root,'../viewer-mobile-concept-2026-09-21.png'),path.join(root,'assets/reference.png'));
|
||||
for(const page of pages)fs.writeFileSync(path.join(root,page.file),`<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover"><title>PhotoLive · ${page.en}</title><link rel="stylesheet" href="styles.css"></head><body data-page="${page.id}"><main id="app" class="app"></main><script src="app.js"></script></body></html>`);
|
||||
fs.writeFileSync(path.join(root,'pages.js'),'window.PREVIEW_PAGES='+JSON.stringify(pages,null,2)+';');
|
||||
const QR=require(require.resolve('qrcode',{paths:[path.resolve(root,'../../../apps/admin')]}));
|
||||
QR.toString('https://example.com/photolive-preview',{type:'svg',margin:2,color:{dark:'#172033',light:'#ffffff'}},(err,svg)=>{if(err)throw err;fs.writeFileSync(path.join(root,'assets/demo-qr.svg'),svg)});
|
||||
console.log('Generated 20 page entry points and offline assets.');
|
||||
@@ -0,0 +1,10 @@
|
||||
<!doctype html><html lang="zh-CN"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>PhotoLive · App 全页面交互预览</title><style>
|
||||
*{box-sizing:border-box}body{margin:0;background:#edf1f7;color:#172033;font:14px/1.5 system-ui,-apple-system,'Segoe UI','PingFang SC',sans-serif}button,select{font:inherit}button{cursor:pointer}header{height:76px;background:#ffffffdd;border-bottom:1px solid #dfe6ef;display:flex;align-items:center;justify-content:space-between;padding:0 32px;gap:16px}.brand{font-size:23px;font-weight:750;letter-spacing:-.7px}.brand span{color:#1a73e8}header p{margin:2px 0 0;font-size:11px;color:#7b8ca3}.header-tools{display:flex;gap:8px}button,select,.open{border:1px solid #d8e1ed;border-radius:8px;background:white;padding:9px 12px;color:#45617e;text-decoration:none;font-size:12px}.workspace{display:flex;min-height:calc(100vh - 76px)}aside{width:248px;flex:none;padding:24px 16px;background:#f8fafd;border-right:1px solid #dfe6ef}aside h2{font-size:10px;font-weight:600;color:#8a9bb1;letter-spacing:1.5px;margin:22px 12px 8px}aside h2:first-child{margin-top:0}.page-link{width:100%;border:0;background:transparent;display:flex;gap:12px;align-items:center;border-radius:8px;text-align:left;padding:10px 12px;line-height:1.3;font-size:12px}.page-link.active{background:#e2edff;color:#1a73e8}.page-link .num{font-size:11px;color:#91a2ba;font-variant-numeric:tabular-nums}.page-link small{display:block;font-size:10px;color:#98a4b5;margin-top:3px}.main{flex:1;min-width:0;padding:26px 28px 36px}.presentation{display:flex;gap:36px;justify-content:center;align-items:flex-start}.phone-column{width:390px;flex:none}.caption{display:flex;justify-content:space-between;align-items:center;color:#60718a;font-size:12px;margin-bottom:12px}.screen{width:100%;height:844px;background:white;border:1px solid #d9e2ed;border-radius:22px;overflow:hidden;box-shadow:0 20px 60px #2b426b17}iframe{width:100%;height:100%;border:0;background:#f6f8fb;display:block}.notes{max-width:230px;padding-top:50px}.notes .eyebrow{font-size:10px;color:#1a73e8;letter-spacing:2px}.notes h1{font-size:28px;margin:12px 0;line-height:1.3;letter-spacing:-.7px}.notes p{font-size:12px;color:#7c8aa0;line-height:1.9}.notes .chips{display:flex;gap:7px;flex-wrap:wrap;margin:20px 0}.chips span{background:#fff9;border:1px solid #dce4ee;padding:5px 9px;font-size:10px;border-radius:6px;color:#6480a1}.pager{display:flex;gap:8px;margin-top:20px}.pager button{flex:1}.gallery{display:grid;grid-template-columns:repeat(auto-fill,minmax(230px,1fr));gap:28px}.gallery a{color:#354b69;text-decoration:none;font-size:12px}.gallery img{display:block;width:100%;margin-top:10px;border-radius:14px;border:1px solid #d7e1ef;box-shadow:0 8px 24px #22395912}.mobile-select{display:none}.footer-note{margin-top:14px;color:#95a1b3;font-size:10px;text-align:center}[hidden]{display:none!important}@media(max-width:1100px){.notes{display:none}.main{padding:24px 18px}}@media(max-width:740px){header{height:auto;min-height:74px;padding:12px 16px;flex-wrap:wrap}.brand{font-size:20px}.header-tools button{display:none}aside{display:none}.main{padding:14px 0 0}.mobile-select{display:block;margin:0 12px 12px;width:calc(100% - 24px)}.phone-column{width:100%!important;max-width:430px}.caption{padding:0 14px}.screen{border-radius:0;border-left:0;border-right:0;box-shadow:none;height:calc(100dvh - 180px);min-height:568px}.footer-note{padding:0 16px 12px}.gallery{padding:0 16px;grid-template-columns:repeat(2,minmax(0,1fr));gap:15px}}
|
||||
</style></head><body><header><div><div class="brand"><span>◈</span> PhotoLive <span style="font-weight:400;color:#97a4b7;font-size:13px;letter-spacing:0;margin-left:12px">APP DESIGN PREVIEW</span></div><p>20 个页面与关键状态 · 可交互 HTML 原型 · 离线可用</p></div><div class="header-tools"><button id="overview">全部页面总览</button><select id="width" aria-label="Preview width"><option value="390">390 × 844</option><option value="320">320 × 568</option><option value="430">430 × 932</option></select><a class="open" id="standalone" target="_blank" rel="noopener">独立打开 ↗</a></div></header><div class="workspace"><aside id="nav"></aside><main class="main"><select class="mobile-select" id="mobilePages" aria-label="选择页面"></select><div class="presentation" id="presentation"><div class="phone-column" id="column"><div class="caption"><span id="caption"></span><span id="sizeLabel">390 × 844</span></div><div class="screen" id="screen"><iframe id="preview" title="PhotoLive App 交互预览" src="05-albums.html"></iframe></div><div class="footer-note">演示账号与样例数据 · 未连接相机、OSS 或生产服务</div></div><div class="notes"><div class="eyebrow">UI–03 / INTERACTIVE PROTOTYPE</div><h1 id="pageTitle"></h1><p id="pageDesc"></p><div class="chips"><span>真实 HTML 组件</span><span>中英文</span><span>可点击跳转</span><span>本地摄影素材</span></div><p>在左侧选择页面,或直接在原型内操作。登录页与设置页可切换语言。相机、上传、成员和权限修改均为当前预览会话的模拟状态。</p><p>分享页二维码为演示码,指向 example.com;“打开观众页预览”可连接此前生成的观众页文件。</p><div class="pager"><button id="previous">← 上一页</button><button id="next">下一页 →</button></div></div></div><div class="gallery" id="gallery" hidden></div></main></div><script src="pages.js"></script><script>
|
||||
const pages=window.PREVIEW_PAGES,$=s=>document.querySelector(s);let selected=5,overview=false;const groups=['ACCOUNT & SETTINGS','ALBUM WORKSPACE','CREATE & COLLABORATE','CAPTURE & UPLOAD','PHOTOS & SHARING'];const descriptions=['摄影拼贴、企业账号登录、设置和语言选择。没有自行注册或飞书入口。','照片主导的相册工作台。详情包含拍摄、选图、成员、分类、分享入口及空态。','统一分组表单、权限草稿、内部成员邀请和双语分类编辑。','深色拍摄界面、本机上传队列、异常处理与独立的服务端历史。','三列照片管理、深色管理大图、相册分享及隐藏确认。'];
|
||||
pages.forEach((p,i)=>{if(i%4===0)$('#nav').insertAdjacentHTML('beforeend','<h2>'+groups[Math.floor(i/4)]+'</h2>');const b=document.createElement('button');b.className='page-link';b.dataset.id=p.id;b.innerHTML='<span class="num">'+String(p.id).padStart(2,'0')+'</span><span>'+p.zh+'<small>'+p.en+'</small></span>';b.onclick=()=>select(p.id);$('#nav').append(b);const opt=new Option(String(p.id).padStart(2,'0')+' · '+p.zh,p.id);$('#mobilePages').append(opt);const a=document.createElement('a');a.href=p.file;a.innerHTML=String(p.id).padStart(2,'0')+' / '+p.zh+'<img loading="lazy" src="screenshots/'+String(p.id).padStart(2,'0')+'.png" alt="'+p.zh+'截图">';a.onclick=e=>{e.preventDefault();select(p.id)};$('#gallery').append(a)});
|
||||
function labels(){const p=pages[selected-1];document.querySelectorAll('.page-link').forEach(b=>b.classList.toggle('active',+b.dataset.id===selected));$('#caption').textContent=String(selected).padStart(2,'0')+' / '+p.en;$('#pageTitle').textContent=p.zh;$('#pageDesc').textContent=descriptions[Math.floor((selected-1)/4)];$('#mobilePages').value=selected;$('#standalone').href=p.file;history.replaceState(null,'','#'+selected)}
|
||||
function showOverview(value){overview=value;$('#gallery').hidden=!value;$('#presentation').hidden=value;$('#overview').textContent=value?'返回交互预览':'全部页面总览'}
|
||||
function select(id){selected=Math.max(1,Math.min(20,Number(id)));showOverview(false);$('#preview').src=pages[selected-1].file;labels()}
|
||||
$('#previous').onclick=()=>select(selected===1?20:selected-1);$('#next').onclick=()=>select(selected===20?1:selected+1);$('#mobilePages').onchange=e=>select(e.target.value);$('#overview').onclick=()=>showOverview(!overview);$('#width').onchange=e=>{const w=+e.target.value,h=w===320?568:w===430?932:844;$('#column').style.width=w+'px';$('#screen').style.height=h+'px';$('#sizeLabel').textContent=w+' × '+h};window.addEventListener('message',e=>{if(e.source!==$('#preview').contentWindow||e.data?.type!=='photolive-preview-page'||!Number.isInteger(e.data.page)||e.data.page<1||e.data.page>20)return;selected=e.data.page;labels()});select(Number(location.hash.slice(1))||5);
|
||||
</script></body></html>
|
||||
@@ -0,0 +1,122 @@
|
||||
window.PREVIEW_PAGES=[
|
||||
{
|
||||
"id": 1,
|
||||
"file": "01-login.html",
|
||||
"zh": "登录",
|
||||
"en": "Login"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"file": "02-settings.html",
|
||||
"zh": "设置",
|
||||
"en": "Settings"
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"file": "03-password.html",
|
||||
"zh": "修改密码",
|
||||
"en": "Change password"
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"file": "04-language.html",
|
||||
"zh": "语言选择",
|
||||
"en": "App language"
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"file": "05-albums.html",
|
||||
"zh": "相册列表",
|
||||
"en": "Albums"
|
||||
},
|
||||
{
|
||||
"id": 6,
|
||||
"file": "06-album-detail.html",
|
||||
"zh": "相册详情",
|
||||
"en": "Album overview"
|
||||
},
|
||||
{
|
||||
"id": 7,
|
||||
"file": "07-album-actions.html",
|
||||
"zh": "相册操作",
|
||||
"en": "Album actions"
|
||||
},
|
||||
{
|
||||
"id": 8,
|
||||
"file": "08-empty-album.html",
|
||||
"zh": "空相册",
|
||||
"en": "Empty album"
|
||||
},
|
||||
{
|
||||
"id": 9,
|
||||
"file": "09-create-album.html",
|
||||
"zh": "创建相册",
|
||||
"en": "New album"
|
||||
},
|
||||
{
|
||||
"id": 10,
|
||||
"file": "10-edit-album.html",
|
||||
"zh": "编辑相册",
|
||||
"en": "Edit album"
|
||||
},
|
||||
{
|
||||
"id": 11,
|
||||
"file": "11-members.html",
|
||||
"zh": "协作成员",
|
||||
"en": "Members"
|
||||
},
|
||||
{
|
||||
"id": 12,
|
||||
"file": "12-categories.html",
|
||||
"zh": "分类管理",
|
||||
"en": "Categories"
|
||||
},
|
||||
{
|
||||
"id": 13,
|
||||
"file": "13-camera.html",
|
||||
"zh": "拍摄",
|
||||
"en": "Camera"
|
||||
},
|
||||
{
|
||||
"id": 14,
|
||||
"file": "14-uploads.html",
|
||||
"zh": "上传中心",
|
||||
"en": "Uploads"
|
||||
},
|
||||
{
|
||||
"id": 15,
|
||||
"file": "15-upload-errors.html",
|
||||
"zh": "异常任务",
|
||||
"en": "Needs attention"
|
||||
},
|
||||
{
|
||||
"id": 16,
|
||||
"file": "16-upload-history.html",
|
||||
"zh": "上传历史",
|
||||
"en": "Upload history"
|
||||
},
|
||||
{
|
||||
"id": 17,
|
||||
"file": "17-photos.html",
|
||||
"zh": "照片管理",
|
||||
"en": "Manage photos"
|
||||
},
|
||||
{
|
||||
"id": 18,
|
||||
"file": "18-photo-detail.html",
|
||||
"zh": "管理大图",
|
||||
"en": "Photo details"
|
||||
},
|
||||
{
|
||||
"id": 19,
|
||||
"file": "19-share.html",
|
||||
"zh": "相册分享",
|
||||
"en": "Share album"
|
||||
},
|
||||
{
|
||||
"id": 20,
|
||||
"file": "20-hide-photo.html",
|
||||
"zh": "隐藏确认",
|
||||
"en": "Hide photo"
|
||||
}
|
||||
];
|
||||
|
After Width: | Height: | Size: 340 KiB |
|
After Width: | Height: | Size: 182 KiB |
|
Before Width: | Height: | Size: 110 KiB After Width: | Height: | Size: 106 KiB |
|
Before Width: | Height: | Size: 53 KiB After Width: | Height: | Size: 51 KiB |
|
After Width: | Height: | Size: 1014 KiB |
|
After Width: | Height: | Size: 279 KiB |
|
After Width: | Height: | Size: 411 KiB |
@@ -0,0 +1,550 @@
|
||||
# UI-03R:App 全页面高保真还原实施方案(替代 UI-03 的视觉验收标准)
|
||||
|
||||
版本:2.0
|
||||
日期:2026-09-22
|
||||
状态:待执行。本文只规划调整,不代表页面已还原。
|
||||
目标:以五张设计板为视觉依据,逐页修复已实现 App 的形态偏差,交付可核验的真实 Flutter 界面。
|
||||
|
||||
## 0. 给执行者的强制说明
|
||||
|
||||
这不是自由设计任务,也不是“功能存在即可”的美化任务。先看图、再看本文件、再检查当前代码,按既定规格实现。保留现有业务和上传引擎,重点替换不匹配的布局与组件外观。
|
||||
|
||||
本文件替代 UI-03 中“接近设计板”“约25%–32%”“常规样式自主决定”等宽泛表述。对于未被本文覆盖的业务规则,继续执行 UI-03/UI-01 与现有权限契约;Web/嵌入组件不在范围。
|
||||
|
||||
本方案的数值是依据效果图重新制定的**工程还原基准**,不是声称从 AI 图片精确测得的全部原始设计参数。AI 图中的字体、图标、文字和画面存在细微不一致,不可能用自动像素差证明100%一致;必须采用“固定素材和数据 + 固定视口 + 布局测量 + 逐页视觉复核”组合验收。不能口头承诺像素级一致后省略证据。
|
||||
|
||||
- 不得直接把设计板作为运行界面背景。
|
||||
- 不得重新发挥为另一套 Material 默认风格。
|
||||
- 不得只更新颜色、标题、注释和验收表。
|
||||
- 不得用缺素材/空数据页面证明照片主导页面还原完成。
|
||||
- 不得把截图工作推迟到全部页面完成之后。
|
||||
- 不得把 widget/集成测试通过等同于视觉验收通过。
|
||||
- 不得用“模拟器不是手机”为由跳过能在固定 widget surface 完成的布局检查。
|
||||
- 不覆盖用户当前改动,不自动提交、推送、打标签或部署。
|
||||
|
||||
## 1. 设计依据与已核实偏差
|
||||
|
||||
### 1.1 唯一视觉参考
|
||||
|
||||
| 板 | 文件 | 页面 |
|
||||
|---|---|---|
|
||||
| 01 | [账号与设置](../designs/app-redesign-2026-09-21/01-account-settings.png) | 01–04 |
|
||||
| 02 | [相册工作台](../designs/app-redesign-2026-09-21/02-albums-workspace.png) | 05–08 |
|
||||
| 03 | [创建与协作](../designs/app-redesign-2026-09-21/03-create-collaborate.png) | 09–12 |
|
||||
| 04 | [拍摄与上传](../designs/app-redesign-2026-09-21/04-capture-uploads.png) | 13–16 |
|
||||
| 05 | [照片与分享](../designs/app-redesign-2026-09-21/05-photos-share.png) | 17–20 |
|
||||
|
||||
每张四屏,按从左到右读取。外部标题、设备外圆角和画板灰底不画入 App。效果图中的年份、人物账号、二维码、描述字数不构成业务规则。
|
||||
|
||||
### 1.2 已检查的运行截图与代码问题
|
||||
|
||||
依据:`docs/plans/progress/ui03-screenshots/after/` 的 01-login、05b-albums-en、06-album-detail、14-uploads,以及当前 theme.dart 和页面代码。
|
||||
|
||||
| 偏差 | 实际观察 | 本轮修正 |
|
||||
|---|---|---|
|
||||
| 登录摄影素材缺失 | 顶部蓝色渐变和半透明矩形 | 必须真实摄影拼贴;占位不能通过主视觉验收 |
|
||||
| 登录品牌/排版不同 | 品牌与标题左对齐、中文“现场影像”、默认字段外观 | 英文品牌固定、主体居中、字段图标/间距按页面01 |
|
||||
| 相册封面缺失 | 灰色占位成为主视觉 | 使用可追溯测试摄影素材和有效封面响应验收正常态 |
|
||||
| 根导航形态不同 | 紫蓝胶囊指示器、较重默认样式 | 无胶囊,蓝色选中图标和文字 |
|
||||
| 详情首屏信息位置不同 | 标题在AppBar重复,封面占高,工具组过厚,照片首屏几乎不可见 | 顶栏仅返回/更多;标题在封面下;薄工具区;照片在首屏出现 |
|
||||
| 上传摘要不同 | 白色大卡、完成数字弱、彩色文字分散 | 直接排在背景上,32号主数字、紧凑同一副行 |
|
||||
| 上传筛选不同 | 带黑边的默认SegmentedButton胶囊 | 轻底色圆角8分段,选中实蓝,无外描边 |
|
||||
| 上传条目不同 | 相册显示内部ID、素材为测试色块、信息层级松散 | 显示真实名称;固定缩略图和状态排版 |
|
||||
| 验收证据不足 | 多页面无截图;05b文件名为en而画面仍为中文 | 所有20项保存真实指定语言截图并人工核对文件与内容 |
|
||||
| 视口不一致 | 历史设备540×960 @240dpi,不能直接与设计板比较 | 固定逻辑画布,另保留设备截图,不按物理像素混比 |
|
||||
|
||||
历史 UI03 验收记录用于了解实现,不作为本轮视觉通过证据。保留历史记录,新建 UI03R 记录,不篡改旧记录。
|
||||
|
||||
## 2. 开发顺序与决策边界
|
||||
|
||||
先完整修好 **01登录、05相册列表、14上传中心** 三个样板页并截图对照,再复用组件推广其余17项。不能先机械改完20页再补截图。
|
||||
|
||||
出现冲突按以下优先级:
|
||||
1. 权限、数据真实性、账号隔离与上传可靠性。
|
||||
2. 本文冻结的布局和组件规格。
|
||||
3. 对应设计图的视觉层级与图片比例。
|
||||
4. 原UI-03一般性说明。
|
||||
5. Flutter组件默认值(优先级最低,不能作为不还原的理由)。
|
||||
|
||||
常规组件拆分无需询问;素材或环境缺失可以继续其他任务,但相关视觉状态标为“未完成”,不能用文字说明换取通过。真机拍摄、iOS编译等资源关口与UI布局验收分开登记。
|
||||
|
||||
## 3. 固定比较环境
|
||||
|
||||
### 3.1 参考画布与坐标
|
||||
|
||||
- 规范画布:逻辑 **390×844 dp**,英文、浅色、文字缩放1.0、无键盘。
|
||||
- 为稳定渲染,测试固定顶部 inset=24、底部 inset=24;测试画布的坐标包含这些区域。
|
||||
- 正式App使用真实系统inset,不绘制假状态栏、时间、电池或Home指示线;截图比较时系统栏蒙版排除。
|
||||
- 常规内容可用区域 y=24..820;内页顶栏 y=24..80,高56。
|
||||
- 根导航视觉主体 y=752..820,高68,底部系统区另计;root body不能延伸到导航下面而无法滚达。
|
||||
- 内页固定双按钮区主体高72,底部再加实际安全区。
|
||||
- 下述y坐标适用于指定参考画布和短英文内容,只用于约束首屏组成。生产长文字、大字体允许向下自然展开并滚动,禁止为保坐标裁字。
|
||||
- 不用整体Transform.scale缩放390画布适配所有设备。以真实约束自适应,保持按钮触控和字号。
|
||||
|
||||
### 3.2 两套证据必须都有
|
||||
|
||||
A. 固定画布widget截图:本地确定性素材/数据,复用真实页面及组件,验证布局。明确标记视觉fixture,不能声称相机或网络实装成功。
|
||||
B. 模拟器/真机运行截图:真实页面入口与隔离测试API,验证路由、交互、实际inset和资源加载。
|
||||
|
||||
需要系统检查逻辑尺寸与DPR,不能看到540px截图就当540dp。缺390设备时固定widget画布完成精确比较,再在现有设备补运行检查;不能强制修改用户设备全局分辨率而不恢复。
|
||||
|
||||
### 3.3 统一截图状态
|
||||
|
||||
固定测试时间、账号、英文文案、相册封面与图片顺序;禁动画、等待字体和图片加载完成、隐藏debug banner。不要直接复用某张错误态截图充当正常态。
|
||||
|
||||
## 4. 素材、字体、图标:先到位再调排版
|
||||
|
||||
### 4.1 素材清单(必做)
|
||||
|
||||
建立 `docs/designs/ui03r-assets-manifest.md`:
|
||||
|
||||
| 素材ID | 用途 | 最低要求 |
|
||||
|---|---|---|
|
||||
| brand-mark | 登录/列表品牌标志 | 同一蓝色光圈或已确认正式标志,所有页一致 |
|
||||
| login-01..06 | 登录六图拼贴 | 清晰活动摄影,竖横图可裁切,风格与设计板同类 |
|
||||
| event-cover-01..03 | 三张相册封面 | 展馆/活动/团队各一,至少720px宽 |
|
||||
| event-photo-01..12 | 网格、缩略图、大图 | 真实摄影风格;包含横图、竖图、人物、产品、场地 |
|
||||
| avatar-owner | 设置/成员 | 有合法素材才用照片,否则首字母;记录视觉偏差 |
|
||||
| empty-album | 空相册插画 | 低对比叠放照片图形,不能换成大彩色卡通 |
|
||||
|
||||
逐项记录路径、来源、许可或用户提供依据、尺寸、SHA256、用途、是否仅测试使用。
|
||||
|
||||
**取消旧计划中以渐变占位视为可交付的做法。** 缺摄影素材时优先查仓库已有资源;可复用用户已认可的生成图中干净摄影区域作为测试参考(不得包含UI文字/边框,质量不足不可使用),或在有图像工具与授权条件时生成独立摄影素材。是否可执行裁切/生成按实际工具规范操作。生产素材来源未确定则单独列阻塞,不假称完成。不得从网络随便抓图。
|
||||
|
||||
将测试照片存入测试fixture,生产登录摄影拼贴使用随App打包的合规资源;生产相册卡仍读取真实API,不给所有用户硬塞测试封面。测试API资产必须可访问且未过期。
|
||||
|
||||
### 4.2 字体冻结
|
||||
|
||||
- 拉丁字形目标:Inter 或仓库已经具备的视觉等价字体,400/500/600/700四档,优先本地随包。
|
||||
- 先检查字体可用性与许可;不可联网获取时不能假称已使用Inter。登记替代字体和字宽差异,对照校准后再通过。
|
||||
- 中文回退到可用中文系统无衬线字体,不强行用拉丁字体显示方块。
|
||||
- 不在每页随机指定fontFamily,不运行时下载字体。
|
||||
- 设置字体后重新测量文本,因为默认Roboto与Inter会改变换行。
|
||||
- 表格中数字采用tabularFigures;禁全局锁死textScaler。
|
||||
|
||||
### 4.3 文字样式(实际写入TextStyle)
|
||||
|
||||
| token | size/lineHeight(dp) | weight | 用途 |
|
||||
|---|---|---|---|
|
||||
| brand | 26/32 | 700 | PhotoLive |
|
||||
| pageTitle | 24/30 | 700 | Albums/Settings |
|
||||
| innerTitle | 18/24 | 600 | 返回页标题 |
|
||||
| heroTitle | 28/34 | 700 | 登录主标题 |
|
||||
| sectionTitle | 17/24 | 600 | Recent photos |
|
||||
| body | 15/22 | 400 | 说明 |
|
||||
| field | 15/20 | 400 | 输入内容 |
|
||||
| rowTitle | 15/20 | 600 | 列表标题 |
|
||||
| secondary | 13/18 | 400 | 时间地点 |
|
||||
| caption | 12/16 | 400 | 辅助标签 |
|
||||
| button | 15/20 | 600 | CTA |
|
||||
| metric | 32/40 | 700 | 82 uploaded |
|
||||
|
||||
不要把所有AppBar都设成24:内页居中18,根页左对齐24,摄影页独立。
|
||||
|
||||
### 4.4 图标冻结
|
||||
|
||||
同一种线型,常规22dp,线宽视觉约1.8–2。若使用现有Material图标,逐项选择outlined版本;禁止相同入口在不同页换成info/check等不相关图标。
|
||||
Public=globe,Uploads on=cloud upload,Members=people,Categories=tag,Share=share nodes,History=clock arrow,Settings=gear。
|
||||
底部选中可填充,同类轮廓一致。没有正式Logo时不要每页使用不同的相机/图库图标冒充品牌。
|
||||
|
||||
## 5. 组件级样式冻结
|
||||
|
||||
### 5.1 配色与表面
|
||||
|
||||
```text
|
||||
primary #1A73E8
|
||||
page #F6F8FB
|
||||
surface #FFFFFF
|
||||
textPrimary #172033
|
||||
textSecondary #647084
|
||||
line #E5EAF1
|
||||
softBlue #EEF5FF
|
||||
photoBackground #10161E
|
||||
successText #16794B
|
||||
waitingText #996300
|
||||
errorText #B42318
|
||||
```
|
||||
|
||||
- 禁止种子派生色自动渗入导航、开关、筛选、操作卡。显式指定每个组件状态的颜色。
|
||||
- 普通卡无明显浮起阴影;需要阴影时black 4%、blur12、offset(0,3),不同时粗边框+重阴影。
|
||||
- card radius16,form field/button radius10,segment radius8,image tile radius4。
|
||||
- 错误、等待色不映射成全局secondary后被导航当选中色使用。
|
||||
|
||||
### 5.2 根底部导航(必须替换当前胶囊样式)
|
||||
|
||||
- 可用NavigationBar但indicatorColor透明、indicatorShape不显示、selected/unselected颜色显式分开;若默认内部布局无法满足则用语义完整的自定义三等分组件。
|
||||
- 白底、顶部1px line、主体高68,图标24,上距12,图标与标签间6,标签11/14。
|
||||
- 选中图标+标签primary,未选textSecondary;无圆角底色、无紫色胶囊。
|
||||
- 每个项目触控区域整个三等分格。
|
||||
- badge直径16,红底白字10,靠上传图标右上;99以上显示99+,不推移布局。
|
||||
|
||||
### 5.3 顶栏与操作
|
||||
|
||||
- 根页标题区56高,左右20;内页返回按钮44,居中innerTitle,右侧44操作。
|
||||
- 内页不在AppBar再重复活动名;详情活动名只在封面下。
|
||||
- surfaceTintColor透明,elevation=0,scrolledUnderElevation=0。
|
||||
- 大图/相机顶栏背景深色,白图标。
|
||||
|
||||
### 5.4 输入框
|
||||
|
||||
- label在输入框上方,非浮动label;label13/18,与框间6。
|
||||
- 输入框高52、白底、1px line、radius10,左右14。
|
||||
- 聚焦1.5px primary;错误1px error并在下方显示说明。
|
||||
- 登录字段允许以placeholder为主且leading22图标;禁止空框只靠浮动中文标签模仿设计。
|
||||
- 密码eye有效宽44;多行描述至少100高;不使用超粗默认outline。
|
||||
|
||||
### 5.5 按钮与分段
|
||||
|
||||
- Primary:高50,primary白字,radius10,无elevation;disabled用明确灰蓝,不能与可点击同色。
|
||||
- Secondary:白底1px primary线,primary字;danger:红色文字+图标,默认不整条红底。
|
||||
- Tabs/segments:高40,浅灰#EEF1F6轨道,padding3,radius8;选中primary实底白字,未选textSecondary;不显示选中check、不画外黑边、不做大胶囊。
|
||||
- 图中Details/Access是浅蓝选中风格:白/浅灰轨道,选中#DDEBFF+primary文字。不要和上传分段混用状态颜色。
|
||||
|
||||
### 5.6 卡片与Sheet
|
||||
|
||||
- 普通分组卡:白底radius16,内边距16,外分组间20;行高56–64,分隔从文字起始位置对齐。
|
||||
- Sheet:白底、顶部radius20,拖柄36×4,距顶10;左右20,标题18/24,底部SafeArea。
|
||||
- Sheet scrim黑色32%,不能灰得看不清背景层次;顶部内容不浮在遮罩之外。
|
||||
- 单选行高60,radio20,row点击生效;不使用Material默认过大的行高。
|
||||
- 内页双按钮条:padding(16,12,16,12),gap12,两等宽,高50,白底;系统inset另算。
|
||||
|
||||
### 5.7 图片封面卡
|
||||
|
||||
- 宽=可用宽,390时左右20得350;高=width×9/16≈197。
|
||||
- 圆角12而非巨圆角,间距16。
|
||||
- scrim:顶部透明,0.42开始变暗,底部黑70%;不把整张图覆盖成灰色。
|
||||
- 标题18/24 semibold白,左16、底部状态行上方约42;meta12/18,status行12/16。
|
||||
- Public左、Uploads on右,中间Spacer;**无黑色独立胶囊背景,无绿色勾徽章**,只白色图标与文字。
|
||||
- 默认单行短日期,使用“Oct 15–19 · Guangzhou”一类真实格式,完整时区/时间放详情;禁止列表用完整起止时间和“未定”撑满。
|
||||
- 正常态必须有摄影封面,缺图态单独验收。
|
||||
|
||||
## 6. 逐屏布局:390×844基准
|
||||
|
||||
所有坐标以第3节画布计。表中“高”指基准英文数据;长文字允许重排,不能硬塞进固定高度。固定按钮区域使用真实SafeArea。
|
||||
|
||||
### 01 登录(图01第一屏)
|
||||
|
||||
| 区域 | x / y / w / h |
|
||||
|---|---|
|
||||
| 白色上部语言区 | 0 / 24 / 390 / 62 |
|
||||
| 摄影六图拼贴 | 0 / 86 / 390 / 254 |
|
||||
| 品牌居中 | 65 / 368 / 260 / 32 |
|
||||
| 主标题居中 | 20 / 424 / 350 / 34 |
|
||||
| 副标题居中 | 20 / 466 / 350 / 22 |
|
||||
| 账号框 | 20 / 538 / 350 / 52 |
|
||||
| 密码框 | 20 / 604 / 350 / 52 |
|
||||
| Sign in | 20 / 678 / 350 / 50 |
|
||||
| 管理员说明 | 20 / 758 / 350 / 36 |
|
||||
|
||||
拼贴3列×2行,缝4,图片cover,禁止渐变矩形替代。语言在右上,正文、品牌、标题居中;账号/锁leading图标。短屏和键盘时图片缩小或滚出,表单可达;不把整个390版压扁。现有loginAskAdmin、用户名等走l10n,品牌英文固定不随UI翻译成“现场影像”。
|
||||
|
||||
### 02 设置(图01第二屏)
|
||||
|
||||
- 根标题x20 y48,24/30。
|
||||
- 账号卡x20 y104 w350 h112:头像56,左16;文字x100;姓名17/24,账号13/18,角色可次行。
|
||||
- 选项组x20 y240 w350:4行各60;leading22,左右16;分隔仅文字区。
|
||||
- 退出卡y504 h64,红色图标与文字,其余白色。
|
||||
- 根导航按统一规格。不要把所有设置都做成散落的ListTile,没有分组表面。
|
||||
- 账号卡无实际编辑能力不画箭头;图中的人物只用于固定fixture。
|
||||
|
||||
### 03 修改密码(图01第三屏)
|
||||
|
||||
内页顶栏后y104安全提示卡h76;y204起三个字段组(label18+gap6+框52),组间20;主按钮距最后框24;下方提示组距32。无第二个页面大标题重复AppBar。
|
||||
说明只是建议,不创建新的密码强制政策;键盘时整页滚动。
|
||||
|
||||
### 04 语言Sheet(图01第四屏)
|
||||
|
||||
参考顶边y440、底部844(含safearea),标题区域高64;三行60,底部Done高50,上下留16。白底、radio左、语言名两行说明在有意义时出现。临时选择,Done提交;关闭不提交。高度随文字增大可扩展至85%屏,不能截断选项。
|
||||
|
||||
### 05 相册列表(图02第一屏)
|
||||
|
||||
- 顶部PhotoLive x20 y42,右加号36圆形但有效44。
|
||||
- Albums x20 y104,说明y139;首卡y184,h197;第二卡y397;第三卡y610部分进入首屏,继续滚动。
|
||||
- 三张封面色彩/构图接近设计板,短白字叠层。正常列表不要用巨大灰色占位。
|
||||
- 根导航y752覆盖区前有列表底部padding,让末卡可完整滚出。
|
||||
- 中文标题同层级,不把PhotoLive隐藏成只有“相册”。
|
||||
|
||||
### 06 相册详情(图02第二屏)
|
||||
|
||||
- 顶栏y24–80仅返回与更多。
|
||||
- 封面x0 y80 w390 h165,照片edge-to-edge。
|
||||
- 信息x16 y260:标题22/28;日期行y299、地点行y325,分开,不把全部信息拼成三行长字符串。
|
||||
- 两个状态单元y357 h32,浅蓝底、普通蓝灰图标;Uploads on不是绿色success大徽章。
|
||||
- 四工具单元x16 y407,单元约80×64,gap12;每个独立极浅底radius10,icon22+label11,**无包裹它们的第二层厚白大卡**。
|
||||
- Recent photos标题y493,grid首行y525;至少一整行照片在首屏可见。
|
||||
- 底部动作固定在可用区域末72,正文让位。
|
||||
- 不重复AppBar中的活动标题,不把封面做成接近半屏高。
|
||||
|
||||
### 07 操作Sheet(图02第三屏)
|
||||
|
||||
复用详情作为背景,Sheet顶边约y450。标题18,4行52,行图标22、字15;Cancel单独轻灰行50。只显示有权限项。不要顶部多一个巨大的默认菜单标题条。
|
||||
|
||||
### 08 空相册(图02第四屏)
|
||||
|
||||
保留详情封面/活动信息至y390;空态插画约112×88居中y486;标题17/24 y605、说明13/20 y640;底部动作同详情。空态不显示“Recent photos + 空列表”两套重复说明。无上传权限则移除动作,空态说明相应调整。
|
||||
|
||||
### 09 新建(图03第一屏)
|
||||
|
||||
- 居中内页标题;body左右16,顶部20。
|
||||
- 基础白色卡x16 y100 w358;标题输入、日期两行、时区、地点分行。卡内部padding16、行高52–56。
|
||||
- 描述语言卡距20:标题17,默认语言选择框52,描述区至少100。
|
||||
- Create album固定底栏;表单底部预留空间。
|
||||
- 所有标签在框上方或有对齐的行label,不把全部字段变成无分组的默认TextFormField。
|
||||
- 真实必填字段完整,设计板首屏没展示的字段允许向下滚动。
|
||||
|
||||
### 10 编辑Access(图03第二屏)
|
||||
|
||||
Tabs x16 y104 w358 h40,距下卡20。开关卡内4项,每项标题15/20与说明13/18,右开关44×26;行高最低86,说明长允许扩高。iOS样式细长开关或自定义视觉,不直接用明显不同的大Material轨道。
|
||||
Content language单独卡距20 h84;Save固定底栏。
|
||||
Details共用新建表单,保持草稿。禁止为了还原图修改服务端开关语义。
|
||||
|
||||
### 11 成员(图03第三屏)
|
||||
|
||||
顶栏返回、标题、加号。Owner分组标题y108,卡y144高88。Collaborators标题y256,白卡y292,两项各88。头像44、名字15 semibold、账号12、权限说明12;文字不溢出右侧overflow按钮。
|
||||
说明框用softBlue和小info,padding12。Invite colleague为底部outlined高50。
|
||||
内部账号搜索面板复用成员能力;图上邮箱不是必须字段;真实缺省显示account。禁止借口“无头像”把所有行改成没有头像占位的稀疏文本。
|
||||
|
||||
### 12 分类与编辑Sheet(图03第四屏)
|
||||
|
||||
列表左右16,行高92,图标/可用缩略图56×56;分类名15/20,编辑22、更多22。没有封面用柔和图标,属于允许偏差。
|
||||
新增Sheet顶边约y452,标题+关闭、语言tabs、label、52高输入、底部Save。语言tabs浅蓝选中,不能采用上传实蓝样式。
|
||||
列表和面板CRUD复用现有实现,不新增照片封面数据表。
|
||||
|
||||
### 13 相机(图04第一屏)
|
||||
|
||||
顶部黑色区域y24–100:返回左、相册/分类居中、真实上传状态右。取景舞台y100–650,按真实相机比例contain或必要的预览适配,禁止人物拉伸。底部黑色控制区:缩略图48,快门76(外圈2、内实白)、切换摄像头44。
|
||||
“Added to upload queue”半透明反馈在取景下边缘上方,不覆盖快门。
|
||||
无Square/Pano;相机无资源时只可用注入fixture验证布局,真机预览另列未验收,不造实机截图。
|
||||
|
||||
### 14 上传中心(图04第二屏)
|
||||
|
||||
- 顶部Uploads x20 y48,History右,不重复品牌占据标题。
|
||||
- Today · This device x20 y108,13/18。
|
||||
- 82 uploaded x20 y142,32/40;数字和标签同一大字号。
|
||||
- 副行x20 y192,13/18,中性次文字,不把所有状态染成一串彩色数字。
|
||||
- 分段x16 y238 w358 h40;其他相册/日期筛选放History旁图标/底层面板,不能挤掉三个分段。
|
||||
- 第一任务卡y300,左右16,白底radius12,minHeight124,内padding12;下一卡gap12。
|
||||
- 缩略图76×88,右文字区域从x116起;文件名15/20粗,相册/分类12/17次色,状态在下方。
|
||||
- uploading:进度条高4,状态文字12;uploaded绿色图标+文字,无巨绿胶囊;confirming小spinner。
|
||||
- **摘要没有包裹白色大卡;筛选无黑色描边、无紫色选中背景。**
|
||||
- 正常截图至少4种任务状态,不用唯一完成记录+大面积空白证明还原。
|
||||
- 相册名必须显示标题;无匹配名称时本地化“相册信息暂不可用”,不要显示长UUID作为正常副标题。
|
||||
|
||||
### 15 Needs attention(图04第三屏)
|
||||
|
||||
同上传摘要和分段;下面两张异常卡,至少152高。缩略图76、文件名、相册、红色错误句;错误解释13/18;Retry或Select again在文字列下方,高40但触控44。底部Retry eligible tasks高50,独立于根导航。
|
||||
不改变原失败分类,不新增UI控制的假重试。摘要仍明确“Today · This device”,不会错误声称为异常筛选结果总数。
|
||||
|
||||
### 16 历史(图04第四屏)
|
||||
|
||||
内页标题、subtitle y104、相册/日期两个筛选y140高40;首记录y206。白/页面背景平铺,无每行重阴影;缩略图80×88,行高124,右侧文件名、状态、时间、设备来源分行,细分隔。
|
||||
状态由服务端真实字段决定,原接口没提供的缩略图或文件名不能硬造。生产回退与视觉fixture正常态分别记录。
|
||||
|
||||
### 17 照片网格(图05第一屏)
|
||||
|
||||
内页顶栏左返回,中间/左标题Photos与小相册名;分段y104高40,网格y164。左右8,列缝4,3列每格约122×150(网格可固定裁切,**管理页不是观众瀑布流**)。优先保持均匀行高。
|
||||
角标只显示Processing/Hidden,半透明深底,图标12+文字11,靠左下,padding6。
|
||||
无根底部导航;列表最后一行可完整滚动,数据仍走管理预览和权限。
|
||||
|
||||
### 18 管理大图(图05第二屏)
|
||||
|
||||
顶栏深色y24–80;图片舞台y104–604,完整contain;左右控制44半透明黑圆。底部信息x20 y636,上传者15粗,时间13,尺寸13;状态badge靠右,同一行。
|
||||
分隔y722,动作条y742–796:Hide photo为深色1px灰线按钮w190,Delete右侧红字图标,无整条鲜红按钮。短屏根据剩余高度缩小舞台,不能遮住动作。
|
||||
不添加观众点赞工具栏。保持现有手势、分页、签名刷新、返回位置。
|
||||
|
||||
### 19 分享(图05第三屏)
|
||||
|
||||
顶栏Share album;分享白卡x16 y104 w358,边线1px、radius16、内padding16。封面w326 h172,radius10;标题18/24,地点日期13分两行。
|
||||
QR区域约196×196,居中浅灰底,真实二维码周围留足quiet zone;下方说明12居中。Copy link高50,与QR说明间20。公开说明位于卡内底部。
|
||||
不把裸链接+一个大二维码直接铺满整个屏幕;原有浏览器打开入口可放更多或次级文本,不抢主按钮视觉。未公开时修改说明,不伪造可访问。
|
||||
|
||||
### 20 隐藏确认(图05第四屏)
|
||||
|
||||
管理大图作为背景,黑32%遮罩;Sheet y≈520,顶拖柄,标题居中18/24,缩略图64×80左、说明13/20右;primary50与cancel50各占整行,间12。
|
||||
说明按权限:“Authorized album managers can publish it again.”,不要向无恢复权限者承诺本人可恢复。
|
||||
photoId打开时捕获,切图/重复点击不作用到别图;真实请求错误保持可理解反馈。
|
||||
|
||||
## 7. 素材/数据/视口固定的视觉fixture
|
||||
|
||||
建立专用 `test/visual/` 与清晰命名的debug-only设计预览入口,复用**真实生产页面和组件**并注入数据,不复制一套漂亮但不被生产使用的静态页面。
|
||||
|
||||
固定样本:
|
||||
- 账号Alex Morgan,头像/首字母,英语。
|
||||
- 三相册Canton Fair · Autumn / Product Launch / Team Stories;首相册Oct15–19,2026,Guangzhou。
|
||||
- 至少12张摄影图片与正确宽高;封面非null;一张Hidden、一张Processing。
|
||||
- 上传范围Today · This device:82完成、3传输中、13等待、2需处理。必须通过可控fixture/provider表达,不写死生产数字。
|
||||
- 两名协作者;三分类;两条失败任务;5条服务端历史。
|
||||
- 分享二维码使用测试相册URL真实生成。
|
||||
- 配套空/断网/不可公开/无预览权限fixture,不能与正常态混为一张。
|
||||
|
||||
debug入口不能携带真实账号密码、不触生产写操作;正式构建不可进入fixture模式。相机测试预览必须标识为fixture,不能作为原生相机验收证据。
|
||||
|
||||
## 8. 精确的截图对照流程(每页都执行)
|
||||
|
||||
1. 打开对应原设计板,定位第几屏。可用图像裁切工具制作参考屏裁片;裁切只用于比较,不用来代替运行界面。保留原图,记录裁框。
|
||||
2. 将参考屏裁片等比例统一宽度至390(不做非等比拉伸);由于生成图屏幕比例不一致,系统栏/画板边界排除。坐标冲突以本文第6节工程基准为准。
|
||||
3. 渲染固定390×844 fixture截图,文件名明确screenId/lang/theme/scale/dataVersion。
|
||||
4. 输出参考/实际左右对照图、50%透明叠加图;对系统栏、不同照片内容、日期文字等合理差异设置明确mask并记录。
|
||||
5. 测量关键框:标题、首卡、首图、分段、底栏;出一行目标/实测/差值表。
|
||||
6. 按差异修复 → 重拍。不得在没查看真实截图时自行写“视觉通过”。
|
||||
7. 相同页面的生产服务冒烟截图另存,证明不是仅fixture页面好看。
|
||||
|
||||
不能用SSIM/整图像素差单一阈值判断通过:照片内容和字体抗锯齿会干扰。可计算结构区差异辅助,但最终必须逐页检查。
|
||||
|
||||
### 8.1 可量化通过标准
|
||||
|
||||
参考画布下:
|
||||
- 主要容器x/y/w/h相对第6节目标偏差≤4dp;涉及自然文本高度累计偏差≤8dp且记录原因。
|
||||
- 明确token的字号偏差≤1sp,字重一致(400/500/600/700);行高偏差≤2dp。
|
||||
- 圆角偏差≤2dp,常规间距偏差≤2dp。
|
||||
- 首屏预期出现的区域必须出现:详情首行照片、上传至少主要任务行、登录主按钮等;不能整体下推到屏外。
|
||||
- 色值以token为准,不接受主题种子自动派生为另一色相。
|
||||
- 不允许残留占位摄影拼贴、根导航胶囊、默认黑框分段、正常态ID裸露、重复活动标题。
|
||||
- 标准英文fixture关键标题换行与规范一致;中文及大字体按可用性允许重排。
|
||||
- 触控、语义、长文案通过独立检查,不能为坐标牺牲可访问性。
|
||||
|
||||
超出阈值必须写出具体数值及业务/平台原因,并标记待修或接受的明确偏差;不能以“效果接近”一笔带过。
|
||||
|
||||
## 9. 逐任务实施计划
|
||||
|
||||
### R00 复核基线
|
||||
- [ ] Git状态、最新UI03代码/验收、五图全部读取。
|
||||
- [ ] 创建 docs/plans/progress/UI03R-验收记录.md。
|
||||
- [ ] 建立20屏“参考/当前/偏差/目标”表。
|
||||
- [ ] 确认逻辑尺寸、字体、图片来源、可用截图工具。
|
||||
出口:不能沿用旧UI03全通过结论。
|
||||
|
||||
### R01 素材和fixture
|
||||
- [ ] 生成资产清单、补足摄影素材及品牌一致性。
|
||||
- [ ] 固定英文数据、12张照片、正常和异常状态。
|
||||
- [ ] fixture注入真实组件;生产开关隔离。
|
||||
出口:正常态不是灰色占位,且数据不会污染生产。
|
||||
|
||||
### R02 公共组件重构
|
||||
- [ ] theme/tokens显式定义,不依赖默认Material外观。
|
||||
- [ ] 无胶囊根导航、两种segment、输入、按钮、Sheet、封面卡。
|
||||
- [ ] 给公共组件截图和语义检查。
|
||||
出口:默认风格造成的偏差已消除。
|
||||
|
||||
### R03 三个样板页
|
||||
- [ ] 完成01登录、05相册列表、14上传中心。
|
||||
- [ ] 三页必须有390英文正常态、对照图和几何差值表。
|
||||
- [ ] 达到第8节标准再推广,不等待用户确认常规像素调整。
|
||||
出口:缺素材或仍用默认样式时不能进入“样板已通过”。
|
||||
|
||||
### R04 账号与工作台
|
||||
- [ ] 页面02/03/04/06/07/08。
|
||||
- [ ] 逐页对照,特别检查详情首屏照片和工具区高度。
|
||||
出口:8页完整证据。
|
||||
|
||||
### R05 表单与协作
|
||||
- [ ] 页面09/10/11/12,邀请与编辑配套弹层。
|
||||
- [ ] 表单草稿、权限、双语内容不回归。
|
||||
出口:分组/字号/开关对齐,不是默认表单集合。
|
||||
|
||||
### R06 拍摄与上传
|
||||
- [ ] 页面13/15/16,与14视觉一致。
|
||||
- [ ] 拍摄fixture与实际设备验证分开,记录真实资源。
|
||||
- [ ] 行级进度、恢复重试、账号隔离回归。
|
||||
出口:明确本地队列/服务端历史区别。
|
||||
|
||||
### R07 照片与分享
|
||||
- [ ] 页面17/18/19/20。
|
||||
- [ ] 大图舞台、资料、底部动作、QR卡和确认Sheet。
|
||||
- [ ] 照片权限、签名过期、切图及返回位置回归。
|
||||
出口:管理摄影界面与图05结构一致。
|
||||
|
||||
### R08 全量验证
|
||||
- [ ] 20页英文正常态全部截图,不以widget测试替代缺图。
|
||||
- [ ] 中文、320短屏、430、平板、横屏、大字体、深色抽查。
|
||||
- [ ] 功能和视觉验收分开记录,失败项回到对应任务。
|
||||
出口:证据齐全,不能以“留待G2”跳过可模拟的文字/布局检查。
|
||||
|
||||
### R09 交接
|
||||
- [ ] 资产清单、截图索引、差异表、测试结果、外部关口整理。
|
||||
- [ ] 总纲标记UI03R真实状态,不覆盖原UI03历史。
|
||||
- [ ] 如有未完成的摄影/字体/截图/真机项,最终明确标为部分完成。
|
||||
出口:用户可打开每个页面对照,而非只能相信测试数字。
|
||||
|
||||
## 10. 回归、响应式与命令
|
||||
|
||||
### 10.1 视口矩阵
|
||||
|
||||
- 主基准390×844 / en / light /1.0:20项全量。
|
||||
- 320×568:登录键盘、详情、编辑Access、上传、分享、Sheet。
|
||||
- 430×932:列表、照片网格、大图。
|
||||
- 844×390横屏:拍摄布局、大图和分享可达。
|
||||
- 768平板:列表/表单/成员;内容maxWidth按版式合理限制,不能把字段拉成全屏一条。
|
||||
- textScaler1.3、2.0:设置、表单、上传错误、隐藏确认。
|
||||
- zh-CN:20页运行检查,至少8个主要页截图,文件名和画面语言一致。
|
||||
- dark:设置、表单、上传、列表;摄影页维持既定深色。
|
||||
|
||||
### 10.2 功能保护
|
||||
|
||||
账号登录/密码/退出,语言持久化,表单未保存,成员/分类权限,上传关闭,公开关闭,拍摄入队,等待网络/重试,源文件丢失,凭证续签,队列清理,照片预览权限和下线,分享复制失败都要按既有逻辑回归。
|
||||
不修改native_transport/upload_engine原生可靠性语义;如样式工程确实触及控制逻辑,必须补针对性测试并登记。
|
||||
|
||||
### 10.3 执行入口
|
||||
|
||||
在apps/mobile中使用仓库固定Flutter:
|
||||
|
||||
```text
|
||||
flutter gen-l10n
|
||||
flutter analyze
|
||||
flutter test
|
||||
```
|
||||
|
||||
另行添加可重复运行的visual fixture测试命令/截图脚本,并在README写明。检查工具是否重置数据,不对生产运行。不能自动更新golden来“让测试变绿”:先查看差异、修好界面,再建立新基线。
|
||||
|
||||
先跑定向后跑全量;只改App样式不必用无关Web构建缓存结果充当主要验收证据。
|
||||
|
||||
## 11. 双轨验收与交付目录
|
||||
|
||||
### 11.1 每页记录模板
|
||||
|
||||
| 字段 | 必填内容 |
|
||||
|---|---|
|
||||
| 页面ID/名称 | 01 Login等 |
|
||||
| 代码入口 | 实际页面和公共组件 |
|
||||
| 参考屏 | 板号/屏号/裁片路径 |
|
||||
| 正常态截图 | 390/en/light路径 |
|
||||
| 当前数据 | fixture版本、素材清单版本 |
|
||||
| 结构测量 | 目标/实测/差值,至少4个关键框 |
|
||||
| 视觉差异 | 已修/剩余及原因 |
|
||||
| 功能结果 | 通过/失败/未执行 |
|
||||
| 视觉结果 | 通过/失败/未完成 |
|
||||
| 可访问性 | 触控、语义、字体缩放 |
|
||||
| 外部限制 | 真机/素材/字体等,具体影响 |
|
||||
|
||||
“功能通过、视觉未完成”必须允许存在;不能合成一个✅遮盖差异。
|
||||
|
||||
### 11.2 目录
|
||||
|
||||
```text
|
||||
docs/designs/ui03r-assets-manifest.md
|
||||
docs/designs/ui03r-implementation/
|
||||
references/ 设计板各屏参考裁片及裁框记录
|
||||
actual/en-light/ 20个固定画布截图
|
||||
actual/zh-light/
|
||||
actual/responsive/
|
||||
device/ 模拟器/真机证据,记录平台参数
|
||||
comparisons/ 左右对照、透明叠加
|
||||
geometry/ 每页测量结果
|
||||
README.md 页面链接和复现命令
|
||||
docs/plans/progress/UI03R-验收记录.md
|
||||
```
|
||||
|
||||
### 11.3 完成门槛
|
||||
|
||||
- 五张图对应20项全部有正常态固定画布截图和视觉结论。
|
||||
- 三个样板页满足尺寸/字体/颜色/素材要求。
|
||||
- 无本方案列明的默认样式偏差残留。
|
||||
- 真实运行路径复用同一套组件,不是只做设计预览页。
|
||||
- 功能回归通过,未执行外部关口如实标注。
|
||||
- 存在主视觉素材缺失或关键页面未截图时,本阶段只能标记“部分完成”。
|
||||
- 严禁在没有看图、没有测量的情况下以源码注释或测试数量宣布视觉100%还原。
|
||||
|
||||
## 12. 可直接交给 Claude 的执行指令
|
||||
|
||||
> 请执行 docs/plans/2026-09-22-UI03R-App高保真还原完整实施方案.md。这次是纠正UI03与效果图差异,不是自由发挥或再次仅做功能。先查看五张原设计板和旧实际截图,准备真实摄影素材与固定390×844英文fixture,显式覆盖Material默认导航/分段/输入/按钮样式。首先完成01登录、05相册列表、14上传中心三页,输出同尺寸对照和关键框测量,达到文档标准后再完成其余17项。每页都要截图、查看、修正,功能和视觉分开验收。不得用渐变占位代替摄影拼贴、不得保留导航胶囊和默认黑框分段、不得用测试通过代替视觉还原。保护当前业务与未提交改动,保留权限和上传引擎,不修改Web与嵌入组件。最终交付真实可运行App、完整20页证据、素材清单、UI03R验收记录及剩余关口;未完成视觉项不得标完成。未经另行授权不推送、不部署、不操作云资源。
|
||||
|
||||