# 一、 group表(群主表)字段设计

字段名 数据类型及描述

默认值

字段含义

id INTEGER(20).UNSIGNED
主键、自增长、UNSIGNED无符号
主键id
uuid string(36)唯一群标识 唯一群标识ID(UUID)
user_id INTEGER(20).UNSIGNED 群主id(关联用户表user的id)
name STRING(50) 群名称
avatar STRING(4000) 如:https://docs-51yrc-com.oss-cn-hangzhou.aliyuncs.com/
chat/group.png
群头像地址(本地、网络图片地址)
remark text '' 群公告
... 随着业务需求增加字段
invite_confirm TINYINT(1) 0 是否需要管理员确认才能进群(0-不需要 1- 需要管理员确认 2-其他情况)
... 随着业务需求增加字段
status TINYINT(1) 1 群状态(0-禁用 1-正常 2-锁定)
order int(11) 50 排序,默认50
create_time DATE CURRENT_TIMESTAMP 数据创建时间
update_time DATE CURRENT_TIMESTAMP 更新时间
  1. 直接在phpMyAdmin中根据表字段设计创建表,或者通过数据库插件写sql语句创建表。
  2. 通过迁移命名创建group表:
  1. 创建迁移文件 命令:
npx sequelize migration:generate --name=group
  1. 创建迁移文件 group.js,内容如下:
'use strict';

/** @type {import('sequelize-cli').Migration} */
module.exports = {
  async up(queryInterface, Sequelize) {
    const { INTEGER, STRING, DATE, TEXT, TINYINT, ENUM, BOOLEAN } = Sequelize;
    await queryInterface.createTable('group', {
      id: {
        type: INTEGER(20).UNSIGNED,
        primaryKey: true,
        autoIncrement: true,
        comment: '主键id'
      },
      uuid: {
        type: STRING(36),
        allowNull: false,
        unique: true,
        comment: '唯一群标识ID(UUID)'
      },
      user_id: {
        type: INTEGER(20).UNSIGNED,
        allowNull: false,
        comment: '群主id',
        references: { //关联关系
          model: 'user', //关联的表
          key: 'id' //关联表的主键
        },
        onDelete: 'CASCADE', //删除时操作
        onUpdate: 'RESTRICT', // 更新时操作
      },
      name: {
        type: STRING(50),
        allowNull: false,
        unique: false, //群名称可以不唯一
        comment: '群名称'
      },
      avatar: {
        type: STRING(4000),
        allowNull: true,
        defaultValue: 'https://docs-51yrc-com.oss-cn-hangzhou.aliyuncs.com/chat/group.png',
        comment: '群头像(本地、网络图片地址)'
      },
      remark: {
        type: TEXT,
        allowNull: true,
        defaultValue: '',
        comment: '群公告'
      },
      invite_confirm: {
        type: TINYINT(1),
        allowNull: false,
        defaultValue: 0,
        comment: '是否需要管理员确认才能进群(0-不需要 1- 需要管理员确认 2-其他情况)'
      },
      status: {
        type: TINYINT(1),
        allowNull: false,
        defaultValue: 1,
        comment: '群状态(0-禁用 1-正常 2-锁定)'
      },
      order: {
        type: INTEGER,//不限定长度.默认int(11)
        allowNull: true,
        defaultValue: 50,
        comment: '排序,默认50'
      },
      // sex: { type: ENUM, values: ['男','女','保密'], allowNull: true, defaultValue: '保密', comment: '留言用户性别'},
      create_time: {type: DATE, allowNull: false, defaultValue:Sequelize.fn('NOW')},
      update_time: {
        type: DATE,
        allowNull: false,
        defaultValue: Sequelize.literal('CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP'),
        comment: '更新时间'
      },
    });
    // 添加索引优化查询
    await queryInterface.addIndex('group', ['uuid']);
    await queryInterface.addIndex('group', ['user_id']);

  },

  async down(queryInterface, Sequelize) {
    await queryInterface.dropTable('group');
  }
};

  1. 执行迁移文件命令生成数据库表:
// 创建数据库表
npx sequelize db:migrate
// 如果有问题需要回滚,可以通过 `db:migrate:undo` 回退一个变更
npx sequelize db:migrate:undo
// 可以通过 `db:migrate:undo:all` 回退到初始状态
npx sequelize db:migrate:undo:all

# group表模型

app/model/group.js

'use strict';
//哈希函数 
// const crypto = require('node:crypto');
// 引入 uuid 库 `npm install uuid`
const { v4: uuidv4 } = require('uuid');

