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) =>
|
setMemberRole: (teamId: number, memberId: number, isTeamAdmin: boolean) =>
|
||||||
api.patch(`/admin/teams/${teamId}/members/${memberId}/role`, { is_team_admin: isTeamAdmin }),
|
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
|
// User management
|
||||||
createUser: (data: {
|
createUser: (data: {
|
||||||
username: string;
|
username: string;
|
||||||
|
|||||||
@ -833,21 +833,53 @@ export function TeamsPage() {
|
|||||||
} catch { showToast('操作失败'); }
|
} catch { showToast('操作失败'); }
|
||||||
}}>主管理员</span>
|
}}>主管理员</span>
|
||||||
) : m.is_team_admin ? (
|
) : m.is_team_admin ? (
|
||||||
<span className={styles.adminBadge} style={{ cursor: 'pointer' }} title="点击取消副管理员" onClick={async () => {
|
<>
|
||||||
try {
|
<span className={styles.adminBadge} style={{ cursor: 'pointer' }} title="点击取消副管理员(变回普通成员)" onClick={async () => {
|
||||||
await adminApi.setMemberRole(detailTeam!.id, m.id, false);
|
try {
|
||||||
showToast('已取消副管理员');
|
await adminApi.setMemberRole(detailTeam!.id, m.id, false);
|
||||||
const { data: refreshed } = await adminApi.getTeamDetail(detailTeam!.id); setDetailTeam(refreshed);
|
showToast('已取消副管理员');
|
||||||
} catch { showToast('操作失败'); }
|
const { data: refreshed } = await adminApi.getTeamDetail(detailTeam!.id); setDetailTeam(refreshed);
|
||||||
}}>副管理员</span>
|
} 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 {
|
<span style={{ cursor: 'pointer', color: 'var(--color-text-secondary)' }} title="点击设为副管理员" onClick={async () => {
|
||||||
await adminApi.setMemberRole(detailTeam!.id, m.id, true);
|
try {
|
||||||
showToast('已设为副管理员');
|
await adminApi.setMemberRole(detailTeam!.id, m.id, true);
|
||||||
const { data: refreshed } = await adminApi.getTeamDetail(detailTeam!.id); setDetailTeam(refreshed);
|
showToast('已设为副管理员');
|
||||||
} catch { showToast('操作失败'); }
|
const { data: refreshed } = await adminApi.getTeamDetail(detailTeam!.id); setDetailTeam(refreshed);
|
||||||
}}>成员</span>
|
} 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>
|
||||||
<td>
|
<td>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user