重构后端服务架构并优化前端错误处理

This commit is contained in:
ylweng
2025-09-05 01:18:40 +08:00
parent 86322c6f50
commit 5853953f79
20 changed files with 608 additions and 772 deletions

View File

@@ -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
View 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
};