/** * 用户模型 * @file User.js * @description 银行系统用户模型定义 */ const { DataTypes } = require('sequelize'); const bcrypt = require('bcryptjs'); const BaseModel = require('./BaseModel'); const { sequelize } = require('../config/database'); class User extends BaseModel { /** * 验证密码 * @param {String} password 待验证的密码 * @returns {Promise} 验证结果 */ async validPassword(password) { try { if (!password || !this.password) { return false; } const bcrypt = require('bcryptjs'); return await bcrypt.compare(password, this.password); } catch (error) { console.error('密码验证错误:', error); return false; } } /** * 获取用户角色 * @returns {Promise} 用户角色列表 */ async getRoles() { try { const { Role } = require('./index'); const role = await Role.findByPk(this.role_id); return role ? [role] : []; } catch (error) { console.error('获取用户角色失败:', error); return []; } } /** * 检查用户是否具有指定角色 * @param {String|Array} roleName 角色名称或角色名称数组 * @returns {Promise} 检查结果 */ async hasRole(roleName) { const roles = await this.getRoles(); const roleNames = roles.map(role => role.name); if (Array.isArray(roleName)) { return roleName.some(name => roleNames.includes(name)); } return roleNames.includes(roleName); } /** * 获取用户账户列表 * @returns {Promise} 账户列表 */ async getAccounts() { try { const { Account } = require('./index'); return await Account.findAll({ where: { user_id: this.id, status: 'active' } }); } catch (error) { console.error('获取用户账户失败:', error); return []; } } /** * 获取用户安全信息(不包含密码) * @returns {Object} 用户安全信息 */ getSafeInfo() { return super.getSafeInfo(['password', 'pin']); } } // 初始化User模型 User.init({ id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true }, username: { type: DataTypes.STRING(50), allowNull: false, unique: true, validate: { len: [3, 50] } }, email: { type: DataTypes.STRING(100), allowNull: false, unique: true, validate: { isEmail: true } }, password: { type: DataTypes.STRING(255), allowNull: false, validate: { len: [6, 255] } }, phone: { type: DataTypes.STRING(20), allowNull: true, validate: { is: /^1[3-9]\d{9}$/ } }, real_name: { type: DataTypes.STRING(50), allowNull: false }, id_card: { type: DataTypes.STRING(18), allowNull: false, unique: true, validate: { is: /^[1-9]\d{5}(18|19|20)\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/ } }, avatar: { type: DataTypes.STRING(255), allowNull: true }, role_id: { type: DataTypes.INTEGER, allowNull: false, defaultValue: 2, // 默认为普通用户角色ID references: { model: 'bank_roles', key: 'id' } }, status: { type: DataTypes.ENUM('active', 'inactive', 'suspended', 'locked'), defaultValue: 'active' }, last_login: { type: DataTypes.DATE, allowNull: true }, login_attempts: { type: DataTypes.INTEGER, defaultValue: 0 }, locked_until: { type: DataTypes.DATE, allowNull: true }, created_at: { type: DataTypes.DATE, allowNull: false, defaultValue: DataTypes.NOW }, updated_at: { type: DataTypes.DATE, allowNull: false, defaultValue: DataTypes.NOW } }, { sequelize, tableName: 'bank_users', modelName: 'User', timestamps: true, underscored: true, createdAt: 'created_at', updatedAt: 'updated_at', hooks: { beforeCreate: async (user) => { if (user.password && !user.password.startsWith('$2a$')) { user.password = await bcrypt.hash(user.password, 10); } }, beforeUpdate: async (user) => { if (user.changed('password') && user.password && !user.password.startsWith('$2a$')) { user.password = await bcrypt.hash(user.password, 10); } } } }); module.exports = User;