This commit is contained in:
2026-05-14 09:55:31 +08:00
16 changed files with 88 additions and 73 deletions
+5 -1
View File
@@ -32,7 +32,11 @@
"Bash(python3 -c \"import sys, json; data=json.load\\(sys.stdin\\); token=data['data']['accessToken']; import jwt; decoded=jwt.decode\\(token, options={'verify_signature': False}\\); print\\(f\\\\\"iat: {decoded['iat']}, exp: {decoded['exp']}, duration: {decoded['exp']-decoded['iat']} seconds \\({\\(decoded['exp']-decoded['iat']\\)/3600} hours\\)\\\\\"\\)\")",
"Bash(curl -s -X GET http://localhost:3000/api/orders -H \"Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxIiwicGhvbmUiOiIxMzgwMDEzODAwMCIsImlhdCI6MTc3ODM4MTc2NywiZXhwIjoxNzc4Mzg4OTY3fQ.-jcY69afC6O6CtKtOj6tRaoiknypwDfvpXYhpz95rVE\")",
"Bash(pnpm install *)",
"Bash(pnpm dev:mp-weixin)"
"Bash(pnpm dev:mp-weixin)",
"Read(//e/project/wb/**)",
"Bash(pnpm dev:server)",
"Bash(pnpm --filter @rent/server run build)",
"Bash(pnpm --filter @rent/server run dev)"
]
}
}
+4 -4
View File
@@ -1,16 +1,16 @@
import request from '@/utils/request';
import { get, post } from '@/utils/request';
// 获取可领取的优惠券列表
export function getAvailableCoupons(params?: { merchantId?: number; roomId?: number }) {
return request.get('/user/coupons/available', params);
return get('/user/coupons/available', params);
}
// 领取优惠券
export function claimCoupon(couponId: number) {
return request.post('/user/coupons/claim', { couponId });
return post('/user/coupons/claim', { couponId });
}
// 获取我的优惠券列表
export function getMyCoupons(params?: { status?: string }) {
return request.get('/user/coupons', params);
return get('/user/coupons', params);
}
+7 -7
View File
@@ -1,31 +1,31 @@
import request from '@/utils/request';
import { get, post, put, del } from '@/utils/request';
// 获取常住人列表
export function getGuestList() {
return request.get('/user/guests');
return get('/user/guests');
}
// 获取常住人详情
export function getGuestDetail(id: number) {
return request.get(`/user/guests/${id}`);
return get(`/user/guests/${id}`);
}
// 添加常住人
export function createGuest(data: any) {
return request.post('/user/guests', data);
return post('/user/guests', data);
}
// 更新常住人
export function updateGuest(id: number, data: any) {
return request.put(`/user/guests/${id}`, data);
return put(`/user/guests/${id}`, data);
}
// 删除常住人
export function deleteGuest(id: number) {
return request.delete(`/user/guests/${id}`);
return del(`/user/guests/${id}`);
}
// 设置默认常住人
export function setDefaultGuest(id: number) {
return request.put(`/user/guests/${id}/default`);
return put(`/user/guests/${id}/default`);
}
+11 -11
View File
@@ -1,4 +1,4 @@
import request from '@/utils/request';
import { get, post } from '@/utils/request';
/**
* 商家财务API
@@ -7,28 +7,28 @@ export const financeApi = {
/**
* 获取钱包信息
*/
getWallet: () => request.get('/seller/finance/wallet'),
getWallet: () => get('/seller/finance/wallet'),
/**
* 获取交易流水
*/
getTransactions: (params?: any) => request.get('/seller/finance/transactions', { params }),
getTransactions: (params?: any) => get('/seller/finance/transactions', params),
/**
* 获取结算记录
*/
getSettlements: (params?: any) => request.get('/seller/finance/settlements', { params }),
getSettlements: (params?: any) => get('/seller/finance/settlements', params),
/**
* 获取结算详情
*/
getSettlementDetail: (id: number) => request.get(`/seller/finance/settlements/${id}`),
getSettlementDetail: (id: number) => get(`/seller/finance/settlements/${id}`),
/**
* 获取结算明细
*/
getSettlementItems: (id: number, params?: any) =>
request.get(`/seller/finance/settlements/${id}/items`, { params }),
get(`/seller/finance/settlements/${id}/items`, params),
/**
* 申请提现
@@ -39,17 +39,17 @@ export const financeApi = {
accountName: string;
accountNumber: string;
bankName?: string;
}) => request.post('/seller/finance/withdrawals', data),
}) => post('/seller/finance/withdrawals', data),
/**
* 获取提现记录
*/
getWithdrawals: (params?: any) => request.get('/seller/finance/withdrawals', { params }),
getWithdrawals: (params?: any) => get('/seller/finance/withdrawals', params),
/**
* 获取提现详情
*/
getWithdrawalDetail: (id: number) => request.get(`/seller/finance/withdrawals/${id}`),
getWithdrawalDetail: (id: number) => get(`/seller/finance/withdrawals/${id}`),
};
/**
@@ -59,11 +59,11 @@ export const statisticsApi = {
/**
* 获取数据概览
*/
getOverview: () => request.get('/seller/statistics/overview'),
getOverview: () => get('/seller/statistics/overview'),
/**
* 获取收入趋势
*/
getIncomeTrend: (type: 'day' | 'week' | 'month' = 'day') =>
request.get('/seller/statistics/income-trend', { params: { type } }),
get('/seller/statistics/income-trend', { type }),
};
+3 -3
View File
@@ -1,4 +1,4 @@
import request from '@/utils/request';
import { request } from '@/utils/request';
// 钱包信息接口
export interface WalletInfo {
@@ -58,7 +58,7 @@ export const walletApi = {
return request<{ items: Transaction[]; total: number }>({
url: '/user/finance/transactions',
method: 'GET',
params,
data: params,
});
},
@@ -85,7 +85,7 @@ export const walletApi = {
return request<{ items: Withdrawal[]; total: number }>({
url: '/user/finance/withdrawals',
method: 'GET',
params,
data: params,
});
},
};
+5 -5
View File
@@ -1,21 +1,21 @@
import request from '@/utils/request';
export function getCouponList(params: any) {
return request.get('/admin/coupons', { params });
return request({ url: '/admin/coupons', method: 'GET', params });
}
export function getCouponDetail(id: number) {
return request.get(`/admin/coupons/${id}`);
return request({ url: `/admin/coupons/${id}`, method: 'GET' });
}
export function createCoupon(data: any) {
return request.post('/admin/coupons', data);
return request({ url: '/admin/coupons', method: 'POST', data });
}
export function updateCoupon(id: number, data: any) {
return request.put(`/admin/coupons/${id}`, data);
return request({ url: `/admin/coupons/${id}`, method: 'PUT', data });
}
export function deleteCoupon(id: number) {
return request.delete(`/admin/coupons/${id}`);
return request({ url: `/admin/coupons/${id}`, method: 'DELETE' });
}
+1 -1
View File
@@ -54,7 +54,7 @@ export class Order {
couponDiscount: number;
@Column({ name: 'user_coupon_id', type: 'bigint', unsigned: true, nullable: true, comment: '使用的用户优惠券ID' })
userCouponId: number;
userCouponId: number | null;
@Column({ name: 'total_amount', type: 'decimal', precision: 10, scale: 2, unsigned: true, comment: '订单总金额' })
totalAmount: number;
@@ -0,0 +1,7 @@
// 统一导出所有财务相关 DTO
export * from './withdrawal.dto';
export * from './transaction.dto';
export * from './account.dto';
export * from './settlement.dto';
export * from './reconciliation.dto';
export * from './report.dto';
@@ -5,11 +5,11 @@ import { ConfigService } from '@nestjs/config';
import { Order } from '@/entities/order.entity';
import { PlatformAccount } from '@/entities/platform-account.entity';
import { PlatformTransaction } from '@/entities/platform-transaction.entity';
import { Wechatpay } from 'wechatpay-node-v3';
import Wechatpay = require('wechatpay-node-v3');
@Injectable()
export class RefundService {
private wechatpayClient: Wechatpay;
private wechatpayClient: Wechatpay | null;
constructor(
@InjectRepository(Order)
@@ -45,9 +45,10 @@ export class RefundService {
this.wechatpayClient = new Wechatpay({
appid,
mchid,
publicKey: Buffer.from(privateKey, 'utf-8'),
privateKey: Buffer.from(privateKey, 'utf-8'),
serialNo,
apiv3Key,
serial_no: serialNo,
key: apiv3Key,
});
console.log('[微信支付] 客户端初始化成功');
} catch (error) {
@@ -153,7 +154,7 @@ export class RefundService {
const totalAmount = Math.round(order.payAmount * 100);
// 调用微信支付退款API
const result = await this.wechatpayClient.refunds({
const result: any = await this.wechatpayClient.refunds({
transaction_id: order.transactionId,
out_refund_no: refundNo,
reason: '用户申请退款',
@@ -11,7 +11,7 @@ import {
} from '@nestjs/common';
import { GuestService } from './guest.service';
import { CreateGuestDto, UpdateGuestDto } from './dto/guest.dto';
import { JwtAuthGuard } from '../auth/jwt-auth.guard';
import { JwtAuthGuard } from '@/common/guards/jwt-auth.guard';
@Controller('user/guests')
@UseGuards(JwtAuthGuard)
@@ -1,9 +1,9 @@
import { Controller, Get, Query, UseGuards } from '@nestjs/common';
import { ApiTags, ApiOperation, ApiBearerAuth } from '@nestjs/swagger';
import { JwtAuthGuard } from '@/modules/auth/jwt-auth.guard';
import { RolesGuard } from '@/modules/auth/roles.guard';
import { Roles } from '@/modules/auth/roles.decorator';
import { CurrentUser } from '@/modules/auth/current-user.decorator';
import { JwtAuthGuard } from '@/common/guards/jwt-auth.guard';
import { RolesGuard } from '@/common/guards/roles.guard';
import { Roles } from '@/common/decorators/roles.decorator';
import { CurrentUser } from '@/common/decorators/current-user.decorator';
import { StatisticsService } from './statistics.service';
@ApiTags('商家统计')
@@ -63,7 +63,7 @@ export class StatisticsService {
month: monthData,
roomCount,
balance: account?.balance || 0,
availableBalance: account?.availableBalance || 0,
availableBalance: account ? Number(account.balance) - Number(account.frozenBalance) : 0,
};
}
@@ -82,7 +82,7 @@ export class OrderService {
// 处理优惠券
let couponDiscount = 0;
let userCouponId = null;
let userCouponId: number | null = null;
if (dto.couponId) {
// 查询用户可用优惠券
@@ -138,7 +138,7 @@ export class OrderService {
serviceFee,
merchantIncome,
couponDiscount,
userCouponId,
userCouponId: userCouponId !== null ? userCouponId : undefined,
totalAmount,
payAmount,
contactName: dto.contactName,
@@ -0,0 +1,25 @@
import { Injectable, Logger } from '@nestjs/common';
import { Cron } from '@nestjs/schedule';
import { SettlementService } from '@/modules/finance/settlement.service';
@Injectable()
export class SettlementSchedule {
private readonly logger = new Logger(SettlementSchedule.name);
constructor(
private readonly settlementService: SettlementService,
) {}
// 每天凌晨2点执行自动结算
@Cron('0 2 * * *')
async autoSettle() {
try {
this.logger.log('开始执行自动结算任务');
// 调用 SettlementService 的周结算方法
await this.settlementService.handleWeeklySettlement();
this.logger.log('自动结算任务执行完成');
} catch (error) {
this.logger.error('自动结算任务执行失败', error.stack);
}
}
}
+6 -2
View File
@@ -10,8 +10,10 @@ USE `rent_platform`;
-- ============================================================
CREATE TABLE `users` (
`id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
`phone` VARCHAR(20) NOT NULL COMMENT '手机号',
`phone` VARCHAR(20) NULL COMMENT '手机号',
`password` VARCHAR(255) DEFAULT NULL COMMENT '密码(AES加密存储)',
`wechat_openid` VARCHAR(100) NULL COMMENT '微信openid',
`wechat_unionid` VARCHAR(100) NULL COMMENT '微信unionid',
`nickname` VARCHAR(50) DEFAULT '' COMMENT '昵称',
`avatar` VARCHAR(500) DEFAULT '' COMMENT '头像URL',
`gender` TINYINT UNSIGNED DEFAULT 0 COMMENT '性别 0-未知 1-男 2-女',
@@ -22,7 +24,9 @@ CREATE TABLE `users` (
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_phone` (`phone`),
KEY `idx_phone` (`phone`),
KEY `idx_wechat_openid` (`wechat_openid`),
KEY `idx_wechat_unionid` (`wechat_unionid`),
KEY `idx_status` (`status`),
KEY `idx_created_at` (`created_at`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户表';
@@ -1,26 +0,0 @@
-- 添加微信登录相关字段
-- 执行时间: 2026-05-13
USE rent_platform;
-- 修改 users 表,添加微信相关字段
ALTER TABLE `users`
-- 手机号改为可空,因为微信登录时可能没有手机号
MODIFY COLUMN `phone` VARCHAR(20) NULL COMMENT '手机号',
-- 删除手机号的唯一索引
DROP INDEX `phone`,
-- 添加手机号的普通索引
ADD INDEX `idx_phone` (`phone`),
-- 添加微信 openid 字段
ADD COLUMN `wechat_openid` VARCHAR(100) NULL COMMENT '微信openid' AFTER `password`,
-- 添加微信 unionid 字段
ADD COLUMN `wechat_unionid` VARCHAR(100) NULL COMMENT '微信unionid' AFTER `wechat_openid`,
-- 添加 openid 索引
ADD INDEX `idx_wechat_openid` (`wechat_openid`),
-- 添加 unionid 索引
ADD INDEX `idx_wechat_unionid` (`wechat_unionid`);
-- 说明:
-- 1. phone 字段改为可空,支持微信登录时无手机号的情况
-- 2. 添加 wechat_openid 和 wechat_unionid 字段用于微信登录
-- 3. 为这些字段添加索引以提高查询性能