feat: 增加账户递增ID、优化管理员排序与用户表格左对齐统一列宽

This commit is contained in:
xuans 2026-10-16 18:36:20 +08:00
parent 3e260cf6d1
commit 225332c1c0
4 changed files with 111 additions and 2 deletions

View File

@ -334,3 +334,32 @@ button:focus-visible {
overflow-wrap: anywhere;
user-select: text;
}
/* 账户表格对齐与列宽优化 */
.user-table th.col-id,
.user-table td.col-id {
width: 80px;
min-width: 80px;
text-align: left;
}
.user-seq-id {
display: inline-flex;
align-items: center;
justify-content: center;
min-width: 28px;
height: 24px;
padding: 0 6px;
background: #f1f4f9;
color: #315aaa;
font-weight: 700;
border-radius: 6px;
font-size: 13px;
}
.user-table th,
.user-table td {
text-align: left;
line-height: 1.5;
vertical-align: middle;
}

View File

@ -11,6 +11,54 @@ const statusLabels = {
disabled: "已禁用",
};
export function sortAndAssignDisplayIds(userList) {
if (!Array.isArray(userList)) return [];
// 1. 超管默认ID为 1,其余用户按创建时间升序自增递增(2, 3, 4...)
const sortedByCreate = [...userList].sort((a, b) => new Date(a.created_at || 0) - new Date(b.created_at || 0));
let superAdminFound = false;
const idMap = new Map();
let nextSeq = 2;
// 先锁定超管为1
for (const u of sortedByCreate) {
if ((u.id === 'primary-super-admin' || u.role === 'super_admin') && !superAdminFound) {
idMap.set(u.id, 1);
superAdminFound = true;
}
}
// 为其他账号按创建顺序分配自增序号
for (const u of sortedByCreate) {
if (!idMap.has(u.id)) {
idMap.set(u.id, nextSeq++);
}
}
// 2. 排序规则:
// 超管(super_admin)第一,排在最前
// 管理员(admin)第二,排在超管后面,按设置为管理员的时间(updated_at 或 created_at)排序
// 普通用户(user)第三,排在管理员后面,按创建时间排序
const rolePriority = { super_admin: 0, admin: 1, user: 2 };
return [...userList].map(u => ({
...u,
account_number: idMap.get(u.id) || 1
})).sort((a, b) => {
const pA = rolePriority[a.role] ?? 99;
const pB = rolePriority[b.role] ?? 99;
if (pA !== pB) return pA - pB;
if (a.role === 'admin') {
const timeA = new Date(a.updated_at || a.created_at || 0).getTime();
const timeB = new Date(b.updated_at || b.created_at || 0).getTime();
if (timeA !== timeB) return timeA - timeB;
}
const timeA = new Date(a.created_at || 0).getTime();
const timeB = new Date(b.created_at || 0).getTime();
if (timeA !== timeB) return timeA - timeB;
return (a.account_number || 0) - (b.account_number || 0);
});
}
export function groupUsers(users) {
const groups = new Map();
const defaults = { name: "默认分组", isDefault: true, users: [] };
@ -72,7 +120,7 @@ export function useUserManagement() {
}
const result = await response.json().catch(() => ({}));
if (!response.ok) throw new Error(result.error || "读取用户列表失败");
users.value = result.items || [];
users.value = sortAndAssignDisplayIds(result.items || []);
currentRole.value = result.current_role || "";
visible.value = true;
} catch (err) {

View File

@ -139,3 +139,33 @@ test("分组页面结构可编译,默认组不折叠,命名组默认关闭
assert.doesNotMatch(dashboard, /@click="openSettings"/);
assert.match(navigation, /\$emit\('settings'\)/);
});
test("账户列表自增ID分配及超管管理员排序规则", async () => {
const { sortAndAssignDisplayIds } = await import("./UserManagement.js");
const users = [
{ id: "user-2", username: "bob", role: "user", created_at: "2026-01-03T00:00:00Z" },
{ id: "admin-1", username: "alice", role: "admin", created_at: "2026-01-02T00:00:00Z", updated_at: "2026-02-01T00:00:00Z" },
{ id: "primary-super-admin", username: "admin", role: "super_admin", created_at: "2026-01-01T00:00:00Z" },
{ id: "admin-2", username: "charlie", role: "admin", created_at: "2026-01-04T00:00:00Z", updated_at: "2026-01-15T00:00:00Z" },
];
const processed = sortAndAssignDisplayIds(users);
// 超管排在第一,分配账户 ID 1
assert.equal(processed[0].id, "primary-super-admin");
assert.equal(processed[0].account_number, 1);
// 管理员排在超管后面,按更新/设置时间升序排序:admin-2 (01-15) 在 admin-1 (02-01) 前面
assert.equal(processed[1].id, "admin-2");
assert.equal(processed[1].role, "admin");
assert.equal(processed[2].id, "admin-1");
assert.equal(processed[2].role, "admin");
// 普通用户排在最后
assert.equal(processed[3].id, "user-2");
assert.equal(processed[3].role, "user");
// 账户ID序号检查:admin-1(created: 01-02 => 2), user-2(created: 01-03 => 3), admin-2(created: 01-04 => 4)
assert.equal(processed.find(u => u.id === "admin-1").account_number, 2);
assert.equal(processed.find(u => u.id === "user-2").account_number, 3);
assert.equal(processed.find(u => u.id === "admin-2").account_number, 4);
});

View File

@ -14,7 +14,8 @@ defineEmits(["edit", "toggle", "delete"]);
<table class="user-table">
<thead>
<tr>
<th scope="col">账号</th>
<th scope="col" class="col-id">账户 ID</th>
<th scope="col" class="col-user">账号</th>
<th scope="col">邮箱</th>
<th scope="col">角色</th>
<th scope="col">状态</th>
@ -24,6 +25,7 @@ defineEmits(["edit", "toggle", "delete"]);
</thead>
<tbody>
<tr v-for="item in users" :key="item.id">
<td class="col-id"><span class="user-seq-id">{{ item.account_number ?? 1 }}</span></td>
<td>
<strong>{{ item.username }}</strong>
<small class="user-account-id" title="可将此账户 ID 提供给项目管理员,用于加入项目">账户 ID:{{ item.id }}</small>