feat: 初始化微信小程序后端骨架

- NestJS + TypeScript + Prisma + PostgreSQL 工程骨架
- 微信登录安全流程:服务端 code2Session 换 openid 后签发 JWT,
  session_key 缓存于 Redis,不信任前端 openid
- 统一响应/异常处理、JWT 全局鉴权(@Public 豁免)、Swagger 文档
- Prisma 全量核心 schema(用户/分类/商品/设计清单/地址/订单/支付/上传/定制任务)+ seed
- 业务模块空壳(商品/分类/设计清单/地址/订单/支付/上传/BullMQ 队列)
- Docker 多阶段镜像 + 本地/生产 docker-compose
- docs:密钥获取指南、COS SDK 移除记录

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-05 17:33:50 +08:00
co-authored by Claude Fable 5
commit deaa0c9ce4
73 changed files with 9533 additions and 0 deletions
+18
View File
@@ -0,0 +1,18 @@
import { Controller, Get, UseGuards } from '@nestjs/common';
import { ApiBearerAuth, ApiOkResponse, ApiOperation, ApiTags } from '@nestjs/swagger';
import { CurrentUser, JwtPayload } from '../common/decorators/current-user.decorator';
import { UsersService } from './users.service';
@ApiTags('用户')
@ApiBearerAuth()
@Controller('users')
export class UsersController {
constructor(private readonly usersService: UsersService) {}
@Get('me')
@ApiOperation({ summary: '获取当前登录用户信息' })
@ApiOkResponse({ description: '当前用户' })
async getMe(@CurrentUser() user: JwtPayload) {
return this.usersService.findById(user.sub);
}
}
+10
View File
@@ -0,0 +1,10 @@
import { Module } from '@nestjs/common';
import { UsersController } from './users.controller';
import { UsersService } from './users.service';
@Module({
controllers: [UsersController],
providers: [UsersService],
exports: [UsersService],
})
export class UsersModule {}
+25
View File
@@ -0,0 +1,25 @@
import { Injectable } from '@nestjs/common';
import { PrismaService } from '../prisma/prisma.service';
@Injectable()
export class UsersService {
constructor(private readonly prisma: PrismaService) {}
/** 按 openid 查询用户,不存在则创建(首次登录) */
async findOrCreateByOpenid(openid: string, unionid?: string) {
return this.prisma.user.upsert({
where: { openid },
update: unionid ? { unionid } : {},
create: { openid, unionid },
});
}
async findById(id: string) {
return this.prisma.user.findUnique({ where: { id } });
}
/** 更新昵称/头像/手机号(由小程序授权后回传) */
async updateProfile(id: string, data: { nickname?: string; avatar?: string; phone?: string }) {
return this.prisma.user.update({ where: { id }, data });
}
}