fix(admin): 超管补「升为主管理员」入口 — 不然主管撤了加不回去
之前只能撤主管不能升,撤完只能新建账号或重建团队,不合理。 后端 admin_team_member_role_view 早就支持 is_team_owner=true(L1254-1260, 设 owner=True 时自动同时 admin=True);前端 setMemberRole API 只传 is_team_admin,从没用过 is_team_owner 参数。 修法: - lib/api.ts 加 adminApi.setMemberAsOwner(teamId, memberId) - TeamsPage 副管/成员行 role badge 旁加小灰字 "→主管" 按钮 - 点击 confirm 提示"不会自动降级现有主管,需自己先撤旧主管再升新主管" (后端没强制约束一团队一主管,降级逻辑交给操作员判断) UX 流程: - 主管 → 单击 badge = 撤销 (现有) - 副管 → 单击 badge = 取消副管(变成员)(现有) + [→主管] 升主管 - 成员 → 单击文字 = 升副管 (现有) + [→主管] 升主管 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
2289ce7d30
commit
2f6d3a60cc
@ -210,6 +210,10 @@ export const adminApi = {
|
||||
setMemberRole: (teamId: number, memberId: number, isTeamAdmin: boolean) =>
|
||||
api.patch(`/admin/teams/${teamId}/members/${memberId}/role`, { is_team_admin: isTeamAdmin }),
|
||||
|
||||
// 升某成员为主管(后端会自动同时设 is_team_admin=true)
|
||||
setMemberAsOwner: (teamId: number, memberId: number) =>
|
||||
api.patch(`/admin/teams/${teamId}/members/${memberId}/role`, { is_team_owner: true }),
|
||||
|
||||
// User management
|
||||
createUser: (data: {
|
||||
username: string;
|
||||
|
||||
@ -833,21 +833,53 @@ export function TeamsPage() {
|
||||
} catch { showToast('操作失败'); }
|
||||
}}>主管理员</span>
|
||||
) : m.is_team_admin ? (
|
||||
<span className={styles.adminBadge} style={{ cursor: 'pointer' }} title="点击取消副管理员" onClick={async () => {
|
||||
try {
|
||||
await adminApi.setMemberRole(detailTeam!.id, m.id, false);
|
||||
showToast('已取消副管理员');
|
||||
const { data: refreshed } = await adminApi.getTeamDetail(detailTeam!.id); setDetailTeam(refreshed);
|
||||
} catch { showToast('操作失败'); }
|
||||
}}>副管理员</span>
|
||||
<>
|
||||
<span className={styles.adminBadge} style={{ cursor: 'pointer' }} title="点击取消副管理员(变回普通成员)" onClick={async () => {
|
||||
try {
|
||||
await adminApi.setMemberRole(detailTeam!.id, m.id, false);
|
||||
showToast('已取消副管理员');
|
||||
const { data: refreshed } = await adminApi.getTeamDetail(detailTeam!.id); setDetailTeam(refreshed);
|
||||
} catch { showToast('操作失败'); }
|
||||
}}>副管理员</span>
|
||||
<button
|
||||
type="button"
|
||||
style={{ marginLeft: 6, fontSize: 11, color: 'var(--color-text-tertiary)',
|
||||
background: 'none', border: 'none', cursor: 'pointer', padding: 0, textDecoration: 'underline' }}
|
||||
title="升为主管理员(原主管不会自动降级,如需保持唯一主管请先撤销原主管)"
|
||||
onClick={async () => {
|
||||
if (!window.confirm(`将 ${m.username} 设为主管理员?\n\n注意:不会自动降级现有主管。如果想换主管,请先撤销原主管再升新主管。`)) return;
|
||||
try {
|
||||
await adminApi.setMemberAsOwner(detailTeam!.id, m.id);
|
||||
showToast('已升为主管理员');
|
||||
const { data: refreshed } = await adminApi.getTeamDetail(detailTeam!.id); setDetailTeam(refreshed);
|
||||
} catch { showToast('操作失败'); }
|
||||
}}
|
||||
>→主管</button>
|
||||
</>
|
||||
) : (
|
||||
<span style={{ cursor: 'pointer', color: 'var(--color-text-secondary)' }} title="点击设为副管理员" onClick={async () => {
|
||||
try {
|
||||
await adminApi.setMemberRole(detailTeam!.id, m.id, true);
|
||||
showToast('已设为副管理员');
|
||||
const { data: refreshed } = await adminApi.getTeamDetail(detailTeam!.id); setDetailTeam(refreshed);
|
||||
} catch { showToast('操作失败'); }
|
||||
}}>成员</span>
|
||||
<>
|
||||
<span style={{ cursor: 'pointer', color: 'var(--color-text-secondary)' }} title="点击设为副管理员" onClick={async () => {
|
||||
try {
|
||||
await adminApi.setMemberRole(detailTeam!.id, m.id, true);
|
||||
showToast('已设为副管理员');
|
||||
const { data: refreshed } = await adminApi.getTeamDetail(detailTeam!.id); setDetailTeam(refreshed);
|
||||
} catch { showToast('操作失败'); }
|
||||
}}>成员</span>
|
||||
<button
|
||||
type="button"
|
||||
style={{ marginLeft: 6, fontSize: 11, color: 'var(--color-text-tertiary)',
|
||||
background: 'none', border: 'none', cursor: 'pointer', padding: 0, textDecoration: 'underline' }}
|
||||
title="直接升为主管理员(原主管不会自动降级)"
|
||||
onClick={async () => {
|
||||
if (!window.confirm(`将 ${m.username} 设为主管理员?\n\n注意:不会自动降级现有主管。如果想换主管,请先撤销原主管再升新主管。`)) return;
|
||||
try {
|
||||
await adminApi.setMemberAsOwner(detailTeam!.id, m.id);
|
||||
showToast('已升为主管理员');
|
||||
const { data: refreshed } = await adminApi.getTeamDetail(detailTeam!.id); setDetailTeam(refreshed);
|
||||
} catch { showToast('操作失败'); }
|
||||
}}
|
||||
>→主管</button>
|
||||
</>
|
||||
)}
|
||||
</td>
|
||||
<td>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user