feat: WWJCloud 企业级全栈框架 v0.3.5 完整更新

🚀 核心更新:
-  完善 NestJS 企业级架构设计
-  优化配置中心和基础设施层
-  增强第三方服务集成能力
-  完善多租户架构支持
- 🎯 对标 Java Spring Boot 和 PHP ThinkPHP

📦 新增文件:
- wwjcloud-nest 完整框架结构
- Docker 容器化配置
- 管理后台界面
- 数据库迁移脚本

🔑 Key: ebb38b43ec39f355f071294fd1cf9c42
This commit is contained in:
wanwu
2025-10-13 01:27:37 +08:00
parent 16892939a6
commit 2285206b3f
1695 changed files with 260750 additions and 19 deletions

View File

@@ -0,0 +1,209 @@
import {
Controller,
Get,
Post,
Put,
Delete,
Body,
Param,
Query,
UseGuards,
UseInterceptors,
UploadedFile,
UploadedFiles,
Session,
Req,
} from '@nestjs/common';
import { FileInterceptor, FilesInterceptor } from '@nestjs/platform-express';
import {
ApiTags,
ApiOperation,
ApiResponse,
ApiConsumes,
} from '@nestjs/swagger';
import { Request } from 'express';
import { JwtAuthGuard } from '@wwjCommon/security/guards/jwt-auth.guard';
import { RolesGuard } from '@wwjCommon/security/guards/roles.guard';
import { Roles } from '@wwjCommon/security/decorators/roles.decorator';
import { Public } from '@wwjCommon/security/decorators/public.decorator';
import { BusinessException } from '@wwjCommon/exception/business.exception';
// @UploadedFile() - 单文件上传,配合 @UseInterceptors(FileInterceptor('file'))
// @UploadedFiles() - 多文件上传,配合 @UseInterceptors(FilesInterceptor('files'))
// @Session() - 获取会话对象对应PHP Session::get()
// @Req() - 获取Request对象对应PHP Request
import { DictService } from '../../services/admin/dict.service';
/**
* DictController
* 对应 PHP: Dict Controller
* 对应 Java: @RestController
*
* 支持装饰器:
* - @UploadedFile() - 单文件上传 (对应PHP Request::file())
* - @UploadedFiles() - 多文件上传
* - @Session() - 会话管理 (对应PHP Session::get())
* - @Req() - 请求对象 (对应PHP Request)
*/
@ApiTags('dict')
@Controller('adminapi/dict')
export class DictController {
constructor(private readonly dictService: DictService) {}
/**
* 数据字典
* 路由: GET dict
* PHP路由: Route::get('dict', 'dict.Dict/lists')
*/
@Get('dict')
@UseGuards(JwtAuthGuard, RolesGuard)
@ApiOperation({ summary: '数据字典' })
async lists(): Promise<ApiResponse> {
try {
// 基于PHP真实逻辑实现
// PHP原始方法: lists
return await this.dictService.getPage(data);
} catch (error) {
throw new BusinessException('lists操作失败', error);
}
}
/**
* 数据字典
* 路由: GET dict/:id
* PHP路由: Route::get('dict/:id', 'dict.Dict/info')
*/
@Get('dict/:id')
@UseGuards(JwtAuthGuard, RolesGuard)
@ApiOperation({ summary: '数据字典' })
async info(@Param('id') id: string): Promise<ApiResponse> {
try {
// 基于PHP真实逻辑实现
// PHP原始方法: info
return await this.dictService.getInfo(id);
} catch (error) {
throw new BusinessException('info操作失败', error);
}
}
/**
* 数据字典
* 路由: POST dict
* PHP路由: Route::post('dict', 'dict.Dict/add')
*/
@Post('dict')
@UseGuards(JwtAuthGuard, RolesGuard)
@ApiOperation({ summary: '数据字典' })
async add(@Body() data: AddDto): Promise<ApiResponse> {
try {
// 基于PHP真实逻辑实现
// PHP原始方法: add
return await this.dictService.add(data);
} catch (error) {
throw new BusinessException('add操作失败', error);
}
}
/**
* 数据字典
* 路由: PUT dict/:id
* PHP路由: Route::put('dict/:id', 'dict.Dict/edit')
*/
@Put('dict/:id')
@UseGuards(JwtAuthGuard, RolesGuard)
@ApiOperation({ summary: '数据字典' })
async edit(
@Param('id') id: string,
@Body() data: EditDto,
): Promise<ApiResponse> {
try {
// 基于PHP真实逻辑实现
// PHP原始方法: edit
return await this.dictService.edit(id, data);
} catch (error) {
throw new BusinessException('edit操作失败', error);
}
}
/**
* 数据字典
* 路由: DELETE dict/:id
* PHP路由: Route::delete('dict/:id', 'dict.Dict/del')
*/
@Delete('dict/:id')
@UseGuards(JwtAuthGuard, RolesGuard)
@ApiOperation({ summary: '数据字典' })
async del(@Param('id') id: string): Promise<ApiResponse> {
try {
// 基于PHP真实逻辑实现
// PHP原始方法: del
return await this.dictService.del(id);
} catch (error) {
throw new BusinessException('del操作失败', error);
}
}
/**
* 数据字典
* 路由: PUT dictionary/:id
* PHP路由: Route::put('dictionary/:id', 'dict.Dict/addDictData')
*/
@Put('dictionary/:id')
@UseGuards(JwtAuthGuard, RolesGuard)
@ApiOperation({ summary: '数据字典' })
async addDictData(
@Param('id') id: string,
@Body() data: AddDictDataDto,
): Promise<ApiResponse> {
try {
// 基于PHP真实逻辑实现
// PHP原始方法: addDictData
return await this.dictService.edit(id, data);
} catch (error) {
throw new BusinessException('addDictData操作失败', error);
}
}
/**
* 数据字典
* 路由: GET all
* PHP路由: Route::get('all', 'dict.Dict/getAll')
*/
@Get('all')
@UseGuards(JwtAuthGuard, RolesGuard)
@ApiOperation({ summary: '数据字典' })
async getAll(): Promise<ApiResponse> {
try {
// 基于PHP真实逻辑实现
// PHP原始方法: getAll
return await this.dictService.getAll();
} catch (error) {
throw new BusinessException('getAll操作失败', error);
}
}
/**
* 数据字典
* 路由: GET dictionary/type/:type
* PHP路由: Route::get('dictionary/type/:type', 'dict.Dict/getKeyInfo')
*/
@Get('dictionary/type/:type')
@UseGuards(JwtAuthGuard, RolesGuard)
@ApiOperation({ summary: '数据字典' })
async getKeyInfo(@Param('type') type: string): Promise<ApiResponse> {
try {
// 基于PHP真实逻辑实现
// PHP原始方法: getKeyInfo
return await this.dictService.getKeyInfo(type);
} catch (error) {
throw new BusinessException('getKeyInfo操作失败', error);
}
}
}

