feat: curd

This commit is contained in:
luchang 2024-05-22 19:13:08 +08:00
parent 410bfc1e38
commit 74c77011ea
27 changed files with 316 additions and 166 deletions

View File

@ -1,17 +1,15 @@
const productConfig = { const productConfig = {
accessKeyId: 'accessKeyId', accessKeyId: 'LTAI5tHfUhFjJ335EVo1vcWm',
accessKeySecret: 'accessKeySecret', accessKeySecret: '0q5JF4862ai5pznfIZMTIjThVjzaqK',
endpoint: 'endpoint', bucket: 'polaris-frontend',
bucket: 'bucket', dir: 'yitu_image/',
region: 'region',
}; };
const localConfig = { const localConfig = {
accessKeyId: 'accessKeyId', accessKeyId: 'LTAI5tHfUhFjJ335EVo1vcWm',
accessKeySecret: 'accessKeySecret', accessKeySecret: '0q5JF4862ai5pznfIZMTIjThVjzaqK',
endpoint: 'endpoint', bucket: 'polaris-frontend',
bucket: 'bucket', dir: 'yitu_image/',
region: 'region',
}; };
// 本地运行是没有 process.env.NODE_ENV 的,借此来区分[开发环境]和[生产环境] // 本地运行是没有 process.env.NODE_ENV 的,借此来区分[开发环境]和[生产环境]

View File

@ -27,6 +27,7 @@
"@nestjs/typeorm": "^10.0.2", "@nestjs/typeorm": "^10.0.2",
"@types/ali-oss": "^6.16.11", "@types/ali-oss": "^6.16.11",
"ali-oss": "^6.20.0", "ali-oss": "^6.20.0",
"dayjs": "^1.11.11",
"multer": "1.4.5-lts.1", "multer": "1.4.5-lts.1",
"mysql2": "^3.9.7", "mysql2": "^3.9.7",
"reflect-metadata": "^0.2.0", "reflect-metadata": "^0.2.0",

3
pnpm-lock.yaml generated
View File

@ -29,6 +29,9 @@ importers:
ali-oss: ali-oss:
specifier: ^6.20.0 specifier: ^6.20.0
version: 6.20.0 version: 6.20.0
dayjs:
specifier: ^1.11.11
version: 1.11.11
multer: multer:
specifier: 1.4.5-lts.1 specifier: 1.4.5-lts.1
version: 1.4.5-lts.1 version: 1.4.5-lts.1

View File

@ -1,10 +1,17 @@
import { Module } from '@nestjs/common'; import { Module } from '@nestjs/common';
import { AppController } from './app.controller'; import { AppController } from './app.controller';
import { AppService } from './app.service'; import { AppService } from './app.service';
import { UserEntity } from './user/entities/user.entity';
import { BannerEntity } from './banner/entities/banner.entity';
import { UserModule } from './user/user.module'; import { UserModule } from './user/user.module';
import { TypeOrmModule } from '@nestjs/typeorm'; import { TypeOrmModule } from '@nestjs/typeorm';
import { BannerModule } from './banner/banner.module'; import { BannerModule } from './banner/banner.module';
import { OssModule } from './oss/oss.module'; import { OssModule } from './oss/oss.module';
import { SysUserModule } from './sys-user/sys-user.module';
const ENTITIES = [UserEntity, BannerEntity];
const MODULE = [UserModule, BannerModule, OssModule];
@Module({ @Module({
imports: [ imports: [
@ -15,10 +22,11 @@ import { OssModule } from './oss/oss.module';
username: 'root', username: 'root',
password: '123456', password: '123456',
database: 'travel-app', database: 'travel-app',
entities: [UserModule], // 这里添加实体类 entities: ENTITIES, // 这里添加实体类
synchronize: true,
}), }),
BannerModule, ...MODULE,
OssModule, SysUserModule,
], ],
controllers: [AppController], controllers: [AppController],
providers: [AppService], providers: [AppService],

View File

