feat(admin,store): landline contact phone and package audit UX
Allow store contactPhone as landline, show pending package audit badge, and split live vs pending packages in HQ review. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import { BadRequestException, Injectable, NotFoundException } from '@nestjs/common';
|
||||
import { Prisma } from '@prisma/client';
|
||||
import { validateBusinessHours } from '@dukang/domain';
|
||||
import { isMobilePhone, isStoreContactPhone, STORE_CONTACT_PHONE_HINT, validateBusinessHours } from '@dukang/domain';
|
||||
import { PrismaService } from '../../common/prisma/prisma.module';
|
||||
import { serializeBigInt } from '../../common/decorators/current-user.decorator';
|
||||
import { mapStoreCompat } from '../../common/compat/v31-compat';
|
||||
@@ -277,14 +277,14 @@ export class AdminStoresService {
|
||||
|
||||
if (dto.phone !== undefined) {
|
||||
const normalizedPhone = dto.phone.trim();
|
||||
if (!/^1[3-9]\d{9}$/.test(normalizedPhone)) {
|
||||
if (!isMobilePhone(normalizedPhone)) {
|
||||
throw new BadRequestException('请输入正确的登录手机号');
|
||||
}
|
||||
}
|
||||
if (dto.contactPhone !== undefined) {
|
||||
const contact = dto.contactPhone.trim();
|
||||
if (contact && !/^1[3-9]\d{9}$/.test(contact)) {
|
||||
throw new BadRequestException('请输入正确的联系电话');
|
||||
if (contact && !isStoreContactPhone(contact)) {
|
||||
throw new BadRequestException(STORE_CONTACT_PHONE_HINT);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -505,7 +505,7 @@ export class AdminStoresService {
|
||||
|
||||
async createStore(dto: CreateStoreDto) {
|
||||
const normalizedPhone = dto.phone.trim();
|
||||
if (!/^1[3-9]\d{9}$/.test(normalizedPhone)) {
|
||||
if (!isMobilePhone(normalizedPhone)) {
|
||||
throw new BadRequestException('请输入正确的手机号码');
|
||||
}
|
||||
const existingAccount = await this.prisma.storeAccount.findUnique({
|
||||
@@ -576,8 +576,8 @@ export class AdminStoresService {
|
||||
: await this.testWhitelist.isPhoneInWhitelist(normalizedPhone);
|
||||
|
||||
const contactPhoneRaw = dto.contactPhone?.trim() || normalizedPhone;
|
||||
if (!/^1[3-9]\d{9}$/.test(contactPhoneRaw)) {
|
||||
throw new BadRequestException('请输入正确的联系电话');
|
||||
if (!isStoreContactPhone(contactPhoneRaw)) {
|
||||
throw new BadRequestException(STORE_CONTACT_PHONE_HINT);
|
||||
}
|
||||
|
||||
const store = await this.prisma.store.create({
|
||||
|
||||
@@ -70,6 +70,11 @@ export class AdminStorePackageController {
|
||||
export class AdminStorePackageAuditController {
|
||||
constructor(private readonly packages: StorePackageService) {}
|
||||
|
||||
@Get('summary')
|
||||
summary() {
|
||||
return this.packages.adminAuditSummary();
|
||||
}
|
||||
|
||||
@Get()
|
||||
list(
|
||||
@Query('status') status?: string,
|
||||
|
||||
@@ -376,4 +376,11 @@ export class StorePackageService {
|
||||
});
|
||||
return serializeBigInt({ id: requestId.toString(), status: 'APPROVED' });
|
||||
}
|
||||
|
||||
async adminAuditSummary() {
|
||||
const pendingCount = await this.prisma.storePackageChangeRequest.count({
|
||||
where: { status: 'PENDING' },
|
||||
});
|
||||
return { pendingCount };
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ import {
|
||||
import { loadAppConfig, ClientApp, SmsScene } from '@dukang/shared-types';
|
||||
import { PARTNER_STAFF_ROLE_LABELS, PartnerStaffRole, type PartnerLeaderboardPeriod } from '@dukang/shared-types';
|
||||
import { normalizeStorePackageImageUrls } from '@dukang/shared-types';
|
||||
import { validateBusinessHours } from '@dukang/domain';
|
||||
import { isStoreContactPhone, STORE_CONTACT_PHONE_HINT, validateBusinessHours } from '@dukang/domain';
|
||||
import { PrismaService } from '../../common/prisma/prisma.module';
|
||||
import { serializeBigInt } from '../../common/decorators/current-user.decorator';
|
||||
import { mapStoreCompat } from '../../common/compat/v31-compat';
|
||||
@@ -371,8 +371,8 @@ export class StoreService {
|
||||
body.contactPhone != null && String(body.contactPhone).trim()
|
||||
? String(body.contactPhone).trim()
|
||||
: normalizedPhone;
|
||||
if (!/^1[3-9]\d{9}$/.test(contactPhoneRaw)) {
|
||||
throw new BadRequestException('联系电话须为11位手机号');
|
||||
if (!isStoreContactPhone(contactPhoneRaw)) {
|
||||
throw new BadRequestException(STORE_CONTACT_PHONE_HINT);
|
||||
}
|
||||
|
||||
const city = await this.resolvePartnerCity(partnerAccountId, body.cityId);
|
||||
@@ -653,8 +653,8 @@ export class StoreService {
|
||||
body.longitude !== undefined ? parseOptionalCoord(body.longitude, 'lng') : undefined;
|
||||
|
||||
if (name !== undefined && !name) throw new BadRequestException('请填写门店名称');
|
||||
if (contactPhone !== undefined && !/^1[3-9]\d{9}$/.test(contactPhone)) {
|
||||
throw new BadRequestException('联系电话须为11位手机号');
|
||||
if (contactPhone !== undefined && !isStoreContactPhone(contactPhone)) {
|
||||
throw new BadRequestException(STORE_CONTACT_PHONE_HINT);
|
||||
}
|
||||
if (address !== undefined && !address) throw new BadRequestException('请填写详细地址');
|
||||
if (introRaw && (introRaw.length < 2 || introRaw.length > 500)) {
|
||||
|
||||
Reference in New Issue
Block a user