Skip to content

NestJS-群组模块

1、模块文件搭建

javascript
nest g controller modules/group --no-spec
nest g module modules/group --no-spec
nest g service modules/group --no-spec

生成的文件

javascript
group.controller.ts
group.module.ts
group.service.ts

2、模块实体创建

创建聊天消息实体(Entity): 我们需要定义一个数据库sys_group表来存储消息

👉sql数据

javascript
CREATE TABLE `sys_group`  (
  `group_id` int(0) NOT NULL AUTO_INCREMENT COMMENT '主键列群组ID',
  `group_name` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_bin NULL DEFAULT NULL COMMENT '群组名称',
  `group_description` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_bin NULL DEFAULT NULL COMMENT '群组描述',
  `creator_userid` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_bin NULL DEFAULT NULL COMMENT '群主ID',
  `member_count` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_bin NULL DEFAULT NULL COMMENT '群组成员数量',
  `status` enum('active','inactive','deleted') CHARACTER SET utf8mb3 COLLATE utf8mb3_bin NOT NULL DEFAULT 'active',
  `isDeleted` tinyint(0) NOT NULL DEFAULT 0,
  `create_time` timestamp(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0) COMMENT '群创建时间',
  `update_time` timestamp(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0) ON UPDATE CURRENT_TIMESTAMP(0) COMMENT '群更新时间',
  PRIMARY KEY (`group_id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb3 COLLATE = utf8mb3_bin ROW_FORMAT = Dynamic;

👉 goup.entity.ts

javascript
import { Entity, PrimaryGeneratedColumn, Column,CreateDateColumn, UpdateDateColumn } from 'typeorm';
import { format } from "date-fns";

@Entity('sys_group')
export class SysGruop {
  @PrimaryGeneratedColumn({ name: 'group_id', comment: '主键列群组ID' }) // 设置主键列
  groupId: number;

  @Column({ nullable: true, name: 'group_name', comment: '群组名称' })
  groupName: string;
  
  @Column({ nullable: true, name: 'group_description', comment: '群组描述' })
  groupDescription: string;

  @Column({ nullable: true, name: 'creator_userid', comment: '群主ID' })
  creatorUserId: string;

  @Column({ nullable: true, name: 'member_count', comment: '群组成员数量' })
  memberCount: string;

   @Column({
    type: 'enum',
    enum: ['active', 'inactive', 'deleted'],
    default: 'active',
  })
  status: 'active' | 'inactive' | 'deleted';

  @Column({ type: 'boolean', default: false })
  isDeleted: boolean;

  @Column({
    type: "timestamp",
    default: () => "CURRENT_TIMESTAMP", // 数据库自动设置创建时间
    transformer: {
      to: (value: Date) => value, // 写入数据库时保持 Date 类型
      from: (value: Date) => 
        value ? format(new Date(value), "yyyy-MM-dd HH:mm:ss") : null, // 读取时转为字符串
    },
    comment: '群创建时间',
    name: 'create_time',
  })
  createTime: Date; // 类型保持为 Date
  
  @Column({
    type: "timestamp",
    default: () => "CURRENT_TIMESTAMP", // 默认值
    onUpdate: "CURRENT_TIMESTAMP", // 关键配置,确保更新时间字段自动更新
    transformer: {
      to: (value: Date) => value,
      from: (value: Date) => 
        value ? format(new Date(value), "yyyy-MM-dd HH:mm:ss") : null,
    },
    comment: '群更新时间',
    name: 'update_time',
  })
  updateTime: Date; // 类型保持为 Date
}

👉主模块引入

common => entity=> index.ts

javascript
import { SysGruop } from './group.entity';

entities: [User, SysChat,SysGruop],

👉 引入实体和控制器

group.module.ts导入需要的部分然后进行导出

javascript
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';

import { GroupService } from './group.service';
import { GroupController } from './group.controller';
import { SysGruop } from './group.entity';

@Module({
  imports: [TypeOrmModule.forFeature([SysGruop])],  // 导入实体
  controllers: [GroupController],               // 注册控制器
  providers: [GroupService],                // 注册服务
  exports: [GroupService] // 导出服务
})
export class GroupModule { }

3、模块功能

增加

👉group.controller.ts

javascript

import { Controller, Get, Post, Body, Param, Put, Delete,Injectable} from '@nestjs/common';
import { ApiOperation, ApiQuery, ApiResponse } from '@nestjs/swagger';
import { Repository } from 'typeorm';

import { GroupService } from './group.service';
import { SysGruop } from './group.entity';

@Controller('groups')
export class GroupController {
    constructor(private readonly groupService) {}

    // 创建群组 : Promise<Group> 
    @ApiOperation({ summary: '新增' }) // 操作描述
    @Post()
    async create(@Body() addFormData){
      const { username, password, name, phone, age, sex,avatar} = addFormData;
      const addData = addFormData;
      return this.groupService.create(addFormData);
    }
}

👉 group.service.ts

这里我们先简单填写一下我们的方法逻辑

javascript
async addOne(addFormData){
  // 通用添加
  const resdata = await addApi(this.groupRepository,addFormData);
  return resdata;
}

// 这里的addApi大致内容如下
const user = await this.groupRepository.create({ ...addFormData });
  const savedUser = await this.groupRepository.save(user);
  console.log(savedUser,'savedUser');
  if(savedUser){
    return {
      message: '添加成功!',
      code: 200,
    };
  }else{
    return {
      message: '添加失败!',
      code: 500,
    };
  }

👉 调用接口

这个时候我们调用接口,返回的信息如下,新增接口就成功了

javascript
{
    "message": "添加成功!",
    "code": 200
}

查找

👉group.service.ts

这里我们先简单填写一下我们的方法逻辑

javascript
// 获取群组列表
async getAll(pageNum: number, pageSize: number, queryParams: any) {
  // 通用分页查询
  const where = await getListApi(this.groupRepository, pageNum, pageSize, queryParams);
  return where;
}

👉group.controller.ts

javascript
@Get('/system/groups')
@ApiOperation({ summary: '获取列表带分页' }) // 操作描述
@ApiQuery({ name: 'pageNum', required: false, description: 'Page number', example: 1 })  // pageNum参数
@ApiQuery({ name: 'pageSize', required: false, description: 'Number of items per page', example: 10 })  // pageSize参数
@ApiQuery({ name: 'groupName', required: false, description: '群组名称', example: 'John' })  // search参数
// 获取列表带分页
async getAll(
  @Query('pageNum') pageNum = 1,  // 默认第1页
  @Query('pageSize') pageSize = 10, // 默认每页10条
  @Query('groupName') groupName?: string,  // 
) {
  // const queryParams: QueryParams = { name, phone, age, sex };
  const queryParams = { groupName };
  const ResponseData = await this.groupService.getAll(pageNum, pageSize, queryParams);
  return ResponseData;
}

👉 调用接口

这个时候我们调用接口,返回的信息如下,查询接口ok

javascript
{
    "message": "查询成功!",
    "code": 200,
    "data": [
        {
            "groupId": 1,
            "groupName": "Zero",
            "groupDescription": "Zero Group",
            "creatorUserId": "1",
            "memberCount": "2",
            "status": "active",
            "isDeleted": false,
            "createTime": "2025-05-14 17:27:47",
            "updateTime": "2025-05-14 17:27:47"
        },
        {
            "groupId": 2,
            "groupName": "Zero",
            "groupDescription": "Zero Group",
            "creatorUserId": "1",
            "memberCount": "2",
            "status": "active",
            "isDeleted": false,
            "createTime": "2025-05-14 17:48:37",
            "updateTime": "2025-05-14 17:48:37"
        },
    ],
    "total": 2
}

详情

👉group.controller.ts

javascript
// 查询单个
  @Get('/system/groups/:id')
  @ApiOperation({ summary: '查询单个' }) // 操作描述
  async getOne(@Param('id') id: string) {
    return this.groupService.getOne(id);
  }

👉 group.service.ts

这里我们先简单填写一下我们的方法逻辑

javascript
// 根据 ID 获取单个消息
  async findOne(chatId: number){
    return this.chatRepository.findOne({ where: { chatId } });
  }

👉 调用接口

这个时候我们调用接口,返回的信息如下,查询接口ok

javascript
{
    "chatId": 1,
    "senderUserId": "57",
    "receiverUserId": "user123",
    "chatType": "single",
    "content": "Hello, how are you?",
    "messageType": "text",
    "status": "sent",
    "attachments": null,
    "groupId": null,
    "groupName": null,
    "isSystem": false,
    "isDeleted": false,
    "createTime": "2025-05-13 16:15:09",
    "updateTime": "2025-05-13 16:15:09",
    "senderUserAvatar": null,
    "senderUserName": null
}

更新

👉group.controller.ts

javascript
// 更新
  @Put('/system/groups')
  @ApiOperation({ summary: '更新' }) // 操作描述
  async updateOne(
    @Body('groupId') groupId: string,
    @Body('groupName') groupName: string,
    @Body('groupDescription') groupDescription: string,
    @Body('status') status: string,
    @Body('isDeleted') isDeleted: number,
  ) {
    const updateFormData: updateFormDataParams = {
      groupName,
      groupDescription,
      status,
      isDeleted,
    }
    console.log(updateFormData, 'updateFormData');
    return this.groupService.updateOne(groupId,updateFormData);
  }

👉 group.service.ts

这里我们先简单填写一下我们的方法逻辑

javascript
// 更新群组
  async updateOne(id,updateFormData) {
    // 通用更新
    const resdata = await updateOneApi(this.groupRepository,updateFormData,{groupId:id});
    return resdata;
  }

👉updateOneApi方法

javascript
export const updateOneApi = async (Repository,updateFormData: any, queryParams: any) => {
 const resData = await Repository.findOneBy(queryParams);
    if (!resData) {
      return {
        code: 404,
        message: '数据不存在!',
        data: null,
      };
    }else{
      // 合并更新的数据 -确保更新时间是最新的
      const updatedData = { ...resData, ...updateFormData, updateTime: new Date() };
      // console.log(updatedData, 'updatedData-----------更新用户信息');
      const result = await Repository.save(updatedData);
      if (result) {
        return {
          code: 200,
          message: '更新成功',
        };
      }else {
        return {
          code: 500,
          message: '更新失败',
        };
      }
    }
}

👉 调用接口

这个时候我们调用接口,返回的信息如下,查询接口ok

javascript
{
    "code": 200,
    "message": "更新成功"
}

删除(软删除)

删除部分我们一般只是做一个假的删除部分,俗称软删除

👉group.controller.ts

javascript
// 删除
@Delete('/system/groups/:id')
@ApiOperation({ summary: '删除' }) // 操作描述
async deleteOne(@Param('id') id: number) {
  return this.groupService.deleteOne(id);
}

👉 group.service.ts

这里我们先简单填写一下我们的方法逻辑

javascript
// 删除群组
  async deleteOne(id) {
    // 通用删除
    const resdata = await deleteOneApi(this.groupRepository,{groupId:id});
    return resdata;
  }

👉deleteOneApi方法

javascript
// 删除消息(软删除)
export const deleteOneApi = async (Repository,queryParams: any) => {
  const findData = await Repository.findOne(queryParams);
  if (findData) {
    const delUpdateData = {...findData,isDeleted: true};
    const delData = await Repository.save(delUpdateData);
    if( delData) {
      return {
        code: 200,
        message: '删除成功',
      };
    }else {
      return {
        code: 200,
        message: '删除失败',
      };
    }
  } else {
    return {
      code: 401,
      message: '请检查数据状态!',
    };
  }
}

👉 调用接口

这个时候我们调用接口,返回的信息如下,查询接口ok

javascript
{
    "code": 200,
    "message": "更新成功"
}

Released under the MIT License.