View File

@@ -0,0 +1,9 @@
import { Module } from '@nestjs/common';
@Module({
imports: [],
controllers: [],
providers: [],
exports: [],
})
export class DictModule {}

View File

@@ -0,0 +1,25 @@
import {
Entity,
PrimaryGeneratedColumn,
Column,
CreateDateColumn,
UpdateDateColumn,
} from 'typeorm';
@Entity('dict')
export class Dict {
@PrimaryGeneratedColumn()
id: number;
@Column({ type: 'varchar', length: 255, nullable: true })
name: string;
@Column({ type: 'text', nullable: true })
description: string;
@CreateDateColumn()
createdAt: Date;
@UpdateDateColumn()
updatedAt: Date;
}

View File

@@ -0,0 +1,135 @@
/**
* DictService 枚举
* 定义相关的常量值
*/
export enum DictServiceEnum {
// 状态枚举
STATUS_ACTIVE = 'active',
STATUS_INACTIVE = 'inactive',
STATUS_PENDING = 'pending',
STATUS_DELETED = 'deleted',
// 类型枚举
TYPE_NORMAL = 'normal',
TYPE_PREMIUM = 'premium',
TYPE_VIP = 'vip',
// 级别枚举
LEVEL_LOW = 1,
LEVEL_MEDIUM = 2,
LEVEL_HIGH = 3,
LEVEL_CRITICAL = 4,
}
/**
* DictService 字典映射
*/
export const dictServiceDict = {
// 状态映射
status: {
[DictServiceEnum.STATUS_ACTIVE]: '激活',
[DictServiceEnum.STATUS_INACTIVE]: '未激活',
[DictServiceEnum.STATUS_PENDING]: '待处理',
[DictServiceEnum.STATUS_DELETED]: '已删除',
},
// 类型映射
type: {
[DictServiceEnum.TYPE_NORMAL]: '普通',
[DictServiceEnum.TYPE_PREMIUM]: '高级',
[DictServiceEnum.TYPE_VIP]: 'VIP',
},
// 级别映射
level: {
[DictServiceEnum.LEVEL_LOW]: '低',
[DictServiceEnum.LEVEL_MEDIUM]: '中',
[DictServiceEnum.LEVEL_HIGH]: '高',
[DictServiceEnum.LEVEL_CRITICAL]: '紧急',
},
} as const;
/**
* DictService 工具类
*/
export class DictServiceEnumUtil {
/**
* 获取状态文本
*/
static getStatusText(status: DictServiceEnum): string {
return (dictServiceDict.status as any)[status] || '未知';
}
/**
* 获取类型文本
*/
static getTypeText(type: DictServiceEnum): string {
return (dictServiceDict.type as any)[type] || '未知';
}
/**
* 获取级别文本
*/
static getLevelText(level: DictServiceEnum): string {
return (dictServiceDict.level as any)[level] || '未知';
}
/**
* 获取所有状态选项
*/
static getStatusOptions(): Array<{ value: string; label: string }> {
return Object.entries(dictServiceDict.status).map(([value, label]) => ({
value,
label: label as string,
}));
}
/**
* 获取所有类型选项
*/
static getTypeOptions(): Array<{ value: string; label: string }> {
return Object.entries(dictServiceDict.type).map(([value, label]) => ({
value,
label: label as string,
}));
}
/**
* 获取所有级别选项
*/
static getLevelOptions(): Array<{ value: number; label: string }> {
return Object.entries(dictServiceDict.level).map(([value, label]) => ({
value: Number(value),
label: label as string,
}));
}
/**
* 验证状态值
*/
static isValidStatus(status: string): boolean {
return Object.values(DictServiceEnum).includes(status as DictServiceEnum);
}
/**
* 验证类型值
*/
static isValidType(type: string): boolean {
return Object.values(DictServiceEnum).includes(type as DictServiceEnum);
}
/**
* 验证级别值
*/
static isValidLevel(level: number): boolean {
return Object.values(DictServiceEnum).includes(level as DictServiceEnum);
}
}
/**
* DictService 类型定义
*/
export type DictServiceEnumStatus = keyof typeof dictServiceDict.status;
export type DictServiceEnumType = keyof typeof dictServiceDict.type;
export type DictServiceEnumLevel = keyof typeof dictServiceDict.level;

