fix
This commit is contained in:
@@ -12,3 +12,4 @@ Thumbs.db
|
||||
*.swo
|
||||
coverage/
|
||||
.nyc_output/
|
||||
apps/server/uploads/
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { post, get, request } from '@/utils/request';
|
||||
import { post, request } from '@/utils/request';
|
||||
|
||||
export interface SellerRegisterParams {
|
||||
phone: string;
|
||||
@@ -1,4 +1,4 @@
|
||||
import { post, get, put, request } from '@/utils/request';
|
||||
import { request } from '@/utils/request';
|
||||
|
||||
export interface ApplyMerchantParams {
|
||||
shopName: string;
|
||||
@@ -27,35 +27,9 @@ export interface UpdateMerchantParams {
|
||||
legalPerson?: string;
|
||||
}
|
||||
|
||||
export interface MerchantInfo {
|
||||
id: number;
|
||||
sellerId: number;
|
||||
shopName: string;
|
||||
logo: string;
|
||||
description: string;
|
||||
phone: string;
|
||||
province: string;
|
||||
city: string;
|
||||
district: string;
|
||||
address: string;
|
||||
longitude: number;
|
||||
latitude: number;
|
||||
businessLicense: string;
|
||||
licenseNo: string;
|
||||
legalPerson: string;
|
||||
status: 'pending' | 'approved' | 'rejected' | 'frozen';
|
||||
rejectReason: string;
|
||||
deposit: number;
|
||||
rating: number;
|
||||
reviewCount: number;
|
||||
autoConfirm: boolean;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
// 申请创建店铺(需要商家token)
|
||||
export function applyMerchant(data: ApplyMerchantParams) {
|
||||
return request<MerchantInfo>({
|
||||
return request({
|
||||
url: '/seller/merchant/apply',
|
||||
method: 'POST',
|
||||
data,
|
||||
@@ -65,7 +39,7 @@ export function applyMerchant(data: ApplyMerchantParams) {
|
||||
|
||||
// 获取我的店铺信息(需要商家token)
|
||||
export function getMyMerchant() {
|
||||
return request<MerchantInfo>({
|
||||
return request({
|
||||
url: '/seller/merchant/mine',
|
||||
method: 'GET',
|
||||
useSellerToken: true,
|
||||
@@ -74,25 +48,10 @@ export function getMyMerchant() {
|
||||
|
||||
// 更新店铺信息(需要商家token)
|
||||
export function updateMerchant(data: UpdateMerchantParams) {
|
||||
return request<MerchantInfo>({
|
||||
return request({
|
||||
url: '/seller/merchant/update',
|
||||
method: 'PUT',
|
||||
data,
|
||||
useSellerToken: true,
|
||||
});
|
||||
}
|
||||
|
||||
// 获取商家详情(公开)
|
||||
export function getMerchantById(id: number) {
|
||||
return get<MerchantInfo>(`/merchants/${id}`);
|
||||
}
|
||||
|
||||
// 获取商家列表(公开,已审核通过)
|
||||
export function getMerchantList(params: {
|
||||
page?: number;
|
||||
pageSize?: number;
|
||||
keyword?: string;
|
||||
city?: string;
|
||||
}) {
|
||||
return get('/merchants', params);
|
||||
}
|
||||
@@ -1,31 +1,4 @@
|
||||
import { get, request } from '@/utils/request';
|
||||
|
||||
// 公开接口
|
||||
export function getRoomList(params: {
|
||||
page?: number;
|
||||
pageSize?: number;
|
||||
keyword?: string;
|
||||
type?: string;
|
||||
minPrice?: number;
|
||||
maxPrice?: number;
|
||||
city?: string;
|
||||
merchantId?: number;
|
||||
sortBy?: string;
|
||||
checkIn?: string;
|
||||
checkOut?: string;
|
||||
roomCount?: number;
|
||||
adultCount?: number;
|
||||
}) {
|
||||
return get('/rooms', params);
|
||||
}
|
||||
|
||||
export function getRoomDetail(id: number) {
|
||||
return get(`/rooms/${id}`);
|
||||
}
|
||||
|
||||
export function getRoomCalendar(id: number, startDate: string, endDate: string) {
|
||||
return get(`/rooms/${id}/calendar`, { startDate, endDate });
|
||||
}
|
||||
import { request } from '@/utils/request';
|
||||
|
||||
// 商家管理接口(需要 sellerToken)
|
||||
export function getMerchantRooms(params: any) {
|
||||
@@ -1,4 +1,4 @@
|
||||
import { post, get, request } from '@/utils/request';
|
||||
import { post, get } from '@/utils/request';
|
||||
|
||||
export function sendCode(phone: string) {
|
||||
return post('/auth/send-code', { phone });
|
||||
@@ -23,7 +23,3 @@ export function refreshToken(refreshToken: string) {
|
||||
export function getUserProfile() {
|
||||
return get('/user/profile');
|
||||
}
|
||||
|
||||
export function getMerchantInfo() {
|
||||
return request({ url: '/merchant/mine', method: 'GET', useSellerToken: true });
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import {request} from '@/utils/request';
|
||||
import { request } from '@/utils/request';
|
||||
|
||||
// 获取我的邀请统计
|
||||
export const getInviteStats = () =>
|
||||
@@ -0,0 +1,42 @@
|
||||
import { get } from '@/utils/request';
|
||||
|
||||
export interface MerchantInfo {
|
||||
id: number;
|
||||
sellerId: number;
|
||||
shopName: string;
|
||||
logo: string;
|
||||
description: string;
|
||||
phone: string;
|
||||
province: string;
|
||||
city: string;
|
||||
district: string;
|
||||
address: string;
|
||||
longitude: number;
|
||||
latitude: number;
|
||||
businessLicense: string;
|
||||
licenseNo: string;
|
||||
legalPerson: string;
|
||||
status: 'pending' | 'approved' | 'rejected' | 'frozen';
|
||||
rejectReason: string;
|
||||
deposit: number;
|
||||
rating: number;
|
||||
reviewCount: number;
|
||||
autoConfirm: boolean;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
// 获取商家详情(公开)
|
||||
export function getMerchantById(id: number) {
|
||||
return get<MerchantInfo>(`/merchants/${id}`);
|
||||
}
|
||||
|
||||
// 获取商家列表(公开,已审核通过)
|
||||
export function getMerchantList(params: {
|
||||
page?: number;
|
||||
pageSize?: number;
|
||||
keyword?: string;
|
||||
city?: string;
|
||||
}) {
|
||||
return get('/merchants', params);
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
import { get } from '@/utils/request';
|
||||
|
||||
// 公开接口
|
||||
export function getRoomList(params: {
|
||||
page?: number;
|
||||
pageSize?: number;
|
||||
keyword?: string;
|
||||
type?: string;
|
||||
minPrice?: number;
|
||||
maxPrice?: number;
|
||||
city?: string;
|
||||
merchantId?: number;
|
||||
sortBy?: string;
|
||||
checkIn?: string;
|
||||
checkOut?: string;
|
||||
roomCount?: number;
|
||||
adultCount?: number;
|
||||
}) {
|
||||
return get('/rooms', params);
|
||||
}
|
||||
|
||||
export function getRoomDetail(id: number) {
|
||||
return get(`/rooms/${id}`);
|
||||
}
|
||||
|
||||
export function getRoomCalendar(id: number, startDate: string, endDate: string) {
|
||||
return get(`/rooms/${id}/calendar`, { startDate, endDate });
|
||||
}
|
||||
@@ -58,7 +58,7 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, watch, onMounted } from 'vue';
|
||||
import { getRoomCalendar } from '@/api/room';
|
||||
import { getRoomCalendar } from '@/api/user/room';
|
||||
|
||||
const props = defineProps<{
|
||||
roomId: number;
|
||||
|
||||
@@ -103,7 +103,7 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, onMounted, onActivated } from 'vue';
|
||||
import { getMerchantList } from '@/api/merchant';
|
||||
import { getMerchantList } from '@/api/user/merchant';
|
||||
import CityPicker from '@/components/CityPicker.vue';
|
||||
import DatePicker from '@/components/DatePicker.vue';
|
||||
import RoomGuestPicker from '@/components/RoomGuestPicker.vue';
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted } from 'vue';
|
||||
import { getCashbackRecords } from '@/api/invite';
|
||||
import { getCashbackRecords } from '@/api/user/invite';
|
||||
|
||||
const records = ref<any[]>([]);
|
||||
const page = ref(1);
|
||||
|
||||
@@ -77,7 +77,7 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, onMounted } from 'vue';
|
||||
import { getInviteStats } from '@/api/invite';
|
||||
import { getInviteStats } from '@/api/user/invite';
|
||||
import { useUserStore } from '@/store/user';
|
||||
|
||||
const stats = ref<any>({
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted } from 'vue';
|
||||
import { getInviteRecords } from '@/api/invite';
|
||||
import { getInviteRecords } from '@/api/user/invite';
|
||||
|
||||
const records = ref<any[]>([]);
|
||||
const page = ref(1);
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, onMounted } from 'vue';
|
||||
import { getInviteStats, createInviteWithdrawal } from '@/api/invite';
|
||||
import { getInviteStats, createInviteWithdrawal } from '@/api/user/invite';
|
||||
|
||||
const stats = ref<any>({ availableBalance: 0 });
|
||||
const amount = ref('');
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted } from 'vue';
|
||||
import { getInviteWithdrawals } from '@/api/invite';
|
||||
import { getInviteWithdrawals } from '@/api/user/invite';
|
||||
|
||||
const records = ref<any[]>([]);
|
||||
const page = ref(1);
|
||||
|
||||
@@ -55,7 +55,7 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
import { getMerchantList } from '@/api/merchant';
|
||||
import { getMerchantList } from '@/api/user/merchant';
|
||||
|
||||
const keyword = ref('');
|
||||
const searchResults = ref<any[]>([]);
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
import { sendCode, loginByPhone } from '@/api/auth';
|
||||
import { sendCode, loginByPhone } from '@/api/user/auth';
|
||||
import { useUserStore } from '@/store/user';
|
||||
|
||||
const phone = ref('');
|
||||
|
||||
@@ -127,9 +127,9 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, onMounted } from 'vue';
|
||||
import { getMerchantById } from '@/api/merchant';
|
||||
import { getRoomList } from '@/api/room';
|
||||
import { getReviewList } from '@/api/review';
|
||||
import { getMerchantById } from '@/api/user/merchant';
|
||||
import { getRoomList } from '@/api/user/room';
|
||||
import { getReviewList } from '@/api/user/review';
|
||||
import RoomCard from '@/components/RoomCard.vue';
|
||||
import DatePicker from '@/components/DatePicker.vue';
|
||||
import RoomGuestPicker from '@/components/RoomGuestPicker.vue';
|
||||
|
||||
@@ -111,8 +111,8 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, onMounted, watch } from 'vue';
|
||||
import { getRoomDetail, getRoomCalendar } from '@/api/room';
|
||||
import { createOrder } from '@/api/order';
|
||||
import { getRoomDetail, getRoomCalendar } from '@/api/user/room';
|
||||
import { createOrder } from '@/api/user/order';
|
||||
import RoomCalendarPicker from '@/components/RoomCalendarPicker.vue';
|
||||
|
||||
const roomId = ref(0);
|
||||
|
||||
@@ -177,8 +177,8 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted } from 'vue';
|
||||
import { getOrderDetail, cancelOrder, payOrder } from '@/api/order';
|
||||
import { createReview, checkOrderReviewed } from '@/api/review';
|
||||
import { getOrderDetail, cancelOrder, payOrder } from '@/api/user/order';
|
||||
import { createReview, checkOrderReviewed } from '@/api/user/review';
|
||||
|
||||
const statusLabels: Record<string, string> = {
|
||||
pending_pay: '待支付',
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted } from 'vue';
|
||||
import { getOrderList } from '@/api/order';
|
||||
import { getOrderList } from '@/api/user/order';
|
||||
|
||||
const tabs = [
|
||||
{ label: '全部', value: '' },
|
||||
|
||||
@@ -113,7 +113,7 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, onMounted } from 'vue';
|
||||
import { getRoomDetail } from '@/api/room';
|
||||
import { getRoomDetail } from '@/api/user/room';
|
||||
|
||||
const typeLabels: Record<string, string> = {
|
||||
hotel: '酒店',
|
||||
|
||||
@@ -67,7 +67,7 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, onMounted } from 'vue';
|
||||
import { getMerchantList } from '@/api/merchant';
|
||||
import { getMerchantList } from '@/api/user/merchant';
|
||||
|
||||
// 筛选条件(从URL获取)
|
||||
const city = ref('上海');
|
||||
|
||||
@@ -128,7 +128,7 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, onMounted } from 'vue';
|
||||
import { useSellerStore } from '@/store/seller';
|
||||
import { getMyMerchant } from '@/api/merchant';
|
||||
import { getMyMerchant } from '@/api/seller/merchant';
|
||||
|
||||
const sellerStore = useSellerStore();
|
||||
const merchant = ref<any>(null);
|
||||
|
||||
@@ -154,7 +154,7 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted } from 'vue';
|
||||
import { getSellerOrderDetail, confirmOrder, rejectOrder, checkinOrder } from '@/api/seller-order';
|
||||
import { getSellerOrderDetail, confirmOrder, rejectOrder, checkinOrder } from '@/api/seller/order';
|
||||
|
||||
const statusLabels: Record<string, string> = {
|
||||
pending_pay: '待支付',
|
||||
|
||||
@@ -75,7 +75,7 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted } from 'vue';
|
||||
import { getSellerOrders, confirmOrder, rejectOrder, checkinOrder } from '@/api/seller-order';
|
||||
import { getSellerOrders, confirmOrder, rejectOrder, checkinOrder } from '@/api/seller/order';
|
||||
|
||||
const tabs = [
|
||||
{ label: '全部', value: '' },
|
||||
|
||||
@@ -142,7 +142,7 @@
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
import { onMounted } from 'vue';
|
||||
import { sellerRegister, sellerLogin, sellerSendCode } from '@/api/seller-auth';
|
||||
import { sellerRegister, sellerLogin, sellerSendCode } from '@/api/seller/auth';
|
||||
import { useSellerStore } from '@/store/seller';
|
||||
|
||||
const sellerStore = useSellerStore();
|
||||
|
||||
@@ -97,8 +97,8 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, watch } from 'vue';
|
||||
import { onShow } from '@dcloudio/uni-app';
|
||||
import { getMerchantRooms } from '@/api/room';
|
||||
import { getRoomCalendar, batchUpdateCalendar, singleDayUpdate } from '@/api/room-calendar';
|
||||
import { getMerchantRooms } from '@/api/seller/room';
|
||||
import { getRoomCalendar, batchUpdateCalendar, singleDayUpdate } from '@/api/seller/room-calendar';
|
||||
|
||||
const weekDays = ['日', '一', '二', '三', '四', '五', '六'];
|
||||
const statusOptions = [
|
||||
|
||||
@@ -90,7 +90,7 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted } from 'vue';
|
||||
import { createMerchantRoom, updateMerchantRoom, getMerchantRoom } from '@/api/room';
|
||||
import { createMerchantRoom, updateMerchantRoom, getMerchantRoom } from '@/api/seller/room';
|
||||
import { chooseAndUpload } from '@/utils/upload';
|
||||
|
||||
const loading = ref(false);
|
||||
|
||||
@@ -54,7 +54,7 @@
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
import { onShow } from '@dcloudio/uni-app';
|
||||
import { getMerchantRooms, removeMerchantRoom, updateMerchantRoom } from '@/api/room';
|
||||
import { getMerchantRooms, removeMerchantRoom, updateMerchantRoom } from '@/api/seller/room';
|
||||
|
||||
const typeLabels: Record<string, string> = { hotel: '酒店', homestay: '民宿', apartment: '公寓', hostel: '青旅' };
|
||||
const auditLabels: Record<string, string> = { pending: '审核中', approved: '已通过', rejected: '已拒绝' };
|
||||
|
||||
@@ -114,7 +114,7 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
import { applyMerchant } from '@/api/merchant';
|
||||
import { applyMerchant } from '@/api/seller/merchant';
|
||||
import { useSellerStore } from '@/store/seller';
|
||||
import RegionSelector from '@/components/RegionSelector.vue';
|
||||
import { chooseAndUpload } from '@/utils/upload';
|
||||
@@ -150,6 +150,7 @@ async function uploadLicense() {
|
||||
try {
|
||||
uni.showLoading({ title: '上传中...' });
|
||||
const urls = await chooseAndUpload({ count: 1, useSellerToken: true });
|
||||
console.log('上传成功,文件URL:', urls);
|
||||
form.value.businessLicense = urls[0];
|
||||
uni.showToast({ title: '上传成功', icon: 'success' });
|
||||
} catch (err: any) {
|
||||
|
||||
@@ -113,7 +113,7 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted } from 'vue';
|
||||
import { updateMerchant, getMyMerchant } from '@/api/merchant';
|
||||
import { updateMerchant, getMyMerchant } from '@/api/seller/merchant';
|
||||
import { useSellerStore } from '@/store/seller';
|
||||
import RegionSelector from '@/components/RegionSelector.vue';
|
||||
import { chooseAndUpload } from '@/utils/upload';
|
||||
|
||||
@@ -19,15 +19,19 @@ export function uploadFile(filePath: string, options?: { useSellerToken?: boolea
|
||||
name: 'file',
|
||||
header: token ? { Authorization: `Bearer ${token}` } : {},
|
||||
success: (res) => {
|
||||
if (res.statusCode === 200) {
|
||||
if (res.statusCode >= 200 && res.statusCode < 300) {
|
||||
try {
|
||||
const data = JSON.parse(res.data);
|
||||
if (data.code >= 200 && data.code < 300 && data.data?.url) {
|
||||
resolve(data.data.url);
|
||||
const data = typeof res.data === 'string' ? JSON.parse(res.data) : res.data;
|
||||
console.log('[upload] response data:', JSON.stringify(data));
|
||||
if ((data.code === 0 || data.code === 200 || data.code === 201) && data.data?.url) {
|
||||
resolve(data.data.url.startsWith('http') ? data.data.url : `${BASE_URL.replace('/api', '')}${data.data.url}`);
|
||||
} else if (data.url) {
|
||||
resolve(data.url);
|
||||
} else {
|
||||
reject(new Error(data.message || '上传失败'));
|
||||
}
|
||||
} catch {
|
||||
} catch (e) {
|
||||
console.error('[upload] parse error:', e, 'raw:', res.data);
|
||||
reject(new Error('解析响应失败'));
|
||||
}
|
||||
} else if (res.statusCode === 401) {
|
||||
|
||||
+3
-57
@@ -7,74 +7,20 @@ import {
|
||||
Query,
|
||||
Param,
|
||||
UseGuards,
|
||||
Request,
|
||||
ParseIntPipe,
|
||||
} from '@nestjs/common';
|
||||
import { ApiTags, ApiOperation, ApiBearerAuth, ApiParam } from '@nestjs/swagger';
|
||||
import { ActivityService } from './activity.service';
|
||||
import { JwtAuthGuard, RolesGuard, Roles, CurrentUser } from '@/common';
|
||||
import {
|
||||
CreateActivityDto,
|
||||
UpdateActivityDto,
|
||||
QueryActivityDto,
|
||||
BindInvitationDto,
|
||||
CreateInviteWithdrawalDto,
|
||||
QueryInviteRecordsDto,
|
||||
RejectInviteWithdrawalDto,
|
||||
QueryAdminInviteWithdrawalsDto,
|
||||
QueryAdminCashbacksDto,
|
||||
QueryInviteRecordsDto,
|
||||
} from './dto/activity.dto';
|
||||
import { JwtAuthGuard, RolesGuard, Roles, CurrentUser } from '@/common';
|
||||
|
||||
// ===== 用户端邀请接口 =====
|
||||
@ApiTags('用户端-邀请返现')
|
||||
@ApiBearerAuth()
|
||||
@UseGuards(JwtAuthGuard)
|
||||
@Controller('user/activity/invite')
|
||||
export class UserInviteController {
|
||||
constructor(private readonly activityService: ActivityService) {}
|
||||
|
||||
@Get('stats')
|
||||
@ApiOperation({ summary: '获取我的邀请统计' })
|
||||
async getStats(@CurrentUser('userId') userId: number) {
|
||||
return this.activityService.getUserStats(userId);
|
||||
}
|
||||
|
||||
@Post('bind')
|
||||
@ApiOperation({ summary: '绑定邀请关系' })
|
||||
async bind(@CurrentUser('userId') userId: number, @Body() dto: BindInvitationDto) {
|
||||
return this.activityService.bindInvitation(userId, dto);
|
||||
}
|
||||
|
||||
@Get('records')
|
||||
@ApiOperation({ summary: '邀请记录列表' })
|
||||
async getRecords(@CurrentUser('userId') userId: number, @Query() dto: QueryInviteRecordsDto) {
|
||||
return this.activityService.getInviteRecords(userId, dto);
|
||||
}
|
||||
|
||||
@Get('cashbacks')
|
||||
@ApiOperation({ summary: '返现记录列表' })
|
||||
async getCashbacks(@CurrentUser('userId') userId: number, @Query() dto: QueryInviteRecordsDto) {
|
||||
return this.activityService.getCashbackRecords(userId, dto);
|
||||
}
|
||||
|
||||
@Post('withdraw')
|
||||
@ApiOperation({ summary: '申请提现' })
|
||||
async createWithdrawal(
|
||||
@CurrentUser('userId') userId: number,
|
||||
@Body() dto: CreateInviteWithdrawalDto,
|
||||
) {
|
||||
return this.activityService.createWithdrawal(userId, dto);
|
||||
}
|
||||
|
||||
@Get('withdrawals')
|
||||
@ApiOperation({ summary: '提现记录列表' })
|
||||
async getWithdrawals(
|
||||
@CurrentUser('userId') userId: number,
|
||||
@Query() dto: QueryInviteRecordsDto,
|
||||
) {
|
||||
return this.activityService.getWithdrawalRecords(userId, dto);
|
||||
}
|
||||
}
|
||||
|
||||
// ===== 管理端活动接口 =====
|
||||
@ApiTags('管理端-活动管理')
|
||||
@@ -82,7 +28,7 @@ export class UserInviteController {
|
||||
@UseGuards(JwtAuthGuard, RolesGuard)
|
||||
@Roles('admin')
|
||||
@Controller('admin/activity')
|
||||
export class AdminActivityController {
|
||||
export class ActivityAdminController {
|
||||
constructor(private readonly activityService: ActivityService) {}
|
||||
|
||||
@Get('list')
|
||||
@@ -0,0 +1,67 @@
|
||||
import {
|
||||
Controller,
|
||||
Get,
|
||||
Post,
|
||||
Body,
|
||||
Query,
|
||||
UseGuards,
|
||||
} from '@nestjs/common';
|
||||
import { ApiTags, ApiOperation, ApiBearerAuth } from '@nestjs/swagger';
|
||||
import { ActivityService } from './activity.service';
|
||||
import { JwtAuthGuard, CurrentUser } from '@/common';
|
||||
import {
|
||||
BindInvitationDto,
|
||||
CreateInviteWithdrawalDto,
|
||||
QueryInviteRecordsDto,
|
||||
} from './dto/activity.dto';
|
||||
|
||||
// ===== 用户端邀请接口 =====
|
||||
@ApiTags('用户端-邀请返现')
|
||||
@ApiBearerAuth()
|
||||
@UseGuards(JwtAuthGuard)
|
||||
@Controller('user/activity/invite')
|
||||
export class ActivityUserController {
|
||||
constructor(private readonly activityService: ActivityService) {}
|
||||
|
||||
@Get('stats')
|
||||
@ApiOperation({ summary: '获取我的邀请统计' })
|
||||
async getStats(@CurrentUser('userId') userId: number) {
|
||||
return this.activityService.getUserStats(userId);
|
||||
}
|
||||
|
||||
@Post('bind')
|
||||
@ApiOperation({ summary: '绑定邀请关系' })
|
||||
async bind(@CurrentUser('userId') userId: number, @Body() dto: BindInvitationDto) {
|
||||
return this.activityService.bindInvitation(userId, dto);
|
||||
}
|
||||
|
||||
@Get('records')
|
||||
@ApiOperation({ summary: '邀请记录列表' })
|
||||
async getRecords(@CurrentUser('userId') userId: number, @Query() dto: QueryInviteRecordsDto) {
|
||||
return this.activityService.getInviteRecords(userId, dto);
|
||||
}
|
||||
|
||||
@Get('cashbacks')
|
||||
@ApiOperation({ summary: '返现记录列表' })
|
||||
async getCashbacks(@CurrentUser('userId') userId: number, @Query() dto: QueryInviteRecordsDto) {
|
||||
return this.activityService.getCashbackRecords(userId, dto);
|
||||
}
|
||||
|
||||
@Post('withdraw')
|
||||
@ApiOperation({ summary: '申请提现' })
|
||||
async createWithdrawal(
|
||||
@CurrentUser('userId') userId: number,
|
||||
@Body() dto: CreateInviteWithdrawalDto,
|
||||
) {
|
||||
return this.activityService.createWithdrawal(userId, dto);
|
||||
}
|
||||
|
||||
@Get('withdrawals')
|
||||
@ApiOperation({ summary: '提现记录列表' })
|
||||
async getWithdrawals(
|
||||
@CurrentUser('userId') userId: number,
|
||||
@Query() dto: QueryInviteRecordsDto,
|
||||
) {
|
||||
return this.activityService.getWithdrawalRecords(userId, dto);
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,8 @@
|
||||
import { Module, forwardRef } from '@nestjs/common';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
import { ActivityService } from './activity.service';
|
||||
import { UserInviteController, AdminActivityController } from './activity.controller';
|
||||
import { ActivityUserController } from './activity-user.controller';
|
||||
import { ActivityAdminController } from './activity-admin.controller';
|
||||
import { MktActivity } from '@/entities/mkt-activity.entity';
|
||||
import { MktInvitation } from '@/entities/mkt-invitation.entity';
|
||||
import { MktCashback } from '@/entities/mkt-cashback.entity';
|
||||
@@ -22,7 +23,7 @@ import { User } from '@/entities/user.entity';
|
||||
User,
|
||||
]),
|
||||
],
|
||||
controllers: [UserInviteController, AdminActivityController],
|
||||
controllers: [ActivityUserController, ActivityAdminController],
|
||||
providers: [ActivityService],
|
||||
exports: [ActivityService],
|
||||
})
|
||||
|
||||
@@ -12,11 +12,14 @@ import { User } from '@/entities/user.entity';
|
||||
TypeOrmModule.forFeature([User]),
|
||||
JwtModule.registerAsync({
|
||||
imports: [ConfigModule],
|
||||
useFactory: async (configService: ConfigService) => ({
|
||||
useFactory: (configService: ConfigService) => ({
|
||||
secret: configService.get<string>('jwt.secret') || 'dev_secret_key',
|
||||
signOptions: {
|
||||
expiresIn: (configService.get<string>('jwt.expiresIn') ||
|
||||
'2h') as any,
|
||||
expiresIn: Number(
|
||||
configService
|
||||
.get<string>('jwt.expiresIn')
|
||||
?.replace(/[^0-9]/g, '') || '7200',
|
||||
),
|
||||
},
|
||||
}),
|
||||
inject: [ConfigService],
|
||||
|
||||
@@ -59,18 +59,19 @@ export class AuthService {
|
||||
return this.generateToken(user);
|
||||
}
|
||||
|
||||
async sendCode(phone: string) {
|
||||
sendCode(phone: string) {
|
||||
const code = Math.random().toString().slice(2, 8);
|
||||
await this.cacheCode(phone, code);
|
||||
this.cacheCode(phone, code);
|
||||
this.logger.log(`验证码已发送至 ${phone}: ${code}`);
|
||||
return { message: '验证码已发送' };
|
||||
}
|
||||
|
||||
async refresh(refreshToken: string) {
|
||||
try {
|
||||
const payload = await this.jwtService.verifyAsync(refreshToken, {
|
||||
secret: this.configService.get<string>('jwt.secret'),
|
||||
});
|
||||
const payload: { sub: number; phone: string } =
|
||||
await this.jwtService.verifyAsync(refreshToken, {
|
||||
secret: this.configService.get<string>('jwt.secret'),
|
||||
});
|
||||
|
||||
const user = await this.userRepo.findOne({ where: { id: payload.sub } });
|
||||
if (!user) {
|
||||
@@ -102,7 +103,7 @@ export class AuthService {
|
||||
return user;
|
||||
}
|
||||
|
||||
const cachedCode = await this.getCachedCode(phone);
|
||||
const cachedCode = this.getCachedCode(phone);
|
||||
if (!cachedCode || cachedCode !== code) {
|
||||
throw new UnauthorizedException('验证码错误或已过期');
|
||||
}
|
||||
@@ -112,7 +113,7 @@ export class AuthService {
|
||||
throw new UnauthorizedException('该手机号未注册');
|
||||
}
|
||||
|
||||
await this.clearCachedCode(phone);
|
||||
this.clearCachedCode(phone);
|
||||
return user;
|
||||
}
|
||||
|
||||
@@ -142,8 +143,11 @@ export class AuthService {
|
||||
const payload = { sub: user.id, phone: user.phone };
|
||||
const accessToken = await this.jwtService.signAsync(payload);
|
||||
const refreshToken = await this.jwtService.signAsync(payload, {
|
||||
expiresIn: (this.configService.get<string>('jwt.refreshExpiresIn') ||
|
||||
'7d') as any,
|
||||
expiresIn: Number(
|
||||
this.configService
|
||||
.get<string>('jwt.refreshExpiresIn')
|
||||
?.replace(/[^0-9]/g, '') || '604800',
|
||||
),
|
||||
});
|
||||
|
||||
return {
|
||||
@@ -159,17 +163,17 @@ export class AuthService {
|
||||
};
|
||||
}
|
||||
|
||||
private async cacheCode(phone: string, code: string): Promise<void> {
|
||||
private cacheCode(phone: string, code: string): void {
|
||||
// TODO: 存入Redis,设置5分钟过期
|
||||
this.logger.debug(`缓存验证码: ${phone} -> ${code}`);
|
||||
}
|
||||
|
||||
private async getCachedCode(phone: string): Promise<string | null> {
|
||||
private getCachedCode(phone: string): string | null {
|
||||
// TODO: 从Redis获取
|
||||
return null;
|
||||
return phone === 'dev' ? '123456' : null; // 开发模式返回固定验证码
|
||||
}
|
||||
|
||||
private async clearCachedCode(phone: string): Promise<void> {
|
||||
private clearCachedCode(phone: string): void {
|
||||
// TODO: 从Redis删除
|
||||
this.logger.debug(`清除验证码: ${phone}`);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,107 @@
|
||||
import {
|
||||
Controller,
|
||||
Get,
|
||||
Put,
|
||||
Param,
|
||||
Body,
|
||||
Query,
|
||||
UseGuards,
|
||||
} from '@nestjs/common';
|
||||
import { ApiTags, ApiOperation, ApiBearerAuth } from '@nestjs/swagger';
|
||||
import { FinanceService } from './finance.service';
|
||||
import { JwtAuthGuard, RolesGuard } from '@/common';
|
||||
import { Roles } from '@/common/decorators/roles.decorator';
|
||||
import { CurrentUser } from '@/common/decorators/current-user.decorator';
|
||||
import {
|
||||
AdminQuerySettlementDto,
|
||||
ApproveSettlementDto,
|
||||
RejectSettlementDto,
|
||||
AdminQueryWithdrawalDto,
|
||||
ApproveWithdrawalDto,
|
||||
RejectWithdrawalDto,
|
||||
PayWithdrawalDto,
|
||||
QueryEarningsDto,
|
||||
} from './dto/finance.dto';
|
||||
|
||||
@ApiTags('财务管理(管理员)')
|
||||
@Controller('admin/finance')
|
||||
@UseGuards(JwtAuthGuard, RolesGuard)
|
||||
@Roles('admin')
|
||||
@ApiBearerAuth()
|
||||
export class FinanceAdminController {
|
||||
constructor(private readonly financeService: FinanceService) {}
|
||||
|
||||
@Get('settlements')
|
||||
@ApiOperation({ summary: '对账单列表' })
|
||||
async getSettlements(@Query() dto: AdminQuerySettlementDto) {
|
||||
return this.financeService.adminGetSettlements(dto);
|
||||
}
|
||||
|
||||
@Get('settlements/:id')
|
||||
@ApiOperation({ summary: '对账单详情' })
|
||||
async getSettlementDetail(@Param('id') id: number) {
|
||||
return this.financeService.adminGetSettlementDetail(id);
|
||||
}
|
||||
|
||||
@Put('settlements/:id/approve')
|
||||
@ApiOperation({ summary: '审核通过对账单' })
|
||||
async approveSettlement(
|
||||
@CurrentUser('sub') reviewerId: number,
|
||||
@Param('id') id: number,
|
||||
@Body() _dto: ApproveSettlementDto,
|
||||
) {
|
||||
return this.financeService.approveSettlement(id, reviewerId);
|
||||
}
|
||||
|
||||
@Put('settlements/:id/reject')
|
||||
@ApiOperation({ summary: '拒绝对账单' })
|
||||
async rejectSettlement(
|
||||
@CurrentUser('sub') reviewerId: number,
|
||||
@Param('id') id: number,
|
||||
@Body() dto: RejectSettlementDto,
|
||||
) {
|
||||
return this.financeService.rejectSettlement(id, reviewerId, dto);
|
||||
}
|
||||
|
||||
@Get('withdrawals')
|
||||
@ApiOperation({ summary: '提现申请列表' })
|
||||
async getWithdrawals(@Query() dto: AdminQueryWithdrawalDto) {
|
||||
return this.financeService.adminGetWithdrawals(dto);
|
||||
}
|
||||
|
||||
@Put('withdrawals/:id/approve')
|
||||
@ApiOperation({ summary: '审核通过提现' })
|
||||
async approveWithdrawal(
|
||||
@CurrentUser('sub') reviewerId: number,
|
||||
@Param('id') id: number,
|
||||
@Body() _dto: ApproveWithdrawalDto,
|
||||
) {
|
||||
return this.financeService.approveWithdrawal(id, reviewerId);
|
||||
}
|
||||
|
||||
@Put('withdrawals/:id/reject')
|
||||
@ApiOperation({ summary: '拒绝提现' })
|
||||
async rejectWithdrawal(
|
||||
@CurrentUser('sub') reviewerId: number,
|
||||
@Param('id') id: number,
|
||||
@Body() dto: RejectWithdrawalDto,
|
||||
) {
|
||||
return this.financeService.rejectWithdrawal(id, reviewerId, dto);
|
||||
}
|
||||
|
||||
@Put('withdrawals/:id/pay')
|
||||
@ApiOperation({ summary: '确认打款' })
|
||||
async payWithdrawal(
|
||||
@CurrentUser('sub') reviewerId: number,
|
||||
@Param('id') id: number,
|
||||
@Body() _dto: PayWithdrawalDto,
|
||||
) {
|
||||
return this.financeService.payWithdrawal(id, reviewerId);
|
||||
}
|
||||
|
||||
@Get('earnings')
|
||||
@ApiOperation({ summary: '平台收益统计' })
|
||||
async getEarnings(@Query() dto: QueryEarningsDto) {
|
||||
return this.financeService.getEarnings(dto);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
import {
|
||||
Controller,
|
||||
Get,
|
||||
Post,
|
||||
Put,
|
||||
Param,
|
||||
Body,
|
||||
Query,
|
||||
UseGuards,
|
||||
NotFoundException,
|
||||
} from '@nestjs/common';
|
||||
import { ApiTags, ApiOperation, ApiBearerAuth } from '@nestjs/swagger';
|
||||
import { FinanceService } from './finance.service';
|
||||
import { SellerJwtAuthGuard } from '@/common/guards/seller-jwt-auth.guard';
|
||||
import { CurrentSeller } from '@/common/decorators/current-seller.decorator';
|
||||
import { MerchantService } from '../merchant/merchant.service';
|
||||
import {
|
||||
QuerySettlementDto,
|
||||
CreateWithdrawalDto,
|
||||
UpdateBankInfoDto,
|
||||
QueryWithdrawalDto,
|
||||
} from './dto/finance.dto';
|
||||
|
||||
@ApiTags('财务管理(商家)')
|
||||
@Controller('seller/finance')
|
||||
@UseGuards(SellerJwtAuthGuard)
|
||||
@ApiBearerAuth()
|
||||
export class FinanceSellerController {
|
||||
constructor(
|
||||
private readonly financeService: FinanceService,
|
||||
private readonly merchantService: MerchantService,
|
||||
) {}
|
||||
|
||||
private async getMerchantId(sellerId: number): Promise<number> {
|
||||
const merchant = await this.merchantService.findBySellerId(sellerId);
|
||||
if (!merchant) throw new NotFoundException('店铺不存在');
|
||||
return merchant.id;
|
||||
}
|
||||
|
||||
@Get('wallet')
|
||||
@ApiOperation({ summary: '获取钱包信息' })
|
||||
async getWallet(@CurrentSeller('sub') sellerId: number) {
|
||||
const merchantId = await this.getMerchantId(sellerId);
|
||||
return this.financeService.getWallet(merchantId);
|
||||
}
|
||||
|
||||
@Put('bank')
|
||||
@ApiOperation({ summary: '更新银行卡信息' })
|
||||
async updateBankInfo(
|
||||
@CurrentSeller('sub') sellerId: number,
|
||||
@Body() dto: UpdateBankInfoDto,
|
||||
) {
|
||||
const merchantId = await this.getMerchantId(sellerId);
|
||||
return this.financeService.updateBankInfo(merchantId, dto);
|
||||
}
|
||||
|
||||
@Post('withdraw')
|
||||
@ApiOperation({ summary: '申请提现' })
|
||||
async createWithdrawal(
|
||||
@CurrentSeller('sub') sellerId: number,
|
||||
@Body() dto: CreateWithdrawalDto,
|
||||
) {
|
||||
const merchantId = await this.getMerchantId(sellerId);
|
||||
return this.financeService.createWithdrawal(merchantId, dto);
|
||||
}
|
||||
|
||||
@Get('settlements')
|
||||
@ApiOperation({ summary: '对账单列表' })
|
||||
async getSettlements(
|
||||
@CurrentSeller('sub') sellerId: number,
|
||||
@Query() dto: QuerySettlementDto,
|
||||
) {
|
||||
const merchantId = await this.getMerchantId(sellerId);
|
||||
return this.financeService.getSettlements(merchantId, dto);
|
||||
}
|
||||
|
||||
@Get('settlements/:id')
|
||||
@ApiOperation({ summary: '对账单详情' })
|
||||
async getSettlementDetail(
|
||||
@CurrentSeller('sub') sellerId: number,
|
||||
@Param('id') id: number,
|
||||
) {
|
||||
const merchantId = await this.getMerchantId(sellerId);
|
||||
return this.financeService.getSettlementDetail(merchantId, id);
|
||||
}
|
||||
|
||||
@Get('withdrawals')
|
||||
@ApiOperation({ summary: '提现记录列表' })
|
||||
async getWithdrawals(
|
||||
@CurrentSeller('sub') sellerId: number,
|
||||
@Query() dto: QueryWithdrawalDto,
|
||||
) {
|
||||
const merchantId = await this.getMerchantId(sellerId);
|
||||
return this.financeService.getWithdrawals(merchantId, dto);
|
||||
}
|
||||
}
|
||||
@@ -1,209 +0,0 @@
|
||||
import {
|
||||
Controller,
|
||||
Get,
|
||||
Post,
|
||||
Put,
|
||||
Param,
|
||||
Body,
|
||||
Query,
|
||||
UseGuards,
|
||||
NotFoundException,
|
||||
} from '@nestjs/common';
|
||||
import { ApiTags, ApiOperation, ApiBearerAuth } from '@nestjs/swagger';
|
||||
import { FinanceService } from './finance.service';
|
||||
import { SellerJwtAuthGuard } from '@/common/guards/seller-jwt-auth.guard';
|
||||
import { JwtAuthGuard, RolesGuard } from '@/common';
|
||||
import { Roles } from '@/common/decorators/roles.decorator';
|
||||
import { CurrentSeller } from '@/common/decorators/current-seller.decorator';
|
||||
import { CurrentUser } from '@/common/decorators/current-user.decorator';
|
||||
import { MerchantService } from '../merchant/merchant.service';
|
||||
import {
|
||||
QuerySettlementDto,
|
||||
CreateWithdrawalDto,
|
||||
UpdateBankInfoDto,
|
||||
QueryWithdrawalDto,
|
||||
AdminQuerySettlementDto,
|
||||
ApproveSettlementDto,
|
||||
RejectSettlementDto,
|
||||
AdminQueryWithdrawalDto,
|
||||
ApproveWithdrawalDto,
|
||||
RejectWithdrawalDto,
|
||||
PayWithdrawalDto,
|
||||
QueryEarningsDto,
|
||||
} from './dto/finance.dto';
|
||||
|
||||
// ==================== 商家端 ====================
|
||||
|
||||
@ApiTags('财务管理(商家)')
|
||||
@Controller('seller/finance')
|
||||
@UseGuards(SellerJwtAuthGuard)
|
||||
@ApiBearerAuth()
|
||||
export class MerchantFinanceController {
|
||||
constructor(
|
||||
private readonly financeService: FinanceService,
|
||||
private readonly merchantService: MerchantService,
|
||||
) {}
|
||||
|
||||
private async getMerchantId(sellerId: number): Promise<number> {
|
||||
const merchant = await this.merchantService.findBySellerId(sellerId);
|
||||
if (!merchant) throw new NotFoundException('店铺不存在');
|
||||
return merchant.id;
|
||||
}
|
||||
|
||||
// 钱包信息
|
||||
@Get('wallet')
|
||||
@ApiOperation({ summary: '获取钱包信息' })
|
||||
async getWallet(@CurrentSeller('sub') sellerId: number) {
|
||||
const merchantId = await this.getMerchantId(sellerId);
|
||||
return this.financeService.getWallet(merchantId);
|
||||
}
|
||||
|
||||
// 更新银行卡
|
||||
@Put('bank')
|
||||
@ApiOperation({ summary: '更新银行卡信息' })
|
||||
async updateBankInfo(
|
||||
@CurrentSeller('sub') sellerId: number,
|
||||
@Body() dto: UpdateBankInfoDto,
|
||||
) {
|
||||
const merchantId = await this.getMerchantId(sellerId);
|
||||
return this.financeService.updateBankInfo(merchantId, dto);
|
||||
}
|
||||
|
||||
// 申请提现
|
||||
@Post('withdraw')
|
||||
@ApiOperation({ summary: '申请提现' })
|
||||
async createWithdrawal(
|
||||
@CurrentSeller('sub') sellerId: number,
|
||||
@Body() dto: CreateWithdrawalDto,
|
||||
) {
|
||||
const merchantId = await this.getMerchantId(sellerId);
|
||||
return this.financeService.createWithdrawal(merchantId, dto);
|
||||
}
|
||||
|
||||
// 对账单列表
|
||||
@Get('settlements')
|
||||
@ApiOperation({ summary: '对账单列表' })
|
||||
async getSettlements(
|
||||
@CurrentSeller('sub') sellerId: number,
|
||||
@Query() dto: QuerySettlementDto,
|
||||
) {
|
||||
const merchantId = await this.getMerchantId(sellerId);
|
||||
return this.financeService.getSettlements(merchantId, dto);
|
||||
}
|
||||
|
||||
// 对账单详情
|
||||
@Get('settlements/:id')
|
||||
@ApiOperation({ summary: '对账单详情' })
|
||||
async getSettlementDetail(
|
||||
@CurrentSeller('sub') sellerId: number,
|
||||
@Param('id') id: number,
|
||||
) {
|
||||
const merchantId = await this.getMerchantId(sellerId);
|
||||
return this.financeService.getSettlementDetail(merchantId, id);
|
||||
}
|
||||
|
||||
// 提现记录
|
||||
@Get('withdrawals')
|
||||
@ApiOperation({ summary: '提现记录列表' })
|
||||
async getWithdrawals(
|
||||
@CurrentSeller('sub') sellerId: number,
|
||||
@Query() dto: QueryWithdrawalDto,
|
||||
) {
|
||||
const merchantId = await this.getMerchantId(sellerId);
|
||||
return this.financeService.getWithdrawals(merchantId, dto);
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== 平台管理端 ====================
|
||||
|
||||
@ApiTags('财务管理(管理员)')
|
||||
@Controller('admin/finance')
|
||||
@UseGuards(JwtAuthGuard, RolesGuard)
|
||||
@Roles('admin')
|
||||
@ApiBearerAuth()
|
||||
export class AdminFinanceController {
|
||||
constructor(private readonly financeService: FinanceService) {}
|
||||
|
||||
// 对账单列表
|
||||
@Get('settlements')
|
||||
@ApiOperation({ summary: '对账单列表' })
|
||||
async getSettlements(@Query() dto: AdminQuerySettlementDto) {
|
||||
return this.financeService.adminGetSettlements(dto);
|
||||
}
|
||||
|
||||
// 对账单详情
|
||||
@Get('settlements/:id')
|
||||
@ApiOperation({ summary: '对账单详情' })
|
||||
async getSettlementDetail(@Param('id') id: number) {
|
||||
return this.financeService.adminGetSettlementDetail(id);
|
||||
}
|
||||
|
||||
// 审核通过对账单
|
||||
@Put('settlements/:id/approve')
|
||||
@ApiOperation({ summary: '审核通过对账单' })
|
||||
async approveSettlement(
|
||||
@CurrentUser('sub') reviewerId: number,
|
||||
@Param('id') id: number,
|
||||
@Body() _dto: ApproveSettlementDto,
|
||||
) {
|
||||
return this.financeService.approveSettlement(id, reviewerId);
|
||||
}
|
||||
|
||||
// 拒绝对账单
|
||||
@Put('settlements/:id/reject')
|
||||
@ApiOperation({ summary: '拒绝对账单' })
|
||||
async rejectSettlement(
|
||||
@CurrentUser('sub') reviewerId: number,
|
||||
@Param('id') id: number,
|
||||
@Body() dto: RejectSettlementDto,
|
||||
) {
|
||||
return this.financeService.rejectSettlement(id, reviewerId, dto);
|
||||
}
|
||||
|
||||
// 提现列表
|
||||
@Get('withdrawals')
|
||||
@ApiOperation({ summary: '提现申请列表' })
|
||||
async getWithdrawals(@Query() dto: AdminQueryWithdrawalDto) {
|
||||
return this.financeService.adminGetWithdrawals(dto);
|
||||
}
|
||||
|
||||
// 审核通过提现
|
||||
@Put('withdrawals/:id/approve')
|
||||
@ApiOperation({ summary: '审核通过提现' })
|
||||
async approveWithdrawal(
|
||||
@CurrentUser('sub') reviewerId: number,
|
||||
@Param('id') id: number,
|
||||
@Body() _dto: ApproveWithdrawalDto,
|
||||
) {
|
||||
return this.financeService.approveWithdrawal(id, reviewerId);
|
||||
}
|
||||
|
||||
// 拒绝提现
|
||||
@Put('withdrawals/:id/reject')
|
||||
@ApiOperation({ summary: '拒绝提现' })
|
||||
async rejectWithdrawal(
|
||||
@CurrentUser('sub') reviewerId: number,
|
||||
@Param('id') id: number,
|
||||
@Body() dto: RejectWithdrawalDto,
|
||||
) {
|
||||
return this.financeService.rejectWithdrawal(id, reviewerId, dto);
|
||||
}
|
||||
|
||||
// 确认打款
|
||||
@Put('withdrawals/:id/pay')
|
||||
@ApiOperation({ summary: '确认打款' })
|
||||
async payWithdrawal(
|
||||
@CurrentUser('sub') reviewerId: number,
|
||||
@Param('id') id: number,
|
||||
@Body() _dto: PayWithdrawalDto,
|
||||
) {
|
||||
return this.financeService.payWithdrawal(id, reviewerId);
|
||||
}
|
||||
|
||||
// 平台收益统计
|
||||
@Get('earnings')
|
||||
@ApiOperation({ summary: '平台收益统计' })
|
||||
async getEarnings(@Query() dto: QueryEarningsDto) {
|
||||
return this.financeService.getEarnings(dto);
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,8 @@ import { Withdrawal } from '@/entities/withdrawal.entity';
|
||||
import { Merchant } from '@/entities/merchant.entity';
|
||||
import { Order } from '@/entities/order.entity';
|
||||
import { FinanceService } from './finance.service';
|
||||
import { MerchantFinanceController, AdminFinanceController } from './finance.controller';
|
||||
import { FinanceSellerController } from './finance-seller.controller';
|
||||
import { FinanceAdminController } from './finance-admin.controller';
|
||||
import { MerchantModule } from '../merchant/merchant.module';
|
||||
|
||||
@Module({
|
||||
@@ -14,7 +15,7 @@ import { MerchantModule } from '../merchant/merchant.module';
|
||||
TypeOrmModule.forFeature([Settlement, SettlementItem, Withdrawal, Merchant, Order]),
|
||||
MerchantModule,
|
||||
],
|
||||
controllers: [MerchantFinanceController, AdminFinanceController],
|
||||
controllers: [FinanceSellerController, FinanceAdminController],
|
||||
providers: [FinanceService],
|
||||
exports: [FinanceService],
|
||||
})
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
import {
|
||||
Controller,
|
||||
Get,
|
||||
Put,
|
||||
Body,
|
||||
Param,
|
||||
Query,
|
||||
UseGuards,
|
||||
} from '@nestjs/common';
|
||||
import { ApiTags, ApiOperation, ApiBearerAuth } from '@nestjs/swagger';
|
||||
import { MerchantService } from './merchant.service';
|
||||
import { JwtAuthGuard, RolesGuard } from '@/common';
|
||||
import { Roles } from '@/common/decorators/roles.decorator';
|
||||
import { QueryMerchantDto } from './dto/merchant.dto';
|
||||
|
||||
@ApiTags('商家管理(管理员)')
|
||||
@Controller('admin/merchants')
|
||||
@UseGuards(JwtAuthGuard, RolesGuard)
|
||||
@Roles('admin')
|
||||
@ApiBearerAuth()
|
||||
export class MerchantAdminController {
|
||||
constructor(private readonly merchantService: MerchantService) {}
|
||||
|
||||
@Get()
|
||||
@ApiOperation({ summary: '获取商家列表' })
|
||||
async findAll(@Query() query: QueryMerchantDto) {
|
||||
return this.merchantService.findAll(query);
|
||||
}
|
||||
|
||||
@Put(':id/approve')
|
||||
@ApiOperation({ summary: '审核通过' })
|
||||
async approve(@Param('id') id: number) {
|
||||
return this.merchantService.approve(id);
|
||||
}
|
||||
|
||||
@Put(':id/reject')
|
||||
@ApiOperation({ summary: '审核拒绝' })
|
||||
async reject(@Param('id') id: number, @Body('reason') reason: string) {
|
||||
return this.merchantService.reject(id, reason);
|
||||
}
|
||||
|
||||
@Put(':id/freeze')
|
||||
@ApiOperation({ summary: '冻结店铺' })
|
||||
async freeze(@Param('id') id: number) {
|
||||
return this.merchantService.freeze(id);
|
||||
}
|
||||
|
||||
@Put(':id/unfreeze')
|
||||
@ApiOperation({ summary: '解冻店铺' })
|
||||
async unfreeze(@Param('id') id: number) {
|
||||
return this.merchantService.unfreeze(id);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
import { Controller, Get, Param, Query } from '@nestjs/common';
|
||||
import { ApiTags, ApiOperation } from '@nestjs/swagger';
|
||||
import { MerchantService } from './merchant.service';
|
||||
import { QueryMerchantDto } from './dto/merchant.dto';
|
||||
|
||||
@ApiTags('商家')
|
||||
@Controller('merchants')
|
||||
export class MerchantPublicController {
|
||||
constructor(private readonly merchantService: MerchantService) {}
|
||||
|
||||
@Get()
|
||||
@ApiOperation({ summary: '商家列表(公开)' })
|
||||
async findAll(@Query() query: QueryMerchantDto) {
|
||||
return this.merchantService.findPublic(query);
|
||||
}
|
||||
|
||||
@Get(':id')
|
||||
@ApiOperation({ summary: '获取商家详情(公开)' })
|
||||
async findById(@Param('id') id: number) {
|
||||
return this.merchantService.findById(id);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
import {
|
||||
Controller,
|
||||
Get,
|
||||
Post,
|
||||
Put,
|
||||
Body,
|
||||
Param,
|
||||
UseGuards,
|
||||
} from '@nestjs/common';
|
||||
import { ApiTags, ApiOperation, ApiBearerAuth } from '@nestjs/swagger';
|
||||
import { MerchantService } from './merchant.service';
|
||||
import { SellerJwtAuthGuard } from '@/common/guards/seller-jwt-auth.guard';
|
||||
import { CurrentSeller } from '@/common/decorators/current-seller.decorator';
|
||||
import {
|
||||
ApplyMerchantDto,
|
||||
UpdateMerchantDto,
|
||||
} from './dto/merchant.dto';
|
||||
|
||||
@ApiTags('商家管理(商家)')
|
||||
@Controller('seller/merchant')
|
||||
@UseGuards(SellerJwtAuthGuard)
|
||||
@ApiBearerAuth()
|
||||
export class MerchantSellerController {
|
||||
constructor(private readonly merchantService: MerchantService) {}
|
||||
|
||||
@Post('apply')
|
||||
@ApiOperation({ summary: '申请商家入驻' })
|
||||
async apply(
|
||||
@CurrentSeller('sub') sellerId: number,
|
||||
@Body() dto: ApplyMerchantDto,
|
||||
) {
|
||||
return this.merchantService.apply(sellerId, dto);
|
||||
}
|
||||
|
||||
@Get('mine')
|
||||
@ApiOperation({ summary: '获取我的店铺信息' })
|
||||
async getMine(@CurrentSeller('sub') sellerId: number) {
|
||||
return this.merchantService.findBySellerId(sellerId);
|
||||
}
|
||||
|
||||
@Put('update')
|
||||
@ApiOperation({ summary: '更新店铺信息' })
|
||||
async update(
|
||||
@CurrentSeller('sub') sellerId: number,
|
||||
@Body() dto: UpdateMerchantDto,
|
||||
) {
|
||||
const merchant = await this.merchantService.findBySellerId(sellerId);
|
||||
if (!merchant) throw new Error('店铺不存在');
|
||||
return this.merchantService.update(merchant.id, dto);
|
||||
}
|
||||
|
||||
@Get('detail/:id')
|
||||
@ApiOperation({ summary: '获取商家详情(公开)' })
|
||||
async findById(@Param('id') id: number) {
|
||||
return this.merchantService.findById(id);
|
||||
}
|
||||
}
|
||||
@@ -1,118 +0,0 @@
|
||||
import {
|
||||
Controller,
|
||||
Get,
|
||||
Post,
|
||||
Put,
|
||||
Body,
|
||||
Param,
|
||||
Query,
|
||||
UseGuards,
|
||||
} from '@nestjs/common';
|
||||
import { ApiTags, ApiOperation, ApiBearerAuth } from '@nestjs/swagger';
|
||||
import { MerchantService } from './merchant.service';
|
||||
import { SellerJwtAuthGuard } from '@/common/guards/seller-jwt-auth.guard';
|
||||
import { JwtAuthGuard, RolesGuard } from '@/common';
|
||||
import { Roles } from '@/common/decorators/roles.decorator';
|
||||
import { CurrentSeller } from '@/common/decorators/current-seller.decorator';
|
||||
import {
|
||||
ApplyMerchantDto,
|
||||
UpdateMerchantDto,
|
||||
QueryMerchantDto,
|
||||
} from './dto/merchant.dto';
|
||||
|
||||
@ApiTags('商家')
|
||||
@Controller('merchants')
|
||||
export class MerchantPublicController {
|
||||
constructor(private readonly merchantService: MerchantService) {}
|
||||
|
||||
@Get()
|
||||
@ApiOperation({ summary: '商家列表(公开)' })
|
||||
async findAll(@Query() query: QueryMerchantDto) {
|
||||
return this.merchantService.findPublic(query);
|
||||
}
|
||||
|
||||
@Get(':id')
|
||||
@ApiOperation({ summary: '获取商家详情(公开)' })
|
||||
async findById(@Param('id') id: number) {
|
||||
return this.merchantService.findById(id);
|
||||
}
|
||||
}
|
||||
|
||||
@ApiTags('商家管理(商家)')
|
||||
@Controller('seller/merchant')
|
||||
@UseGuards(SellerJwtAuthGuard)
|
||||
@ApiBearerAuth()
|
||||
export class MerchantController {
|
||||
constructor(private readonly merchantService: MerchantService) {}
|
||||
|
||||
@Post('apply')
|
||||
@ApiOperation({ summary: '申请商家入驻' })
|
||||
async apply(
|
||||
@CurrentSeller('sub') sellerId: number,
|
||||
@Body() dto: ApplyMerchantDto,
|
||||
) {
|
||||
return this.merchantService.apply(sellerId, dto);
|
||||
}
|
||||
|
||||
@Get('mine')
|
||||
@ApiOperation({ summary: '获取我的店铺信息' })
|
||||
async getMine(@CurrentSeller('sub') sellerId: number) {
|
||||
return this.merchantService.findBySellerId(sellerId);
|
||||
}
|
||||
|
||||
@Put('update')
|
||||
@ApiOperation({ summary: '更新店铺信息' })
|
||||
async update(
|
||||
@CurrentSeller('sub') sellerId: number,
|
||||
@Body() dto: UpdateMerchantDto,
|
||||
) {
|
||||
const merchant = await this.merchantService.findBySellerId(sellerId);
|
||||
if (!merchant) throw new Error('店铺不存在');
|
||||
return this.merchantService.update(merchant.id, dto);
|
||||
}
|
||||
|
||||
@Get('detail/:id')
|
||||
@ApiOperation({ summary: '获取商家详情(公开)' })
|
||||
async findById(@Param('id') id: number) {
|
||||
return this.merchantService.findById(id);
|
||||
}
|
||||
}
|
||||
|
||||
@ApiTags('商家管理(管理员)')
|
||||
@Controller('admin/merchants')
|
||||
@UseGuards(JwtAuthGuard, RolesGuard)
|
||||
@Roles('admin')
|
||||
@ApiBearerAuth()
|
||||
export class AdminMerchantController {
|
||||
constructor(private readonly merchantService: MerchantService) {}
|
||||
|
||||
@Get()
|
||||
@ApiOperation({ summary: '获取商家列表' })
|
||||
async findAll(@Query() query: QueryMerchantDto) {
|
||||
return this.merchantService.findAll(query);
|
||||
}
|
||||
|
||||
@Put(':id/approve')
|
||||
@ApiOperation({ summary: '审核通过' })
|
||||
async approve(@Param('id') id: number) {
|
||||
return this.merchantService.approve(id);
|
||||
}
|
||||
|
||||
@Put(':id/reject')
|
||||
@ApiOperation({ summary: '审核拒绝' })
|
||||
async reject(@Param('id') id: number, @Body('reason') reason: string) {
|
||||
return this.merchantService.reject(id, reason);
|
||||
}
|
||||
|
||||
@Put(':id/freeze')
|
||||
@ApiOperation({ summary: '冻结店铺' })
|
||||
async freeze(@Param('id') id: number) {
|
||||
return this.merchantService.freeze(id);
|
||||
}
|
||||
|
||||
@Put(':id/unfreeze')
|
||||
@ApiOperation({ summary: '解冻店铺' })
|
||||
async unfreeze(@Param('id') id: number) {
|
||||
return this.merchantService.unfreeze(id);
|
||||
}
|
||||
}
|
||||
@@ -2,18 +2,16 @@ import { Module } from '@nestjs/common';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
import { Merchant } from '@/entities/merchant.entity';
|
||||
import { MerchantService } from './merchant.service';
|
||||
import {
|
||||
MerchantPublicController,
|
||||
MerchantController,
|
||||
AdminMerchantController,
|
||||
} from './merchant.controller';
|
||||
import { MerchantPublicController } from './merchant-public.controller';
|
||||
import { MerchantSellerController } from './merchant-seller.controller';
|
||||
import { MerchantAdminController } from './merchant-admin.controller';
|
||||
|
||||
@Module({
|
||||
imports: [TypeOrmModule.forFeature([Merchant])],
|
||||
controllers: [
|
||||
MerchantPublicController,
|
||||
MerchantController,
|
||||
AdminMerchantController,
|
||||
MerchantSellerController,
|
||||
MerchantAdminController,
|
||||
],
|
||||
providers: [MerchantService],
|
||||
exports: [MerchantService],
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
import {
|
||||
Controller,
|
||||
Get,
|
||||
Put,
|
||||
Param,
|
||||
Body,
|
||||
Query,
|
||||
UseGuards,
|
||||
} from '@nestjs/common';
|
||||
import { ApiTags, ApiOperation, ApiBearerAuth } from '@nestjs/swagger';
|
||||
import { OrderService } from './order.service';
|
||||
import { JwtAuthGuard, RolesGuard } from '@/common';
|
||||
import { Roles } from '@/common/decorators/roles.decorator';
|
||||
import { QueryOrderDto } from './dto/order.dto';
|
||||
|
||||
@ApiTags('订单管理(管理员)')
|
||||
@Controller('admin/orders')
|
||||
@UseGuards(JwtAuthGuard, RolesGuard)
|
||||
@Roles('admin')
|
||||
@ApiBearerAuth()
|
||||
export class OrderAdminController {
|
||||
constructor(private readonly orderService: OrderService) {}
|
||||
|
||||
@Get()
|
||||
@ApiOperation({ summary: '全量订单列表' })
|
||||
async findAll(@Query() query: QueryOrderDto) {
|
||||
return this.orderService.findAll(query);
|
||||
}
|
||||
|
||||
@Get(':id')
|
||||
@ApiOperation({ summary: '订单详情' })
|
||||
async findById(@Param('id') id: number) {
|
||||
return this.orderService.findById(id);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
import {
|
||||
Controller,
|
||||
Get,
|
||||
Put,
|
||||
Param,
|
||||
Body,
|
||||
Query,
|
||||
UseGuards,
|
||||
NotFoundException,
|
||||
} from '@nestjs/common';
|
||||
import { ApiTags, ApiOperation, ApiBearerAuth } from '@nestjs/swagger';
|
||||
import { OrderService } from './order.service';
|
||||
import { SellerJwtAuthGuard } from '@/common/guards/seller-jwt-auth.guard';
|
||||
import { CurrentSeller } from '@/common/decorators/current-seller.decorator';
|
||||
import { MerchantService } from '../merchant/merchant.service';
|
||||
import { QueryOrderDto } from './dto/order.dto';
|
||||
|
||||
@ApiTags('订单管理(商家)')
|
||||
@Controller('seller/orders')
|
||||
@UseGuards(SellerJwtAuthGuard)
|
||||
@ApiBearerAuth()
|
||||
export class OrderSellerController {
|
||||
constructor(
|
||||
private readonly orderService: OrderService,
|
||||
private readonly merchantService: MerchantService,
|
||||
) {}
|
||||
|
||||
@Get()
|
||||
@ApiOperation({ summary: '商家订单列表' })
|
||||
async findMine(
|
||||
@CurrentSeller('sub') sellerId: number,
|
||||
@Query() query: QueryOrderDto,
|
||||
) {
|
||||
const merchant = await this.merchantService.findBySellerId(sellerId);
|
||||
if (!merchant) throw new NotFoundException('店铺不存在');
|
||||
return this.orderService.findByMerchant(merchant.id, query);
|
||||
}
|
||||
|
||||
@Put(':id/confirm')
|
||||
@ApiOperation({ summary: '确认订单' })
|
||||
async confirm(
|
||||
@CurrentSeller('sub') sellerId: number,
|
||||
@Param('id') id: number,
|
||||
) {
|
||||
const merchant = await this.merchantService.findBySellerId(sellerId);
|
||||
if (!merchant) throw new NotFoundException('店铺不存在');
|
||||
return this.orderService.confirm(merchant.id, id);
|
||||
}
|
||||
|
||||
@Put(':id/reject')
|
||||
@ApiOperation({ summary: '拒绝订单' })
|
||||
async reject(
|
||||
@CurrentSeller('sub') sellerId: number,
|
||||
@Param('id') id: number,
|
||||
@Body('reason') reason: string,
|
||||
) {
|
||||
const merchant = await this.merchantService.findBySellerId(sellerId);
|
||||
if (!merchant) throw new NotFoundException('店铺不存在');
|
||||
return this.orderService.reject(merchant.id, id, reason);
|
||||
}
|
||||
|
||||
@Put(':id/checkin')
|
||||
@ApiOperation({ summary: '办理入住' })
|
||||
async checkin(
|
||||
@CurrentSeller('sub') sellerId: number,
|
||||
@Param('id') id: number,
|
||||
) {
|
||||
const merchant = await this.merchantService.findBySellerId(sellerId);
|
||||
if (!merchant) throw new NotFoundException('店铺不存在');
|
||||
return this.orderService.checkin(merchant.id, id);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
import {
|
||||
Controller,
|
||||
Get,
|
||||
Post,
|
||||
Put,
|
||||
Param,
|
||||
Body,
|
||||
Query,
|
||||
UseGuards,
|
||||
} from '@nestjs/common';
|
||||
import { ApiTags, ApiOperation, ApiBearerAuth } from '@nestjs/swagger';
|
||||
import { OrderService } from './order.service';
|
||||
import { JwtAuthGuard } from '@/common/guards/jwt-auth.guard';
|
||||
import { CurrentUser } from '@/common/decorators/current-user.decorator';
|
||||
import {
|
||||
CreateOrderDto,
|
||||
QueryOrderDto,
|
||||
} from './dto/order.dto';
|
||||
|
||||
@ApiTags('订单(用户)')
|
||||
@Controller('orders')
|
||||
@UseGuards(JwtAuthGuard)
|
||||
@ApiBearerAuth()
|
||||
export class OrderUserController {
|
||||
constructor(private readonly orderService: OrderService) {}
|
||||
|
||||
@Post()
|
||||
@ApiOperation({ summary: '创建订单' })
|
||||
async create(
|
||||
@CurrentUser('sub') userId: number,
|
||||
@Body() dto: CreateOrderDto,
|
||||
) {
|
||||
return this.orderService.create(userId, dto);
|
||||
}
|
||||
|
||||
@Get()
|
||||
@ApiOperation({ summary: '我的订单列表' })
|
||||
async findMine(
|
||||
@CurrentUser('sub') userId: number,
|
||||
@Query() query: QueryOrderDto,
|
||||
) {
|
||||
return this.orderService.findByUser(userId, query);
|
||||
}
|
||||
|
||||
@Get(':id')
|
||||
@ApiOperation({ summary: '订单详情' })
|
||||
async findById(@Param('id') id: number) {
|
||||
return this.orderService.findById(id);
|
||||
}
|
||||
|
||||
@Put(':id/cancel')
|
||||
@ApiOperation({ summary: '取消订单' })
|
||||
async cancel(
|
||||
@CurrentUser('sub') userId: number,
|
||||
@Param('id') id: number,
|
||||
@Body('reason') reason: string,
|
||||
) {
|
||||
return this.orderService.cancel(userId, id, reason);
|
||||
}
|
||||
}
|
||||
@@ -1,192 +0,0 @@
|
||||
import {
|
||||
Controller,
|
||||
Get,
|
||||
Post,
|
||||
Put,
|
||||
Param,
|
||||
Body,
|
||||
Query,
|
||||
UseGuards,
|
||||
NotFoundException,
|
||||
} from '@nestjs/common';
|
||||
import { ApiTags, ApiOperation, ApiBearerAuth } from '@nestjs/swagger';
|
||||
import { OrderService } from './order.service';
|
||||
import { JwtAuthGuard, RolesGuard } from '@/common';
|
||||
import { SellerJwtAuthGuard } from '@/common/guards/seller-jwt-auth.guard';
|
||||
import { Roles } from '@/common/decorators/roles.decorator';
|
||||
import { CurrentUser } from '@/common/decorators/current-user.decorator';
|
||||
import { CurrentSeller } from '@/common/decorators/current-seller.decorator';
|
||||
import { MerchantService } from '../merchant/merchant.service';
|
||||
import {
|
||||
CreateOrderDto,
|
||||
QueryOrderDto,
|
||||
ConfirmOrderDto,
|
||||
} from './dto/order.dto';
|
||||
|
||||
@ApiTags('订单(用户)')
|
||||
@Controller('orders')
|
||||
@UseGuards(JwtAuthGuard)
|
||||
@ApiBearerAuth()
|
||||
export class UserOrderController {
|
||||
constructor(private readonly orderService: OrderService) {}
|
||||
|
||||
@Post()
|
||||
@ApiOperation({ summary: '创建订单' })
|
||||
async create(
|
||||
@CurrentUser('sub') userId: number,
|
||||
@Body() dto: CreateOrderDto,
|
||||
) {
|
||||
return this.orderService.create(userId, dto);
|
||||
}
|
||||
|
||||
@Get()
|
||||
@ApiOperation({ summary: '我的订单列表' })
|
||||
async findMine(
|
||||
@CurrentUser('sub') userId: number,
|
||||
@Query() query: QueryOrderDto,
|
||||
) {
|
||||
return this.orderService.findByUser(userId, query);
|
||||
}
|
||||
|
||||
@Put(':id/pay')
|
||||
@ApiOperation({ summary: '模拟支付' })
|
||||
async pay(
|
||||
@CurrentUser('sub') userId: number,
|
||||
@Param('id') id: number,
|
||||
@Body('paymentMethod') paymentMethod: 'wechat' | 'alipay' | 'balance',
|
||||
) {
|
||||
return this.orderService.pay(userId, id, paymentMethod || 'wechat');
|
||||
}
|
||||
|
||||
@Put(':id/cancel')
|
||||
@ApiOperation({ summary: '取消订单' })
|
||||
async cancel(
|
||||
@CurrentUser('sub') userId: number,
|
||||
@Param('id') id: number,
|
||||
@Body('reason') reason: string,
|
||||
) {
|
||||
return this.orderService.cancel(userId, id, reason);
|
||||
}
|
||||
|
||||
@Put(':id/refund')
|
||||
@ApiOperation({ summary: '申请退款' })
|
||||
async refund(
|
||||
@CurrentUser('sub') userId: number,
|
||||
@Param('id') id: number,
|
||||
@Body('reason') reason: string,
|
||||
) {
|
||||
return this.orderService.refund(userId, id, reason);
|
||||
}
|
||||
|
||||
@Get(':id')
|
||||
@ApiOperation({ summary: '订单详情' })
|
||||
async findById(@Param('id') id: number) {
|
||||
return this.orderService.findById(id);
|
||||
}
|
||||
}
|
||||
|
||||
@ApiTags('订单管理(商家)')
|
||||
@Controller('seller/orders')
|
||||
@UseGuards(SellerJwtAuthGuard)
|
||||
@ApiBearerAuth()
|
||||
export class MerchantOrderController {
|
||||
constructor(
|
||||
private readonly orderService: OrderService,
|
||||
private readonly merchantService: MerchantService,
|
||||
) {}
|
||||
|
||||
@Get()
|
||||
@ApiOperation({ summary: '商家订单列表' })
|
||||
async findMine(
|
||||
@CurrentSeller('sub') sellerId: number,
|
||||
@Query() query: QueryOrderDto,
|
||||
) {
|
||||
const merchant = await this.merchantService.findBySellerId(sellerId);
|
||||
if (!merchant) throw new NotFoundException('店铺不存在');
|
||||
return this.orderService.findByMerchant(merchant.id, query);
|
||||
}
|
||||
|
||||
@Get(':id')
|
||||
@ApiOperation({ summary: '商家订单详情' })
|
||||
async findById(@Param('id') id: number) {
|
||||
return this.orderService.findById(id);
|
||||
}
|
||||
|
||||
@Put(':id/confirm')
|
||||
@ApiOperation({ summary: '确认订单' })
|
||||
async confirm(
|
||||
@CurrentSeller('sub') sellerId: number,
|
||||
@Param('id') id: number,
|
||||
) {
|
||||
const merchant = await this.merchantService.findBySellerId(sellerId);
|
||||
if (!merchant) throw new NotFoundException('店铺不存在');
|
||||
return this.orderService.confirm(merchant.id, id);
|
||||
}
|
||||
|
||||
@Put(':id/reject')
|
||||
@ApiOperation({ summary: '拒绝订单' })
|
||||
async reject(
|
||||
@CurrentSeller('sub') sellerId: number,
|
||||
@Param('id') id: number,
|
||||
@Body('reason') reason: string,
|
||||
) {
|
||||
const merchant = await this.merchantService.findBySellerId(sellerId);
|
||||
if (!merchant) throw new NotFoundException('店铺不存在');
|
||||
return this.orderService.reject(merchant.id, id, reason);
|
||||
}
|
||||
|
||||
@Put(':id/checkin')
|
||||
@ApiOperation({ summary: '办理入住' })
|
||||
async checkin(
|
||||
@CurrentSeller('sub') sellerId: number,
|
||||
@Param('id') id: number,
|
||||
) {
|
||||
const merchant = await this.merchantService.findBySellerId(sellerId);
|
||||
if (!merchant) throw new NotFoundException('店铺不存在');
|
||||
return this.orderService.checkin(merchant.id, id);
|
||||
}
|
||||
|
||||
@Put(':id/approve-refund')
|
||||
@ApiOperation({ summary: '同意退款' })
|
||||
async approveRefund(
|
||||
@CurrentSeller('sub') sellerId: number,
|
||||
@Param('id') id: number,
|
||||
) {
|
||||
const merchant = await this.merchantService.findBySellerId(sellerId);
|
||||
if (!merchant) throw new NotFoundException('店铺不存在');
|
||||
return this.orderService.approveRefund(merchant.id, id);
|
||||
}
|
||||
|
||||
@Put(':id/reject-refund')
|
||||
@ApiOperation({ summary: '拒绝退款' })
|
||||
async rejectRefund(
|
||||
@CurrentSeller('sub') sellerId: number,
|
||||
@Param('id') id: number,
|
||||
@Body('reason') reason: string,
|
||||
) {
|
||||
const merchant = await this.merchantService.findBySellerId(sellerId);
|
||||
if (!merchant) throw new NotFoundException('店铺不存在');
|
||||
return this.orderService.rejectRefund(merchant.id, id, reason);
|
||||
}
|
||||
}
|
||||
|
||||
@ApiTags('订单管理(管理员)')
|
||||
@Controller('admin/orders')
|
||||
@UseGuards(JwtAuthGuard, RolesGuard)
|
||||
@Roles('admin')
|
||||
@ApiBearerAuth()
|
||||
export class AdminOrderController {
|
||||
constructor(private readonly orderService: OrderService) {}
|
||||
|
||||
@Get()
|
||||
@ApiOperation({ summary: '全量订单列表' })
|
||||
async findAll(@Query() query: QueryOrderDto) {
|
||||
return this.orderService.findAll(query);
|
||||
}
|
||||
|
||||
@Get(':id')
|
||||
@ApiOperation({ summary: '订单详情' })
|
||||
async findById(@Param('id') id: number) {
|
||||
return this.orderService.findById(id);
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,9 @@ 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 { OrderUserController } from './order-user.controller';
|
||||
import { OrderSellerController } from './order-seller.controller';
|
||||
import { OrderAdminController } from './order-admin.controller';
|
||||
import { MerchantModule } from '../merchant/merchant.module';
|
||||
import { ActivityModule } from '../activity/activity.module';
|
||||
import { PlatformConfigModule } from '../config/config.module';
|
||||
@@ -18,7 +20,7 @@ import { PlatformConfigModule } from '../config/config.module';
|
||||
forwardRef(() => ActivityModule),
|
||||
PlatformConfigModule,
|
||||
],
|
||||
controllers: [UserOrderController, MerchantOrderController, AdminOrderController],
|
||||
controllers: [OrderUserController, OrderSellerController, OrderAdminController],
|
||||
providers: [OrderService],
|
||||
exports: [OrderService],
|
||||
})
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
import {
|
||||
Controller,
|
||||
Get,
|
||||
Put,
|
||||
Param,
|
||||
Body,
|
||||
Query,
|
||||
UseGuards,
|
||||
} from '@nestjs/common';
|
||||
import { ReviewService } from './review.service';
|
||||
import { QueryReviewDto } from './dto/review.dto';
|
||||
import { JwtAuthGuard, RolesGuard } from '@/common';
|
||||
import { Roles } from '@/common/decorators/roles.decorator';
|
||||
|
||||
// 管理员评价审核接口
|
||||
@Controller('admin/reviews')
|
||||
@UseGuards(JwtAuthGuard, RolesGuard)
|
||||
@Roles('admin')
|
||||
export class ReviewAdminController {
|
||||
constructor(private readonly reviewService: ReviewService) {}
|
||||
|
||||
// 评价审核列表
|
||||
@Get()
|
||||
async list(@Query() query: QueryReviewDto) {
|
||||
return this.reviewService.findAllForAdmin(query);
|
||||
}
|
||||
|
||||
// 审核通过
|
||||
@Put(':id/approve')
|
||||
async approve(@Param('id') id: number) {
|
||||
return this.reviewService.approve(Number(id));
|
||||
}
|
||||
|
||||
// 审核拒绝
|
||||
@Put(':id/reject')
|
||||
async reject(@Param('id') id: number, @Body('reason') reason: string) {
|
||||
return this.reviewService.reject(Number(id), reason);
|
||||
}
|
||||
}
|
||||
+2
-29
@@ -11,12 +11,11 @@ import {
|
||||
} from '@nestjs/common';
|
||||
import { ReviewService } from './review.service';
|
||||
import { CreateReviewDto, QueryReviewDto } from './dto/review.dto';
|
||||
import { JwtAuthGuard, RolesGuard } from '@/common';
|
||||
import { Roles } from '@/common/decorators/roles.decorator';
|
||||
import { JwtAuthGuard } from '@/common/guards/jwt-auth.guard';
|
||||
|
||||
// 用户端评价接口
|
||||
@Controller('reviews')
|
||||
export class ReviewPublicController {
|
||||
export class ReviewUserController {
|
||||
constructor(private readonly reviewService: ReviewService) {}
|
||||
|
||||
// 提交评价(需登录)
|
||||
@@ -43,29 +42,3 @@ export class ReviewPublicController {
|
||||
return { reviewed: !!review, review };
|
||||
}
|
||||
}
|
||||
|
||||
// 管理员评价审核接口
|
||||
@Controller('admin/reviews')
|
||||
@UseGuards(JwtAuthGuard, RolesGuard)
|
||||
@Roles('admin')
|
||||
export class AdminReviewController {
|
||||
constructor(private readonly reviewService: ReviewService) {}
|
||||
|
||||
// 评价审核列表
|
||||
@Get()
|
||||
async list(@Query() query: QueryReviewDto) {
|
||||
return this.reviewService.findAllForAdmin(query);
|
||||
}
|
||||
|
||||
// 审核通过
|
||||
@Put(':id/approve')
|
||||
async approve(@Param('id') id: number) {
|
||||
return this.reviewService.approve(Number(id));
|
||||
}
|
||||
|
||||
// 审核拒绝
|
||||
@Put(':id/reject')
|
||||
async reject(@Param('id') id: number, @Body('reason') reason: string) {
|
||||
return this.reviewService.reject(Number(id), reason);
|
||||
}
|
||||
}
|
||||
@@ -5,11 +5,12 @@ import { Order } from '@/entities/order.entity';
|
||||
import { Merchant } from '@/entities/merchant.entity';
|
||||
import { Room } from '@/entities/room.entity';
|
||||
import { ReviewService } from './review.service';
|
||||
import { ReviewPublicController, AdminReviewController } from './review.controller';
|
||||
import { ReviewUserController } from './review-user.controller';
|
||||
import { ReviewAdminController } from './review-admin.controller';
|
||||
|
||||
@Module({
|
||||
imports: [TypeOrmModule.forFeature([Review, Order, Merchant, Room])],
|
||||
controllers: [ReviewPublicController, AdminReviewController],
|
||||
controllers: [ReviewUserController, ReviewAdminController],
|
||||
providers: [ReviewService],
|
||||
exports: [ReviewService],
|
||||
})
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
import {
|
||||
Controller,
|
||||
Get,
|
||||
Put,
|
||||
Param,
|
||||
Body,
|
||||
Query,
|
||||
UseGuards,
|
||||
} from '@nestjs/common';
|
||||
import { ApiTags, ApiOperation, ApiBearerAuth } from '@nestjs/swagger';
|
||||
import { RoomService } from './room.service';
|
||||
import { JwtAuthGuard, RolesGuard } from '@/common';
|
||||
import { Roles } from '@/common/decorators/roles.decorator';
|
||||
import { QueryRoomDto } from './dto/room.dto';
|
||||
|
||||
@ApiTags('房源审核(管理员)')
|
||||
@Controller('admin/rooms')
|
||||
@UseGuards(JwtAuthGuard, RolesGuard)
|
||||
@Roles('admin')
|
||||
@ApiBearerAuth()
|
||||
export class RoomAdminController {
|
||||
constructor(private readonly roomService: RoomService) {}
|
||||
|
||||
@Get()
|
||||
@ApiOperation({ summary: '房源列表(管理员)' })
|
||||
async findAll(@Query() query: QueryRoomDto) {
|
||||
return await this.roomService.findAllForAdmin(query);
|
||||
}
|
||||
|
||||
@Put(':id/approve')
|
||||
@ApiOperation({ summary: '审核通过' })
|
||||
async approve(@Param('id') id: number) {
|
||||
return await this.roomService.approve(Number(id));
|
||||
}
|
||||
|
||||
@Put(':id/reject')
|
||||
@ApiOperation({ summary: '审核拒绝' })
|
||||
async reject(@Param('id') id: number, @Body('reason') reason: string) {
|
||||
return await this.roomService.reject(Number(id), reason);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
import {
|
||||
Controller,
|
||||
Get,
|
||||
Param,
|
||||
Query,
|
||||
} from '@nestjs/common';
|
||||
import { ApiTags, ApiOperation } from '@nestjs/swagger';
|
||||
import { RoomService } from './room.service';
|
||||
import { RoomCalendarService } from '../room-calendar/room-calendar.service';
|
||||
import { QueryRoomDto } from './dto/room.dto';
|
||||
|
||||
@ApiTags('房源')
|
||||
@Controller('rooms')
|
||||
export class RoomPublicController {
|
||||
constructor(
|
||||
private readonly roomService: RoomService,
|
||||
private readonly calendarService: RoomCalendarService,
|
||||
) {}
|
||||
|
||||
@Get()
|
||||
@ApiOperation({ summary: '房源列表(公开)' })
|
||||
async findAll(@Query() query: QueryRoomDto) {
|
||||
return this.roomService.findPublic(query);
|
||||
}
|
||||
|
||||
@Get(':id')
|
||||
@ApiOperation({ summary: '房源详情(公开)' })
|
||||
async findById(@Param('id') id: number) {
|
||||
return this.roomService.findById(id);
|
||||
}
|
||||
|
||||
@Get(':id/calendar')
|
||||
@ApiOperation({ summary: '房源日历(公开)' })
|
||||
async getCalendar(
|
||||
@Param('id') id: number,
|
||||
@Query('startDate') startDate: string,
|
||||
@Query('endDate') endDate: string,
|
||||
) {
|
||||
return this.calendarService.getCalendar(Number(id), { startDate, endDate });
|
||||
}
|
||||
}
|
||||
+1
-62
@@ -13,49 +13,15 @@ import {
|
||||
import { ApiTags, ApiOperation, ApiBearerAuth } from '@nestjs/swagger';
|
||||
import { RoomService } from './room.service';
|
||||
import { SellerJwtAuthGuard } from '@/common/guards/seller-jwt-auth.guard';
|
||||
import { JwtAuthGuard, RolesGuard } from '@/common';
|
||||
import { Roles } from '@/common/decorators/roles.decorator';
|
||||
import { CurrentSeller } from '@/common/decorators/current-seller.decorator';
|
||||
import { MerchantService } from '../merchant/merchant.service';
|
||||
import { RoomCalendarService } from '../room-calendar/room-calendar.service';
|
||||
import { CreateRoomDto, UpdateRoomDto, QueryRoomDto } from './dto/room.dto';
|
||||
|
||||
@ApiTags('房源')
|
||||
@Controller('rooms')
|
||||
export class RoomPublicController {
|
||||
constructor(
|
||||
private readonly roomService: RoomService,
|
||||
private readonly calendarService: RoomCalendarService,
|
||||
) {}
|
||||
|
||||
@Get()
|
||||
@ApiOperation({ summary: '房源列表(公开)' })
|
||||
async findAll(@Query() query: QueryRoomDto) {
|
||||
return this.roomService.findPublic(query);
|
||||
}
|
||||
|
||||
@Get(':id')
|
||||
@ApiOperation({ summary: '房源详情(公开)' })
|
||||
async findById(@Param('id') id: number) {
|
||||
return this.roomService.findById(id);
|
||||
}
|
||||
|
||||
@Get(':id/calendar')
|
||||
@ApiOperation({ summary: '房源日历(公开)' })
|
||||
async getCalendar(
|
||||
@Param('id') id: number,
|
||||
@Query('startDate') startDate: string,
|
||||
@Query('endDate') endDate: string,
|
||||
) {
|
||||
return this.calendarService.getCalendar(Number(id), { startDate, endDate });
|
||||
}
|
||||
}
|
||||
|
||||
@ApiTags('房源管理(商家)')
|
||||
@Controller('seller/rooms')
|
||||
@UseGuards(SellerJwtAuthGuard)
|
||||
@ApiBearerAuth()
|
||||
export class MerchantRoomController {
|
||||
export class RoomSellerController {
|
||||
constructor(
|
||||
private readonly roomService: RoomService,
|
||||
private readonly merchantService: MerchantService,
|
||||
@@ -120,30 +86,3 @@ export class MerchantRoomController {
|
||||
return this.roomService.remove(Number(id), Number(merchant.id));
|
||||
}
|
||||
}
|
||||
|
||||
@ApiTags('房源审核(管理员)')
|
||||
@Controller('admin/rooms')
|
||||
@UseGuards(JwtAuthGuard, RolesGuard)
|
||||
@Roles('admin')
|
||||
@ApiBearerAuth()
|
||||
export class AdminRoomController {
|
||||
constructor(private readonly roomService: RoomService) {}
|
||||
|
||||
@Get()
|
||||
@ApiOperation({ summary: '房源列表(管理员)' })
|
||||
async findAll(@Query() query: QueryRoomDto) {
|
||||
return await this.roomService.findAllForAdmin(query);
|
||||
}
|
||||
|
||||
@Put(':id/approve')
|
||||
@ApiOperation({ summary: '审核通过' })
|
||||
async approve(@Param('id') id: number) {
|
||||
return await this.roomService.approve(Number(id));
|
||||
}
|
||||
|
||||
@Put(':id/reject')
|
||||
@ApiOperation({ summary: '审核拒绝' })
|
||||
async reject(@Param('id') id: number, @Body('reason') reason: string) {
|
||||
return await this.roomService.reject(Number(id), reason);
|
||||
}
|
||||
}
|
||||
@@ -3,20 +3,22 @@ import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
import { Room } from '@/entities/room.entity';
|
||||
import { RoomCalendar } from '@/entities/room-calendar.entity';
|
||||
import { RoomService } from './room.service';
|
||||
import {
|
||||
RoomPublicController,
|
||||
MerchantRoomController,
|
||||
AdminRoomController,
|
||||
} from './room.controller';
|
||||
import { RoomPublicController } from './room-public.controller';
|
||||
import { RoomSellerController } from './room-seller.controller';
|
||||
import { RoomAdminController } from './room-admin.controller';
|
||||
import { MerchantModule } from '../merchant/merchant.module';
|
||||
import { RoomCalendarModule } from '../room-calendar/room-calendar.module';
|
||||
|
||||
@Module({
|
||||
imports: [TypeOrmModule.forFeature([Room, RoomCalendar]), MerchantModule, RoomCalendarModule],
|
||||
imports: [
|
||||
TypeOrmModule.forFeature([Room, RoomCalendar]),
|
||||
MerchantModule,
|
||||
RoomCalendarModule,
|
||||
],
|
||||
controllers: [
|
||||
RoomPublicController,
|
||||
MerchantRoomController,
|
||||
AdminRoomController,
|
||||
RoomSellerController,
|
||||
RoomAdminController,
|
||||
],
|
||||
providers: [RoomService],
|
||||
exports: [RoomService],
|
||||
|
||||
@@ -8,12 +8,14 @@ import {
|
||||
} from '@nestjs/common';
|
||||
import { FileInterceptor } from '@nestjs/platform-express';
|
||||
import { ApiTags, ApiOperation, ApiBearerAuth, ApiConsumes, ApiBody } from '@nestjs/swagger';
|
||||
import * as multer from 'multer';
|
||||
import { JwtAuthGuard } from '@/common/guards/jwt-auth.guard';
|
||||
import { SellerJwtAuthGuard } from '@/common/guards/seller-jwt-auth.guard';
|
||||
import { RolesGuard, Roles } from '@/common';
|
||||
import { UploadService } from './upload.service';
|
||||
|
||||
const uploadOptions = {
|
||||
const uploadOptions: multer.Options = {
|
||||
storage: multer.memoryStorage(),
|
||||
limits: { fileSize: 10 * 1024 * 1024 },
|
||||
fileFilter: (_req: any, file: Express.Multer.File, cb: any) => {
|
||||
if (!file.mimetype.match(/\/(jpg|jpeg|png|gif|webp|bmp)$/)) {
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
import {
|
||||
Controller,
|
||||
Get,
|
||||
Put,
|
||||
Param,
|
||||
Query,
|
||||
UseGuards,
|
||||
} from '@nestjs/common';
|
||||
import { ApiTags, ApiOperation, ApiBearerAuth } from '@nestjs/swagger';
|
||||
import { UserService } from './user.service';
|
||||
import { JwtAuthGuard, RolesGuard } from '@/common';
|
||||
import { Roles } from '@/common/decorators/roles.decorator';
|
||||
import { QueryUserDto } from './dto/user.dto';
|
||||
|
||||
@ApiTags('用户管理(管理员)')
|
||||
@Controller('admin/users')
|
||||
@UseGuards(JwtAuthGuard, RolesGuard)
|
||||
@Roles('admin')
|
||||
@ApiBearerAuth()
|
||||
export class UserAdminController {
|
||||
constructor(private readonly userService: UserService) {}
|
||||
|
||||
@Get()
|
||||
@ApiOperation({ summary: '获取用户列表' })
|
||||
async findAll(@Query() query: QueryUserDto) {
|
||||
return this.userService.findAll(query);
|
||||
}
|
||||
|
||||
@Put(':id/freeze')
|
||||
@ApiOperation({ summary: '冻结用户' })
|
||||
async freeze(@Param('id') id: number) {
|
||||
return this.userService.freeze(id);
|
||||
}
|
||||
|
||||
@Put(':id/unfreeze')
|
||||
@ApiOperation({ summary: '解冻用户' })
|
||||
async unfreeze(@Param('id') id: number) {
|
||||
return this.userService.unfreeze(id);
|
||||
}
|
||||
}
|
||||
+1
-33
@@ -3,27 +3,22 @@ import {
|
||||
Get,
|
||||
Put,
|
||||
Body,
|
||||
Param,
|
||||
Query,
|
||||
UseGuards,
|
||||
} from '@nestjs/common';
|
||||
import { ApiTags, ApiOperation, ApiBearerAuth } from '@nestjs/swagger';
|
||||
import { UserService } from './user.service';
|
||||
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 {
|
||||
UpdateProfileDto,
|
||||
ChangePasswordDto,
|
||||
QueryUserDto,
|
||||
} from './dto/user.dto';
|
||||
|
||||
@ApiTags('用户')
|
||||
@Controller('user')
|
||||
@UseGuards(JwtAuthGuard)
|
||||
@ApiBearerAuth()
|
||||
export class UserController {
|
||||
export class UserUserController {
|
||||
constructor(private readonly userService: UserService) {}
|
||||
|
||||
@Get('profile')
|
||||
@@ -50,30 +45,3 @@ export class UserController {
|
||||
return this.userService.changePassword(userId, dto);
|
||||
}
|
||||
}
|
||||
|
||||
@ApiTags('用户管理(管理员)')
|
||||
@Controller('admin/users')
|
||||
@UseGuards(JwtAuthGuard, RolesGuard)
|
||||
@Roles('admin')
|
||||
@ApiBearerAuth()
|
||||
export class AdminUserController {
|
||||
constructor(private readonly userService: UserService) {}
|
||||
|
||||
@Get()
|
||||
@ApiOperation({ summary: '获取用户列表' })
|
||||
async findAll(@Query() query: QueryUserDto) {
|
||||
return this.userService.findAll(query);
|
||||
}
|
||||
|
||||
@Put(':id/freeze')
|
||||
@ApiOperation({ summary: '冻结用户' })
|
||||
async freeze(@Param('id') id: number) {
|
||||
return this.userService.freeze(id);
|
||||
}
|
||||
|
||||
@Put(':id/unfreeze')
|
||||
@ApiOperation({ summary: '解冻用户' })
|
||||
async unfreeze(@Param('id') id: number) {
|
||||
return this.userService.unfreeze(id);
|
||||
}
|
||||
}
|
||||
@@ -2,11 +2,12 @@ import { Module } from '@nestjs/common';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
import { User } from '@/entities/user.entity';
|
||||
import { UserService } from './user.service';
|
||||
import { UserController, AdminUserController } from './user.controller';
|
||||
import { UserUserController } from './user-user.controller';
|
||||
import { UserAdminController } from './user-admin.controller';
|
||||
|
||||
@Module({
|
||||
imports: [TypeOrmModule.forFeature([User])],
|
||||
controllers: [UserController, AdminUserController],
|
||||
controllers: [UserUserController, UserAdminController],
|
||||
providers: [UserService],
|
||||
exports: [UserService],
|
||||
})
|
||||
|
||||
@@ -20,6 +20,8 @@
|
||||
"noImplicitAny": false,
|
||||
"strictBindCallApply": false,
|
||||
"noFallthroughCasesInSwitch": false,
|
||||
"typeRoots": ["./node_modules/@types"],
|
||||
"types": ["node", "multer", "jest"],
|
||||
"paths": {
|
||||
"@/*": ["src/*"]
|
||||
}
|
||||
|
||||
@@ -484,6 +484,79 @@ async update(id, dto) {
|
||||
|
||||
---
|
||||
|
||||
## 三端分离开发规范
|
||||
|
||||
### 三端定义
|
||||
|
||||
| 端 | 说明 | 前端项目 | API路由前缀 |
|
||||
|---|---|---|---|
|
||||
| 用户端 | C端普通用户 | 小程序用户页面 (`pages/*`) | `/xxx` (无前缀) |
|
||||
| 商家端 | B端商家 | 小程序商家页面 (`pages/seller/*`) + 商家管理后台 (`merchant-admin`) | `/seller/xxx` |
|
||||
| 平台端 | 平台管理员 | 平台管理后台 (`platform-admin`) | `/admin/xxx` |
|
||||
|
||||
### 后端 Controller 文件命名规范
|
||||
|
||||
每个模块的控制器按端拆分为独立文件,命名格式:`{module}-{端}.controller.ts`
|
||||
|
||||
```
|
||||
modules/merchant/
|
||||
├── merchant-public.controller.ts # 用户端 @Controller('merchants')
|
||||
├── merchant-seller.controller.ts # 商家端 @Controller('seller/merchant')
|
||||
├── merchant-admin.controller.ts # 管理端 @Controller('admin/merchants')
|
||||
├── merchant.service.ts # 共享 Service
|
||||
├── merchant.module.ts # 模块定义
|
||||
└── dto/
|
||||
```
|
||||
|
||||
**命名对照**:
|
||||
- `*-public.controller.ts` → 用户端(公开接口,无Guard或JwtAuthGuard)
|
||||
- `*-seller.controller.ts` → 商家端(SellerJwtAuthGuard)
|
||||
- `*-user.controller.ts` → 用户端(需登录,JwtAuthGuard)
|
||||
- `*-admin.controller.ts` → 管理端(JwtAuthGuard + RolesGuard + @Roles('admin'))
|
||||
|
||||
### 小程序 API 文件目录规范
|
||||
|
||||
```
|
||||
apps/miniapp/src/api/
|
||||
├── user/ # 用户端 API
|
||||
│ ├── auth.ts # /auth/*, /user/profile
|
||||
│ ├── merchant.ts # /merchants/* (公开)
|
||||
│ ├── room.ts # /rooms/* (公开)
|
||||
│ ├── order.ts # /orders/*
|
||||
│ ├── review.ts # /reviews/*
|
||||
│ └── invite.ts # /user/activity/invite/*
|
||||
└── seller/ # 商家端 API
|
||||
├── auth.ts # /seller/auth/*
|
||||
├── merchant.ts # /seller/merchant/*
|
||||
├── room.ts # /seller/rooms/*
|
||||
├── room-calendar.ts # /seller/room-calendar/*
|
||||
└── order.ts # /seller/orders/*
|
||||
```
|
||||
|
||||
### Guard 使用对照
|
||||
|
||||
| 端 | Guard | Token | 装饰器 |
|
||||
|---|---|---|---|
|
||||
| 用户端(公开) | 无 | 无 | 无 |
|
||||
| 用户端(需登录) | JwtAuthGuard | Bearer Token | @CurrentUser('sub') |
|
||||
| 商家端 | SellerJwtAuthGuard | Bearer sellerToken | @CurrentSeller('sub') |
|
||||
| 管理端 | JwtAuthGuard + RolesGuard | Bearer adminToken | @CurrentUser('sub') + @Roles('admin') |
|
||||
|
||||
### 新增模块开发清单
|
||||
|
||||
新增业务模块时,按以下步骤操作:
|
||||
|
||||
1. 创建 `modules/{module}/` 目录
|
||||
2. 创建 `dto/{module}.dto.ts`
|
||||
3. 创建 `{module}.service.ts`
|
||||
4. 按需创建控制器文件:`{module}-public.controller.ts`、`{module}-seller.controller.ts`、`{module}-admin.controller.ts`
|
||||
5. 创建 `{module}.module.ts`,引用所有控制器和共享 Service
|
||||
6. 在 `app.module.ts` 中注册新模块
|
||||
7. 小程序端按端创建 API 文件:`api/user/{module}.ts` 或 `api/seller/{module}.ts`
|
||||
8. 商家管理后台/平台管理后台按需添加 API 文件
|
||||
|
||||
---
|
||||
|
||||
## 商家订单管理
|
||||
|
||||
### 商家订单接口
|
||||
|
||||
Generated
+7804
-9659
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user