task-253(admin.html观感对齐): 数据权限分组页对齐(新建/编辑/删除 + 组员 chips + 组长锁定)
This commit is contained in:
@@ -1,13 +1,20 @@
|
||||
/** 数据权限分组列表模型(任务 59):解析 Java ShopManageGroupItemVo + 摘要统计,纯逻辑。 */
|
||||
/** 数据权限分组列表模型(任务 59;module 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)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user