dev
This commit is contained in:
@@ -16,6 +16,12 @@ request.interceptors.request.use((config) => {
|
||||
request.interceptors.response.use(
|
||||
(response) => {
|
||||
const { data } = response;
|
||||
if (data.code === 401) {
|
||||
localStorage.removeItem('seller_token');
|
||||
localStorage.removeItem('seller_info');
|
||||
window.location.href = '/login';
|
||||
return Promise.reject(new Error(data.message || '登录已过期'));
|
||||
}
|
||||
if (data.code >= 200 && data.code < 300) {
|
||||
return data;
|
||||
}
|
||||
|
||||
@@ -51,7 +51,8 @@ export function request<T = any>(options: RequestOptions): Promise<ApiResponse<T
|
||||
|
||||
const responseData = res.data as ApiResponse<T>;
|
||||
|
||||
if (res.statusCode === 401) {
|
||||
// 检查响应体中的 code 是否为 401
|
||||
if (responseData.code === 401 || res.statusCode === 401) {
|
||||
// 如果是 skipAuthRedirect,只清除 token 不跳转页面
|
||||
if (skipAuthRedirect) {
|
||||
if (useSellerToken) {
|
||||
@@ -67,9 +68,10 @@ export function request<T = any>(options: RequestOptions): Promise<ApiResponse<T
|
||||
|
||||
// 正常 401 处理,只清除对应账户的 token,不互相干扰
|
||||
if (useSellerToken) {
|
||||
// 商家 token 失效,只清除商家登录状态,不跳转页面
|
||||
// 商家 token 失效,跳转到商家登录页
|
||||
uni.removeStorageSync('sellerToken');
|
||||
uni.removeStorageSync('sellerInfo');
|
||||
uni.navigateTo({ url: '/pages/seller/register?mode=login' });
|
||||
} else {
|
||||
// 用户 token 失效,清除用户登录状态并跳转登录页
|
||||
uni.removeStorageSync('token');
|
||||
|
||||
@@ -34,11 +34,13 @@ export const getInviteConfig = () =>
|
||||
|
||||
// 更新邀请活动配置
|
||||
export const updateInviteConfig = (data: {
|
||||
firstOrderRate?: number;
|
||||
secondOrderRate?: number;
|
||||
minCashback?: number;
|
||||
maxCashback?: number;
|
||||
withdrawThreshold?: number;
|
||||
config?: {
|
||||
firstOrderRate?: number;
|
||||
secondOrderRate?: number;
|
||||
minCashback?: number;
|
||||
maxCashback?: number;
|
||||
withdrawThreshold?: number;
|
||||
};
|
||||
enabled?: boolean;
|
||||
}) =>
|
||||
request.put('/admin/activity/invite/config', data);
|
||||
@@ -77,8 +77,8 @@ const InviteManage: React.FC = () => {
|
||||
try {
|
||||
const res = await getInviteConfig();
|
||||
setConfig(res.data);
|
||||
if (res.data) {
|
||||
form.setFieldsValue(res.data);
|
||||
if (res.data?.config) {
|
||||
form.setFieldsValue(res.data.config);
|
||||
}
|
||||
} finally {
|
||||
setConfigLoading(false);
|
||||
@@ -121,9 +121,9 @@ const InviteManage: React.FC = () => {
|
||||
const handleSaveConfig = async () => {
|
||||
try {
|
||||
const values = await form.validateFields();
|
||||
await updateInviteConfig(values);
|
||||
await updateInviteConfig({ config: values });
|
||||
message.success('配置已保存');
|
||||
setConfig({ ...config, ...values });
|
||||
setConfig({ ...config, config: { ...config?.config, ...values } });
|
||||
} catch {}
|
||||
};
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ import { ScheduleModule as TaskScheduleModule } from './schedule/schedule.module
|
||||
password: process.env.DB_PASSWORD || '',
|
||||
database: process.env.DB_DATABASE || 'rent_platform',
|
||||
entities: [__dirname + '/entities/**/*.entity{.ts,.js}'],
|
||||
synchronize: process.env.NODE_ENV === 'development',
|
||||
synchronize: false,
|
||||
logging: process.env.NODE_ENV === 'development',
|
||||
charset: 'utf8mb4',
|
||||
timezone: '+08:00',
|
||||
|
||||
@@ -29,15 +29,15 @@ export class Admin {
|
||||
@Column({ type: 'enum', enum: ['active', 'frozen'], default: 'active', comment: '状态' })
|
||||
status: 'active' | 'frozen';
|
||||
|
||||
@Column({ type: 'datetime', nullable: true, comment: '最后登录时间' })
|
||||
@Column({ name: 'last_login_at', type: 'datetime', nullable: true, comment: '最后登录时间' })
|
||||
lastLoginAt: Date;
|
||||
|
||||
@Column({ length: 50, nullable: true, comment: '最后登录IP' })
|
||||
@Column({ name: 'last_login_ip', length: 50, nullable: true, comment: '最后登录IP' })
|
||||
lastLoginIp: string;
|
||||
|
||||
@CreateDateColumn({ comment: '创建时间' })
|
||||
@CreateDateColumn({ name: 'created_at', comment: '创建时间' })
|
||||
createdAt: Date;
|
||||
|
||||
@UpdateDateColumn({ comment: '更新时间' })
|
||||
@UpdateDateColumn({ name: 'updated_at', comment: '更新时间' })
|
||||
updatedAt: Date;
|
||||
}
|
||||
|
||||
@@ -44,6 +44,6 @@ export class Coupon {
|
||||
@Column({ name: 'created_by', type: 'bigint', unsigned: true, nullable: true, comment: '创建人ID' })
|
||||
createdBy: number;
|
||||
|
||||
@CreateDateColumn({ comment: '创建时间' })
|
||||
@CreateDateColumn({ name: 'created_at', comment: '创建时间' })
|
||||
createdAt: Date;
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ export class Merchant {
|
||||
@Column({ name: 'seller_id', type: 'bigint', unsigned: true, unique: true, comment: '关联商家账户ID' })
|
||||
sellerId: number;
|
||||
|
||||
@Column({ length: 100, comment: '店铺名称' })
|
||||
@Column({ name: 'shop_name', length: 100, comment: '店铺名称' })
|
||||
shopName: string;
|
||||
|
||||
@Column({ length: 500, default: '', comment: '店铺Logo' })
|
||||
@@ -43,20 +43,20 @@ export class Merchant {
|
||||
@Column({ type: 'decimal', precision: 10, scale: 7, nullable: true, comment: '纬度' })
|
||||
latitude: number;
|
||||
|
||||
@Column({ length: 500, default: '', comment: '营业执照图片' })
|
||||
@Column({ name: 'business_license', length: 500, default: '', comment: '营业执照图片' })
|
||||
businessLicense: string;
|
||||
|
||||
@Column({ length: 50, default: '', comment: '营业执照编号' })
|
||||
@Column({ name: 'license_no', length: 50, default: '', comment: '营业执照编号' })
|
||||
licenseNo: string;
|
||||
|
||||
@Column({ length: 50, default: '', comment: '法人姓名' })
|
||||
@Column({ name: 'legal_person', length: 50, default: '', comment: '法人姓名' })
|
||||
legalPerson: string;
|
||||
|
||||
@Index()
|
||||
@Column({ type: 'enum', enum: ['pending', 'approved', 'rejected', 'frozen'], default: 'pending', comment: '状态' })
|
||||
status: 'pending' | 'approved' | 'rejected' | 'frozen';
|
||||
|
||||
@Column({ length: 500, nullable: true, comment: '拒绝原因' })
|
||||
@Column({ name: 'reject_reason', length: 500, nullable: true, comment: '拒绝原因' })
|
||||
rejectReason?: string;
|
||||
|
||||
@Column({ type: 'decimal', precision: 10, scale: 2, unsigned: true, default: 0, comment: '保证金' })
|
||||
@@ -78,18 +78,18 @@ export class Merchant {
|
||||
@Column({ type: 'decimal', precision: 2, scale: 1, unsigned: true, default: 5.0, comment: '评分' })
|
||||
rating: number;
|
||||
|
||||
@Column({ type: 'int', unsigned: true, default: 0, comment: '评价数' })
|
||||
@Column({ name: 'review_count', type: 'int', unsigned: true, default: 0, comment: '评价数' })
|
||||
reviewCount: number;
|
||||
|
||||
@Column({ type: 'boolean', default: false, comment: '是否自动接单' })
|
||||
@Column({ name: 'auto_confirm', type: 'boolean', default: false, comment: '是否自动接单' })
|
||||
autoConfirm: boolean;
|
||||
|
||||
@Column({ type: 'json', nullable: true, comment: '自动接单规则配置' })
|
||||
@Column({ name: 'auto_confirm_rules', type: 'json', nullable: true, comment: '自动接单规则配置' })
|
||||
autoConfirmRules: object;
|
||||
|
||||
@CreateDateColumn({ comment: '创建时间' })
|
||||
@CreateDateColumn({ name: 'created_at', comment: '创建时间' })
|
||||
createdAt: Date;
|
||||
|
||||
@UpdateDateColumn({ comment: '更新时间' })
|
||||
@UpdateDateColumn({ name: 'updated_at', comment: '更新时间' })
|
||||
updatedAt: Date;
|
||||
}
|
||||
|
||||
@@ -37,9 +37,9 @@ export class MktActivity {
|
||||
@Column({ name: 'end_time', type: 'datetime', nullable: true, comment: '活动结束时间' })
|
||||
endTime: Date;
|
||||
|
||||
@CreateDateColumn({ comment: '创建时间' })
|
||||
@CreateDateColumn({ name: 'created_at', comment: '创建时间' })
|
||||
createdAt: Date;
|
||||
|
||||
@UpdateDateColumn({ comment: '更新时间' })
|
||||
@UpdateDateColumn({ name: 'updated_at', comment: '更新时间' })
|
||||
updatedAt: Date;
|
||||
}
|
||||
|
||||
@@ -69,6 +69,6 @@ export class MktCashback {
|
||||
@JoinColumn({ name: 'order_id' })
|
||||
order: Order;
|
||||
|
||||
@CreateDateColumn({ comment: '创建时间' })
|
||||
@CreateDateColumn({ name: 'created_at', comment: '创建时间' })
|
||||
createdAt: Date;
|
||||
}
|
||||
|
||||
@@ -37,6 +37,6 @@ export class MktInvitation {
|
||||
@JoinColumn({ name: 'invitee_id' })
|
||||
invitee: User;
|
||||
|
||||
@CreateDateColumn({ comment: '邀请时间' })
|
||||
@CreateDateColumn({ name: 'created_at', comment: '邀请时间' })
|
||||
createdAt: Date;
|
||||
}
|
||||
|
||||
@@ -49,9 +49,9 @@ export class MktInviteWithdrawal {
|
||||
@JoinColumn({ name: 'user_id' })
|
||||
user: User;
|
||||
|
||||
@CreateDateColumn({ comment: '申请时间' })
|
||||
@CreateDateColumn({ name: 'created_at', comment: '申请时间' })
|
||||
createdAt: Date;
|
||||
|
||||
@UpdateDateColumn({ comment: '更新时间' })
|
||||
@UpdateDateColumn({ name: 'updated_at', comment: '更新时间' })
|
||||
updatedAt: Date;
|
||||
}
|
||||
|
||||
@@ -41,9 +41,9 @@ export class MktUserInviteStats {
|
||||
@JoinColumn({ name: 'user_id' })
|
||||
user: User;
|
||||
|
||||
@CreateDateColumn({ comment: '创建时间' })
|
||||
@CreateDateColumn({ name: 'created_at', comment: '创建时间' })
|
||||
createdAt: Date;
|
||||
|
||||
@UpdateDateColumn({ comment: '更新时间' })
|
||||
@UpdateDateColumn({ name: 'updated_at', comment: '更新时间' })
|
||||
updatedAt: Date;
|
||||
}
|
||||
|
||||
@@ -26,6 +26,6 @@ export class Notification {
|
||||
@Column({ type: 'json', nullable: true, comment: '附加数据' })
|
||||
extra: object;
|
||||
|
||||
@CreateDateColumn({ comment: '创建时间' })
|
||||
@CreateDateColumn({ name: 'created_at', comment: '创建时间' })
|
||||
createdAt: Date;
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ export class Order {
|
||||
@PrimaryGeneratedColumn({ type: 'bigint', unsigned: true })
|
||||
id: number;
|
||||
|
||||
@Column({ length: 32, unique: true, comment: '订单号' })
|
||||
@Column({ name: 'order_no', length: 32, unique: true, comment: '订单号' })
|
||||
orderNo: string;
|
||||
|
||||
@Index()
|
||||
@@ -124,9 +124,9 @@ export class Order {
|
||||
room: Room;
|
||||
|
||||
@Index()
|
||||
@CreateDateColumn({ comment: '创建时间' })
|
||||
@CreateDateColumn({ name: 'created_at', comment: '创建时间' })
|
||||
createdAt: Date;
|
||||
|
||||
@UpdateDateColumn({ comment: '更新时间' })
|
||||
@UpdateDateColumn({ name: 'updated_at', comment: '更新时间' })
|
||||
updatedAt: Date;
|
||||
}
|
||||
|
||||
@@ -5,18 +5,18 @@ export class PlatformConfig {
|
||||
@PrimaryGeneratedColumn({ type: 'bigint', unsigned: true })
|
||||
id: number;
|
||||
|
||||
@Column({ name: 'config_key', length: 50, unique: true, comment: '配置键' })
|
||||
@Column({ name: 'config_key', length: 100, unique: true, comment: '配置键' })
|
||||
configKey: string;
|
||||
|
||||
@Column({ name: 'config_value', length: 500, comment: '配置值' })
|
||||
@Column({ name: 'config_value', type: 'text', comment: '配置值' })
|
||||
configValue: string;
|
||||
|
||||
@Column({ length: 200, nullable: true, comment: '配置说明' })
|
||||
description: string;
|
||||
|
||||
@CreateDateColumn({ comment: '创建时间' })
|
||||
@CreateDateColumn({ name: 'created_at', comment: '创建时间' })
|
||||
createdAt: Date;
|
||||
|
||||
@UpdateDateColumn({ comment: '更新时间' })
|
||||
@UpdateDateColumn({ name: 'updated_at', comment: '更新时间' })
|
||||
updatedAt: Date;
|
||||
}
|
||||
@@ -46,15 +46,12 @@ export class Review {
|
||||
@Column({ name: 'is_anonymous', type: 'boolean', default: false, comment: '是否匿名' })
|
||||
isAnonymous: boolean;
|
||||
|
||||
@Column({ name: 'audit_status', type: 'enum', enum: ['pending', 'approved', 'rejected'], default: 'pending', comment: '审核状态' })
|
||||
auditStatus: 'pending' | 'approved' | 'rejected';
|
||||
@Column({ type: 'enum', enum: ['visible', 'hidden'], default: 'visible', comment: '状态' })
|
||||
status: 'visible' | 'hidden';
|
||||
|
||||
@Column({ name: 'audit_reject_reason', type: 'varchar', length: 500, nullable: true, comment: '审核拒绝原因' })
|
||||
auditRejectReason: string;
|
||||
|
||||
@CreateDateColumn({ comment: '创建时间' })
|
||||
@CreateDateColumn({ name: 'created_at', comment: '创建时间' })
|
||||
createdAt: Date;
|
||||
|
||||
@UpdateDateColumn({ comment: '更新时间' })
|
||||
@UpdateDateColumn({ name: 'updated_at', comment: '更新时间' })
|
||||
updatedAt: Date;
|
||||
}
|
||||
|
||||
@@ -12,18 +12,18 @@ export class RoomCalendarLog {
|
||||
@Column({ name: 'operator_id', type: 'bigint', unsigned: true, comment: '操作人ID' })
|
||||
operatorId: number;
|
||||
|
||||
@Column({ length: 100, comment: '变更日期范围' })
|
||||
@Column({ name: 'date_range', length: 100, comment: '变更日期范围' })
|
||||
dateRange: string;
|
||||
|
||||
@Column({ type: 'enum', enum: ['price', 'stock', 'status'], comment: '变更类型' })
|
||||
@Column({ name: 'change_type', type: 'enum', enum: ['price', 'stock', 'status'], comment: '变更类型' })
|
||||
changeType: 'price' | 'stock' | 'status';
|
||||
|
||||
@Column({ length: 100, nullable: true, comment: '变更前值' })
|
||||
@Column({ name: 'old_value', length: 100, nullable: true, comment: '变更前值' })
|
||||
oldValue: string;
|
||||
|
||||
@Column({ length: 100, nullable: true, comment: '变更后值' })
|
||||
@Column({ name: 'new_value', length: 100, nullable: true, comment: '变更后值' })
|
||||
newValue: string;
|
||||
|
||||
@CreateDateColumn({ comment: '创建时间' })
|
||||
@CreateDateColumn({ name: 'created_at', comment: '创建时间' })
|
||||
createdAt: Date;
|
||||
}
|
||||
|
||||
@@ -29,9 +29,9 @@ export class RoomCalendar {
|
||||
@Column({ type: 'enum', enum: ['available', 'unavailable'], default: 'available', comment: '房态' })
|
||||
status: 'available' | 'unavailable';
|
||||
|
||||
@CreateDateColumn({ comment: '创建时间' })
|
||||
@CreateDateColumn({ name: 'created_at', comment: '创建时间' })
|
||||
createdAt: Date;
|
||||
|
||||
@UpdateDateColumn({ comment: '更新时间' })
|
||||
@UpdateDateColumn({ name: 'updated_at', comment: '更新时间' })
|
||||
updatedAt: Date;
|
||||
}
|
||||
|
||||
@@ -24,10 +24,10 @@ export class Room {
|
||||
@Column({ type: 'decimal', precision: 6, scale: 2, default: 0, comment: '面积(平方米)' })
|
||||
area: number;
|
||||
|
||||
@Column({ length: 50, default: '', comment: '床型' })
|
||||
@Column({ name: 'bed_type', length: 50, default: '', comment: '床型' })
|
||||
bedType: string;
|
||||
|
||||
@Column({ type: 'tinyint', unsigned: true, default: 1, comment: '最多入住人数' })
|
||||
@Column({ name: 'max_guests', type: 'tinyint', unsigned: true, default: 1, comment: '最多入住人数' })
|
||||
maxGuests: number;
|
||||
|
||||
@Column({ length: 20, default: '', comment: '楼层' })
|
||||
@@ -39,7 +39,7 @@ export class Room {
|
||||
@Column({ type: 'json', nullable: true, comment: '图片URL列表' })
|
||||
images: string[];
|
||||
|
||||
@Column({ length: 500, default: '', comment: '封面图' })
|
||||
@Column({ name: 'cover_image', length: 500, default: '', comment: '封面图' })
|
||||
coverImage: string;
|
||||
|
||||
@Index()
|
||||
@@ -50,28 +50,28 @@ export class Room {
|
||||
status: 'on_sale' | 'off_sale';
|
||||
|
||||
@Index()
|
||||
@Column({ type: 'enum', enum: ['pending', 'approved', 'rejected'], default: 'pending', comment: '审核状态' })
|
||||
@Column({ name: 'audit_status', type: 'enum', enum: ['pending', 'approved', 'rejected'], default: 'pending', comment: '审核状态' })
|
||||
auditStatus: 'pending' | 'approved' | 'rejected';
|
||||
|
||||
@Column({ length: 500, nullable: true, comment: '审核拒绝原因' })
|
||||
@Column({ name: 'audit_reject_reason', length: 500, nullable: true, comment: '审核拒绝原因' })
|
||||
auditRejectReason?: string;
|
||||
|
||||
@Index()
|
||||
@Column({ type: 'decimal', precision: 2, scale: 1, unsigned: true, default: 5.0, comment: '评分' })
|
||||
rating: number;
|
||||
|
||||
@Column({ type: 'int', unsigned: true, default: 0, comment: '评价数' })
|
||||
@Column({ name: 'review_count', type: 'int', unsigned: true, default: 0, comment: '评价数' })
|
||||
reviewCount: number;
|
||||
|
||||
@Column({ type: 'text', nullable: true, comment: '房源描述' })
|
||||
description: string;
|
||||
|
||||
@Column({ type: 'enum', enum: ['free', 'flexible', 'strict'], default: 'flexible', comment: '取消政策' })
|
||||
@Column({ name: 'cancel_policy', type: 'enum', enum: ['free', 'flexible', 'strict'], default: 'flexible', comment: '取消政策' })
|
||||
cancelPolicy: 'free' | 'flexible' | 'strict';
|
||||
|
||||
@CreateDateColumn({ comment: '创建时间' })
|
||||
@CreateDateColumn({ name: 'created_at', comment: '创建时间' })
|
||||
createdAt: Date;
|
||||
|
||||
@UpdateDateColumn({ comment: '更新时间' })
|
||||
@UpdateDateColumn({ name: 'updated_at', comment: '更新时间' })
|
||||
updatedAt: Date;
|
||||
}
|
||||
|
||||
@@ -31,9 +31,9 @@ export class Seller {
|
||||
@OneToOne(() => Merchant, merchant => merchant.seller)
|
||||
merchant: Merchant;
|
||||
|
||||
@CreateDateColumn({ comment: '创建时间' })
|
||||
@CreateDateColumn({ name: 'created_at', comment: '创建时间' })
|
||||
createdAt: Date;
|
||||
|
||||
@UpdateDateColumn({ comment: '更新时间' })
|
||||
@UpdateDateColumn({ name: 'updated_at', comment: '更新时间' })
|
||||
updatedAt: Date;
|
||||
}
|
||||
|
||||
@@ -24,6 +24,6 @@ export class SettlementItem {
|
||||
@Column({ name: 'order_amount', type: 'decimal', precision: 10, scale: 2, unsigned: true, comment: '订单金额' })
|
||||
orderAmount: number;
|
||||
|
||||
@CreateDateColumn({ comment: '创建时间' })
|
||||
@CreateDateColumn({ name: 'created_at', comment: '创建时间' })
|
||||
createdAt: Date;
|
||||
}
|
||||
|
||||
@@ -56,9 +56,9 @@ export class Settlement {
|
||||
@OneToMany(() => SettlementItem, item => item.settlement)
|
||||
items: SettlementItem[];
|
||||
|
||||
@CreateDateColumn({ comment: '创建时间' })
|
||||
@CreateDateColumn({ name: 'created_at', comment: '创建时间' })
|
||||
createdAt: Date;
|
||||
|
||||
@UpdateDateColumn({ comment: '更新时间' })
|
||||
@UpdateDateColumn({ name: 'updated_at', comment: '更新时间' })
|
||||
updatedAt: Date;
|
||||
}
|
||||
|
||||
@@ -20,22 +20,22 @@ export class User {
|
||||
@Column({ type: 'tinyint', unsigned: true, default: 0, comment: '性别 0-未知 1-男 2-女' })
|
||||
gender: number;
|
||||
|
||||
@Column({ length: 50, nullable: true, comment: '真实姓名' })
|
||||
@Column({ name: 'real_name', length: 50, nullable: true, comment: '真实姓名' })
|
||||
realName: string;
|
||||
|
||||
@Column({ length: 255, nullable: true, select: false, comment: '身份证号' })
|
||||
@Column({ name: 'id_card', length: 255, nullable: true, select: false, comment: '身份证号' })
|
||||
idCard: string;
|
||||
|
||||
@Index()
|
||||
@Column({ type: 'enum', enum: ['active', 'frozen', 'deleted'], default: 'active', comment: '状态' })
|
||||
status: 'active' | 'frozen' | 'deleted';
|
||||
|
||||
@Column({ type: 'datetime', nullable: true, comment: '最后登录时间' })
|
||||
@Column({ name: 'last_login_at', type: 'datetime', nullable: true, comment: '最后登录时间' })
|
||||
lastLoginAt: Date;
|
||||
|
||||
@CreateDateColumn({ comment: '创建时间' })
|
||||
@CreateDateColumn({ name: 'created_at', comment: '创建时间' })
|
||||
createdAt: Date;
|
||||
|
||||
@UpdateDateColumn({ comment: '更新时间' })
|
||||
@UpdateDateColumn({ name: 'updated_at', comment: '更新时间' })
|
||||
updatedAt: Date;
|
||||
}
|
||||
|
||||
@@ -54,9 +54,9 @@ export class Withdrawal {
|
||||
@Column({ name: 'paid_at', type: 'datetime', nullable: true, comment: '打款时间' })
|
||||
paidAt: Date;
|
||||
|
||||
@CreateDateColumn({ comment: '创建时间' })
|
||||
@CreateDateColumn({ name: 'created_at', comment: '创建时间' })
|
||||
createdAt: Date;
|
||||
|
||||
@UpdateDateColumn({ comment: '更新时间' })
|
||||
@UpdateDateColumn({ name: 'updated_at', comment: '更新时间' })
|
||||
updatedAt: Date;
|
||||
}
|
||||
|
||||
@@ -236,11 +236,11 @@ export class ActivityService {
|
||||
const inviteeIds = list.map((item) => item.inviteeId);
|
||||
const orderCounts = await this.orderRepo
|
||||
.createQueryBuilder('order')
|
||||
.select('order.userId', 'userId')
|
||||
.select('order.user_id', 'userId')
|
||||
.addSelect('COUNT(*)', 'count')
|
||||
.where('order.userId IN (:...ids)', { ids: inviteeIds })
|
||||
.where('order.user_id IN (:...ids)', { ids: inviteeIds })
|
||||
.andWhere('order.status = :status', { status: 'completed' })
|
||||
.groupBy('order.userId')
|
||||
.groupBy('order.user_id')
|
||||
.getRawMany();
|
||||
|
||||
const orderCountMap = new Map(orderCounts.map((item) => [item.userId, parseInt(item.count)]));
|
||||
@@ -436,11 +436,10 @@ export class ActivityService {
|
||||
// ===== 管理端功能 =====
|
||||
|
||||
async getInviteCashbackConfig() {
|
||||
const activity = await this.activityRepo.findOne({
|
||||
let activity = await this.activityRepo.findOne({
|
||||
where: { type: 'invite_cashback' },
|
||||
});
|
||||
if (!activity) {
|
||||
// 创建默认配置
|
||||
activity = this.activityRepo.create({
|
||||
name: '邀请返现',
|
||||
type: 'invite_cashback',
|
||||
|
||||
@@ -24,6 +24,33 @@ export class InviteCashbackConfig {
|
||||
withdrawThreshold: number;
|
||||
}
|
||||
|
||||
export class UpdateInviteCashbackConfig {
|
||||
@ApiPropertyOptional({ description: '首单返现比例' })
|
||||
@IsOptional()
|
||||
@IsNumber()
|
||||
firstOrderRate?: number;
|
||||
|
||||
@ApiPropertyOptional({ description: '二单返现比例' })
|
||||
@IsOptional()
|
||||
@IsNumber()
|
||||
secondOrderRate?: number;
|
||||
|
||||
@ApiPropertyOptional({ description: '最低返现' })
|
||||
@IsOptional()
|
||||
@IsNumber()
|
||||
minCashback?: number;
|
||||
|
||||
@ApiPropertyOptional({ description: '最高返现' })
|
||||
@IsOptional()
|
||||
@IsNumber()
|
||||
maxCashback?: number;
|
||||
|
||||
@ApiPropertyOptional({ description: '提现门槛' })
|
||||
@IsOptional()
|
||||
@IsNumber()
|
||||
withdrawThreshold?: number;
|
||||
}
|
||||
|
||||
// ===== 活动 DTO =====
|
||||
|
||||
export class CreateActivityDto {
|
||||
@@ -63,12 +90,17 @@ export class UpdateActivityDto {
|
||||
@IsString()
|
||||
name?: string;
|
||||
|
||||
@ApiPropertyOptional({ description: '是否启用' })
|
||||
@IsOptional()
|
||||
@IsBoolean()
|
||||
enabled?: boolean;
|
||||
|
||||
@ApiPropertyOptional({ description: '活动配置' })
|
||||
@IsOptional()
|
||||
@IsObject()
|
||||
@ValidateNested()
|
||||
@Type(() => InviteCashbackConfig)
|
||||
config?: InviteCashbackConfig;
|
||||
@Type(() => UpdateInviteCashbackConfig)
|
||||
config?: UpdateInviteCashbackConfig;
|
||||
|
||||
@ApiPropertyOptional({ description: '活动开始时间' })
|
||||
@IsOptional()
|
||||
|
||||
@@ -10,4 +10,7 @@ import { ConfigController } from './config.controller';
|
||||
providers: [ConfigService],
|
||||
exports: [ConfigService],
|
||||
})
|
||||
export class ConfigModule {}
|
||||
export class ConfigModule {}
|
||||
|
||||
// 别名导出,保持兼容性
|
||||
export { ConfigModule as PlatformConfigModule };
|
||||
@@ -63,7 +63,7 @@ export class MerchantService {
|
||||
.where('m.status = :status', { status: 'approved' });
|
||||
|
||||
if (keyword) {
|
||||
qb.andWhere('m.shopName LIKE :kw', { kw: `%${keyword}%` });
|
||||
qb.andWhere('m.shop_name LIKE :kw', { kw: `%${keyword}%` });
|
||||
}
|
||||
if (city) {
|
||||
qb.andWhere('m.city = :city', { city });
|
||||
@@ -87,7 +87,7 @@ export class MerchantService {
|
||||
const qb = this.merchantRepo.createQueryBuilder('m');
|
||||
|
||||
if (keyword) {
|
||||
qb.andWhere('(m.shopName LIKE :kw OR m.phone LIKE :kw)', {
|
||||
qb.andWhere('(m.shop_name LIKE :kw OR m.phone LIKE :kw)', {
|
||||
kw: `%${keyword}%`,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -3,6 +3,8 @@ import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
import { Order } from '@/entities/order.entity';
|
||||
import { Room } from '@/entities/room.entity';
|
||||
import { RoomCalendar } from '@/entities/room-calendar.entity';
|
||||
import { User } from '@/entities/user.entity';
|
||||
import { Merchant } from '@/entities/merchant.entity';
|
||||
import { OrderService } from './order.service';
|
||||
import { UserOrderController, MerchantOrderController, AdminOrderController } from './order.controller';
|
||||
import { MerchantModule } from '../merchant/merchant.module';
|
||||
@@ -11,7 +13,7 @@ import { PlatformConfigModule } from '../config/config.module';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
TypeOrmModule.forFeature([Order, Room, RoomCalendar]),
|
||||
TypeOrmModule.forFeature([Order, Room, RoomCalendar, User, Merchant]),
|
||||
MerchantModule,
|
||||
forwardRef(() => ActivityModule),
|
||||
PlatformConfigModule,
|
||||
|
||||
@@ -86,7 +86,7 @@ export class OrderService {
|
||||
const qb = this.orderRepo.createQueryBuilder('o')
|
||||
.leftJoinAndSelect('o.room', 'r')
|
||||
.leftJoinAndSelect('o.merchant', 'm')
|
||||
.where('o.userId = :userId', { userId });
|
||||
.where('o.user_id = :userId', { userId });
|
||||
|
||||
if (status) {
|
||||
qb.andWhere('o.status = :status', { status });
|
||||
@@ -104,12 +104,12 @@ export class OrderService {
|
||||
const qb = this.orderRepo.createQueryBuilder('o')
|
||||
.leftJoinAndSelect('o.room', 'r')
|
||||
.leftJoinAndSelect('o.user', 'u')
|
||||
.where('o.merchantId = :merchantId', { merchantId });
|
||||
.where('o.merchant_id = :merchantId', { merchantId });
|
||||
|
||||
if (status) qb.andWhere('o.status = :status', { status });
|
||||
if (orderNo) qb.andWhere('o.orderNo LIKE :orderNo', { orderNo: `%${orderNo}%` });
|
||||
if (startDate) qb.andWhere('o.createdAt >= :startDate', { startDate });
|
||||
if (endDate) qb.andWhere('o.createdAt <= :endDate', { endDate });
|
||||
if (orderNo) qb.andWhere('o.order_no LIKE :orderNo', { orderNo: `%${orderNo}%` });
|
||||
if (startDate) qb.andWhere('o.created_at >= :startDate', { startDate });
|
||||
if (endDate) qb.andWhere('o.created_at <= :endDate', { endDate });
|
||||
|
||||
qb.orderBy('o.createdAt', 'DESC');
|
||||
qb.skip((page - 1) * pageSize).take(pageSize);
|
||||
@@ -349,9 +349,9 @@ export class OrderService {
|
||||
.leftJoinAndSelect('o.user', 'u');
|
||||
|
||||
if (status) qb.andWhere('o.status = :status', { status });
|
||||
if (orderNo) qb.andWhere('o.orderNo LIKE :orderNo', { orderNo: `%${orderNo}%` });
|
||||
if (startDate) qb.andWhere('o.createdAt >= :startDate', { startDate });
|
||||
if (endDate) qb.andWhere('o.createdAt <= :endDate', { endDate });
|
||||
if (orderNo) qb.andWhere('o.order_no LIKE :orderNo', { orderNo: `%${orderNo}%` });
|
||||
if (startDate) qb.andWhere('o.created_at >= :startDate', { startDate });
|
||||
if (endDate) qb.andWhere('o.created_at <= :endDate', { endDate });
|
||||
|
||||
qb.orderBy('o.createdAt', 'DESC');
|
||||
qb.skip((page - 1) * pageSize).take(pageSize);
|
||||
|
||||
@@ -47,26 +47,26 @@ export class ReviewService {
|
||||
content: dto.content,
|
||||
images: dto.images,
|
||||
isAnonymous: dto.isAnonymous || false,
|
||||
auditStatus: 'pending',
|
||||
status: 'visible',
|
||||
});
|
||||
|
||||
await this.reviewRepo.save(review);
|
||||
return { message: '评价已提交,等待审核' };
|
||||
return { message: '评价已提交' };
|
||||
}
|
||||
|
||||
// 查询评价列表(公开,只显示审核通过的)
|
||||
// 查询评价列表(公开,只显示可见的)
|
||||
async findPublic(query: QueryReviewDto) {
|
||||
const { page = 1, pageSize = 10, merchantId, roomId } = query;
|
||||
const qb = this.reviewRepo
|
||||
.createQueryBuilder('r')
|
||||
.leftJoinAndSelect('r.order', 'o')
|
||||
.where('r.auditStatus = :auditStatus', { auditStatus: 'approved' });
|
||||
.where('r.status = :status', { status: 'visible' });
|
||||
|
||||
if (merchantId) {
|
||||
qb.andWhere('r.merchantId = :merchantId', { merchantId: Number(merchantId) });
|
||||
qb.andWhere('r.merchant_id = :merchantId', { merchantId: Number(merchantId) });
|
||||
}
|
||||
if (roomId) {
|
||||
qb.andWhere('r.roomId = :roomId', { roomId: Number(roomId) });
|
||||
qb.andWhere('r.room_id = :roomId', { roomId: Number(roomId) });
|
||||
}
|
||||
|
||||
qb.orderBy('r.createdAt', 'DESC');
|
||||
@@ -83,7 +83,7 @@ export class ReviewService {
|
||||
return this.reviewRepo.findOne({ where: { orderId } });
|
||||
}
|
||||
|
||||
// 管理员审核评价列表
|
||||
// 管理员评价列表
|
||||
async findAllForAdmin(query: QueryReviewDto) {
|
||||
const { page = 1, pageSize = 10, auditStatus } = query;
|
||||
const qb = this.reviewRepo
|
||||
@@ -91,7 +91,7 @@ export class ReviewService {
|
||||
.leftJoinAndSelect('r.order', 'o');
|
||||
|
||||
if (auditStatus) {
|
||||
qb.andWhere('r.auditStatus = :auditStatus', { auditStatus });
|
||||
qb.andWhere('r.status = :status', { status: auditStatus });
|
||||
}
|
||||
|
||||
qb.orderBy('r.createdAt', 'DESC');
|
||||
@@ -103,27 +103,27 @@ export class ReviewService {
|
||||
return { list, total, page: safePage, pageSize: safePageSize, totalPages: Math.ceil(total / safePageSize) };
|
||||
}
|
||||
|
||||
// 审核通过
|
||||
// 显示评价
|
||||
async approve(id: number) {
|
||||
const review = await this.reviewRepo.findOne({ where: { id } });
|
||||
if (!review) throw new NotFoundException('评价不存在');
|
||||
|
||||
await this.reviewRepo.update(id, { auditStatus: 'approved', auditRejectReason: '' });
|
||||
await this.reviewRepo.update(id, { status: 'visible' });
|
||||
|
||||
// 更新商家和房源的评分
|
||||
await this.updateMerchantRating(review.merchantId);
|
||||
await this.updateRoomRating(review.roomId);
|
||||
|
||||
return { message: '评价已通过审核' };
|
||||
return { message: '评价已显示' };
|
||||
}
|
||||
|
||||
// 审核拒绝
|
||||
async reject(id: number, reason: string) {
|
||||
// 隐藏评价
|
||||
async reject(id: number, _reason: string) {
|
||||
const review = await this.reviewRepo.findOne({ where: { id } });
|
||||
if (!review) throw new NotFoundException('评价不存在');
|
||||
|
||||
await this.reviewRepo.update(id, { auditStatus: 'rejected', auditRejectReason: reason });
|
||||
return { message: '评价已拒绝' };
|
||||
await this.reviewRepo.update(id, { status: 'hidden' });
|
||||
return { message: '评价已隐藏' };
|
||||
}
|
||||
|
||||
// 更新商家平均评分
|
||||
@@ -132,8 +132,8 @@ export class ReviewService {
|
||||
.createQueryBuilder('r')
|
||||
.select('AVG(r.rating)', 'avgRating')
|
||||
.addSelect('COUNT(r.id)', 'count')
|
||||
.where('r.merchantId = :merchantId', { merchantId })
|
||||
.andWhere('r.auditStatus = :auditStatus', { auditStatus: 'approved' })
|
||||
.where('r.merchant_id = :merchantId', { merchantId })
|
||||
.andWhere('r.status = :status', { status: 'visible' })
|
||||
.getRawOne();
|
||||
|
||||
if (result) {
|
||||
@@ -150,8 +150,8 @@ export class ReviewService {
|
||||
.createQueryBuilder('r')
|
||||
.select('AVG(r.rating)', 'avgRating')
|
||||
.addSelect('COUNT(r.id)', 'count')
|
||||
.where('r.roomId = :roomId', { roomId })
|
||||
.andWhere('r.auditStatus = :auditStatus', { auditStatus: 'approved' })
|
||||
.where('r.room_id = :roomId', { roomId })
|
||||
.andWhere('r.status = :status', { status: 'visible' })
|
||||
.getRawOne();
|
||||
|
||||
if (result) {
|
||||
|
||||
@@ -90,7 +90,7 @@ export class RoomService {
|
||||
.createQueryBuilder('r')
|
||||
.leftJoinAndSelect('r.merchant', 'm')
|
||||
.where('r.status = :status', { status: 'on_sale' })
|
||||
.andWhere('r.auditStatus = :auditStatus', { auditStatus: 'approved' });
|
||||
.andWhere('r.audit_status = :auditStatus', { auditStatus: 'approved' });
|
||||
|
||||
if (keyword) {
|
||||
qb.andWhere('r.name LIKE :kw', { kw: `%${keyword}%` });
|
||||
@@ -108,15 +108,15 @@ export class RoomService {
|
||||
qb.andWhere('m.city = :city', { city });
|
||||
}
|
||||
if (merchantId) {
|
||||
qb.andWhere('r.merchantId = :merchantId', { merchantId: Number(merchantId) });
|
||||
qb.andWhere('r.merchant_id = :merchantId', { merchantId: Number(merchantId) });
|
||||
}
|
||||
|
||||
// 人数筛选:房间可住人数 >= 成人数
|
||||
if (adultCount && !roomCount) {
|
||||
qb.andWhere('r.maxGuests >= :adultCount', { adultCount });
|
||||
qb.andWhere('r.max_guests >= :adultCount', { adultCount });
|
||||
} else if (adultCount && roomCount) {
|
||||
// 多间房时,总可住人数 >= 成人数
|
||||
qb.andWhere('r.maxGuests * :roomCount >= :adultCount', { roomCount, adultCount });
|
||||
qb.andWhere('r.max_guests * :roomCount >= :adultCount', { roomCount, adultCount });
|
||||
}
|
||||
|
||||
const sortMap: Record<string, string> = {
|
||||
@@ -203,7 +203,7 @@ export class RoomService {
|
||||
}
|
||||
const qb = this.roomRepo
|
||||
.createQueryBuilder('r')
|
||||
.where('r.merchantId = :merchantId', { merchantId: safeMerchantId });
|
||||
.where('r.merchant_id = :merchantId', { merchantId: safeMerchantId });
|
||||
|
||||
if (status) {
|
||||
qb.andWhere('r.status = :status', { status });
|
||||
@@ -232,7 +232,7 @@ export class RoomService {
|
||||
qb.andWhere('r.name LIKE :kw', { kw: `%${keyword}%` });
|
||||
}
|
||||
if (auditStatus) {
|
||||
qb.andWhere('r.auditStatus = :auditStatus', { auditStatus });
|
||||
qb.andWhere('r.audit_status = :auditStatus', { auditStatus });
|
||||
}
|
||||
if (type) {
|
||||
qb.andWhere('r.type = :type', { type });
|
||||
|
||||
Generated
+9654
-7800
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user