feat(store): add store sortOrder and swipeable package gallery

Enable HQ-controlled store list ordering and horizontal multi-image browsing on package detail.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-08-07 19:58:38 +08:00
parent fe1c6c8158
commit 34a1897c09
9 changed files with 69 additions and 32 deletions
+3
View File
@@ -1277,6 +1277,8 @@ model Store {
withdrawWhitelistEnabled Boolean @default(false) @map("withdraw_whitelist_enabled")
/// 测试门店:不计结算 / HQ 可手动标记
isTest Boolean @default(false) @map("is_test")
/// C 端 / 列表排序:数值越小越靠前
sortOrder Int @default(0) @map("sort_order")
createdAt DateTime @default(now()) @map("created_at") @db.DateTime(3)
updatedAt DateTime @updatedAt @map("updated_at") @db.DateTime(3)
@@ -1299,6 +1301,7 @@ model Store {
@@index([partnerAccountId])
@@index([auditStatus, createdAt])
@@index([isTest])
@@index([sortOrder])
@@map("store_store")
}
@@ -72,7 +72,7 @@ export class AdminStoresService {
const [items, total] = await Promise.all([
this.prisma.store.findMany({
where,
orderBy: { createdAt: 'desc' },
orderBy: [{ sortOrder: 'asc' }, { createdAt: 'desc' }],
skip: (page - 1) * pageSize,
take: pageSize,
include: {
@@ -365,6 +365,7 @@ export class AdminStoresService {
? { visibilityWhitelistEnabled: !!dto.visibilityWhitelistEnabled }
: {}),
...(dto.isTest !== undefined ? { isTest: !!dto.isTest } : {}),
...(dto.sortOrder !== undefined ? { sortOrder: Math.floor(Number(dto.sortOrder)) || 0 } : {}),
...(latitude != null && longitude != null ? { latitude, longitude } : {}),
},
});
@@ -582,6 +583,7 @@ export class AdminStoresService {
closeTime2: closeTime2 || null,
visibilityWhitelistEnabled: whitelistEnabled,
isTest,
sortOrder: dto.sortOrder != null ? Math.floor(Number(dto.sortOrder)) || 0 : 0,
...(latitude != null && longitude != null ? { latitude, longitude } : {}),
status: 'OPEN',
auditStatus: 'APPROVED',
@@ -145,6 +145,12 @@ export class CreateStoreDto {
@IsOptional()
@IsBoolean()
isTest?: boolean;
/** 列表排序,越小越靠前 */
@IsOptional()
@IsNumber()
@Min(0)
sortOrder?: number;
}
export class UpdateStoreDto {
@@ -259,6 +265,12 @@ export class UpdateStoreDto {
@IsOptional()
@IsBoolean()
isTest?: boolean;
/** 列表排序,越小越靠前 */
@IsOptional()
@IsNumber()
@Min(0)
sortOrder?: number;
}
export class CreateStoreAccountDto {
@@ -154,7 +154,7 @@ export class StoreService {
category: true,
coverResource: true,
},
orderBy: { createdAt: 'desc' },
orderBy: [{ sortOrder: 'asc' }, { createdAt: 'desc' }],
});
const whitelistPhones = stores.some((s) => s.visibilityWhitelistEnabled)
@@ -172,6 +172,7 @@ export class StoreService {
distanceMeters: number | null;
latitude?: unknown;
longitude?: unknown;
sortOrder?: number;
};
const items: StoreListItem[] = [];
@@ -190,13 +191,16 @@ export class StoreService {
items.push({ ...mapped, distanceMeters });
}
if (hasUser) {
items.sort((a, b) => {
items.sort((a, b) => {
const so = (a.sortOrder ?? 0) - (b.sortOrder ?? 0);
if (so !== 0) return so;
if (hasUser) {
const da = a.distanceMeters ?? Number.POSITIVE_INFINITY;
const db = b.distanceMeters ?? Number.POSITIVE_INFINITY;
return da - db;
});
}
}
return 0;
});
return serializeBigInt(items);
}
@@ -268,7 +272,7 @@ export class StoreService {
const stores = await this.prisma.store.findMany({
where,
include: { category: true, coverResource: true },
orderBy: { createdAt: 'desc' },
orderBy: [{ sortOrder: 'asc' }, { createdAt: 'desc' }],
});
return serializeBigInt(stores.map(mapStoreCompat));
}