@ -1,7 +1,6 @@
import { Controller, Get, Post, Body, Patch, Param, Delete } from '@nestjs/common'; import { Controller, Get, Post, Body, Param, Delete } from '@nestjs/common';
import { BannerService } from './banner.service'; import { BannerService } from './banner.service';
import { CreateBannerDto } from './dto/create-banner.dto'; import { CreateBannerDto } from './dto/create-banner.dto';
import { UpdateBannerDto } from './dto/update-banner.dto';
@Controller('banner') @Controller('banner')
export class BannerController { export class BannerController {
@ -22,11 +21,6 @@ export class BannerController {
return this.bannerService.findOne(+id); return this.bannerService.findOne(+id);
} }
@Patch(':id')
update(@Param('id') id: string, @Body() updateBannerDto: UpdateBannerDto) {
return this.bannerService.update(+id, updateBannerDto);
}
@Delete(':id') @Delete(':id')
remove(@Param('id') id: string) { remove(@Param('id') id: string) {
return this.bannerService.remove(+id); return this.bannerService.remove(+id);

View File

@ -1,8 +1,11 @@
import { Module } from '@nestjs/common'; import { Module } from '@nestjs/common';
import { BannerService } from './banner.service'; import { BannerService } from './banner.service';
import { BannerController } from './banner.controller'; import { BannerController } from './banner.controller';
import { TypeOrmModule } from '@nestjs/typeorm';
import { BannerEntity } from './entities/banner.entity';
@Module({ @Module({
imports: [TypeOrmModule.forFeature([BannerEntity])],
controllers: [BannerController], controllers: [BannerController],
providers: [BannerService], providers: [BannerService],
}) })

View File

@ -1,26 +1,34 @@
import { Injectable } from '@nestjs/common'; import { Injectable, NotFoundException } from '@nestjs/common';
import { Repository } from 'typeorm';
import { CreateBannerDto } from './dto/create-banner.dto'; import { CreateBannerDto } from './dto/create-banner.dto';
import { UpdateBannerDto } from './dto/update-banner.dto'; import { BannerEntity } from './entities/banner.entity';
import { InjectRepository } from '@nestjs/typeorm';
@Injectable() @Injectable()
export class BannerService { export class BannerService {
create(createBannerDto: CreateBannerDto) { constructor(
return 'This action adds a new banner'; @InjectRepository(BannerEntity)
private readonly bannerRepository: Repository<BannerEntity>,
) {}
async create(createBannerDto: CreateBannerDto) {
const res = await this.bannerRepository.create(createBannerDto);
await this.bannerRepository.save(res);
return res;
} }
findAll() { findAll() {
return `This action returns all banner`; return this.bannerRepository.find();
} }
findOne(id: number) { findOne(id: number) {
return `This action returns a #${id} banner`; return `This action returns a #${id} banner`;
} }
update(id: number, updateBannerDto: UpdateBannerDto) { async remove(id: number) {
return `This action updates a #${id} banner`; const result = await this.bannerRepository.delete(id);
if (result.affected === 0) {
throw new NotFoundException(`User with ID ${id} not found`);
} }
return result;
remove(id: number) {
return `This action removes a #${id} banner`;
} }
} }

View File

@ -1 +1,15 @@
export class Banner {} import { Entity, PrimaryGeneratedColumn, Column } from 'typeorm';
@Entity()
export class BannerEntity {
@PrimaryGeneratedColumn()
id: number;
@Column()
url: string;
@Column()
type: number;
@Column({ type: 'timestamp', default: () => 'CURRENT_TIMESTAMP' })
createTime: Date;
}

View File

@ -0,0 +1,22 @@
import {
ExceptionFilter,
Catch,
ArgumentsHost,
HttpException,
} from '@nestjs/common';
import { Response } from 'express';
@Catch(HttpException)
export class HttpExceptionFilter implements ExceptionFilter {
catch(exception: HttpException, host: ArgumentsHost) {
const ctx = host.switchToHttp();
const response = ctx.getResponse<Response>();
const status = exception.getStatus();
response.status(status).json({
code: 1,
message: '服务错误',
data: null,
});
}
}

View File

@ -1,8 +1,15 @@
import { NestFactory } from '@nestjs/core'; import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module'; import { AppModule } from './app.module';
import { HttpExceptionFilter } from './http-exception/http-exception.filter';
import { TransformInterceptor } from './transoform/transform.interceptor';
async function bootstrap() { async function bootstrap() {
const app = await NestFactory.create(AppModule); const app = await NestFactory.create(AppModule);
// 设置全局路由前缀,例如 'api'
app.setGlobalPrefix('api');
app.enableCors();
app.useGlobalFilters(new HttpExceptionFilter());
app.useGlobalInterceptors(new TransformInterceptor());
await app.listen(3000); await app.listen(3000);
} }
bootstrap(); bootstrap();

View File

@ -1,34 +1,17 @@
import { import { Controller, Get } from '@nestjs/common';
Controller,
Post,
UseInterceptors,
UploadedFile,
} from '@nestjs/common';
import { FileInterceptor } from '@nestjs/platform-express';
import { UploadService } from '../upload/upload.server';
import multer = require('multer');
@Controller('demo') import { OssService } from './oss.service';
@Controller()
export class OssController { export class OssController {
constructor(private readonly uploadService: UploadService) {} constructor(private readonly uploadService: OssService) {}
/** /**
* oss * oss签名
* @param body * @returns
*/ */
@Post('uploadImage') @Get('signature')
@UseInterceptors( getOssSignature() {
FileInterceptor('file', { return this.uploadService.getSignature();
storage: multer.diskStorage({
destination: (req, file, cb) => {
cb(null, 'D:/oss/image');
},
filename: (req, file, cb) => {
cb(null, file.originalname);
},
}),
}),
)
async uploadImage(@UploadedFile() file: any): Promise<any> {
return await this.uploadService.uploadImage(file);
} }
} }

View File

@ -1,10 +1,9 @@
import { Module } from '@nestjs/common'; import { Module } from '@nestjs/common';
import { OssService } from './oss.service'; import { OssService } from './oss.service';
import { OssController } from './oss.controller'; import { OssController } from './oss.controller';
import { UploadService } from '../upload/upload.server';
@Module({ @Module({
controllers: [OssController], controllers: [OssController],
providers: [OssService, UploadService], providers: [OssService],
}) })
export class OssModule {} export class OssModule {}

View File

@ -1,80 +1,38 @@
import * as OSS from 'ali-oss'; import * as OSS from 'ali-oss';
import { Injectable } from '@nestjs/common'; import { Injectable } from '@nestjs/common';
import ossConfig from '../../config/oss'; import ossConfig from '../../config/oss';
import * as dayjs from 'dayjs';
@Injectable() @Injectable()
export class OssService { export class OssService {
private client: any; async getSignature() {
public constructor() { const config = {
this.client = new OSS({ // 填写你自己的 AccessKey
accessKeyId: ossConfig.accessKeyId, accessKeyId: ossConfig.accessKeyId,
accessKeySecret: ossConfig.accessKeySecret, accessKeySecret: ossConfig.accessKeySecret, // 存储桶名字
region: ossConfig.region, bucket: ossConfig.bucket, // 文件存储路径
bucket: ossConfig.bucket, dir: ossConfig.dir,
}); };
} const client = new OSS(config);
// 创建存储空间。 const date = new Date(); // 时长加 1 天,作为签名的有限期
private async putBucket() { date.setDate(date.getDate() + 1);
try { const policy = {
const result = await this.client.putBucket('test'); // 设置签名的有效期格式为Unix时间戳
console.log(result); expiration: date.toISOString(),
} catch (err) { conditions: [
console.log(err); ['content-length-range', 0, 10485760000], // 设置上传文件的大小限制
} ],
} }; // 生成签名,策略等信息
// 列举所有的存储空间 const formData = await client.calculatePostSignature(policy); // 生成 bucket 域名,客户端将向此地址发送请求
private async listBuckets() { const location = await client.getBucketLocation(ossConfig.bucket);
try { const host = `https://${config.bucket}.${location.location}.aliyuncs.com`; // 响应给客户端的签名和策略等信息
const result = await this.client.listBuckets(); return {
console.log(result); expire: dayjs().add(1, 'days').unix().toString(),
} catch (err) { policy: formData.policy,
console.log(err); signature: formData.Signature,
} accessId: formData.OSSAccessKeyId,
} host,
// 上传文件到oss 并返回 图片oss 地址 dir: config.dir,
public async putOssFile(ossPath: string, localPath: string): Promise<string> { };
let res: any;
try {
res = await this.client.put(ossPath, localPath);
// 将文件设置为公共可读
await this.client.putACL(ossPath, 'public-read');
} catch (error) {
console.log(error);
}
return res.url;
}
/**
* url
* @param filePath
*/
public async getFileSignatureUrl(filePath: string): Promise<string> {
if (filePath == null) {
console.log('get file signature failed: file name can not be empty');
return null;
}
let result = '';
try {
result = this.client.signatureUrl(filePath, { expires: 36000 });
} catch (err) {
console.log(err);
}
return result;
}
/**
*
* @param localPath
* @param ossPath
* @param size
*/
public async validateFile(
ossPath: string,
localPath: string,
size: number,
): Promise<string> {
if (size > 5 * 1024 * 1024) {
return;
} else {
return await this.putOssFile(ossPath, localPath);
}
} }
} }

View File

@ -0,0 +1 @@
export class CreateSysUserDto {}

View File

@ -0,0 +1,4 @@
import { PartialType } from '@nestjs/mapped-types';
import { CreateSysUserDto } from './create-sys-user.dto';
export class UpdateSysUserDto extends PartialType(CreateSysUserDto) {}

View File

@ -0,0 +1,13 @@
import { Entity, PrimaryGeneratedColumn, Column } from 'typeorm';
@Entity()
export class SysUserEntity {
@PrimaryGeneratedColumn()
id: number;
@Column()
name: string;
@Column()
password: string;
}

View File

@ -0,0 +1,20 @@
import { Test, TestingModule } from '@nestjs/testing';
import { SysUserController } from './sys-user.controller';
import { SysUserService } from './sys-user.service';
describe('SysUserController', () => {
let controller: SysUserController;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
controllers: [SysUserController],
providers: [SysUserService],
}).compile();
controller = module.get<SysUserController>(SysUserController);
});
it('should be defined', () => {
expect(controller).toBeDefined();
});
});

