feat(admin): v3.5.18 用户详情明文手机、任务关联版本与核销快链
HQ 后台:用户/核销记录展示完整手机号;任务列表与编辑可关联版本;账单核销单号与券号/用户可快链;门店账单日标明为出账自然日;技术支持操作按钮右对齐。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -156,10 +156,16 @@ export class DevPlanService {
|
||||
|
||||
},
|
||||
|
||||
extras?: { creatorName?: string | null; supportTicketNo?: string | null },
|
||||
extras?: {
|
||||
creatorName?: string | null;
|
||||
supportTicketNo?: string | null;
|
||||
versions?: Array<{ id: string; versionNo: string }>;
|
||||
},
|
||||
|
||||
): DevPlanTaskDto {
|
||||
|
||||
const versions = extras?.versions ?? [];
|
||||
|
||||
return {
|
||||
|
||||
id: String(row.id),
|
||||
@@ -188,6 +194,10 @@ export class DevPlanService {
|
||||
|
||||
attachmentUrls: parseAttachmentUrls(row.attachmentUrls),
|
||||
|
||||
versions,
|
||||
|
||||
versionIds: versions.map((v) => v.id),
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
@@ -306,7 +316,7 @@ export class DevPlanService {
|
||||
|
||||
const ticketIds = rows.map((r) => r.supportTicketId).filter((id): id is bigint => id != null);
|
||||
|
||||
const [names, tickets] = await Promise.all([
|
||||
const [names, tickets, versionMap] = await Promise.all([
|
||||
|
||||
this.loadHqNames(creatorIds),
|
||||
|
||||
@@ -322,6 +332,8 @@ export class DevPlanService {
|
||||
|
||||
: Promise.resolve([]),
|
||||
|
||||
this.loadTaskVersionMap(rows.map((r) => r.id)),
|
||||
|
||||
]);
|
||||
|
||||
const ticketMap = new Map<string, string>(
|
||||
@@ -340,6 +352,8 @@ export class DevPlanService {
|
||||
|
||||
supportTicketNo: r.supportTicketId != null ? ticketMap.get(String(r.supportTicketId)) ?? null : null,
|
||||
|
||||
versions: versionMap.get(String(r.id)) ?? [],
|
||||
|
||||
}),
|
||||
|
||||
);
|
||||
@@ -374,12 +388,16 @@ export class DevPlanService {
|
||||
|
||||
}
|
||||
|
||||
const versionMap = await this.loadTaskVersionMap([row.id]);
|
||||
|
||||
return this.mapTask(row, {
|
||||
|
||||
creatorName: names.get(String(row.creatorHqAccountId)) ?? null,
|
||||
|
||||
supportTicketNo,
|
||||
|
||||
versions: versionMap.get(String(row.id)) ?? [],
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
@@ -508,6 +526,10 @@ export class DevPlanService {
|
||||
|
||||
await this.prisma.devPlanTask.update({ where: { id }, data });
|
||||
|
||||
if (dto.versionIds !== undefined) {
|
||||
await this.replaceTaskVersions(id, dto.versionIds);
|
||||
}
|
||||
|
||||
return this.getTask(id);
|
||||
|
||||
}
|
||||
@@ -606,6 +628,41 @@ export class DevPlanService {
|
||||
|
||||
|
||||
|
||||
private async loadTaskVersionMap(
|
||||
taskIds: bigint[],
|
||||
): Promise<Map<string, Array<{ id: string; versionNo: string }>>> {
|
||||
const map = new Map<string, Array<{ id: string; versionNo: string }>>();
|
||||
if (!taskIds.length) return map;
|
||||
const links = await this.prisma.devPlanVersionTask.findMany({
|
||||
where: { taskId: { in: taskIds } },
|
||||
include: { version: { select: { id: true, versionNo: true } } },
|
||||
orderBy: { versionId: 'asc' },
|
||||
});
|
||||
for (const link of links) {
|
||||
const key = String(link.taskId);
|
||||
const list = map.get(key) ?? [];
|
||||
list.push({ id: String(link.version.id), versionNo: link.version.versionNo });
|
||||
map.set(key, list);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
private async replaceTaskVersions(taskId: bigint, versionIds: string[]) {
|
||||
const unique = [...new Set(versionIds.map((id) => id.trim()).filter(Boolean))];
|
||||
const ids = unique.map(BigInt);
|
||||
if (ids.length) {
|
||||
const versions = await this.prisma.devPlanVersion.findMany({
|
||||
where: { id: { in: ids } },
|
||||
select: { id: true },
|
||||
});
|
||||
if (versions.length !== ids.length) throw new BadRequestException('部分版本不存在');
|
||||
}
|
||||
await this.prisma.devPlanVersionTask.deleteMany({ where: { taskId } });
|
||||
for (const versionId of ids) {
|
||||
await this.appendVersionTasks(versionId, [String(taskId)]);
|
||||
}
|
||||
}
|
||||
|
||||
private async loadVersionTasks(versionId: bigint): Promise<{ tasks: DevPlanTaskDto[]; taskIds: string[] }> {
|
||||
|
||||
const links = await this.prisma.devPlanVersionTask.findMany({
|
||||
|
||||
@@ -62,6 +62,11 @@ export class UpdateDevPlanTaskDto {
|
||||
@IsArray()
|
||||
@IsString({ each: true })
|
||||
attachmentUrls?: string[];
|
||||
|
||||
@IsOptional()
|
||||
@IsArray()
|
||||
@IsString({ each: true })
|
||||
versionIds?: string[];
|
||||
}
|
||||
|
||||
export class CreateDevPlanVersionDto {
|
||||
|
||||
@@ -54,7 +54,7 @@ export class AdminRedeemService {
|
||||
skip: (page - 1) * pageSize,
|
||||
take: pageSize,
|
||||
include: {
|
||||
user: { select: { id: true, userNo: true, phone: true, nickname: true } },
|
||||
user: { select: { id: true, userNo: true, phone: true, nickname: true, hqRemark: true } },
|
||||
store: { select: { id: true, name: true, cityName: true } },
|
||||
coupon: { select: { id: true, couponNo: true, balance: true } },
|
||||
},
|
||||
@@ -77,7 +77,7 @@ export class AdminRedeemService {
|
||||
const record = await this.prisma.redeemRecord.findUnique({
|
||||
where: { id },
|
||||
include: {
|
||||
user: { select: { id: true, userNo: true, phone: true, nickname: true } },
|
||||
user: { select: { id: true, userNo: true, phone: true, nickname: true, hqRemark: true } },
|
||||
store: {
|
||||
select: {
|
||||
id: true,
|
||||
|
||||
Reference in New Issue
Block a user