diff --git a/docs/designs/admin-preview-2026-09-22/01-login.html b/docs/designs/admin-preview-2026-09-22/01-login.html
new file mode 100644
index 0000000..8cbba6d
--- /dev/null
+++ b/docs/designs/admin-preview-2026-09-22/01-login.html
@@ -0,0 +1 @@
+
PhotoLive · 登录
\ No newline at end of file
diff --git a/docs/designs/admin-preview-2026-09-22/02-albums.html b/docs/designs/admin-preview-2026-09-22/02-albums.html
new file mode 100644
index 0000000..11a009a
--- /dev/null
+++ b/docs/designs/admin-preview-2026-09-22/02-albums.html
@@ -0,0 +1 @@
+PhotoLive · 相册管理
\ No newline at end of file
diff --git a/docs/designs/admin-preview-2026-09-22/03-photos.html b/docs/designs/admin-preview-2026-09-22/03-photos.html
new file mode 100644
index 0000000..84bc0fb
--- /dev/null
+++ b/docs/designs/admin-preview-2026-09-22/03-photos.html
@@ -0,0 +1 @@
+PhotoLive · 相册照片
\ No newline at end of file
diff --git a/docs/designs/admin-preview-2026-09-22/04-members.html b/docs/designs/admin-preview-2026-09-22/04-members.html
new file mode 100644
index 0000000..5f533e4
--- /dev/null
+++ b/docs/designs/admin-preview-2026-09-22/04-members.html
@@ -0,0 +1 @@
+PhotoLive · 相册成员
\ No newline at end of file
diff --git a/docs/designs/admin-preview-2026-09-22/05-categories.html b/docs/designs/admin-preview-2026-09-22/05-categories.html
new file mode 100644
index 0000000..0b8e738
--- /dev/null
+++ b/docs/designs/admin-preview-2026-09-22/05-categories.html
@@ -0,0 +1 @@
+PhotoLive · 分类管理
\ No newline at end of file
diff --git a/docs/designs/admin-preview-2026-09-22/06-watermark.html b/docs/designs/admin-preview-2026-09-22/06-watermark.html
new file mode 100644
index 0000000..69eadeb
--- /dev/null
+++ b/docs/designs/admin-preview-2026-09-22/06-watermark.html
@@ -0,0 +1 @@
+PhotoLive · 水印配置
\ No newline at end of file
diff --git a/docs/designs/admin-preview-2026-09-22/07-sharing.html b/docs/designs/admin-preview-2026-09-22/07-sharing.html
new file mode 100644
index 0000000..7ef5742
--- /dev/null
+++ b/docs/designs/admin-preview-2026-09-22/07-sharing.html
@@ -0,0 +1 @@
+PhotoLive · 相册分享
\ No newline at end of file
diff --git a/docs/designs/admin-preview-2026-09-22/08-create-album.html b/docs/designs/admin-preview-2026-09-22/08-create-album.html
new file mode 100644
index 0000000..264c660
--- /dev/null
+++ b/docs/designs/admin-preview-2026-09-22/08-create-album.html
@@ -0,0 +1 @@
+PhotoLive · 新建相册
\ No newline at end of file
diff --git a/docs/designs/admin-preview-2026-09-22/09-edit-album.html b/docs/designs/admin-preview-2026-09-22/09-edit-album.html
new file mode 100644
index 0000000..e7339b7
--- /dev/null
+++ b/docs/designs/admin-preview-2026-09-22/09-edit-album.html
@@ -0,0 +1 @@
+PhotoLive · 编辑相册
\ No newline at end of file
diff --git a/docs/designs/admin-preview-2026-09-22/10-users.html b/docs/designs/admin-preview-2026-09-22/10-users.html
new file mode 100644
index 0000000..ec78480
--- /dev/null
+++ b/docs/designs/admin-preview-2026-09-22/10-users.html
@@ -0,0 +1 @@
+PhotoLive · 账号管理
\ No newline at end of file
diff --git a/docs/designs/admin-preview-2026-09-22/11-user-sync.html b/docs/designs/admin-preview-2026-09-22/11-user-sync.html
new file mode 100644
index 0000000..103c994
--- /dev/null
+++ b/docs/designs/admin-preview-2026-09-22/11-user-sync.html
@@ -0,0 +1 @@
+PhotoLive · 用户同步
\ No newline at end of file
diff --git a/docs/designs/admin-preview-2026-09-22/12-usage.html b/docs/designs/admin-preview-2026-09-22/12-usage.html
new file mode 100644
index 0000000..66d1301
--- /dev/null
+++ b/docs/designs/admin-preview-2026-09-22/12-usage.html
@@ -0,0 +1 @@
+PhotoLive · 存储与用量
\ No newline at end of file
diff --git a/docs/designs/admin-preview-2026-09-22/13-embed-slots.html b/docs/designs/admin-preview-2026-09-22/13-embed-slots.html
new file mode 100644
index 0000000..9490137
--- /dev/null
+++ b/docs/designs/admin-preview-2026-09-22/13-embed-slots.html
@@ -0,0 +1 @@
+PhotoLive · 网站展示位
\ No newline at end of file
diff --git a/docs/designs/admin-preview-2026-09-22/14-embed-editor.html b/docs/designs/admin-preview-2026-09-22/14-embed-editor.html
new file mode 100644
index 0000000..d77f034
--- /dev/null
+++ b/docs/designs/admin-preview-2026-09-22/14-embed-editor.html
@@ -0,0 +1 @@
+PhotoLive · 配置展示位
\ No newline at end of file
diff --git a/docs/designs/admin-preview-2026-09-22/15-branding.html b/docs/designs/admin-preview-2026-09-22/15-branding.html
new file mode 100644
index 0000000..ad98d58
--- /dev/null
+++ b/docs/designs/admin-preview-2026-09-22/15-branding.html
@@ -0,0 +1 @@
+PhotoLive · 宣传图与资产
\ No newline at end of file
diff --git a/docs/designs/admin-preview-2026-09-22/16-photo-viewer.html b/docs/designs/admin-preview-2026-09-22/16-photo-viewer.html
new file mode 100644
index 0000000..0e9d177
--- /dev/null
+++ b/docs/designs/admin-preview-2026-09-22/16-photo-viewer.html
@@ -0,0 +1 @@
+PhotoLive · 照片大图
\ No newline at end of file
diff --git a/docs/designs/admin-preview-2026-09-22/17-403.html b/docs/designs/admin-preview-2026-09-22/17-403.html
new file mode 100644
index 0000000..a0e5bef
--- /dev/null
+++ b/docs/designs/admin-preview-2026-09-22/17-403.html
@@ -0,0 +1 @@
+PhotoLive · 无权限
\ No newline at end of file
diff --git a/docs/designs/admin-preview-2026-09-22/18-404.html b/docs/designs/admin-preview-2026-09-22/18-404.html
new file mode 100644
index 0000000..e1e2560
--- /dev/null
+++ b/docs/designs/admin-preview-2026-09-22/18-404.html
@@ -0,0 +1 @@
+PhotoLive · 页面不存在
\ No newline at end of file
diff --git a/docs/designs/admin-preview-2026-09-22/19-500.html b/docs/designs/admin-preview-2026-09-22/19-500.html
new file mode 100644
index 0000000..2a728db
--- /dev/null
+++ b/docs/designs/admin-preview-2026-09-22/19-500.html
@@ -0,0 +1 @@
+PhotoLive · 服务异常
\ No newline at end of file
diff --git a/docs/designs/admin-preview-2026-09-22/20-sync-detail.html b/docs/designs/admin-preview-2026-09-22/20-sync-detail.html
new file mode 100644
index 0000000..ccefad9
--- /dev/null
+++ b/docs/designs/admin-preview-2026-09-22/20-sync-detail.html
@@ -0,0 +1 @@
+PhotoLive · 同步批次详情
\ No newline at end of file
diff --git a/docs/designs/admin-preview-2026-09-22/README.md b/docs/designs/admin-preview-2026-09-22/README.md
new file mode 100644
index 0000000..88fa861
--- /dev/null
+++ b/docs/designs/admin-preview-2026-09-22/README.md
@@ -0,0 +1,63 @@
+# PhotoLive 管理后台新版 HTML 原型
+
+打开 **index.html**,使用左侧菜单浏览;点击“全部页面目录”查看20个入口。每个页面也有独立HTML文件,可双击打开。无需启动服务或访问互联网。
+
+视觉基于Art Design Pro / Element Plus的后台布局,但此目录是独立原生HTML原型,没有改动 `apps/admin`。
+
+## 交付文件
+
+- `index.html`:默认相册管理入口。
+- `01-*.html` 至 `20-*.html`:独立页面,见下表。
+- `styles.css`、`admin.js`、`icons.js`、`pages.js`:共享外观、交互及索引。
+- `assets/`:离线示例图片与演示二维码。
+- `screenshots/01.png` 至 `20.png`:实际HTML渲染截图;mobile前缀为窄屏检查。
+- `validation.json`:本次浏览器检查结果。
+- `image-prompt.txt`:概念图完整生成提示词。
+- `../../plans/2026-09-22-UI05-管理后台分析与新版设计说明.md`:现状分析、接口差异及实施映射。
+
+## 页面目录
+
+| 编号 | 内容 | 文件 |
+|---|---|---|
+| 01 | 账号密码登录 | 01-login.html |
+| 02 | 相册卡片/表格列表 | 02-albums.html |
+| 03 | 相册照片网格/表格 | 03-photos.html |
+| 04 | 成员与所有者交接 | 04-members.html |
+| 05 | 双语分类 | 05-categories.html |
+| 06 | 水印预览、生成任务 | 06-watermark.html |
+| 07 | 分享卡、二维码、链接 | 07-sharing.html |
+| 08 | 新建相册表单 | 08-create-album.html |
+| 09 | 编辑资料、访问开关 | 09-edit-album.html |
+| 10 | 账号、角色与治理 | 10-users.html |
+| 11 | 用户目录同步 | 11-user-sync.html |
+| 12 | 用量、阈值与告警 | 12-usage.html |
+| 13 | 展示位、绑定、接入代码 | 13-embed-slots.html |
+| 14 | v1/v2配置与小窗预览 | 14-embed-editor.html |
+| 15 | 宣传图与资产入口 | 15-branding.html |
+| 16 | 管理大图及操作 | 16-photo-viewer.html |
+| 17 | 403 | 17-403.html |
+| 18 | 404 | 18-404.html |
+| 19 | 500 | 19-500.html |
+| 20 | 同步批次失败明细 | 20-sync-detail.html |
+
+## 可以体验
+
+- 中英文切换、相册搜索、卡片/表格切换、照片分类/状态筛选。
+- 查看大图、单张隐藏/恢复/软删除、选择已公开照片批量隐藏。
+- 创建和编辑示例相册、邀请内部示例用户、交接所有者、分类增改。
+- 水印文字/位置/透明度/字号即时预览。
+- 账号搜索、角色修改、重置密码流程、激活/锁定;自身账号角色不可改。
+- 同步运行模拟、失败详情、用量阈值对话框。
+- 展示位开关/绑定、v1/v2设置、固定195×280预览、收起展开、模拟气泡、复制示例代码。
+
+## 重要边界
+
+所有数据和操作为样例,不调用生产接口、不真正重置密码或上传/删除文件。请勿输入真实账号密码。原型状态只存在当前标签页内存,重新打开独立页会重置。
+
+摄影局部来自本次生成的后台概念图,`assets/photo-reference.png` 保留离线来源。界面文字、表单、卡片和表格均为真实DOM。样例文件名、时间、人数和数据不能抄进生产默认值。
+
+分享QR指向 `https://example.com/photolive-preview`,仅用于展示,不是相册链接。跨原型链接依赖上一层已生成的 `viewer-preview-2026-09-22.html` / `embed-preview-2026-09-22.html`;搬运目录时请一同携带,或修改为实际目标。
+
+嵌入配置中的预览为简化CSS展示;正式组件须复用现有UI04代码。此次未完成真实角色权限、OSS、网络异常、水印生成、用户同步或Art Design Pro运行集成验收。
+
+`build-preview.cjs` / `check-preview.cjs` 是本仓库的生成和检查辅助脚本。普通浏览无需执行它们。
diff --git a/docs/designs/admin-preview-2026-09-22/admin.js b/docs/designs/admin-preview-2026-09-22/admin.js
new file mode 100644
index 0000000..a3f8b6b
--- /dev/null
+++ b/docs/designs/admin-preview-2026-09-22/admin.js
@@ -0,0 +1,65 @@
+/* PhotoLive admin design prototype. All writes are local sample-state changes. */
+const $=s=>document.querySelector(s),$$=s=>[...document.querySelectorAll(s)];
+const icon=n=>` `;
+const esc=s=>String(s).replace(/[&<>"']/g,c=>({'&':'&','<':'<','>':'>','"':'"',"'":'''}[c]));
+let lang='zh',page=2,albumIndex=0,albumMode='grid',photoMode='grid',photoFilter='all',photoCategory='all',photoQuery='',albumQuery='',albumStatus='all',currentPhoto=0,selected=new Set(),toastTimer,syncRunning=false,wmVersion=3,wmPosition='bottom-right',slotIndex=0;
+const T=(en,zh)=>lang==='zh'?zh:en;
+const albums=[{title:'Canton Fair · Autumn',zh:'广交会 · 秋季',date:'2026.10.15 – 10.19',venue:'Guangzhou',owner:'Alex Morgan',public:true,upload:true,photo:0},{title:'Product Launch 2026',zh:'2026 新品发布会',date:'2026.09.28',venue:'Shenzhen',owner:'Emma Chen',public:true,upload:true,photo:5},{title:'Team Stories',zh:'团队故事',date:'2026.09.22',venue:'Shanghai',owner:'Daniel Lee',public:false,upload:true,photo:2},{title:'Design Summit',zh:'设计峰会',date:'2026.10.08 – 10.09',venue:'Hangzhou',owner:'Alex Morgan',public:true,upload:false,photo:4},{title:'Partner Conference',zh:'合作伙伴大会',date:'2026.11.12',venue:'Singapore',owner:'Emma Chen',public:false,upload:true,photo:1},{title:'Innovation Week',zh:'创新周',date:'2026.11.20 – 11.24',venue:'Guangzhou',owner:'Daniel Lee',public:true,upload:true,photo:3}];
+const people=[{name:'Alex Morgan',account:'alex.morgan',role:'admin',source:'local',credential:'active',locked:false},{name:'Emma Chen',account:'emma.chen',role:'staff',source:'active',credential:'active',locked:false},{name:'Daniel Lee',account:'daniel.lee',role:'staff',source:'active',credential:'pending',locked:false},{name:'Olivia Wang',account:'olivia.wang',role:'staff',source:'disabled',credential:'active',locked:true},{name:'James Wilson',account:'james.wilson',role:'staff',source:'active',credential:'active',locked:false}];
+let memberIds=[0,1,2],cats=[{en:'Exhibition',zh:'展会现场'},{en:'People',zh:'人物交流'},{en:'Highlights',zh:'精彩瞬间'}];
+const photoStates=Array.from({length:12},(_,i)=>i===6?'hidden':i===10?'unpublished':i===11?'deleted':'published');
+const slots=[{name:'Corporate website',zh:'企业官网',album:0,enabled:true,mode:'v2',version:4,speed:16},{name:'Event landing page',zh:'活动专题页',album:1,enabled:true,mode:'v1',version:2,speed:16},{name:'Partner portal',zh:'合作伙伴门户',album:null,enabled:false,mode:'v2',version:1,speed:16}];
+// Photographic regions only; the full source board is never used as the UI.
+const pics=[[292,165,393,149],[612,565,292,117],[931,565,292,117],[1247,565,289,117],[279,786,295,118],[608,786,295,118],[934,786,289,118],[1250,786,287,118]];
+function photo(i,cls=''){const[x,y,w,h]=pics[(i+pics.length)%pics.length];return `
`}
+function btn(label,action,cls='',ic=''){return `${ic?icon(ic):''}${label} `}
+function pill(label,cls=''){return ` ${label} `}
+function title(a=albums[albumIndex]){return esc(lang==='zh'?a.zh:a.title)}
+function avatar(name,cls=''){return `${esc(name.split(' ').map(x=>x[0]).join(''))} `}
+function field(label,id,value='',type='text',note=''){return `${label} ${note?`${note} `:''} `}
+function select(label,id,opts,value){return `${label}${opts.map(([v,s])=>`${s} `).join('')} `}
+function switchRow(label,desc,id,on){return `${label} ${desc}
`}
+function table(headers,rows){return `${headers.map(x=>`${x} `).join('')} ${rows.map(cols=>`${cols.map(x=>`${x} `).join('')} `).join('')}
`}
+function heading(name,desc,actions=''){return ``}
+function tabs(){return `${[[3,'Photos','照片'],[4,'Members','成员'],[5,'Categories','分类'],[6,'Watermark','水印'],[7,'Sharing','分享'],[15,'Branding','宣传图与资产']].map(([id,en,zh])=>`${T(en,zh)} `).join('')} `}
+function albumHeader(){const a=albums[albumIndex];return heading(title(),T('Album workspace · Manage the moments that matter','相册工作区 · 管理活动中的精彩瞬间'),btn(T('Edit album','编辑相册'),'go:9','outline','edit')+btn(T('Share album','分享相册'),'go:7','primary','share'))+`${photo(a.photo,'cover')}
`+tabs()}
+function shell(content){const selectedRoute=[2,3,4,5,6,7,8,9,15,16].includes(page)?2:[13,14].includes(page)?13:page===20?11:page;const link=(id,ic,en,zh)=>`${icon(ic)}${T(en,zh)} `;return `PhotoLive / ${window.ADMIN_PAGES.find(p=>p.id===page)?.[lang]||T('Workspace','工作空间')}
${T('DESIGN PREVIEW · SAMPLE DATA','设计预览 · 示例数据')} 中文 EN ${avatar('Alex Morgan')}Alex Morgan
${content} `}
+function login(){return `${photo(0)}${icon('logo')}PhotoLive
EVERY EVENT. EVERY MOMENT.
${T('Bring your events into focus.','每个精彩现场, 从这里开始。')} ${T('One workspace for your event albums, team and shared moments.','集中管理活动相册、协作团队与照片,让每个精彩瞬间及时抵达观众。')}
PhotoLive · Staff workspace
`}
+function albumList(){const rows=albums.map((a,i)=>({a,i})).filter(({a})=>(!albumQuery||JSON.stringify(a).toLowerCase().includes(albumQuery.toLowerCase()))&&(albumStatus==='all'||String(a.public)===albumStatus));return heading(T('Albums','相册管理'),T('A clear view of every event and the team behind it.','以活动为中心,管理相册、团队和每一张照片。'),btn(T('New album','新建相册'),'go:8','primary','plus'))+`${T('Loaded sample albums','已加载示例相册')} · ${rows.length} ${T('Sorted by creation time · cursor-based loading','按创建时间排序 · 沿用游标加载')}
${albumMode==='grid'?`${rows.map(({a,i})=>`
${photo(a.photo)}${pill(a.public?T('Public','公开'):T('Private','未公开'),a.public?'green':'gray')} ${title(a)} ${a.date} · ${a.venue}
`).join('')}
`:`${table([T('Album','相册'),T('Owner','创建者'),T('Event date','活动日期'),T('Public access','公开访问'),T('Actions','操作')],rows.map(({a,i})=>[title(a),a.owner,a.date,pill(a.public?T('Public','公开'):T('Private','未公开'),a.public?'green':'gray'),btn(T('Manage','管理'),'album:'+i,'small outline')]))}
`}${rows.length?T('All sample albums are loaded','示例相册已全部加载'):T('No albums match these filters','没有符合筛选条件的相册')}
`}
+function visibility(state){return {published:T('Published','已公开'),hidden:T('Hidden','已隐藏'),unpublished:T('Unpublished','未公开'),deleted:T('Deleted','已删除')}[state]}
+function filteredPhotos(){return Array.from({length:12},(_,i)=>i).filter(i=>(photoFilter==='all'||photoStates[i]===photoFilter)&&(photoCategory==='all'||i%3===Number(photoCategory))&&(!photoQuery||('DSC0'+(4872+i)+'.jpg').toLowerCase().includes(photoQuery.toLowerCase())))}
+function photosPage(){const list=filteredPhotos();return albumHeader()+`${selected.size} ${T('selected','张已选')} ${btn(T('Hide selected','隐藏选中照片'),'batchHide','small outline','eye')}${T('Only published photos can be selected','仅已公开照片可批量选择')}
${photoMode==='grid'?`${list.map(i=>`
DSC0${4872+i}.jpg ${people[i%3].name} · Oct 15, 2026
${icon('more')} `).join('')}
`:`${table([T('Photo','照片'),T('Processing','处理状态'),T('Visibility','可见性'),T('Uploader','上传者'),T('Likes (replica)','点赞数(副本)'),T('Actions','操作')],list.map(i=>[`
${photo(i,'tiny-photo')}DSC0${4872+i}.jpg
`,pill(i===10?T('Processing','处理中'):T('Ready','已就绪'),i===10?'':'green'),pill(visibility(photoStates[i]),photoStates[i]==='published'?'green':'gray'),people[i%3].name,[128,86,54,102][i%4],btn(T('Details','详情'),'photo:'+i,'small')]))}
`}${T('Sample photos · Statistics replica updated at 14:32 · No live API connection','示例照片 · 统计副本更新时间 14:32 · 未连接真实接口')}
`}
+function membersPage(){return albumHeader()+`${T('Album members','相册成员')} ${T('Owners manage all photos. Collaborators manage their own uploads.','创建者管理全部照片;协作者管理自己上传的照片。')}
${btn(T('Invite colleague','邀请同事'),'invite','primary','users')}
${table([T('Member','成员'),T('Account','账号'),T('Role','角色'),T('Scope','权限范围'),T('Actions','操作')],memberIds.map((id,index)=>{const p=people[id];return [`
${avatar(p.name)}${p.name}
`,p.account,pill(index===0?T('Owner','创建者'):T('Collaborator','协作者'),index===0?'':'gray'),index===0?T('All photos and members','全部照片及成员'):T('Own uploaded photos','自己上传的照片'),index===0?btn(T('Transfer ownership','交接相册'),'transfer','small'):btn(T('Remove','移除'),'removeMember:'+id,'small danger')]}))}
`}
+function categoriesPage(){return albumHeader()+`${T('Photo categories','照片分类')} ${T('Keep both content languages together when saving.','保存时保留所有语言内容,避免覆盖其他语言。')}
${btn(T('New category','新增分类'),'category:new','primary','plus')}
${table([T('Category','分类名称'),T('Chinese','中文'),T('English','English'),T('Actions','操作')],cats.map((c,i)=>[`
${icon('tag')} ${esc(c[lang])}
`,esc(c.zh),esc(c.en),btn(T('Edit','编辑'),'category:'+i,'small')+' '+btn(T('Delete','删除'),'deleteCategory:'+i,'small danger')]))}
${T('A category with photos cannot be deleted.','已有照片的分类不能直接删除。')}
`}
+function watermarkPage(){return albumHeader()+`
${T('Watermark settings','水印配置')} ${pill('v'+wmVersion,'green')}
${T('Visual preview','效果预览')} CSS ${T('simulation','示意')} ${photo(1)}PhotoLive
${T('Preview placement only. Final rendering is produced by the server.','此处仅示意位置,最终水印由服务端生成。')}
${T('Generation history','生成任务')} ${btn(T('Regenerate','重新生成'),'regenerate','outline','flip')}${table([T('Version','版本'),T('State','状态'),T('Processed','已处理'),T('Failed','失败'),T('Created','创建时间')],[['v'+wmVersion,pill(T('Completed','已完成'),'green'),'124 / 124','0','2026-09-22 14:20'],['v2',pill(T('Completed','已完成'),'green'),'118 / 118','0','2026-09-21 16:42']])}
`}
+function sharingPage(){return albumHeader()+`${photo(albums[albumIndex].photo,'cover')}
${title()} ${albums[albumIndex].date} · ${albums[albumIndex].venue}
${T('Demo code · example.com · not a public event link','演示二维码 · 指向 example.com · 非真实活动链接')}
${T('Share your event','分享活动相册')} ${T('Visitors browse without signing in. Public access must be enabled.','观众凭链接或扫码免登录浏览,须先开启相册公开访问。')}
${icon('globe')}${albums[albumIndex].public?T('Public access is enabled in this sample.','当前示例已开启公开访问。'):T('Public access is disabled in this sample.','当前示例已关闭公开访问。')}
${field(T('Preview link','预览链接'),'shareLink',new URL('../viewer-preview-2026-09-22.html',location.href).href)}
${btn(T('Copy preview link','复制预览链接'),'copyShare','primary','link')}${btn(T('Open viewer','打开观众页'),'viewer','outline')}
${T('Local file links work on this computer only. Production QR codes must use the public album URL.','本地链接仅用于本机预览,生产二维码必须使用真实公开相册 URL。')}
`}
+function albumForm(edit){const a=albums[albumIndex];return heading(edit?T('Edit album','编辑相册'):T('Create album','新建相册'),T('Event details, content languages and public access in one place.','统一配置活动资料、多语言内容与访问权限。'),btn(T('Cancel','取消'),'go:2'))+``}
+function usersPage(){return heading(T('Accounts','账号管理'),T('Provisioned company accounts, credential state and local access controls.','统一查看企业来源状态、登录凭据与本地账号治理。'),btn(T('View user sync','查看用户同步'),'go:11','outline','flip'))+`${icon('help')}${T('User information is pulled from the company directory. No public registration. Source state and local lock are independent.','用户信息来自企业接口定期拉取,不开放注册;来源状态与本地锁定相互独立。')}
`}
+function usersTable(query='',status='all'){return table([T('User','用户'),T('Role','角色'),T('Source status','来源状态'),T('Credentials','凭据状态'),T('Local lock','本地锁定'),T('Actions','操作')],people.map((p,i)=>({p,i})).filter(({p})=>(p.name+p.account).toLowerCase().includes(query.toLowerCase())&&(status==='all'||status==='locked'&&p.locked||status==='pending'&&p.credential==='pending')).map(({p,i})=>[`${avatar(p.name)}
${p.name} ${i===0?' '+pill(T('You','当前用户')):''}
${p.account}
`,pill(p.role==='admin'?T('Admin','管理员'):T('Staff','员工'),p.role==='admin'?'':'gray'),pill(p.source==='local'?T('Local','本地'):p.source==='active'?T('Active','来源有效'):T('Disabled','来源停用'),p.source==='disabled'?'red':'gray'),pill(p.credential==='pending'?T('Pending','待激活'):T('Active','已激活'),p.credential==='pending'?'amber':'green'),pill(p.locked?T('Locked','已锁定'):T('Unlocked','未锁定'),p.locked?'red':'gray'),`${btn(T('Edit','编辑'),'userEdit:'+i,'small')}${btn(T('Reset password','重置密码'),'resetPassword:'+i,'small')}${i>0?btn(p.credential==='pending'?T('Activate','激活'):p.locked?T('Unlock','解锁'):T('Lock','锁定'),'userState:'+i,'small'):''}
`]))}
+function syncPage(){return heading(T('User sync','用户同步'),T('Review scheduled directory pulls and resolve failed records.','查看企业用户接口的定时拉取结果,定位失败记录。'),btn(syncRunning?T('Running…','运行中…'):T('Pull now','手动补拉'),'sync','primary','flip'))+`${T('Engine state','同步引擎状态')}
${syncRunning?T('Running','运行中'):T('Idle','空闲')} ${T('Last success','最近成功')} 2026-09-22 14:30 ${T('Last batch','最近批次')}
128 ${T('processed','条处理')} ${T('3 created · 124 updated · 1 failed','新增 3 · 更新 124 · 失败 1')} ${T('Source version','来源版本')}
20260922.1430 ${T('User directory watermark, not photo replication','用户目录水位,并非照片跨境同步')}
${T('Run history','运行历史')} ${T('Sample scheduled jobs','示例定时任务')} ${table([T('Triggered','触发方式'),T('State','运行状态'),T('Started','开始时间'),T('Created','新增'),T('Updated','更新'),T('Failed','失败'),T('Details','详情')],Array.from({length:4},(_,i)=>[pill(i===1?T('Manual','手动'):T('Scheduled','定时'),'gray'),pill(i===0?T('Partial failure','部分失败'):T('Completed','完成'),i===0?'amber':'green'),`2026-09-22 ${14-i}:30`,i===0?'3':'0',i===0?'124':'128',i===0?'1':'0',btn(T('View run','查看批次'),'syncDetail:'+i,'small outline')]))}
`}
+function usagePage(){return heading(T('Storage & usage','存储与用量'),T('Understand retained assets and act before thresholds are exceeded.','查看长期保留的照片资产与告警阈值。'),btn(T('Threshold settings','告警阈值'),'thresholds','outline','settings'))+`${T('Total photos','照片总数')}
18,420 ${T('Sample aggregate from the usage response','示例用量接口汇总')} ${T('Stored assets','存储用量')}
148.6 GB ${T('Originals + viewing variants','原图 + 浏览变体')} ${T('Storage alert threshold','总存储告警阈值')}
200 GB ${T('An alert threshold, not a hard storage quota','告警阈值,并非存储硬配额')}
${T('Asset composition','资产构成')} ${T('OSS · retained by default','OSS · 默认长期保留')}
● ${T('Originals','原图')} 114.8 GB ● ${T('Variants','变体')} 33.8 GB
${T('Usage by album','相册用量')} ${table([T('Album','相册'),T('Photos','照片数'),T('Originals','原图'),T('Variants','变体'),T('Total','合计')],albums.slice(0,4).map((a,i)=>[title(a),[6280,4210,3150,4780][i],[42.5,26.1,18.7,27.5][i]+' GB',[12.3,8.2,5.8,7.5][i]+' GB',[54.8,34.3,24.5,35][i]+' GB']))}
${T('Alerts','用量告警')} ${table([T('State','状态'),T('Kind','类别'),T('Message','说明'),T('Time','时间')],[[pill(T('Active','未解决'),'amber'),T('Per-album storage','单相册存储'),T('Canton Fair exceeds the 50 GB sample threshold.','广交会相册超过示例阈值 50 GB。'),'2026-09-22 14:20'],[pill(T('Resolved','已解决'),'gray'),T('Storage','存储'),T('Previous threshold alert resolved.','历史阈值告警已解除。'),'2026-09-20 09:30']])}
`}
+function slotsPage(){return heading(T('Embed widgets','网站展示位'),T('Publish a small live photo window on your websites.','在企业网站中展示活动照片,管理绑定与展示配置。'),btn(T('New widget','新增展示位'),'newSlot','primary','plus'))+`${icon('photo')}${T('New design: 195 × 280 px on desktop and mobile. v1 carousel and v2 vertical stream remain distinct.','新版照片窗:电脑与手机统一 195 × 280 px;v1 轮播与 v2 上滚模式分开管理。')}
${table([T('Widget','展示位名称'),T('Bound album','绑定相册'),T('Mode','展示模式'),T('Enabled','启用'),T('Config version','配置版本'),T('Actions','操作')],slots.map((s,i)=>[esc(lang==='zh'?s.zh:s.name),s.album===null?pill(T('Unbound','未绑定'),'gray'):title(albums[s.album]),pill(s.mode==='v2'?T('v2 · Vertical stream','v2 · 照片上滚'):T('v1 · Carousel','v1 · 旧版轮播')),`
`,'v'+s.version,`
${btn(T('Configure','配置'),'slot:'+i,'small outline')}${btn(T('Bind album','绑定相册'),'bind:'+i,'small')}${btn(T('Get code','获取代码'),'code:'+i,'small')}
`]))}
`}
+function embedPreview(){const seq=[0,1,2,0,1,2];return `COMPANY WEBSITE / PREVIEW
${seq.map(i=>photo(i)).join('')}
♥ − ${T('Photos','照片')} `}
+function slotEditor(){const s=slots[slotIndex];return heading(T('Configure widget','配置展示位'),esc(lang==='zh'?s.zh:s.name),btn(T('Back to widgets','返回展示位'),'go:13'))+`${field(T('Name','名称'),'slotName',lang==='zh'?s.zh:s.name)}${select(T('Display mode','展示模式'),'slotMode',[['v2',T('v2 · Vertical stream','v2 · 照片上滚')],['v1',T('v1 · Existing carousel','v1 · 保留旧轮播')]],s.mode)}${field(T('Width (fixed)','宽度(固定)'),'slotWidth','195','number')}${field(T('Height (fixed)','高度(固定)'),'slotHeight','280','number')}${field(T('Scroll speed (px/s)','滚动速度(px/s)'),'slotSpeed',s.speed,'number')}${select(T('Position','悬浮位置'),'slotPosition',[['right',T('Right','右侧')],['left',T('Left','左侧')]],'right')}
${switchRow(T('Like bubbles','点赞气泡'),T('Real reactions in production; simulated here','正式版使用真实事件,此处仅模拟'),'slotReactions',true)}
${field(T('Width','宽度'),'legacyWidth','320','number')}${field(T('Interval (ms)','切图间隔(ms)'),'legacyInterval','5000','number')}
${T('Legacy settings are retained. The preview at right depicts the new design.','旧版配置继续保留。右侧展示新版设计参考。')}
${field(T('Horizontal offset','水平偏移'),'offsetX','16','number')}${field(T('Bottom offset','底部偏移'),'offsetY','24','number')}
${switchRow(T('Start collapsed on mobile','手机默认收起'),T('User choice has priority','用户主动选择优先'),'slotCollapsed',true)}
${T('Save configuration','保存配置')}
${T('Unsaved preview','未保存预览')} ${pill('195 × 280 px')}${embedPreview()}
${btn(T('Simulate a reaction','模拟点赞事件'),'embedHeart','small outline')}${btn(T('Open full widget demo','打开完整组件原型'),'widgetDemo','small')}
${T('Presentation mock only. The standalone widget demo implements the precise 16 px/s stream.','此面板为样式示意;独立组件原型实现精确 16 px/s 上滚。')}
`}
+function brandingPage(){return albumHeader()+`${T('Public album banner','观众页宣传图')} ${T('Prefer a wide image. Do not crop away embedded poster text.','建议使用横幅图片,保留海报中的文字内容。')}
${photo(albums[albumIndex].photo,'cover')}
${btn(T('Choose sample banner','选择示例宣传图'),'banner','primary','photo')}${btn(T('Preview public album','预览观众相册'),'viewer','outline')}
${T('Asset workflow','资产管理')} ${icon('upload')}${T('Init → OSS direct upload → completion verification','初始化凭证 → OSS 直传 → 完成核验')}
${T('The existing API accepts banner, cover and logo asset types. Production must keep signature expiry and upload verification behavior. This prototype only swaps sample photographs.','现有接口支持 banner、cover、logo 资产类型。正式实现保留签名过期与上传核验流程。本原型仅切换示例照片。')}
${T('Current sample','当前示例')} event-banner.jpg · image/jpeg · ${T('Sample preview','示意预览')}
`}
+function exceptionPage(code){const text={403:[T('Access restricted','暂无访问权限'),T('Your current account cannot access this workspace.','当前账号无权访问此页面,请联系公司管理员。')],404:[T('Page not found','页面不存在'),T('The link may have changed or the resource is unavailable.','链接可能已失效,或资源暂不可用。')],500:[T('Something went wrong','服务暂时不可用'),T('Please try again. Your saved data has not been changed by this preview.','请稍后重试,已保存的数据不会因本次预览发生变化。')]}[code];return `${code} ${text[0]} ${text[1]}
${btn(T('Back to albums','返回相册'),'go:2','primary')} `}
+function modal(name,body,footer='',wide=false){$('.modal')?.remove();const wrap=document.createElement('div');wrap.className='modal';wrap.innerHTML=`
${name} ${icon('close')} ${body}${footer?``:''} `;document.body.append(wrap);$('#root').inert=true;wrap.onclick=e=>{if(e.target===wrap)closeModal()};wrap.querySelector('input,button,select')?.focus();return wrap}
+function closeModal(){ $('.modal')?.remove();$('#root').inert=false;if(page===16)go(3);if(page===20)go(11)}
+function toast(text){$('.toast')?.remove();const el=document.createElement('div');el.className='toast';el.setAttribute('role','status');el.textContent=text;document.body.append(el);clearTimeout(toastTimer);toastTimer=setTimeout(()=>el.remove(),3200)}
+function go(id){if(page===Number(id)){render();return}location.hash=id}
+function render(){page=Number(location.hash.slice(1))||Number(document.body.dataset.page)||2;if(page<1||page>20)page=18;$('.modal')?.remove();$('#root').inert=false;document.documentElement.lang=lang==='zh'?'zh-CN':'en';if(page===1){$('#root').innerHTML=login();bind();return}let content='';switch(page){case 2:content=albumList();break;case 3:case 16:content=photosPage();break;case 4:content=membersPage();break;case 5:content=categoriesPage();break;case 6:content=watermarkPage();break;case 7:content=sharingPage();break;case 8:content=albumForm(false);break;case 9:content=albumForm(true);break;case 10:content=usersPage();break;case 11:case 20:content=syncPage();break;case 12:content=usagePage();break;case 13:content=slotsPage();break;case 14:content=slotEditor();break;case 15:content=brandingPage();break;case 17:content=exceptionPage(403);break;case 18:content=exceptionPage(404);break;case 19:content=exceptionPage(500);break}$('#root').innerHTML=shell(content);bind();if(page===16)openPhoto(currentPhoto);if(page===20)syncDetail(0);document.title='PhotoLive · '+(window.ADMIN_PAGES.find(p=>p.id===page)?.[lang]||'Preview')}
+function openPhoto(i){currentPhoto=i;const state=photoStates[i];if(state==='deleted'){toast(T('This sample photo has been deleted.','该示例照片已删除。'));return}const wrap=modal(T('Photo details','照片详情'),'');wrap.querySelector('.dialog').className='dialog viewer-dialog';wrap.querySelector('.dialog').innerHTML=`${icon('close')} ${photo(i)}
DSC0${4872+i}.jpg ${people[i%3].name}
2026-10-15 10:42 2400 × 1600 · 2.8 MB
${pill(visibility(state),state==='published'?'green':'gray')}
${T('Likes (statistics replica)','点赞数(统计副本)')} · ${[128,86,54,102][i%4]}
${state!=='unpublished'?btn(state==='hidden'?T('Publish again','恢复公开'):T('Hide photo','隐藏照片'),'visibility:'+i,'outline','eye'):''}${btn(T('Delete photo','删除照片'),'deletePhoto:'+i,'danger','trash')}
${T('Staff management actions only. No public like or download controls.','此处为工作人员管理操作,不提供观众点赞或下载按钮。')}
`}
+function syncDetail(i){modal(T('Sync run details','同步批次详情'),`${icon('flip')}${i===0?T('127 succeeded · 1 failed','127 条成功 · 1 条失败'):T('128 succeeded · 0 failed','128 条成功 · 0 条失败')}
${table([T('Record','记录'),T('Result','结果'),T('Reason','原因')],i===0?[['sample.user.129',pill(T('Failed','失败'),'red'),T('Missing required account field','缺少必填账号字段')]]:[['—',pill(T('Completed','完成'),'green'),T('No failed records','没有失败记录')]])}${T('Example failure details are redacted. Correct the source data before the next run.','失败明细为脱敏示例,请修正来源数据后再进行补拉。')}
`,btn(T('Close','关闭'),'close'))}
+function filterInput(id,current,assign){const el=$('#'+id);if(el)el.oninput=e=>{const start=e.target.selectionStart;assign(e.target.value);render();const next=$('#'+id);next.focus();next.setSelectionRange(start,start)}}
+function bind(){const locale=$('#language');if(locale)locale.onchange=e=>{lang=e.target.value;render()};const loginForm=$('#loginForm');if(loginForm)loginForm.onsubmit=e=>{e.preventDefault();if(!$('#loginAccount').value.trim()){$('#formError').textContent=T('Enter a sample account.','请输入演示账号。');return}go(2)};filterInput('albumSearch',albumQuery,x=>albumQuery=x);filterInput('photoSearch',photoQuery,x=>photoQuery=x);if($('#albumStatus'))$('#albumStatus').onchange=e=>{albumStatus=e.target.value;render()};if($('#photoCategory'))$('#photoCategory').onchange=e=>{photoCategory=e.target.value;render()};$$('.photo-check').forEach(el=>el.onchange=()=>{const i=Number(el.value);if(el.checked)selected.add(i);else selected.delete(i);render()});const filterUsers=()=>$('#usersTable').innerHTML=usersTable($('#userSearch').value,$('#userStatus').value);if($('#userSearch')){$('#userSearch').oninput=filterUsers;$('#userStatus').onchange=filterUsers}$$('[data-slot-toggle]').forEach(el=>el.onchange=()=>{const s=slots[Number(el.dataset.slotToggle)];s.enabled=el.checked;s.version++;render();toast(T('Sample widget state updated','示例展示位状态已更新'))});
+const form=$('#albumForm');if(form){$('#albumDownload').onchange=e=>{$('#albumOriginal').disabled=!e.target.checked;if(!e.target.checked)$('#albumOriginal').checked=false};form.onsubmit=e=>{e.preventDefault();if(!$('#titleZh').value.trim()||!$('#titleEn').value.trim()||!$('#startDate').value||$('#endDate').value<$('#startDate').value){$('#formError').textContent=T('Enter both sample titles and a valid date range.','请填写示例双语标题及有效日期范围。');return}const data={title:$('#titleEn').value,zh:$('#titleZh').value,date:$('#startDate').value+' – '+$('#endDate').value,venue:$('#venueEn').value||$('#venueZh').value,owner:'Alex Morgan',public:$('#albumPublic').checked,upload:$('#albumUpload').checked,photo:0};if(page===8){albums.unshift(data);albumIndex=0}else albums[albumIndex]={...albums[albumIndex],...data};go(3)}}
+if($('#watermarkForm')){const preview=()=>{const el=$('#wmPreview');el.textContent=$('#wmText').value;el.hidden=!$('#wmOn').checked;el.style.opacity=$('#wmOpacity').value/100;el.style.fontSize=Math.min(72,Math.max(8,Number($('#wmFont').value)||20))+'px';const pos=$('#wmPosition').value;el.style.top=pos.startsWith('top')?'18px':pos==='center'?'50%':'auto';el.style.bottom=pos.startsWith('bottom')?'18px':'auto';el.style.left=pos.endsWith('left')?'18px':pos==='center'?'50%':'auto';el.style.right=pos.endsWith('right')?'18px':'auto';el.style.transform=pos==='center'?'translate(-50%,-50%)':''};['wmText','wmOpacity','wmFont','wmPosition','wmOn'].forEach(id=>$('#'+id).oninput=preview);$('#watermarkForm').onsubmit=e=>{e.preventDefault();wmVersion++;toast(T('Sample generation job accepted. No images are modified.','示例生成任务已受理,未修改任何图片。'))}}
+if($('#slotForm')){const s=slots[slotIndex];$('#slotWidth').readOnly=true;$('#slotHeight').readOnly=true;$('#slotSpeed').min=8;$('#slotSpeed').max=32;const mode=()=>{$('#v2Fields').hidden=$('#slotMode').value!=='v2';$('#v1Fields').hidden=$('#slotMode').value!=='v1'};$('#slotMode').onchange=mode;mode();$('#offsetX').oninput=()=>{$('#embedded').style.right=Math.max(0,Number($('#offsetX').value))+'px'};$('#offsetY').oninput=()=>{$('#embedded').style.bottom=Math.max(0,Number($('#offsetY').value))+'px'};$('#slotPosition').onchange=e=>{$('#embedded').style.left=e.target.value==='left'?'16px':'auto';$('#embedded').style.right=e.target.value==='right'?'16px':'auto'};$('#slotForm').onsubmit=e=>{e.preventDefault();const speed=Number($('#slotSpeed').value);if(!$('#slotName').value.trim()||speed<8||speed>32){$('#formError').textContent=T('Name required. Speed must be between 8 and 32.','请填写名称,速度须在 8–32 之间。');return}s.name=$('#slotName').value;s.zh=s.name;s.speed=speed;s.mode=$('#slotMode').value;s.version++;go(13)}}}
+function confirm(titleText,body,callback){modal(titleText,`${body}
`,btn(T('Cancel','取消'),'close')+btn(T('Confirm','确认'),'confirm','primary'));$('[data-action="confirm"]').onclick=()=>{closeModal();callback()}}
+function action(raw){const [name,...rest]=raw.split(':'),value=rest.join(':');switch(name){case 'go':go(value);break;case 'close':closeModal();break;case 'menu':$('#sidebar').classList.toggle('open');break;case 'directory':modal(T('All preview pages','全部预览页面'),`${window.ADMIN_PAGES.map(p=>btn(String(p.id).padStart(2,'0')+' · '+p[lang],'go:'+p.id,'')).join('')}
`,'',true);break;case 'album':albumIndex=Number(value);go(3);break;case 'albumMode':albumMode=value;render();break;case 'photoMode':photoMode=value;render();break;case 'photoFilter':photoFilter=value;render();break;case 'photo':openPhoto(Number(value));break;case 'batchHide':if(!selected.size)return;confirm(T('Hide selected photos?','隐藏选中的照片?'),T('This changes sample visibility only. Real batches must report per-photo success and failure.','仅修改示例可见性。真实批处理需逐项反馈成功和失败。'),()=>{selected.forEach(i=>photoStates[i]='hidden');selected.clear();render();toast(T('Sample photos hidden','示例照片已隐藏'))});break;case 'visibility':{const i=Number(value);confirm(photoStates[i]==='hidden'?T('Publish this photo?','恢复公开这张照片?'):T('Hide this photo?','隐藏这张照片?'),T('Public visibility changes. The original remains stored.','改变公开可见性,原图仍保留在存储中。'),()=>{photoStates[i]=photoStates[i]==='hidden'?'published':'hidden';selected.delete(i);render()});break}case 'deletePhoto':confirm(T('Delete photo?','删除照片?'),T('Soft deletion removes the sample from active management. This does not immediately physically delete OSS files.','软删除会让照片退出有效管理列表,不代表立即物理删除 OSS 文件。'),()=>{photoStates[Number(value)]='deleted';selected.delete(Number(value));render()});break;
+case 'invite':{modal(T('Invite colleague','邀请同事'),`${icon('user')}
${people.map((p,i)=>!memberIds.includes(i)?`${avatar(p.name)}${p.name} · ${p.account} `:'').join('')}
${T('No external email or registration invitation is sent.','仅选择内部账号,不发送外部邮件或注册邀请。')}
`);$('#inviteSearch').oninput=e=>$$('.candidate').forEach(el=>el.hidden=!el.textContent.toLowerCase().includes(e.target.value.toLowerCase()));break}case 'addMember':memberIds.push(Number(value));closeModal();render();break;case 'removeMember':confirm(T('Remove collaborator?','移除协作者?'),T('The sample account loses collaborator access to this album.','该示例账号将不再作为本相册协作者。'),()=>{memberIds=memberIds.filter(i=>i!==Number(value));render()});break;case 'transfer':modal(T('Transfer album ownership','交接相册'),select(T('New owner','新创建者'),'newOwner',people.slice(1).map((p,i)=>[String(i+1),p.name]),'1')+`${T('Production must recheck the target account and creator permissions.','正式版需再次校验目标账号与创建者权限。')}
`,btn(T('Cancel','取消'),'close')+btn(T('Transfer sample','交接示例'),'confirmTransfer','primary'));break;case 'confirmTransfer':{const id=Number($('#newOwner').value);albums[albumIndex].owner=people[id].name;memberIds=[id,...memberIds.filter(i=>i!==id)];closeModal();render();break}
+case 'category':{const i=value==='new'?-1:Number(value);modal(i<0?T('New category','新增分类'):T('Edit category','编辑分类'),`${field('中文','catZh',i<0?'':cats[i].zh)}${field('English','catEn',i<0?'':cats[i].en)}${T('Save category','保存分类')} `);$('#categoryForm').onsubmit=e=>{e.preventDefault();if(!$('#catZh').value.trim()||!$('#catEn').value.trim()){toast(T('Complete both sample language fields','请填写示例双语名称'));return}const item={zh:$('#catZh').value,en:$('#catEn').value};if(i<0)cats.push(item);else cats[i]=item;closeModal();render()};break}case 'deleteCategory':if(Number(value)<3)toast(T('This sample category contains photos and cannot be deleted.','该示例分类已有照片,不能删除。'));else confirm(T('Delete empty category?','删除空分类?'),T('Only this empty sample category is removed.','仅移除该空示例分类。'),()=>{cats.splice(Number(value),1);render()});break;case 'regenerate':confirm(T('Regenerate viewing variants?','重新生成浏览变体?'),T('Production creates an asynchronous job. This preview does not modify OSS.','正式版创建异步生成任务,此预览不修改 OSS。'),()=>{wmVersion++;render();toast(T('Sample job created','示例任务已创建'))});break;case 'copyShare':copy($('#shareLink').value);break;case 'viewer':window.open('../viewer-preview-2026-09-22.html','_blank','noopener,noreferrer');break;
+case 'userEdit':{const i=Number(value),p=people[i];modal(T('Edit account','编辑账号'),`${field(T('Display name','显示名称'),'userName',p.name)}${select(T('Role','角色'),'userRole',[['admin',T('Administrator','管理员')],['staff',T('Staff','员工')]],p.role)}${i===0?T('Your own role cannot be changed here.','不能在这里修改自己的角色。'):T('Source status remains controlled by the company directory.','来源状态仍由企业用户接口控制。')}
${T('Save','保存')} `);$('#userRole').disabled=i===0;$('#userEditForm').onsubmit=e=>{e.preventDefault();p.name=$('#userName').value||p.name;if(i!==0)p.role=$('#userRole').value;closeModal();render()};break}case 'resetPassword':{const p=people[Number(value)];modal(T('Reset password','重置密码'),`${p.name} · ${p.account}
${field(T('Temporary password (demo only)','临时密码(仅演示)'),'tempPassword','','password')}${T('Do not enter real credentials. Nothing is stored or sent.','请勿输入真实凭据,此处不保存或发送密码。')}
${T('Confirm reset preview','确认重置演示')} `);$('#resetForm').onsubmit=e=>{e.preventDefault();closeModal();toast(T('Password reset flow previewed. No credentials changed.','已演示密码重置流程,未修改真实凭据。'))};break}case 'userState':{const i=Number(value);if(i===0)return;const p=people[i];confirm(T('Change local account state?','修改本地账号状态?'),T('The company directory state remains unchanged.','来源接口状态不会随本地治理动作改变。'),()=>{if(p.credential==='pending')p.credential='active';else p.locked=!p.locked;render()});break}case 'resetUserFilters':$('#userSearch').value='';$('#userStatus').value='all';$('#usersTable').innerHTML=usersTable();break;case 'sync':if(syncRunning)return;confirm(T('Run a sample pull?','模拟一次用户补拉?'),T('This is a local animation; no company directory is contacted.','仅在本地演示运行状态,不请求企业用户接口。'),()=>{syncRunning=true;render();setTimeout(()=>{syncRunning=false;if([11,20].includes(page))render();toast(T('Sample pull completed','模拟补拉已完成'))},1800)});break;case 'syncDetail':syncDetail(Number(value));break;case 'thresholds':modal(T('Alert thresholds','告警阈值'),`${field(T('Total storage threshold (GB)','总存储阈值(GB)'),'totalThreshold','200','number')}${field(T('Per-album threshold (GB)','单相册阈值(GB)'),'albumThreshold','50','number')}${T('Thresholds trigger alerts, not automatic deletion.','达到阈值仅触发告警,不自动删除照片。')}
${T('Save sample thresholds','保存示例阈值')} `);$('#thresholdForm').onsubmit=e=>{e.preventDefault();const value=Number($('#totalThreshold').value);if(value<0){toast(T('Use a non-negative number','请输入非负数字'));return}closeModal();if($('#thresholdValue'))$('#thresholdValue').textContent=value+' GB';toast(T('Sample threshold updated','示例阈值已更新'))};break;
+case 'newSlot':slots.push({name:'New widget',zh:'新展示位',album:null,enabled:false,mode:'v2',version:1,speed:16});slotIndex=slots.length-1;go(14);break;case 'slot':slotIndex=Number(value);go(14);break;case 'bind':{slotIndex=Number(value);modal(T('Bind album','绑定相册'),select(T('Album','相册'),'bindAlbum',[['none',T('Unbind','解除绑定')],...albums.map((a,i)=>[String(i),lang==='zh'?a.zh:a.title])],slots[slotIndex].album===null?'none':String(slots[slotIndex].album))+`${T('The same embedded slot will display the newly bound album after configuration refresh.','配置刷新后,使用此展示位的网站将展示新绑定的相册。')}
`,btn(T('Cancel','取消'),'close')+btn(T('Confirm binding','确认绑定'),'confirmBind','primary'));break}case 'confirmBind':slots[slotIndex].album=$('#bindAlbum').value==='none'?null:Number($('#bindAlbum').value);slots[slotIndex].version++;closeModal();render();break;case 'code':{const s=slots[Number(value)];const code='