f6cb90cd70
- main.tsx 挂 AuthProvider 门控:未登录→登录页;must_change_password→强制改密页 - 登录页/改密页/顶栏身份(头像+姓名+角色徽章+退出)按 A·Data-console token 样式 - 全局 fetch 拦截器:任意业务请求 401 自动回登录页(会话过期/被撤销不留死表单) - 系统设置新增「成员与角色」分区(仅 admin 可见):名单、角色调整、启停、重置临时密码、新增成员 - 消灭全部手填操作人:审核/封批/确认计划集/范围规则/来源调度/UI 设置/开始处理/批量重试/ 目录差异确认共 9 处输入框删除,请求体不再携带 actor 字段(服务端从会话注入) - 测试断言方向翻转:显式验证请求体不含 operator_ref/created_by 等字段 - 附带修复:登录失败计数 SQL 参数类型无法推断导致 500(pgx 扩展协议),显式 cast 解决 前端门禁:tsc 0 错、125 用例全绿、build 通过
32 lines
2.5 KiB
TypeScript
32 lines
2.5 KiB
TypeScript
import { useState } from 'react'
|
||
import type { ClearScopeRuleDecision, ScopeRule, ScopeRuleDecision, ScopeRuleTarget, Visibility } from './scopeRules'
|
||
|
||
interface Props {
|
||
target: ScopeRuleTarget
|
||
currentRule?: ScopeRule
|
||
saving: boolean
|
||
error?: string|null
|
||
onSave: (decision:ScopeRuleDecision)=>void
|
||
onClear: (decision:ClearScopeRuleDecision)=>void
|
||
}
|
||
|
||
export function ScopeRuleEditor({target,currentRule,saving,error,onSave,onClear}:Props){
|
||
const [visibility,setVisibility]=useState<Visibility|''>(currentRule?.visibility||'')
|
||
const [reason,setReason]=useState('')
|
||
const reasonReady=reason.trim()!==''&&!saving
|
||
const saveReady=reasonReady&&visibility!==''
|
||
const label=target.target_type==='item'?'仅此文件':target.directory_path?'此目录及子目录':'整个来源'
|
||
const base={...target,reason:reason.trim()}
|
||
return <section className="scope-editor" aria-label="对内对外范围设置">
|
||
<div className="scope-editor-heading"><div><strong>对内/对外设置</strong><span>{label}</span></div>{currentRule?<span className={`scope-badge ${currentRule.visibility}`}>当前设置:{currentRule.visibility==='external'?'对外':'对内'}</span>:<span className="inherited-badge">当前没有本级设置</span>}</div>
|
||
{currentRule?<p className="scope-rule-meta">由 {currentRule.updated_by} 设置 · 原因:{currentRule.reason}</p>:<p className="scope-rule-meta">当前继承上级规则或来源原始标记。</p>}
|
||
<div className="scope-editor-fields">
|
||
<label>拟修改为<select value={visibility} onChange={event=>setVisibility(event.target.value as Visibility|'')}><option value="">选择新范围</option><option value="internal">对内</option><option value="external">对外</option></select></label>
|
||
<label className="scope-reason">判断原因<input value={reason} maxLength={500} placeholder="例如:官网已公开 / 含内部参数" onChange={event=>setReason(event.target.value)} /></label>
|
||
</div>
|
||
{error?<p className="scope-error" role="alert">{error}</p>:null}
|
||
<div className="scope-editor-actions"><button disabled={!saveReady} onClick={()=>onSave({...base,visibility:visibility as Visibility})}>{saving?'保存中…':'保存范围'}</button>{currentRule?<button className="secondary" disabled={!reasonReady} onClick={()=>onClear(base)}>移除本级设置,恢复继承</button>:null}</div>
|
||
<small>这里只更新治理规则并记录审计,操作自动记在当前登录人名下;不会修改源文件,也不会自动发布到生产。</small>
|
||
</section>
|
||
}
|