重构后端服务架构并优化前端错误处理
This commit is contained in:
@@ -1,122 +0,0 @@
|
||||
const { DataTypes } = require('sequelize');
|
||||
const { sequelize } = require('../config/database');
|
||||
const bcrypt = require('bcryptjs');
|
||||
|
||||
// 用户模型
|
||||
const User = sequelize.define('User', {
|
||||
id: {
|
||||
type: DataTypes.BIGINT,
|
||||
primaryKey: true,
|
||||
autoIncrement: true
|
||||
},
|
||||
uuid: {
|
||||
type: DataTypes.STRING(36),
|
||||
allowNull: false,
|
||||
unique: true,
|
||||
defaultValue: DataTypes.UUIDV4
|
||||
},
|
||||
username: {
|
||||
type: DataTypes.STRING(50),
|
||||
allowNull: false,
|
||||
unique: true,
|
||||
validate: {
|
||||
len: [2, 50]
|
||||
}
|
||||
},
|
||||
password_hash: {
|
||||
type: DataTypes.STRING(255),
|
||||
allowNull: false
|
||||
},
|
||||
phone: {
|
||||
type: DataTypes.STRING(20),
|
||||
allowNull: false,
|
||||
unique: true,
|
||||
validate: {
|
||||
is: /^1[3-9]\d{9}$/
|
||||
}
|
||||
},
|
||||
email: {
|
||||
type: DataTypes.STRING(100),
|
||||
validate: {
|
||||
isEmail: true
|
||||
}
|
||||
},
|
||||
real_name: DataTypes.STRING(50),
|
||||
avatar_url: DataTypes.STRING(255),
|
||||
user_type: {
|
||||
type: DataTypes.ENUM('client', 'supplier', 'driver', 'staff', 'admin'),
|
||||
allowNull: false,
|
||||
defaultValue: 'client'
|
||||
},
|
||||
status: {
|
||||
type: DataTypes.ENUM('active', 'inactive', 'locked'),
|
||||
defaultValue: 'active'
|
||||
},
|
||||
last_login_at: DataTypes.DATE,
|
||||
login_count: {
|
||||
type: DataTypes.INTEGER,
|
||||
defaultValue: 0
|
||||
}
|
||||
}, {
|
||||
tableName: 'users',
|
||||
timestamps: true,
|
||||
paranoid: true, // 软删除
|
||||
indexes: [
|
||||
{ fields: ['phone'] },
|
||||
{ fields: ['user_type'] },
|
||||
{ fields: ['status'] },
|
||||
{ fields: ['username'] }
|
||||
],
|
||||
hooks: {
|
||||
beforeCreate: async (user) => {
|
||||
if (user.password_hash) {
|
||||
user.password_hash = await bcrypt.hash(user.password_hash, 12);
|
||||
}
|
||||
},
|
||||
beforeUpdate: async (user) => {
|
||||
if (user.changed('password_hash')) {
|
||||
user.password_hash = await bcrypt.hash(user.password_hash, 12);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// 实例方法:验证密码
|
||||
User.prototype.validatePassword = async function(password) {
|
||||
return await bcrypt.compare(password, this.password_hash);
|
||||
};
|
||||
|
||||
// 实例方法:更新登录信息
|
||||
User.prototype.updateLoginInfo = async function() {
|
||||
this.last_login_at = new Date();
|
||||
this.login_count += 1;
|
||||
await this.save();
|
||||
};
|
||||
|
||||
// 类方法:根据用户名或手机号查找用户
|
||||
User.findByLoginIdentifier = async function(identifier) {
|
||||
return await this.findOne({
|
||||
where: {
|
||||
[sequelize.Sequelize.Op.or]: [
|
||||
{ username: identifier },
|
||||
{ phone: identifier }
|
||||
]
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// 类方法:创建用户
|
||||
User.createUser = async function(userData) {
|
||||
const { username, password, phone, email, real_name, user_type = 'client' } = userData;
|
||||
|
||||
return await this.create({
|
||||
username,
|
||||
password_hash: password,
|
||||
phone,
|
||||
email,
|
||||
real_name,
|
||||
user_type
|
||||
});
|
||||
};
|
||||
|
||||
module.exports = User;
|
||||
140
backend/models/index.js
Normal file
140
backend/models/index.js
Normal file
@@ -0,0 +1,140 @@
|
||||
// 数据库连接和模型定义
|
||||
const { Sequelize } = require('sequelize');
|
||||
const config = require('../config/database.js');
|
||||
|
||||
// 根据环境变量选择配置
|
||||
const env = process.env.NODE_ENV || 'development';
|
||||
const dbConfig = config[env];
|
||||
|
||||
// 创建Sequelize实例
|
||||
const sequelize = new Sequelize(
|
||||
dbConfig.database,
|
||||
dbConfig.username,
|
||||
dbConfig.password,
|
||||
{
|
||||
host: dbConfig.host,
|
||||
port: dbConfig.port,
|
||||
dialect: dbConfig.dialect,
|
||||
dialectOptions: dbConfig.dialectOptions,
|
||||
timezone: dbConfig.timezone,
|
||||
logging: dbConfig.logging,
|
||||
pool: dbConfig.pool
|
||||
}
|
||||
);
|
||||
|
||||
// 测试数据库连接
|
||||
const testConnection = async () => {
|
||||
try {
|
||||
await sequelize.authenticate();
|
||||
console.log('✅ 数据库连接成功');
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error('❌ 数据库连接失败:', error);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
// 定义模型
|
||||
const models = {
|
||||
sequelize,
|
||||
Sequelize,
|
||||
|
||||
// 用户模型(匹配实际数据库结构)
|
||||
User: sequelize.define('User', {
|
||||
id: {
|
||||
type: Sequelize.INTEGER,
|
||||
primaryKey: true,
|
||||
autoIncrement: true
|
||||
},
|
||||
openid: {
|
||||
type: Sequelize.STRING(64),
|
||||
allowNull: false,
|
||||
unique: true
|
||||
},
|
||||
nickname: {
|
||||
type: Sequelize.STRING(50),
|
||||
allowNull: false
|
||||
},
|
||||
avatar: {
|
||||
type: Sequelize.STRING(255)
|
||||
},
|
||||
gender: {
|
||||
type: Sequelize.ENUM('male', 'female', 'other')
|
||||
},
|
||||
birthday: {
|
||||
type: Sequelize.DATE
|
||||
},
|
||||
phone: {
|
||||
type: Sequelize.STRING(20),
|
||||
unique: true
|
||||
},
|
||||
email: {
|
||||
type: Sequelize.STRING(100),
|
||||
unique: true
|
||||
},
|
||||
uuid: {
|
||||
type: Sequelize.STRING(36),
|
||||
unique: true
|
||||
}
|
||||
}, {
|
||||
tableName: 'users',
|
||||
timestamps: true,
|
||||
createdAt: 'created_at',
|
||||
updatedAt: 'updated_at'
|
||||
}),
|
||||
|
||||
// 为了兼容现有API,创建一个简化版的用户模型
|
||||
ApiUser: sequelize.define('ApiUser', {
|
||||
id: {
|
||||
type: Sequelize.INTEGER,
|
||||
primaryKey: true,
|
||||
autoIncrement: true
|
||||
},
|
||||
username: {
|
||||
type: Sequelize.STRING(50),
|
||||
allowNull: false,
|
||||
unique: true
|
||||
},
|
||||
password_hash: {
|
||||
type: Sequelize.STRING(255),
|
||||
allowNull: false
|
||||
},
|
||||
phone: {
|
||||
type: Sequelize.STRING(20),
|
||||
allowNull: false,
|
||||
unique: true
|
||||
},
|
||||
email: {
|
||||
type: Sequelize.STRING(100)
|
||||
},
|
||||
user_type: {
|
||||
type: Sequelize.ENUM('client', 'supplier', 'driver', 'staff', 'admin'),
|
||||
allowNull: false
|
||||
},
|
||||
status: {
|
||||
type: Sequelize.ENUM('active', 'inactive', 'locked'),
|
||||
defaultValue: 'active'
|
||||
}
|
||||
}, {
|
||||
tableName: 'api_users',
|
||||
timestamps: true
|
||||
})
|
||||
};
|
||||
|
||||
// 同步数据库模型
|
||||
const syncModels = async () => {
|
||||
try {
|
||||
// 只同步API用户表(如果不存在则创建)
|
||||
await models.ApiUser.sync({ alter: true });
|
||||
console.log('✅ API用户表同步成功');
|
||||
console.log('✅ 数据库模型同步完成');
|
||||
} catch (error) {
|
||||
console.error('❌ 数据库模型同步失败:', error);
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
...models,
|
||||
testConnection,
|
||||
syncModels
|
||||
};
|
||||
Reference in New Issue
Block a user