module.exports = app => {
    const { INTEGER, STRING, DATE, TEXT, TINYINT, ENUM, BOOLEAN } = app.Sequelize;

    const Group = app.model.define('group', {
        id: {
            type: INTEGER(20).UNSIGNED,
            primaryKey: true,
            autoIncrement: true,
            comment: '主键ID'
        },
        uuid: {
            type: STRING(36),
            allowNull: false,
            unique: true,
            comment: '唯一群标识ID(UUID)',
            defaultValue: () => uuidv4(), // 自动生成 UUID
        },
        user_id: {
            type: INTEGER(20).UNSIGNED,
            allowNull: false,
            comment: '群主id',
            references: { //关联关系
                model: 'user', //关联的表
                key: 'id' //关联表的主键
            },
            onDelete: 'CASCADE', //删除时操作
            onUpdate: 'RESTRICT', // 更新时操作
        },
        name: {
            type: STRING(50),
            allowNull: false,
            unique: false, //群名称可以不唯一
            comment: '群名称'
        },
        avatar: {
            type: STRING(4000),
            allowNull: true,
            defaultValue: 'https://docs-51yrc-com.oss-cn-hangzhou.aliyuncs.com/chat/group.png',
            comment: '群头像(本地、网络图片地址)'
        },
        remark: {
            type: TEXT,
            allowNull: true,
            defaultValue: '',
            comment: '群公告'
        },
        invite_confirm: {
            type: TINYINT(1),
            allowNull: false,
            defaultValue: 0,
            comment: '是否需要管理员确认才能进群(0-不需要 1- 需要管理员确认 2-其他情况)'
        },
        status: {
            type: TINYINT(1),
            allowNull: false,
            defaultValue: 1,
            comment: '群状态(0-禁用 1-正常 2-锁定)'
        },
        order: {
            type: INTEGER,//不限定长度.默认int(11)
            allowNull: true,
            defaultValue: 50,
            comment: '排序,默认50'
        },
        // sex: { type: ENUM, values: ['男','女','保密'], allowNull: true, defaultValue: '保密', comment: '留言用户性别'},
        create_time: {
            type: DATE,
            allowNull: false,
            defaultValue: app.Sequelize.fn('NOW'),
            get() {
                return app.formatTime(this.getDataValue('create_time'));
            }
        },
        update_time: { type: DATE, allowNull: false, defaultValue: app.Sequelize.fn('NOW') },
    });

    // 模型关联
    Group.associate = function (models) {
        // 关联user 反向一对多
        Group.belongsTo(app.model.User, {
            foreignKey: 'user_id', //外键
            //as: 'user', //别名
        });

        // 关联group_user 一对多
        Group.hasMany(app.model.GroupUser);
    };

    return Group;
}

# 二、 group_user表(群用户关联表)字段设计

字段名 数据类型及描述

默认值

字段含义

id INTEGER(20).UNSIGNED
主键、自增长、UNSIGNED无符号
主键id
group_id INTEGER(20).UNSIGNED 群id(关联group表的id)
user_id INTEGER(20).UNSIGNED 用户id(关联用户表user的id)
nickname STRING(50) '' 在群里的称呼(默认为空,则默认为用户账户昵称或者账号)
avatar STRING(1000) '' 在群里面的头像地址(本地、网络图片地址)(默认为空,则默认为用户账户头像)
... 随着业务需求增加字段
status TINYINT(1) 1 用户在群里面的状态(0-禁用 1-正常 2-锁定)
order int(11) 50 排序,默认50
create_time DATE CURRENT_TIMESTAMP 数据创建时间
update_time DATE CURRENT_TIMESTAMP 更新时间
  1. 直接在phpMyAdmin中根据表字段设计创建表,或者通过数据库插件写sql语句创建表。
  2. 通过迁移命名创建group_user表:
  1. 创建迁移文件 命令:
npx sequelize migration:generate --name=group_user
  1. 创建迁移文件 group_user.js,内容如下:
'use strict';

