feat(panel-kit): 写入窗口时长升级为配置驱动 window_hours

苍耳提请:一次授权3小时太短,胖头鱼升至12小时。
- server.js:WINDOW_HOURS 读 config.json(缺省3h保持向后兼容),
  TTL/全部文案/唤醒链/领取规则/git代理提示动态化;state() 新增 windowHours
- config.example.json:新增 window_hours 字段(示例12)
- INDEX.hdlp:窗口制说明与铁律同步
- 两套前端示例:授权按钮改读 s.windowHours 动态时长
- 钩子模板:拒绝文案去掉写死时长
This commit is contained in:
冰朔 2026-08-07 18:56:35 +08:00
commit a6ad978b04
6 changed files with 20 additions and 17 deletions

View file

@ -376,7 +376,7 @@ function render(s){
const prs=s.openPRs||[];setCnt("cnt-sign",prs.length);
document.getElementById("prs").innerHTML=prs.length?prs.map(p=>'<div class="item"><div class="t">PR #'+p.index+' · '+esc(p.title)+'</div><div class="m">'+esc(p.author)+' · '+fmtDate(p.created)+' · → '+esc(p.base)+' · '+p.files+' 文件 <span style="color:var(--mint)">+'+p.adds+'</span> <span style="color:var(--seal)">-'+p.dels+'</span></div>'+(p.summary?'<div class="body">'+esc(p.summary)+'</div>':'')+'<div class="row"><button class="act btn-sign" onclick="openModal('+p.index+',this.dataset.t,\'merge\')" data-t="'+esc(p.title).replace(/"/g,"&quot;")+'">同意签字</button><button class="act btn-deny" onclick="openModal('+p.index+',this.dataset.t,\'reject\')" data-t="'+esc(p.title).replace(/"/g,"&quot;")+'">拒绝</button></div></div>').join(""):(session?'<div class="empty">没有待签的合并请求。</div>':'<div class="locked-note">🔒 登录后此处显示待签的合并请求</div>');
const reqs=s.accessRequests||[];setCnt("cnt-access",reqs.length);
document.getElementById("access-reqs").innerHTML=reqs.length?reqs.map(r=>'<div class="item"><div class="t">'+ptag(r.persona)+'申请写入权限</div><div class="m">'+esc(r.reason||"未说明用途")+'</div><div class="m">'+fmtDate(r.ts)+'</div><div class="row"><button class="act btn-sign" onclick="accessDecision(\''+r.id+'\',\'approve\')">授权3小时</button><button class="act btn-deny" onclick="accessDecision(\''+r.id+'\',\'reject\')">拒绝</button></div></div>').join(""):(session?'<div class="empty">暂无写入申请。</div>':'<div class="locked-note">🔒 登录后此处显示写入申请</div>');
document.getElementById("access-reqs").innerHTML=reqs.length?reqs.map(r=>'<div class="item"><div class="t">'+ptag(r.persona)+'申请写入权限</div><div class="m">'+esc(r.reason||"未说明用途")+'</div><div class="m">'+fmtDate(r.ts)+'</div><div class="row"><button class="act btn-sign" onclick="accessDecision(\''+r.id+'\',\'approve\')">'+(s.windowHours||3)+'小时授权</button><button class="act btn-deny" onclick="accessDecision(\''+r.id+'\',\'reject\')">拒绝</button></div></div>').join(""):(session?'<div class="empty">暂无写入申请。</div>':'<div class="locked-note">🔒 登录后此处显示写入申请</div>');
document.getElementById("access-wins").innerHTML=(s.activeGrants||[]).length?'<div style="font-size:11px;color:var(--faint);letter-spacing:.2em;margin:14px 0 8px;font-family:var(--mono)">生效中的写入窗口</div>'+s.activeGrants.map(g=>'<div class="win-item"><span>'+ptag(g.persona)+'写入窗口</span><span style="color:var(--mint)">'+fmtLeft(g.expiresAt)+'</span></div>').join(""):"";
const dprs=s.deployPRs||[];setCnt("cnt-deploy",dprs.length);
document.getElementById("deploy-prs").innerHTML=dprs.length?dprs.map(p=>'<div class="item" style="border-left-color:rgba(232,180,90,.6)"><div class="t">部署申请 PR #'+p.index+' · '+esc(p.title)+'</div><div class="m">'+esc(p.author)+' · '+esc(p.head)+' → deploy · '+p.files+' 文件</div><div class="row"><button class="act btn-sign" onclick="deployApproveAction('+p.index+')">批准部署</button></div></div>').join(""):(session?'<div class="empty">部署通道无待审申请。PR 目标设为 deploy 即进入此通道。</div>':'<div class="locked-note">🔒 登录后此处显示部署申请</div>');