View File

@@ -0,0 +1,135 @@
/**
* Dict 枚举
* 定义相关的常量值
*/
export enum DictEnum {
// 状态枚举
STATUS_ACTIVE = 'active',
STATUS_INACTIVE = 'inactive',
STATUS_PENDING = 'pending',
STATUS_DELETED = 'deleted',
// 类型枚举
TYPE_NORMAL = 'normal',
TYPE_PREMIUM = 'premium',
TYPE_VIP = 'vip',
// 级别枚举
LEVEL_LOW = 1,
LEVEL_MEDIUM = 2,
LEVEL_HIGH = 3,
LEVEL_CRITICAL = 4,
}
/**
* Dict 字典映射
*/
export const dictDict = {
// 状态映射
status: {
[DictEnum.STATUS_ACTIVE]: '激活',
[DictEnum.STATUS_INACTIVE]: '未激活',
[DictEnum.STATUS_PENDING]: '待处理',
[DictEnum.STATUS_DELETED]: '已删除',
},
// 类型映射
type: {
[DictEnum.TYPE_NORMAL]: '普通',
[DictEnum.TYPE_PREMIUM]: '高级',
[DictEnum.TYPE_VIP]: 'VIP',
},
// 级别映射
level: {
[DictEnum.LEVEL_LOW]: '低',
[DictEnum.LEVEL_MEDIUM]: '中',
[DictEnum.LEVEL_HIGH]: '高',
[DictEnum.LEVEL_CRITICAL]: '紧急',
},
} as const;
/**
* Dict 工具类
*/
export class DictEnumUtil {
/**
* 获取状态文本
*/
static getStatusText(status: DictEnum): string {
return (dictDict.status as any)[status] || '未知';
}
/**
* 获取类型文本
*/
static getTypeText(type: DictEnum): string {
return (dictDict.type as any)[type] || '未知';
}
/**
* 获取级别文本
*/
static getLevelText(level: DictEnum): string {
return (dictDict.level as any)[level] || '未知';
}
/**
* 获取所有状态选项
*/
static getStatusOptions(): Array<{ value: string; label: string }> {
return Object.entries(dictDict.status).map(([value, label]) => ({
value,
label: label as string,
}));
}
/**
* 获取所有类型选项
*/
static getTypeOptions(): Array<{ value: string; label: string }> {
return Object.entries(dictDict.type).map(([value, label]) => ({
value,
label: label as string,
}));
}
/**
* 获取所有级别选项
*/
static getLevelOptions(): Array<{ value: number; label: string }> {
return Object.entries(dictDict.level).map(([value, label]) => ({
value: Number(value),
label: label as string,
}));
}
/**
* 验证状态值
*/
static isValidStatus(status: string): boolean {
return Object.values(DictEnum).includes(status as DictEnum);
}
/**
* 验证类型值
*/
static isValidType(type: string): boolean {
return Object.values(DictEnum).includes(type as DictEnum);
}
/**
* 验证级别值
*/
static isValidLevel(level: number): boolean {
return Object.values(DictEnum).includes(level as DictEnum);
}
}
/**
* Dict 类型定义
*/
export type DictEnumStatus = keyof typeof dictDict.status;
export type DictEnumType = keyof typeof dictDict.type;
export type DictEnumLevel = keyof typeof dictDict.level;

