@@ -0,0 +1,21 @@
|
||||
import { Body, Controller, Param, Put, UseGuards } from '@nestjs/common';
|
||||
import { AuthService } from './auth.service';
|
||||
import { SaveHqListColumnPrefsDto } from './dto/auth.dto';
|
||||
import { JwtAuthGuard } from '../../common/guards/jwt-auth.guard';
|
||||
import { CurrentUser } from '../../common/decorators/current-user.decorator';
|
||||
import { AuthUser } from '../../common/guards/jwt-auth.guard';
|
||||
|
||||
@Controller('admin/me')
|
||||
@UseGuards(JwtAuthGuard)
|
||||
export class AdminMeController {
|
||||
constructor(private readonly authService: AuthService) {}
|
||||
|
||||
@Put('list-columns/:listKey')
|
||||
saveListColumns(
|
||||
@CurrentUser() user: AuthUser,
|
||||
@Param('listKey') listKey: string,
|
||||
@Body() dto: SaveHqListColumnPrefsDto,
|
||||
) {
|
||||
return this.authService.updateMyListColumnPrefs(user.actorType, user.actorId, listKey, dto);
|
||||
}
|
||||
}
|
||||
@@ -10,7 +10,7 @@ import {
|
||||
UnauthorizedException,
|
||||
} from '@nestjs/common';
|
||||
import { JwtService } from '@nestjs/jwt';
|
||||
import { ClientApp, SmsScene } from '@dukang/shared-types';
|
||||
import { ClientApp, SmsScene, isHqListColumnKey, type HqListColumnPrefsMap } from '@dukang/shared-types';
|
||||
import { generateUserNo } from '@dukang/domain';
|
||||
import { PrismaService } from '../../common/prisma/prisma.module';
|
||||
import { RedisService } from '../../common/redis/redis.service';
|
||||
@@ -55,6 +55,20 @@ type UserRow = Pick<
|
||||
avatar?: { url: string } | null;
|
||||
};
|
||||
|
||||
function parseListColumnPrefs(raw: unknown): HqListColumnPrefsMap {
|
||||
if (!raw || typeof raw !== 'object' || Array.isArray(raw)) return {};
|
||||
const out: HqListColumnPrefsMap = {};
|
||||
for (const [key, value] of Object.entries(raw as Record<string, unknown>)) {
|
||||
if (!isHqListColumnKey(key) || !value || typeof value !== 'object' || Array.isArray(value)) continue;
|
||||
const row = value as { order?: unknown; hidden?: unknown };
|
||||
out[key] = {
|
||||
order: Array.isArray(row.order) ? row.order.filter((v): v is string => typeof v === 'string') : [],
|
||||
hidden: Array.isArray(row.hidden) ? row.hidden.filter((v): v is string => typeof v === 'string') : [],
|
||||
};
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class AuthService {
|
||||
constructor(
|
||||
@@ -1207,11 +1221,48 @@ export class AuthService {
|
||||
const account = await this.prisma.hqAccount.findUnique({ where: { id: actorId } });
|
||||
if (!account) return null;
|
||||
const permissionKeys = await this.hqPermissions.resolveEffectiveKeys(actorId);
|
||||
return serializeBigInt({ ...account, permissionKeys });
|
||||
const cityScope = await this.hqPermissions.resolveCityScope(actorId);
|
||||
const { passwordHash: _passwordHash, ...safeAccount } = account;
|
||||
return serializeBigInt({
|
||||
...safeAccount,
|
||||
listColumnPrefs: parseListColumnPrefs(account.listColumnPrefs),
|
||||
permissionKeys,
|
||||
cityIds: (cityScope ?? []).map((id) => id.toString()),
|
||||
cityScoped: cityScope !== null,
|
||||
});
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
async updateMyListColumnPrefs(
|
||||
actorType: string,
|
||||
actorId: bigint,
|
||||
listKey: string,
|
||||
dto: { reset?: boolean; order?: string[]; hidden?: string[] },
|
||||
) {
|
||||
if (actorType !== 'HQ') throw new ForbiddenException('仅总部账号可保存列表列设置');
|
||||
if (!isHqListColumnKey(listKey)) throw new BadRequestException('未知列表');
|
||||
const account = await this.prisma.hqAccount.findUnique({
|
||||
where: { id: actorId },
|
||||
select: { id: true, listColumnPrefs: true },
|
||||
});
|
||||
if (!account) throw new NotFoundException('账号不存在');
|
||||
const current = parseListColumnPrefs(account.listColumnPrefs);
|
||||
if (dto.reset) {
|
||||
delete current[listKey];
|
||||
} else {
|
||||
current[listKey] = {
|
||||
order: (dto.order ?? []).filter((k) => typeof k === 'string' && k.trim()),
|
||||
hidden: (dto.hidden ?? []).filter((k) => typeof k === 'string' && k.trim()),
|
||||
};
|
||||
}
|
||||
const updated = await this.prisma.hqAccount.update({
|
||||
where: { id: actorId },
|
||||
data: { listColumnPrefs: current },
|
||||
});
|
||||
return { listColumnPrefs: parseListColumnPrefs(updated.listColumnPrefs) };
|
||||
}
|
||||
|
||||
wechatDisabled() {
|
||||
throw new NotImplementedException('FEATURE_DISABLED');
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { IsIn, IsNotEmpty, IsOptional, IsString } from 'class-validator';
|
||||
import { IsArray, IsBoolean, IsIn, IsNotEmpty, IsOptional, IsString } from 'class-validator';
|
||||
import { SmsScene } from '@dukang/shared-types';
|
||||
|
||||
export class SendSmsDto {
|
||||
@@ -129,3 +129,19 @@ export class CheckPartnerPhoneDto {
|
||||
@IsNotEmpty()
|
||||
phone: string;
|
||||
}
|
||||
|
||||
export class SaveHqListColumnPrefsDto {
|
||||
@IsOptional()
|
||||
@IsBoolean()
|
||||
reset?: boolean;
|
||||
|
||||
@IsOptional()
|
||||
@IsArray()
|
||||
@IsString({ each: true })
|
||||
order?: string[];
|
||||
|
||||
@IsOptional()
|
||||
@IsArray()
|
||||
@IsString({ each: true })
|
||||
hidden?: string[];
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ import { PartnerStaffService } from './partner-staff.service';
|
||||
import { StoreStaffController } from './store-staff.controller';
|
||||
import { StoreStaffService } from './store-staff.service';
|
||||
import { AdminAuthController } from './admin-auth.controller';
|
||||
import { AdminMeController } from './admin-me.controller';
|
||||
import { JwtAuthGuard } from '../../common/guards/jwt-auth.guard';
|
||||
import { PhoneVerifiedGuard } from '../../common/guards/phone-verified.guard';
|
||||
import { OptionalJwtAuthGuard } from '../../common/guards/optional-jwt-auth.guard';
|
||||
@@ -50,6 +51,7 @@ import { CommonModule } from '../common/common.module';
|
||||
UserProfileController,
|
||||
UserAddressController,
|
||||
AdminAuthController,
|
||||
AdminMeController,
|
||||
],
|
||||
providers: [
|
||||
AuthService,
|
||||
|
||||
Reference in New Issue
Block a user