refactor(data): 收口关系表运行时数据源
Some checks failed
Deploy Production / Build, push, deploy, verify (push) Has been cancelled
Some checks failed
Deploy Production / Build, push, deploy, verify (push) Has been cancelled
- 移除已迁移业务 AppData 运行时 fallback,改走领域 API 和关系表快读 - 补齐需求产品负责人、版本计划任务 JSON 和成员 username 回填迁移 - 统一治理字典入口,并补充 AI provider、数据源契约和领域服务测试 Co-Authored-By: Codex GPT-5 <codex@openai.com>
This commit is contained in:
@@ -25,13 +25,30 @@ const KIND_LABEL: Record<GovernanceKind, string> = {
|
||||
requirement_source: '需求来源',
|
||||
};
|
||||
|
||||
const TASK_CATEGORY_GROUPS = [
|
||||
{ value: 'development', label: '开发' },
|
||||
{ value: 'testing', label: '测试' },
|
||||
{ value: 'implementation', label: '实施' },
|
||||
{ value: 'other', label: '其他' },
|
||||
];
|
||||
|
||||
const SOURCE_TYPE_GROUPS = [
|
||||
{ value: 'customer', label: '客户' },
|
||||
{ value: 'internal', label: '内部' },
|
||||
{ value: 'operation', label: '运营' },
|
||||
{ value: 'aftersale', label: '售后' },
|
||||
{ value: 'market', label: '市场' },
|
||||
{ value: 'competitor', label: '竞品' },
|
||||
{ value: 'management', label: '管理层' },
|
||||
];
|
||||
|
||||
function GovernancePageInner() {
|
||||
const user = useAuthStore((s) => s.user);
|
||||
const role = useMemberStore((s) => s.roles.find((item) => item.id === user?.roleId));
|
||||
const [kind, setKind] = useState<GovernanceKind>('task_category');
|
||||
const [items, setItems] = useState<GovernanceItem[]>([]);
|
||||
const [name, setName] = useState('');
|
||||
const [group, setGroup] = useState('other');
|
||||
const [group, setGroup] = useState(defaultGroupForKind('task_category'));
|
||||
const [exportText, setExportText] = useState('');
|
||||
const actorId = user?.id ?? '';
|
||||
const permissions = role?.permissions ?? [];
|
||||
@@ -45,9 +62,13 @@ function GovernancePageInner() {
|
||||
void reload().catch(() => setItems([]));
|
||||
}, [kind]);
|
||||
|
||||
useEffect(() => {
|
||||
setGroup(defaultGroupForKind(kind));
|
||||
}, [kind]);
|
||||
|
||||
const create = async () => {
|
||||
if (!actorId || !name.trim()) return;
|
||||
await api.post('/governance/dictionaries', { actorId, permissions, kind, name: name.trim(), group });
|
||||
await api.post('/governance/dictionaries', { actorId, permissions, kind, name: name.trim(), group: groupForPayload(kind, group) });
|
||||
setName('');
|
||||
await reload();
|
||||
};
|
||||
@@ -99,9 +120,15 @@ function GovernancePageInner() {
|
||||
</div>
|
||||
|
||||
<section className="rounded-lg border border-[var(--line)] bg-[var(--bg-card)]">
|
||||
<div className="grid grid-cols-[1fr_140px_auto] gap-2 border-b border-[var(--line)] p-3">
|
||||
<div className={`grid gap-2 border-b border-[var(--line)] p-3 ${groupOptionsForKind(kind) ? 'grid-cols-[1fr_140px_auto]' : 'grid-cols-[1fr_auto]'}`}>
|
||||
<input value={name} onChange={(event) => setName(event.target.value)} placeholder={`新增${KIND_LABEL[kind]}`} className="h-8 rounded-md border border-[var(--line)] bg-[var(--bg)] px-3 text-[12px] focus:border-[var(--accent)] focus:outline-none" />
|
||||
<input value={group} onChange={(event) => setGroup(event.target.value)} placeholder="分组" className="h-8 rounded-md border border-[var(--line)] bg-[var(--bg)] px-3 text-[12px] focus:border-[var(--accent)] focus:outline-none" />
|
||||
{groupOptionsForKind(kind) && (
|
||||
<select value={group} onChange={(event) => setGroup(event.target.value)} className="h-8 rounded-md border border-[var(--line)] bg-[var(--bg)] px-3 text-[12px] focus:border-[var(--accent)] focus:outline-none">
|
||||
{groupOptionsForKind(kind)?.map((option) => (
|
||||
<option key={option.value} value={option.value}>{option.label}</option>
|
||||
))}
|
||||
</select>
|
||||
)}
|
||||
<button onClick={create} disabled={!name.trim()} className="inline-flex h-8 items-center gap-1 rounded-md bg-[var(--accent)] px-3 text-[12px] font-medium text-white disabled:opacity-50">
|
||||
<Plus className="h-3.5 w-3.5" /> 添加
|
||||
</button>
|
||||
@@ -143,6 +170,22 @@ function GovernancePageInner() {
|
||||
);
|
||||
}
|
||||
|
||||
function groupOptionsForKind(kind: GovernanceKind) {
|
||||
if (kind === 'task_category') return TASK_CATEGORY_GROUPS;
|
||||
if (kind === 'requirement_source') return SOURCE_TYPE_GROUPS;
|
||||
return null;
|
||||
}
|
||||
|
||||
function defaultGroupForKind(kind: GovernanceKind) {
|
||||
if (kind === 'task_category') return 'development';
|
||||
if (kind === 'requirement_source') return 'customer';
|
||||
return '';
|
||||
}
|
||||
|
||||
function groupForPayload(kind: GovernanceKind, group: string) {
|
||||
return groupOptionsForKind(kind) ? group : undefined;
|
||||
}
|
||||
|
||||
export default function GovernancePage() {
|
||||
return (
|
||||
<RouteGuard permission="governance:manage">
|
||||
|
||||
Reference in New Issue
Block a user