View File

@@ -0,0 +1,250 @@
import { Injectable, Logger } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { ConfigService } from '@nestjs/config';
import { BaseService } from '@wwjCommon/base/base.service';
import { CacheService } from '@wwjCommon/cache/cache.service';
import { LoggingService } from '@wwjCommon/logging/logging.service';
import { UploadService } from '@wwjVendor/upload/upload.service';
import { PayService } from '@wwjVendor/pay/pay.service';
import { SmsService } from '@wwjVendor/sms/sms.service';
import { NoticeService } from '@wwjVendor/notice/notice.service';
@Injectable()
export class DictService extends BaseService<any> {
private readonly logger = new Logger(DictService.name);
constructor(
@InjectRepository(Object)
protected readonly repository: Repository<any>,
private readonly cacheService: CacheService,
private readonly configService: ConfigService,
private readonly loggingService: LoggingService,
private readonly uploadService: UploadService,
private readonly payService: PayService,
private readonly smsService: SmsService,
private readonly noticeService: NoticeService,
) {
super(repository);
}
/**
* getPage
* 对应 PHP: DictService_admin::getPage()
* 逻辑类型: undefined - undefined
*/
async getPage(where: any[]) {
// 基于PHP真实逻辑: getPage
// PHP原文: $field = 'id,name,key,memo,create_time,update_time'; $order = 'id desc'; $search_model = $this->model->withSearch(["name","key"], $wh...
const field = 'id,name,key,memo,create_time,update_time';
const order = 'id desc';
const search_model = this.model.withSearch(["name","key"), where).field(field).order(order];
const list = this.pageQuery(search_model);
return list;
}
/**
* 获取数据字典信息
* @param int id
* @return */
async getInfo(int id)
{
const field = 'id,name,key,dictionary,memo,create_time,update_time';
const info = this.model.field(field).where([['id', '=', id))).findOrEmpty().toArray(];
if (info.dictionary === null) {
info.dictionary = [];
}
/**
* getInfo
* 对应 PHP: DictService_admin::getInfo()
* 逻辑类型: undefined - undefined
*/
async getInfo(id: number) {
// 基于PHP真实逻辑: getInfo
// PHP原文: $field = 'id,name,key,dictionary,memo,create_time,update_time'; $info = $this->model->field($field)->where([['id', '=', $id]])->findOrEmpty()...
const field = 'id,name,key,dictionary,memo,create_time,update_time';
const info = this.model.field(field).where([['id', '=', id))).findOrEmpty().toArray(];
if (info.dictionary === null) {
info.dictionary = [];
}
/**
* add
* 对应 PHP: DictService_admin::add()
* 逻辑类型: undefined - undefined
*/
async add(data: any[]) {
// 基于PHP真实逻辑: add
// PHP原文: $res = $this->model->create($data); return $res->id; } /** * 数据字典编辑 * @param int $id * @param array $data * @ret...
const res = this.model.create(data);
return res.id;
}
/**
* 数据字典编辑
* @param int id
* @param data
* @return bool
*/
async edit(int id, data)
{
data.update_time = time(];
this.model.where([['id', '=', id))).update(data);
return true;
}
/**
* 删除数据字典
* @param int id
* @return bool
*/
async del(int id)
{
const res = this.model.where([['id', '=', id))).delete(];
return res;
}
/**
* 获取全部数据字典
* @return * @throws DataNotFoundBusinessException
* @throws DbBusinessException
* @throws ModelNotFoundBusinessException
*/
async getAll()
{
const field = 'id,name,key,dictionary,memo,create_time,update_time';
const list = this.model.field(field).select().toArray(];
return list;
}
async getKeyInfo(key)
{
const field = 'id,name,key,dictionary,memo,create_time,update_time';
const info = this.model.field(field).where([['key', '=', key))).findOrEmpty().toArray(];
if (info.dictionary === null) {
info.dictionary = [];
}
/**
* edit
* 对应 PHP: DictService_admin::edit()
* 逻辑类型: undefined - undefined
*/
async edit(id: any[], data: any[]) {
// 基于PHP真实逻辑: edit
// PHP原文: $data['update_time'] = time(); $this->model->where([['id', '=', $id]])->update($data); return true; } /** * 删除数据字典 ...
data.update_time = time(];
this.model.where([['id', '=', id))).update(data);
return true;
}
/**
* 删除数据字典
* @param int id
* @return bool
*/
async del(int id)
{
const res = this.model.where([['id', '=', id))).delete(];
return res;
}
/**
* 获取全部数据字典
* @return * @throws DataNotFoundBusinessException
* @throws DbBusinessException
* @throws ModelNotFoundBusinessException
*/
async getAll()
{
const field = 'id,name,key,dictionary,memo,create_time,update_time';
const list = this.model.field(field).select().toArray(];
return list;
}
async getKeyInfo(key)
{
const field = 'id,name,key,dictionary,memo,create_time,update_time';
const info = this.model.field(field).where([['key', '=', key))).findOrEmpty().toArray(];
if (info.dictionary === null) {
info.dictionary = [];
}
/**
* del
* 对应 PHP: DictService_admin::del()
* 逻辑类型: undefined - undefined
*/
async del(id: number) {
// 基于PHP真实逻辑: del
// PHP原文: $res = $this->model->where([['id', '=', $id]])->delete(); return $res; } /** * 获取全部数据字典 * @return array * @throws Data...
const res = this.model.where([['id', '=', id))).delete(];
return res;
}
/**
* 获取全部数据字典
* @return * @throws DataNotFoundBusinessException
* @throws DbBusinessException
* @throws ModelNotFoundBusinessException
*/
async getAll()
{
const field = 'id,name,key,dictionary,memo,create_time,update_time';
const list = this.model.field(field).select().toArray(];
return list;
}
async getKeyInfo(key)
{
const field = 'id,name,key,dictionary,memo,create_time,update_time';
const info = this.model.field(field).where([['key', '=', key))).findOrEmpty().toArray(];
if (info.dictionary === null) {
info.dictionary = [];
}
/**
* getAll
* 对应 PHP: DictService_admin::getAll()
* 逻辑类型: undefined - undefined
*/
async getAll() {
// 基于PHP真实逻辑: getAll
// PHP原文: $field = 'id,name,key,dictionary,memo,create_time,update_time'; $list = $this->model->field($field)->select()->toArray(); return $list...
const field = 'id,name,key,dictionary,memo,create_time,update_time';
const list = this.model.field(field).select().toArray(];
return list;
}
async getKeyInfo(key)
{
const field = 'id,name,key,dictionary,memo,create_time,update_time';
const info = this.model.field(field).where([['key', '=', key))).findOrEmpty().toArray(];
if (info.dictionary === null) {
info.dictionary = [];
}
/**
* getKeyInfo
* 对应 PHP: DictService_admin::getKeyInfo()
* 逻辑类型: undefined - undefined
*/
async getKeyInfo(key: any) {
// 基于PHP真实逻辑: getKeyInfo
// PHP原文: $field = 'id,name,key,dictionary,memo,create_time,update_time'; $info = $this->model->field($field)->where([['key', '=', $key]])->findOrEmpty...
const field = 'id,name,key,dictionary,memo,create_time,update_time';
const info = this.model.field(field).where([['key', '=', key))).findOrEmpty().toArray(];
if (info.dictionary === null) {
info.dictionary = [];
}
}