View File

@ -0,0 +1,42 @@
import {
Controller,
Get,
Post,
Body,
Patch,
Param,
Delete,
} from '@nestjs/common';
import { SysUserService } from './sys-user.service';
import { CreateSysUserDto } from './dto/create-sys-user.dto';
import { UpdateSysUserDto } from './dto/update-sys-user.dto';
@Controller('sys-user')
export class SysUserController {
constructor(private readonly sysUserService: SysUserService) {}
@Post()
create(@Body() createSysUserDto: CreateSysUserDto) {
return this.sysUserService.create(createSysUserDto);
}
@Get()
findAll() {
return this.sysUserService.findAll();
}
@Get(':id')
findOne(@Param('id') id: string) {
return this.sysUserService.findOne(+id);
}
@Patch(':id')
update(@Param('id') id: string, @Body() updateSysUserDto: UpdateSysUserDto) {
return this.sysUserService.update(+id, updateSysUserDto);
}
@Delete(':id')
remove(@Param('id') id: string) {
return this.sysUserService.remove(+id);
}
}

View File

@ -0,0 +1,9 @@
import { Module } from '@nestjs/common';
import { SysUserService } from './sys-user.service';
import { SysUserController } from './sys-user.controller';
@Module({
controllers: [SysUserController],
providers: [SysUserService],
})
export class SysUserModule {}

