这是一个基于Node.js和Express的论文投稿系统,支持作者投稿、专家审稿和编辑管理等功能。
- 后端:Node.js, Express.js
- 数据库:MySQL, Sequelize ORM
- 认证:JSON Web Token (JWT)
- 模板引擎:EJS
- 文件上传:Multer
- 密码加密:bcrypt
- 邮件发送:nodemailer
├── app/
│ ├── controllers/ # 控制器,处理业务逻辑
│ ├── middlewares/ # 中间件,处理认证和授权
│ ├── models/ # 数据模型,定义数据库结构
│ ├── routes/ # 路由,定义API接口
│ └── database.js # 数据库连接配置
├── config/
│ └── db.config.js # 数据库配置文件
├── views/ # EJS视图文件
├── public/ # 静态资源文件
├── uploads/ # 上传文件存储
├── server.js # 服务器入口文件
├── package.json # 项目依赖配置
└── README.md # 项目说明文档
- Node.js (v14或更高版本)
- MySQL (v5.7或更高版本)
npm install-
在MySQL中创建数据库:
CREATE DATABASE paper_submission_system;
-
修改
config/db.config.js文件中的数据库配置:module.exports = { HOST: 'localhost', USER: 'root', PASSWORD: 'your_password', // 修改为你的MySQL密码 DB: 'paper_submission_system', dialect: 'mysql', pool: { max: 5, min: 0, acquire: 30000, idle: 10000 } };
-
修改JWT密钥:
在
app/controllers/auth.controller.js和app/middlewares/auth.middleware.js文件中,将'your_jwt_secret'替换为你自己的密钥。
npm run devnpm start服务器将在端口3000上运行,访问 http://localhost:3000 查看首页。
- 用户注册(作者、专家、编辑)
- 用户登录
- 个人信息管理
- 论文投稿
- 查看论文状态
- 修改稿提交
- 机构管理
- 审稿任务接收
- 评审意见提交
- 审稿费用提现
- 论文初审
- 论文送审
- 论文决策
- 发送通知
- 论文排期
POST /api/auth/register- 用户注册POST /api/auth/login- 用户登录GET /api/auth/profile- 获取当前用户信息
GET /api/users/me- 获取当前用户详细信息PUT /api/users/me- 更新用户信息POST /api/users/author/institutions- 作者添加机构GET /api/users/author/institutions- 作者获取所有机构DELETE /api/users/author/institutions/:id- 作者移除机构POST /api/users/expert/withdraw- 专家提现
POST /api/papers- 投稿论文GET /api/papers- 获取个人论文列表GET /api/papers/:id- 查看论文详情PUT /api/papers/:id- 更新论文信息POST /api/papers/:id/revision- 提交修改稿GET /api/papers/:id/progress- 查看审稿进度POST /api/papers/:id/payment- 支付版面费
GET /api/reviews/pending- 获取待审论文列表GET /api/reviews/:id- 查看审稿任务详情POST /api/reviews/:id/submit- 提交评审意见GET /api/reviews/completed- 查看已完成审稿任务
GET /api/editor/pending- 获取待初审论文列表POST /api/editor/:id/initial-review- 初审论文POST /api/editor/:id/assign-reviewer- 送审论文POST /api/editor/:id/decision- 编辑决策POST /api/editor/:id/notify- 发送通知POST /api/editor/:id/schedule- 论文排期
本项目使用Sequelize ORM框架进行数据库操作,遵循MVC架构设计,将数据访问逻辑与业务逻辑分离。
数据库连接配置位于app/database.js文件中,主要实现如下:
const Sequelize = require('sequelize');
const dbConfig = require('../config/db.config.js');
// 创建Sequelize实例,连接到MySQL数据库
const sequelize = new Sequelize(dbConfig.DB, dbConfig.USER, dbConfig.PASSWORD, {
host: dbConfig.HOST,
dialect: dbConfig.dialect,
operatorsAliases: false,
pool: {
max: dbConfig.pool.max, // 连接池最大连接数
min: dbConfig.pool.min, // 连接池最小连接数
acquire: dbConfig.pool.acquire, // 尝试获取连接的最大时间(毫秒)
idle: dbConfig.pool.idle // 连接空闲超时时间(毫秒)
}
});
const db = {};
db.Sequelize = Sequelize;
db.sequelize = sequelize;
// 导出数据库连接实例
exports = module.exports = db;数据库的具体配置参数在config/db.config.js文件中定义,包括主机名、用户名、密码、数据库名称等。
项目采用模型优先的设计方式,所有的数据模型都定义在app/models/目录下。每个模型对应数据库中的一张表,主要包括:
user.model.js- 用户表模型authorProfile.model.js- 作者信息表模型expertProfile.model.js- 专家信息表模型paper.model.js- 论文表模型paperAuthor.model.js- 论文作者关联表模型correspondingAuthor.model.js- 通讯作者表模型institution.model.js- 机构表模型fund.model.js- 基金项目表模型
模型定义示例(以User模型为例):
const { DataTypes } = require('sequelize');
const db = require('../database.js');
const User = db.sequelize.define('User', {
id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
},
username: {
type: DataTypes.STRING(50),
allowNull: false,
unique: true
},
password: {
type: DataTypes.STRING(100),
allowNull: false
},
email: {
type: DataTypes.STRING(100),
allowNull: false,
unique: true
},
role: {
type: DataTypes.ENUM('author', 'expert', 'editor'),
allowNull: false
},
createdAt: {
type: DataTypes.DATE,
defaultValue: DataTypes.NOW
},
updatedAt: {
type: DataTypes.DATE,
defaultValue: DataTypes.NOW
}
}, {
tableName: 'users'
});
module.exports = User;在server.js文件中,项目启动时会调用db.sequelize.sync()方法进行数据库同步,确保数据库表结构与模型定义一致:
// 同步数据库
const syncDatabase = async () => {
try {
await db.sequelize.sync();
console.log('Database synchronized successfully!');
} catch (error) {
console.error('Failed to synchronize database:', error);
}
};
// 启动服务器前同步数据库
syncDatabase().then(() => {
app.listen(PORT, () => {
console.log(`Server is running on port ${PORT}.`);
});
});此方法默认会创建不存在的表,但不会修改已存在的表结构。如果需要强制更新表结构,可以使用{ force: true }参数(注意:这会删除所有现有数据)。
控制器层通过导入模型,使用Sequelize提供的API进行数据库操作。以下是常见的数据库操作示例:
// 创建用户示例
const user = await User.create({
username: req.body.username,
email: req.body.email,
password: hashedPassword,
role: req.body.role
});// 根据条件查询单个记录
const user = await User.findOne({ where: { username: req.body.username } });
// 根据主键查询记录
const user = await User.findByPk(decoded.id, {
attributes: ['id', 'username', 'email', 'role'] // 指定返回字段
});// 更新用户信息示例
await User.update(
{
username: req.body.username,
email: req.body.email
},
{ where: { id: req.userId } }
);// 删除用户示例
await User.destroy({ where: { id: req.params.id } });对于需要保证数据一致性的操作,Sequelize提供了事务支持:
// 事务示例
const transaction = await db.sequelize.transaction();
try {
// 在事务中执行操作
const user = await User.create(
{ username: 'newuser', email: 'newuser@example.com' },
{ transaction }
);
// 提交事务
await transaction.commit();
} catch (error) {
// 发生错误时回滚事务
await transaction.rollback();
throw error;
}- 确保MySQL服务正在运行
- 首次运行时,Sequelize会自动创建数据库表
- 文件上传功能需要创建
uploads目录 - 数据库连接错误时,检查
config/db.config.js中的配置是否正确 - 数据库操作采用异步方式,使用async/await处理异步操作