# 一、 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 | 更新时间 |
- 直接在
phpMyAdmin中根据表字段设计创建表,或者通过数据库插件写sql语句创建表。- 通过迁移命名创建
group表:
- 创建迁移文件 命令:
npx sequelize migration:generate --name=group
- 创建迁移文件
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'); } };
- 执行迁移文件命令生成数据库表:
// 创建数据库表 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 | 更新时间 |
- 直接在
phpMyAdmin中根据表字段设计创建表,或者通过数据库插件写sql语句创建表。- 通过迁移命名创建
group_user表:
- 创建迁移文件 命令:
npx sequelize migration:generate --name=group_user
- 创建迁移文件
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'); } };
- 执行迁移文件命令生成数据库表:
// 创建数据库表 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;
}