/** @type {import('sequelize-cli').Migration} */
module.exports = {
  async up(queryInterface, Sequelize) {
    const { INTEGER, STRING, DATE, TEXT, TINYINT, ENUM, BOOLEAN } = Sequelize;
    await queryInterface.createTable('group_user', {
      id: {
        type: INTEGER(20).UNSIGNED,
        primaryKey: true,
        autoIncrement: true,
        comment: '主键id'
      },
      group_id: {
        type: INTEGER(20).UNSIGNED,
        allowNull: false,
        comment: '群id(关联group表的id)',
        references: { //关联关系
          model: 'group', //关联的表
          key: 'id' //关联表的主键
        },
        onDelete: 'CASCADE', //删除时操作
        onUpdate: 'RESTRICT', // 更新时操作
      },
      user_id: {
        type: INTEGER(20).UNSIGNED,
        allowNull: false,
        comment: '用户id',
        references: { //关联关系
          model: 'user', //关联的表
          key: 'id' //关联表的主键
        },
        onDelete: 'CASCADE', //删除时操作
        onUpdate: 'RESTRICT', // 更新时操作
      },
      nickname: {
        type: STRING(50),
        allowNull: true,
        unique: false, //群称呼可以不唯一
        comment: '在群里的称呼(默认为空,则默认为用户账户昵称或者账号)',
        defaultValue: '',
      },
      avatar: {
        type: STRING(1000),
        allowNull: true,
        defaultValue: '',
        comment: '在群里面的头像地址(本地、网络图片地址)(默认为空,则默认为用户账户头像)'
      },
      status: {
        type: TINYINT(1),
        allowNull: false,
        defaultValue: 1,
        comment: '用户在群里面的状态(0-禁用 1-正常 2-锁定)'
      },
      order: {
        type: INTEGER,//不限定长度.默认int(11)
        allowNull: true,
        defaultValue: 50,
        comment: '排序,默认50'
      },
      // sex: { type: ENUM, values: ['男','女','保密'], allowNull: true, defaultValue: '保密', comment: '留言用户性别'},
      create_time: { type: DATE, allowNull: false, defaultValue: Sequelize.fn('NOW') },
      update_time: {
        type: DATE,
        allowNull: false,
        defaultValue: Sequelize.literal('CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP'),
        comment: '更新时间'
      },
    });

    // 添加索引优化查询
    await queryInterface.addIndex('group_user', ['group_id']);
    await queryInterface.addIndex('group_user', ['user_id']);
  },

  async down(queryInterface, Sequelize) {
    await queryInterface.dropTable('group_user');
  }
};

  1. 执行迁移文件命令生成数据库表:
// 创建数据库表
npx sequelize db:migrate
// 如果有问题需要回滚,可以通过 `db:migrate:undo` 回退一个变更
npx sequelize db:migrate:undo
// 可以通过 `db:migrate:undo:all` 回退到初始状态
npx sequelize db:migrate:undo:all

# group_user表模型

app/model/group_user.js

'use strict';
//哈希函数 
//const crypto = require('node:crypto');
// 引入 uuid 库 `npm install uuid`
//const { v4: uuidv4 } = require('uuid');

module.exports = app => {
    const { INTEGER, STRING, DATE, TEXT, TINYINT, ENUM, BOOLEAN } = app.Sequelize;

    const GroupUser = app.model.define('group_user', {
        id: {
            type: INTEGER(20).UNSIGNED,
            primaryKey: true,
            autoIncrement: true,
            comment: '主键ID'
        },
        group_id: {
            type: INTEGER(20).UNSIGNED,
            allowNull: false,
            comment: '群id(关联group表的id)',
            references: { //关联关系
                model: 'group', //关联的表
                key: 'id' //关联表的主键
            },
            onDelete: 'CASCADE', //删除时操作
            onUpdate: 'RESTRICT', // 更新时操作
        },
        user_id: {
            type: INTEGER(20).UNSIGNED,
            allowNull: false,
            comment: '用户id',
            references: { //关联关系
                model: 'user', //关联的表
                key: 'id' //关联表的主键
            },
            onDelete: 'CASCADE', //删除时操作
            onUpdate: 'RESTRICT', // 更新时操作
        },
        nickname: {
            type: STRING(50),
            allowNull: true,
            unique: false, //群称呼可以不唯一
            comment: '在群里的称呼(默认为空,则默认为用户账户昵称或者账号)',
            defaultValue: '',
        },
        avatar: {
            type: STRING(1000),
            allowNull: true,
            defaultValue: '',
            comment: '在群里面的头像地址(本地、网络图片地址)(默认为空,则默认为用户账户头像)'
        },
        status: {
            type: TINYINT(1),
            allowNull: false,
            defaultValue: 1,
            comment: '用户在群里面的状态(0-禁用 1-正常 2-锁定)'
        },
        order: {
            type: INTEGER,//不限定长度.默认int(11)
            allowNull: true,
            defaultValue: 50,
            comment: '排序,默认50'
        },
        // sex: { type: ENUM, values: ['男','女','保密'], allowNull: true, defaultValue: '保密', comment: '留言用户性别'},
        create_time: {
            type: DATE,
            allowNull: false,
            defaultValue: app.Sequelize.fn('NOW'),
            get() {
                return app.formatTime(this.getDataValue('create_time'));
            }
        },
        update_time: { type: DATE, allowNull: false, defaultValue: app.Sequelize.fn('NOW') },
    });

    // 模型关联
    GroupUser.associate = function (models) {
        // 反向一对多belongsTo
        GroupUser.belongsTo(app.model.Group, {
            foreignKey: 'group_id', //外键
            //as: 'group', //别名
        });
        // 反向一对多belongsTo
        GroupUser.belongsTo(app.model.User, {
            foreignKey: 'user_id', //外键
            //as: 'user', //别名
        });
    };

    return GroupUser;
}
更新时间: 2025年8月7日星期四下午5点16分