View File

@ -0,0 +1,18 @@
import { Test, TestingModule } from '@nestjs/testing';
import { SysUserService } from './sys-user.service';
describe('SysUserService', () => {
let service: SysUserService;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [SysUserService],
}).compile();
service = module.get<SysUserService>(SysUserService);
});
it('should be defined', () => {
expect(service).toBeDefined();
});
});

View File

@ -0,0 +1,26 @@
import { Injectable } from '@nestjs/common';
import { CreateSysUserDto } from './dto/create-sys-user.dto';
import { UpdateSysUserDto } from './dto/update-sys-user.dto';
@Injectable()
export class SysUserService {
create(createSysUserDto: CreateSysUserDto) {
return 'This action adds a new sysUser';
}
findAll() {
return `This action returns all sysUser`;
}
findOne(id: number) {
return `This action returns a #${id} sysUser`;
}
update(id: number, updateSysUserDto: UpdateSysUserDto) {
return `This action updates a #${id} sysUser`;
}
remove(id: number) {
return `This action removes a #${id} sysUser`;
}
}

View File

@ -0,0 +1,23 @@
import {
Injectable,
NestInterceptor,
ExecutionContext,
CallHandler,
} from '@nestjs/common';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
@Injectable()
export class TransformInterceptor implements NestInterceptor {
intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
return next.handle().pipe(
map((data) => {
return {
code: 0,
data,
message: null,
};
}),
);
}
}

