task-253(admin.html观感对齐): 数据权限分组页对齐(新建/编辑/删除 + 组员 chips + 组长锁定)

This commit is contained in:
2026-09-05 21:21:49 +08:00
parent 8b4955d9b5
commit f765b3ce67
5 changed files with 367 additions and 10 deletions
@@ -1,13 +1,20 @@
/** 数据权限分组列表模型(任务 59):解析 Java ShopManageGroupItemVo + 摘要统计,纯逻辑。 */
/** 数据权限分组列表模型(任务 59module 13 task 253 扩展编辑能力):解析 VO + 摘要 + 提交载荷。 */
import { unwrap } from '../../api/envelope.ts'
export interface ShopGroupItem {
id: number
name: string
leaderUsername: string
leaderUserId?: number
memberCount: number
memberUsernames: string[]
memberUserIds?: number[]
createdAt?: string
updatedAt?: string
}
export interface ShopGroupFormErrors {
groupName?: string
}
function text(value: unknown): string {
@@ -27,6 +34,9 @@ export function parseShopGroupItem(raw: unknown): ShopGroupItem | null {
const names = Array.isArray(record.memberUsernames)
? record.memberUsernames.map((v) => text(v)).filter(Boolean)
: []
const memberIds = Array.isArray(record.memberUserIds)
? record.memberUserIds.map((v) => numberOrNull(v)).filter((v): v is number => v !== null && v > 0)
: []
const count = numberOrNull(record.memberCount)
const item: ShopGroupItem = {
id,
@@ -35,8 +45,13 @@ export function parseShopGroupItem(raw: unknown): ShopGroupItem | null {
memberCount: count === null ? names.length : count,
memberUsernames: names,
}
const leaderId = numberOrNull(record.leaderUserId ?? record.leader_user_id)
if (leaderId !== null && leaderId > 0) item.leaderUserId = leaderId
if (memberIds.length) item.memberUserIds = memberIds
const createdAt = text(record.createdAt ?? record.created_at)
if (createdAt) item.createdAt = createdAt
const updatedAt = text(record.updatedAt ?? record.updated_at)
if (updatedAt) item.updatedAt = updatedAt
return item
}
@@ -55,3 +70,34 @@ export function shopGroupSummary(groups: ShopGroupItem[]): { groupCount: number;
for (const group of groups) memberTotal += group.memberCount || 0
return { groupCount: groups.length, memberTotal }
}
/** 分组名必填校验(镜像后端 NotBlank 文案「请输入分组名称」)。 */
export function validateShopGroupForm(name: string): ShopGroupFormErrors {
const errors: ShopGroupFormErrors = {}
if (!text(name)) errors.groupName = '请输入分组名称'
return errors
}
/** 创建载荷:groupName + 成员 + 创建人(= 组长,当前操作者)。 */
export function toShopGroupCreatePayload(
name: string,
memberUserIds: number[],
createdById: number,
): { groupName: string; memberUserIds: number[]; createdById: number } {
return { groupName: text(name), memberUserIds: dedupeIds(memberUserIds), createdById }
}
/** 更新载荷:groupName + 成员(组长/创建人不可改)。 */
export function toShopGroupUpdatePayload(name: string, memberUserIds: number[]): { groupName: string; memberUserIds: number[] } {
return { groupName: text(name), memberUserIds: dedupeIds(memberUserIds) }
}
function dedupeIds(ids: unknown[]): number[] {
if (!Array.isArray(ids)) return []
const set = new Set<number>()
for (const v of ids) {
const id = numberOrNull(v)
if (id !== null && id > 0) set.add(id)
}
return [...set].sort((a, b) => a - b)
}