feat(M08-B): 补保洁员资料细节

This commit is contained in:
Codex
2026-06-30 11:02:43 +08:00
parent d35c39e33f
commit 335adcdc22
13 changed files with 105 additions and 20 deletions
+13 -1
View File
@@ -10,11 +10,13 @@ export interface ManagedUser {
userType: string;
status: string;
nickname: string;
avatarUrl: string;
maskedPhone: string;
maskedLastIp: string;
note: string;
roles: string[];
storeIds: string[];
wechatMiniappBound: boolean;
registeredAt: Date;
lastLoginAt: Date | null;
}
@@ -42,9 +44,11 @@ interface UserRow extends RowDataPacket {
userType: string;
status: string;
nickname: string;
avatarUrl: string;
phone: string;
lastIp: string | null;
note: string;
wechatMiniappBound: number;
registeredAt: Date;
lastLoginAt: Date | null;
}
@@ -99,9 +103,15 @@ export class UserManagementRepository {
params
);
const [rows] = await this.pool.execute<UserRow[]>(
`SELECT u.id, u.user_type AS userType, u.status, u.nickname, u.phone,
`SELECT u.id, u.user_type AS userType, u.status, u.nickname,
u.avatar_url AS avatarUrl, u.phone,
u.created_at AS registeredAt, u.last_login_at AS lastLoginAt,
COALESCE(p.note, '') AS note,
EXISTS (
SELECT 1 FROM qipai_user_identities i
WHERE i.tenant_id = u.tenant_id AND i.user_id = u.id
AND i.provider = 'WECHAT_MINIAPP' AND i.deleted_at IS NULL
) AS wechatMiniappBound,
(SELECT s.ip FROM qipai_auth_sessions s
WHERE s.tenant_id = u.tenant_id AND s.user_id = u.id
ORDER BY s.created_at DESC LIMIT 1) AS lastIp
@@ -117,11 +127,13 @@ export class UserManagementRepository {
userType: row.userType,
status: row.status,
nickname: row.nickname,
avatarUrl: row.avatarUrl,
maskedPhone: maskPhone(row.phone),
maskedLastIp: maskIp(row.lastIp ?? ''),
note: row.note,
roles: await this.getCodes('role', input.actor.tenantId, String(row.id)),
storeIds: await this.getCodes('store', input.actor.tenantId, String(row.id)),
wechatMiniappBound: Boolean(row.wechatMiniappBound),
registeredAt: row.registeredAt,
lastLoginAt: row.lastLoginAt
})));
+21 -1
View File
@@ -50,6 +50,7 @@ const token = signAccessToken({
}, secret, 900);
let createdInput;
let listedInput;
let updatedInput;
const app = await buildApp({
userManagement: {
jwtSecret: secret,
@@ -81,7 +82,10 @@ const app = await buildApp({
createdInput = input;
return { userId: '22' };
},
async updateUser() { return { userId: '22' }; },
async updateUser(_actor, _userId, input) {
updatedInput = input;
return { userId: '22' };
},
async resetSessions() { return { userId: '22', revokedSessions: 2 }; }
}
}
@@ -111,6 +115,22 @@ assert.equal(listedInput.role, 'CLEANER');
assert.equal(listedInput.status, 'ACTIVE');
assert.equal(listedInput.search, '保洁');
const updated = await app.inject({
method: 'PATCH',
url: '/admin-api/users/22',
headers: { authorization: `Bearer ${token}` },
payload: {
nickname: '保洁一号',
phone: '13800138009',
roles: ['CLEANER'],
storeIds: ['11'],
note: '夜班'
}
});
assert.equal(updated.statusCode, 200);
assert.equal(updatedInput.phone, '13800138009');
assert.deepEqual(updatedInput.roles, ['CLEANER']);
const unauthenticated = await app.inject({ method: 'GET', url: '/admin-api/users' });
assert.equal(unauthenticated.statusCode, 401);
await app.close();