diff --git a/src/components/adminRdmSections.tsx b/src/components/adminRdmSections.tsx index a0cab8d..16d0fa2 100644 --- a/src/components/adminRdmSections.tsx +++ b/src/components/adminRdmSections.tsx @@ -3,14 +3,14 @@ // 门控集中在 src/rdmManagement.ts;分区可见性由 AdminZone/ProjectSettingsModal // 按 store 的 rdm*Available 门控(命令面不齐不渲染,普通基座零暴露)。样式只复用 // 既有 ad-*/lg-*/settings-* 类(design-guard 棘轮:不新增裸色值/字号)。 -import { useEffect, useState } from 'react' +import { useEffect, useState, useRef, useCallback } from 'react' import { api } from '../api' import { useStore } from '../store' -import { Btn, EmptyState, Icon } from '@ui' +import { Btn, EmptyState, Icon, Picker} from '@ui' import { ROLE_ACTIONS, parseReviewers, roleCreatePayload, roleActionPayload, roleAssignPayload, roleDisablePayload, - memberAddPayload, memberRemovePayload, + memberAddPayload, memberRemovePayload, memberSetRolePayload, assignDocDutiesPayload, docSubmitPayload, docApprovePayload, docRejectPayload, docFinalPayload, docStatusPayload, permCheckPayload, describeSource, rolesListPlaceholder, describeRoleListError, @@ -144,17 +144,43 @@ export function RdmRolesPanel() { ) } -// ---- 项目设置:成员 ---- +// ---- 项目设置:成员(P7:可搜索人员选择器 + 专业角色/项目身份两列 + 显式身份调整)---- -interface MemberRow { owner: string; role: string; addedBy: string; addedAt: string } +interface MemberRow { + owner: string; role: string; addedBy: string; addedAt: string + profRole?: { roleId: string; name: string } | null +} export function RdmMembersSection({ projectId }: { projectId: string }) { const [rows, setRows] = useState(null) const [err, setErr] = useState('') const [notice, setNotice] = useState('') const [busy, setBusy] = useState(false) - const [member, setMember] = useState('') + const [picked, setPicked] = useState([]) const [role, setRole] = useState<'member' | 'owner'>('member') + // 成员表经 ref 参与取数(已加入标记),保持 fetchPage 身份稳定(Picker 依赖)。 + const rowsRef = useRef(null) + rowsRef.current = rows + + /** 人员选择器取数适配(P7-A):rdm.account.list 目录(member.manage 生效者)。 + * query 透传后端(基座升级 AccountSearcher 后全量生效);旧基座忽略 query 时 + * 对首页做本地包含匹配降级(翻页为浏览模式,不过滤)。 */ + const fetchPage = useCallback(async (query: string, cursor: string, limit: number) => { + const out = await api.rdmCommand<{ accounts?: { owner: string; name?: string; valid: boolean }[]; next?: string }>( + 'rdm.account.list', { projectId, cursor, limit, query }) + const joined = new Set((rowsRef.current ?? []).map(m => m.owner)) + let items = (out.accounts ?? []).filter(a => a.valid).map(a => ({ + id: a.owner, + title: a.name || a.owner, + subtitle: a.owner, + badge: joined.has(a.owner) ? '已加入' : undefined, + })) + if (query !== '' && cursor === '') { + const q = query.toLowerCase() + items = items.filter(it => it.id.toLowerCase().includes(q) || it.title.toLowerCase().includes(q)) + } + return { items, nextCursor: out.next || undefined } + }, [projectId]) const refresh = async () => { try { @@ -162,7 +188,7 @@ export function RdmMembersSection({ projectId }: { projectId: string }) { setRows(out.members ?? []) } catch (e) { setErr(String(e)) } } - useEffect(() => { refresh() }, [projectId]) + useEffect(() => { setPicked([]); refresh() }, [projectId]) const run = async (label: string, fn: () => Promise) => { setErr(''); setNotice(''); setBusy(true) @@ -170,40 +196,56 @@ export function RdmMembersSection({ projectId }: { projectId: string }) { catch (e) { setErr(String(e)) } finally { setBusy(false) } } + const pickedId = picked[0] ?? '' + return (
- setMember(e.target.value)} /> + -
-

加入后成员即可见本项目;移除即时生效。最后一位负责人不可移除/降级。

+

候选来自系统账号目录(姓名为空时显示账号);「已加入」标记避免重复添加造成隐式变更——调整身份请在成员表中操作。最后一位负责人不可移除/降级。

- + {(rows ?? []).map(m => ( - - + + + - + ))} - {rows !== null && rows.length === 0 && } - {rows === null && } + {rows !== null && rows.length === 0 && } + {rows === null && }
账号项目角色添加人添加时间
成员专业角色项目身份添加人添加时间
{m.owner}{m.role === 'owner' ? OWNER : MEMBER}{m.owner}{m.profRole?.name ? · {m.profRole.name} : null}{m.profRole?.name || '—'}{m.role === 'owner' ? 项目负责人 : 项目成员} {m.addedBy || '—'} {m.addedAt ? new Date(m.addedAt).toLocaleString() : '—'} + {' '} + +
暂无成员
加载中…
暂无成员
加载中…
{notice &&
{notice}
} diff --git a/src/rdmManagement.ts b/src/rdmManagement.ts index 220b3c0..18fa78e 100644 --- a/src/rdmManagement.ts +++ b/src/rdmManagement.ts @@ -76,6 +76,7 @@ export const roleDisablePayload = (roleId: string, disabled: boolean) => ({ role export const memberAddPayload = (projectId: string, member: string, role: 'owner' | 'member' = 'member') => ({ projectId, member, role }) export const memberRemovePayload = (projectId: string, member: string) => ({ projectId, member }) +export const memberSetRolePayload = (projectId: string, member: string, role: 'owner' | 'member') => ({ projectId, member, role }) export const assignDocDutiesPayload = ( projectId: string, docId: string, author: string, reviewers: string[], approver: string,