View File

@ -1,26 +0,0 @@
import { Injectable } from '@nestjs/common';
import { OssService } from '../oss/oss.service';
@Injectable()
export class UploadService {
constructor(private readonly ossService: OssService) {}
// 上传照片
async uploadImage(file: any): Promise<any> {
try {
const ossUrl = await this.ossService.putOssFile(
`/image/${file.originalname}`,
`D:/oss/image/${file.originalname}`,
);
return {
code: 200,
data: ossUrl,
message: '上传成功',
};
} catch (error) {
return {
code: 503,
msg: `Service error: ${error}`,
};
}
}
}

View File

@ -1,7 +1,7 @@
import { Entity, PrimaryGeneratedColumn, Column } from 'typeorm'; import { Entity, PrimaryGeneratedColumn, Column } from 'typeorm';
@Entity() @Entity()
export class User { export class UserEntity {
@PrimaryGeneratedColumn() @PrimaryGeneratedColumn()
id: number; id: number;

View File

@ -16,8 +16,8 @@ export class UserController {
constructor(private readonly userService: UserService) {} constructor(private readonly userService: UserService) {}
@Post() @Post()
create(@Body() createUserDto: CreateUserDto) { async create(@Body() createUserDto: CreateUserDto) {
return this.userService.create(createUserDto); return await this.userService.create(createUserDto);
} }
@Get() @Get()
@ -25,6 +25,11 @@ export class UserController {
return this.userService.findAll(); return this.userService.findAll();
} }
@Post('/login')
async login(@Body() user: any) {
return await this.userService.login(user);
}
@Get(':id') @Get(':id')
findOne(@Param('id') id: string) { findOne(@Param('id') id: string) {
return this.userService.findOne(+id); return this.userService.findOne(+id);

View File

@ -1,8 +1,11 @@
import { Module } from '@nestjs/common'; import { Module } from '@nestjs/common';
import { UserService } from './user.service'; import { UserService } from './user.service';
import { UserEntity } from './entities/user.entity';
import { UserController } from './user.controller'; import { UserController } from './user.controller';
import { TypeOrmModule } from '@nestjs/typeorm';
@Module({ @Module({
imports: [TypeOrmModule.forFeature([UserEntity])],
controllers: [UserController], controllers: [UserController],
providers: [UserService], providers: [UserService],
}) })

View File

@ -1,18 +1,30 @@
import { Injectable, NotFoundException } from '@nestjs/common'; import { Injectable, NotFoundException } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm'; import { Repository } from 'typeorm';
import { User } from './entities/user.entity'; import { UserEntity } from './entities/user.entity';
import { CreateUserDto } from './dto/create-user.dto'; import { CreateUserDto } from './dto/create-user.dto';
import { UpdateUserDto } from './dto/update-user.dto'; import { UpdateUserDto } from './dto/update-user.dto';
@Injectable() @Injectable()
export class UserService { export class UserService {
private readonly userRepository: Repository<User>; constructor(
async create(createUserDto: CreateUserDto): Promise<User> { @InjectRepository(UserEntity)
private readonly userRepository: Repository<UserEntity>,
) {}
async create(createUserDto: CreateUserDto): Promise<UserEntity> {
const newUser = await this.userRepository.create(createUserDto); const newUser = await this.userRepository.create(createUserDto);
await this.userRepository.save(newUser); await this.userRepository.save(newUser);
return newUser; return newUser;
} }
async login(user: any) {
return {
status: 'ok',
...user,
};
}
findAll() { findAll() {
return this.userRepository.find(); return this.userRepository.find();
} }
@ -30,7 +42,8 @@ export class UserService {
id, id,
}, },
}); });
return this.userRepository.merge(oldData, updateUserDto); const mergedData = this.userRepository.merge(oldData, updateUserDto);
return await this.userRepository.save(mergedData);
} }
async remove(id: number) { async remove(id: number) {
@ -38,5 +51,6 @@ export class UserService {
if (result.affected === 0) { if (result.affected === 0) {
throw new NotFoundException(`User with ID ${id} not found`); throw new NotFoundException(`User with ID ${id} not found`);
} }
return result;
} }
} }