feat: add scoped device catalog and unlimited custom area hierarchy
This commit is contained in:
+7
-6
@@ -1,11 +1,12 @@
|
||||
'use strict';
|
||||
pageInfo.households=['家庭管理','一户一家园,资料各有归属。'];
|
||||
pageInfo.households=['家庭与场所','家庭、办公室或工厂,分别组织,各自授权。'];
|
||||
const scopeKind=h=>({home:'家庭',office:'办公场所',factory:'工厂'}[h.kind||'home']||'家庭');
|
||||
function renderHouseholds(){
|
||||
const homes=state.households||[];
|
||||
setOptions($('#household-filter'),homes.map(h=>`<option value="${esc(h.id)}">${esc(h.name)}</option>`).join(''));
|
||||
setOptions($('#household-filter'),homes.map(h=>`<option value="${esc(h.id)}">${esc(scopeKind(h)+' · '+h.name)}</option>`).join(''));
|
||||
$('#household-filter').value=state.familyId||'';
|
||||
if(activePage!=='households')return;
|
||||
$('#household-list').innerHTML=homes.map(h=>`<article class="site-card"><div class="site-heading"><span class="badge">${h.id===state.familyId?'当前家庭':'独立家庭'}</span><button class="quiet" data-edit-household="${esc(h.id)}">编辑档案</button></div><h3>${esc(h.name)}</h3><p class="description">${esc(h.note||'一户一家园')}</p><dl><div><dt>一家之主</dt><dd>${esc(h.ownerName||'待指定')}</dd></div><div><dt>备用负责人</dt><dd>${esc(h.successorName||'待指定')}</dd></div><div><dt>账号 / 空间</dt><dd>${h.members} 个 / ${h.sites} 处</dd></div></dl>${!h.successorId?'<p class="description">尚未指定备用负责人,建议提前安排家人接管。</p>':''}<div class="household-actions"><button class="secondary" data-enter-household="${esc(h.id)}">${h.id===state.familyId?'管理本家庭成员':'进入该家庭'}</button>${h.canAssignOwner?`<button class="quiet" data-leadership="${esc(h.id)}">家主与权限交接</button>`:''}</div>${h.leadershipHistory?.length?`<details><summary>交接记录</summary>${h.leadershipHistory.slice().reverse().map(r=>`<p class="description">${esc(new Date(r.at).toLocaleString())} · ${esc(r.actor)}<br>${esc(r.reason)}</p>`).join('')}</details>`:''}</article>`).join('');
|
||||
$('#household-list').innerHTML=homes.map(h=>`<article class="site-card"><div class="site-heading"><span class="badge">${h.id===state.familyId?'当前归属 · ':''}${scopeKind(h)}</span><button class="quiet" data-edit-household="${esc(h.id)}">编辑档案</button></div><h3>${esc(h.name)}</h3><p class="description">${esc(h.note||'区域与设备归属独立管理')}</p><dl><div><dt>${!h.kind||h.kind==='home'?'一家之主':'主要负责人'}</dt><dd>${esc(h.ownerName||'待指定')}</dd></div><div><dt>备用负责人</dt><dd>${esc(h.successorName||'待指定')}</dd></div><div><dt>账号 / 空间</dt><dd>${h.members} 个 / ${h.sites} 处</dd></div></dl>${!h.successorId?'<p class="description">尚未指定备用负责人,建议提前安排可信人员接管。</p>':''}<div class="household-actions"><button class="secondary" data-enter-household="${esc(h.id)}">${h.id===state.familyId?'管理本归属成员':'进入该归属'}</button>${h.canAssignOwner?`<button class="quiet" data-leadership="${esc(h.id)}">负责人安排与交接</button>`:''}</div>${h.leadershipHistory?.length?`<details><summary>交接记录</summary>${h.leadershipHistory.slice().reverse().map(r=>`<p class="description">${esc(new Date(r.at).toLocaleString())} · ${esc(r.actor)}<br>${esc(r.reason)}</p>`).join('')}</details>`:''}</article>`).join('');
|
||||
}
|
||||
async function switchHousehold(id){
|
||||
if(!isPlatformAdmin()||!id||id===state.familyId)return;
|
||||
@@ -29,7 +30,7 @@ async function openLeadership(id){
|
||||
const result=await api('/api/users');
|
||||
const candidates=result.users.filter(u=>u.role==='family_admin'&&!u.disabled);
|
||||
const f=$('#leadership-form'),options=candidates.map(u=>`<option value="${esc(u.id)}">${esc(u.name+' / '+u.username)}</option>`).join('');
|
||||
f.elements.ownerId.innerHTML='<option value="">请选择一家之主</option>'+options;
|
||||
f.elements.ownerId.innerHTML='<option value="">请选择主要负责人</option>'+options;
|
||||
f.elements.successorId.innerHTML='<option value="">暂未指定</option>'+options;
|
||||
fillForm(f,{id:home.id,revision:home.leadershipRevision||0,ownerId:home.ownerId||'',successorId:home.successorId||''});
|
||||
$('#leadership-dialog').showModal();
|
||||
@@ -37,14 +38,14 @@ async function openLeadership(id){
|
||||
}
|
||||
$('#leadership-form').addEventListener('submit',async e=>{
|
||||
e.preventDefault();const f=e.currentTarget,b=f.querySelector('[type=submit]');b.disabled=true;
|
||||
try{const d=formValues(f);d.revision=Number(d.revision);await api('/api/households/leadership',d);f.closest('dialog').close();await refresh();showPage('households');toast('家庭负责人已更新,交接记录已保存');}
|
||||
try{const d=formValues(f);d.revision=Number(d.revision);await api('/api/households/leadership',d);f.closest('dialog').close();await refresh();showPage('households');toast('负责人已更新,交接记录已保存');}
|
||||
catch(error){if(!error.stale)f.querySelector('.form-error').textContent=error.message;}finally{b.disabled=false;}
|
||||
});
|
||||
$('#household-filter').onchange=e=>switchHousehold(e.target.value);
|
||||
$('#new-household').onclick=()=>openHousehold();
|
||||
$('#household-form').addEventListener('submit',async e=>{
|
||||
e.preventDefault();const f=e.currentTarget,b=f.querySelector('[type=submit]');b.disabled=true;
|
||||
try{await api('/api/households',formValues(f));f.closest('dialog').close();await refresh();toast('家庭档案已保存');}
|
||||
try{await api('/api/households',formValues(f));f.closest('dialog').close();await refresh();toast('归属档案已保存');}
|
||||
catch(error){if(!error.stale)f.querySelector('.form-error').textContent=error.message;}
|
||||
finally{b.disabled=false;}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user