更新政府端和银行端

This commit is contained in:
2025-09-17 18:04:28 +08:00
parent f35ceef31f
commit e4287b83fe
185 changed files with 78320 additions and 189 deletions

61
government-backend/app.js Normal file
View File

@@ -0,0 +1,61 @@
require('dotenv').config();
const express = require('express');
const cors = require('cors');
const bodyParser = require('body-parser');
const helmet = require('helmet');
const morgan = require('morgan');
const path = require('path');
const fs = require('fs');
// 创建Express应用
const app = express();
// 中间件
app.use(cors());
app.use(helmet());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
// 日志配置
const accessLogStream = fs.createWriteStream(
path.join(__dirname, 'logs', 'access.log'),
{ flags: 'a' }
);
app.use(morgan('combined', { stream: accessLogStream }));
// 数据库连接
const sequelize = require('./config/database');
// 路由
app.use('/api/auth', require('./routes/auth'));
app.use('/api/supervision', require('./routes/supervision'));
app.use('/api/approval', require('./routes/approval'));
app.use('/api/personnel', require('./routes/personnel'));
app.use('/api/warehouse', require('./routes/warehouse'));
app.use('/api/epidemic', require('./routes/epidemic'));
app.use('/api/service', require('./routes/service'));
app.use('/api/visualization', require('./routes/visualization'));
app.use('/api/system', require('./routes/system'));
app.use('/api/files', require('./routes/files'));
// 健康检查
app.get('/health', (req, res) => {
res.json({ status: 'ok', timestamp: new Date() });
});
// 错误处理
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(500).json({
code: 500,
message: 'Internal Server Error',
error: process.env.NODE_ENV === 'development' ? err.message : undefined
});
});
// 启动服务器
const PORT = process.env.PORT || 5352;
app.listen(PORT, () => {
console.log(`政府管理系统后端服务已启动,端口: ${PORT}`);
console.log(`数据库: ${process.env.DB_NAME}@${process.env.DB_HOST}:${process.env.DB_PORT}`);
});

View File

@@ -0,0 +1,42 @@
require('dotenv').config();
const { Sequelize } = require('sequelize');
const sequelize = new Sequelize(
process.env.DB_NAME,
process.env.DB_USER,
process.env.DB_PASSWORD,
{
host: process.env.DB_HOST,
port: process.env.DB_PORT,
dialect: process.env.DB_DIALECT,
logging: process.env.NODE_ENV === 'development' ? console.log : false,
pool: {
max: 5,
min: 0,
acquire: 30000,
idle: 10000
},
define: {
timestamps: true,
paranoid: true,
underscored: true,
freezeTableName: true
},
timezone: '+08:00' // 设置为中国时区
}
);
// 测试数据库连接
async function testConnection() {
try {
await sequelize.authenticate();
console.log('数据库连接成功');
} catch (error) {
console.error('数据库连接失败:', error);
process.exit(1);
}
}
testConnection();
module.exports = sequelize;

View File

@@ -0,0 +1,11 @@
module.exports = {
JWT_SECRET: 'your-secret-key-here', // 请在生产环境中替换为强密钥
DB_CONFIG: {
host: 'localhost',
user: 'root',
password: '',
database: 'government_db',
port: 3306
},
PORT: 5352
}

View File

@@ -0,0 +1,29 @@
const jwt = require('jsonwebtoken')
const { JWT_SECRET } = require('../config')
exports.login = async (req, res) => {
try {
const { username, password } = req.body
// 临时模拟登录验证
if (username === 'admin' && password === '123456') {
const token = jwt.sign({ username }, JWT_SECRET, { expiresIn: '2h' })
return res.json({
code: 200,
message: '登录成功',
data: { token }
})
}
res.status(401).json({
code: 401,
message: '用户名或密码错误'
})
} catch (err) {
res.status(500).json({
code: 500,
message: '服务器错误',
error: err.message
})
}
}

View File

@@ -0,0 +1,43 @@
const jwt = require('jsonwebtoken');
const { promisify } = require('util');
const db = require('../config/database');
module.exports = async (req, res, next) => {
// 获取token
const token = req.header('Authorization')?.replace('Bearer ', '');
if (!token) {
return res.status(401).json({
code: 401,
message: '未提供认证令牌'
});
}
try {
// 验证token
const decoded = await promisify(jwt.verify)(token, process.env.JWT_SECRET);
// 检查用户是否存在
const [user] = await db.query(
'SELECT id, username, role FROM users WHERE id = ?',
[decoded.id]
);
if (!user || user.length === 0) {
return res.status(401).json({
code: 401,
message: '用户不存在或已被删除'
});
}
// 将用户信息添加到请求对象
req.user = user[0];
next();
} catch (err) {
console.error(err);
return res.status(401).json({
code: 401,
message: '无效的认证令牌'
});
}
};

1780
government-backend/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,26 @@
{
"name": "government-backend",
"version": "1.0.0",
"description": "宁夏政府管理系统后端",
"main": "app.js",
"scripts": {
"start": "node app.js",
"dev": "nodemon app.js"
},
"dependencies": {
"express": "^4.18.2",
"mysql2": "^3.6.5",
"jsonwebtoken": "^9.0.2",
"bcryptjs": "^2.4.3",
"cors": "^2.8.5",
"dotenv": "^16.3.1",
"body-parser": "^1.20.2",
"helmet": "^7.1.0",
"morgan": "^1.10.0",
"sequelize": "^6.37.1",
"mysql2": "^3.9.7"
},
"devDependencies": {
"nodemon": "^3.1.0"
}
}

View File

@@ -0,0 +1,14 @@
const express = require('express');
const router = express.Router();
// 审批流程列表
router.get('/', (req, res) => {
res.json({ code: 200, data: [] });
});
// 创建审批流程
router.post('/', (req, res) => {
res.json({ code: 200, message: '审批流程创建成功' });
});
module.exports = router;

View File

@@ -0,0 +1,8 @@
const express = require('express')
const router = express.Router()
const { login } = require('../controllers/authController')
// 用户登录
router.post('/login', login)
module.exports = router

View File

@@ -0,0 +1,15 @@
const express = require('express');
const router = express.Router();
// 防疫数据统计
router.get('/stats', (req, res) => {
res.json({
code: 200,
data: {
vaccinated: 0,
tested: 0
}
});
});
module.exports = router;

View File

@@ -0,0 +1,22 @@
const express = require('express');
const router = express.Router();
const path = require('path');
const fs = require('fs');
// 文件列表
router.get('/', (req, res) => {
res.json({
code: 200,
data: []
});
});
// 文件上传
router.post('/upload', (req, res) => {
res.json({
code: 200,
message: '文件上传成功'
});
});
module.exports = router;

View File

@@ -0,0 +1,12 @@
const express = require('express');
const router = express.Router();
// 人员列表
router.get('/', (req, res) => {
res.json({
code: 200,
data: []
});
});
module.exports = router;

View File

@@ -0,0 +1,12 @@
const express = require('express');
const router = express.Router();
// 服务请求列表
router.get('/', (req, res) => {
res.json({
code: 200,
data: []
});
});
module.exports = router;

View File

@@ -0,0 +1,15 @@
const express = require('express');
const router = express.Router();
// 监管数据统计
router.get('/stats', (req, res) => {
res.json({
code: 200,
data: {
entityCount: 0,
inspectionCount: 0
}
});
});
module.exports = router;

View File

@@ -0,0 +1,15 @@
const express = require('express');
const router = express.Router();
// 系统配置
router.get('/config', (req, res) => {
res.json({
code: 200,
data: {
version: "1.0.0",
settings: {}
}
});
});
module.exports = router;

View File

@@ -0,0 +1,15 @@
const express = require('express');
const router = express.Router();
// 可视化数据接口
router.get('/data', (req, res) => {
res.json({
code: 200,
data: {
charts: [],
indicators: []
}
});
});
module.exports = router;

View File

@@ -0,0 +1,12 @@
const express = require('express');
const router = express.Router();
// 仓库物资列表
router.get('/', (req, res) => {
res.json({
code: 200,
data: []
});
});
module.exports = router;

View File

@@ -0,0 +1,56 @@
const mysql = require('mysql2/promise');
const path = require('path');
const fs = require('fs');
// 数据库配置(从.env读取或使用默认值
const config = {
host: process.env.DB_HOST || '129.211.213.226',
port: process.env.DB_PORT || 9527,
user: process.env.DB_USER || 'root',
password: process.env.DB_PASSWORD || 'aiotAiot123!',
database: process.env.DB_NAME || 'ningxia_zhengfu',
multipleStatements: true // 允许执行多条SQL语句
};
async function run() {
let connection;
try {
// 1. 连接数据库
connection = await mysql.createConnection(config);
console.log('数据库连接成功');
// 2. 执行建表SQL
const schemaSql = fs.readFileSync(
path.join(__dirname, '../sql/schema.sql'),
'utf8'
);
await connection.query(schemaSql);
console.log('数据库表创建完成');
// 3. 插入测试数据
const dataSql = fs.readFileSync(
path.join(__dirname, '../sql/seed-data.sql'),
'utf8'
);
await connection.query(dataSql);
console.log('测试数据插入完成');
// 4. 验证数据
const [entities] = await connection.query('SELECT COUNT(*) as count FROM supervision_entities');
const [inspections] = await connection.query('SELECT COUNT(*) as count FROM inspections');
console.log('\n数据验证结果:');
console.log(`监管实体数量: ${entities[0].count}`);
console.log(`检查记录数量: ${inspections[0].count}`);
} catch (err) {
console.error('数据库操作失败:', err.message);
} finally {
if (connection) {
await connection.end();
console.log('数据库连接已关闭');
}
}
}
// 立即执行
run();

View File

@@ -0,0 +1,66 @@
-- 1. 创建监管实体表
CREATE TABLE IF NOT EXISTS supervision_entities (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(100) NOT NULL,
type ENUM('farm', 'business', 'facility') NOT NULL,
address TEXT,
contact_person VARCHAR(50),
contact_phone VARCHAR(20),
status ENUM('active', 'inactive', 'suspended') DEFAULT 'active',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
INDEX idx_type (type),
INDEX idx_status (status)
);
-- 2. 创建检查记录表
CREATE TABLE IF NOT EXISTS inspections (
id INT AUTO_INCREMENT PRIMARY KEY,
entity_id INT NOT NULL,
inspector_id INT NOT NULL,
date DATE NOT NULL,
result ENUM('passed', 'failed', 'pending') DEFAULT 'pending',
notes TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (entity_id) REFERENCES supervision_entities(id),
INDEX idx_entity (entity_id),
INDEX idx_date (date)
);
-- 3. 创建违规记录表
CREATE TABLE IF NOT EXISTS violations (
id INT AUTO_INCREMENT PRIMARY KEY,
entity_id INT NOT NULL,
inspection_id INT,
type VARCHAR(50) NOT NULL,
description TEXT,
status ENUM('reported', 'processed', 'resolved') DEFAULT 'reported',
penalty DECIMAL(10,2),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (entity_id) REFERENCES supervision_entities(id),
FOREIGN KEY (inspection_id) REFERENCES inspections(id),
INDEX idx_status (status)
);
-- 4. 创建审批流程表
CREATE TABLE IF NOT EXISTS approval_workflows (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(100) NOT NULL,
description TEXT,
steps JSON NOT NULL,
created_by INT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);
-- 5. 创建用户表
CREATE TABLE IF NOT EXISTS users (
id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) NOT NULL UNIQUE,
password VARCHAR(255) NOT NULL,
role ENUM('admin', 'manager', 'inspector', 'clerk') NOT NULL,
status ENUM('active', 'inactive') DEFAULT 'active',
last_login TIMESTAMP NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);

View File

@@ -0,0 +1,32 @@
-- 1. 插入测试用户 (密码都是123456的bcrypt哈希)
INSERT INTO users (username, password, role) VALUES
('admin', '$2a$10$xJwL5v5zP6zE5Jf7QYqZNuYQd9WkZf9XvLd1UcJm3VbK6sN8rLbW', 'admin'),
('inspector1', '$2a$10$xJwL5v5zP6zE5Jf7QYqZNuYQd9WkZf9XvLd1UcJm3VbK6sN8rLbW', 'inspector'),
('clerk1', '$2a$10$xJwL5v5zP6zE5Jf7QYqZNuYQd9WkZf9XvLd1UcJm3VbK6sN8rLbW', 'clerk');
-- 2. 插入监管实体
INSERT INTO supervision_entities (name, type, address, contact_person, contact_phone) VALUES
('宁夏第一农场', 'farm', '宁夏银川市兴庆区农场路1号', '张农场主', '13800138001'),
('银川商贸有限公司', 'business', '宁夏银川市金凤区商业街88号', '李经理', '13900139002'),
('银川市污水处理厂', 'facility', '宁夏银川市西夏区环保路5号', '王厂长', '13700137003'),
('贺兰山养殖基地', 'farm', '宁夏银川市贺兰县养殖区88号', '赵场长', '13500135004'),
('银川食品加工厂', 'business', '宁夏银川市永宁县工业区66号', '钱主管', '13600136005');
-- 3. 插入检查记录
INSERT INTO inspections (entity_id, inspector_id, date, result, notes) VALUES
(1, 2, '2025-09-10', 'passed', '防疫措施完善,卫生达标'),
(2, 2, '2025-09-12', 'failed', '消防设备不齐全,限期整改'),
(3, 2, '2025-09-15', 'pending', '例行检查,报告待提交'),
(4, 2, '2025-09-16', 'passed', '养殖环境良好,符合标准'),
(5, 2, '2025-09-17', 'failed', '卫生条件不达标,需整改');
-- 4. 插入违规记录
INSERT INTO violations (entity_id, inspection_id, type, description, status, penalty) VALUES
(2, 2, '消防安全', '灭火器数量不足,安全通道堵塞', 'reported', 5000.00),
(1, NULL, '环保违规', '废弃物处理不规范', 'processed', 3000.00),
(5, 5, '卫生违规', '操作间发现蟑螂,卫生条件差', 'reported', 8000.00);
-- 5. 插入审批流程
INSERT INTO approval_workflows (name, description, steps, created_by) VALUES
('企业注册审批', '新企业注册审批流程', '[{"name":"资料初审","role":"clerk"},{"name":"现场核查","role":"inspector"},{"name":"最终审批","role":"manager"}]', 1),
('违规处理审批', '违规处罚审批流程', '[{"name":"违规确认","role":"inspector"},{"name":"处罚方案","role":"manager"},{"name":"执行确认","role":"clerk"}]', 1);

View File

@@ -0,0 +1,45 @@
require('dotenv').config();
const mysql = require('mysql2/promise');
async function testConnection() {
try {
// 从环境变量获取数据库配置
const config = {
host: process.env.DB_HOST || '129.211.213.226',
port: process.env.DB_PORT || 9527,
user: process.env.DB_USER || 'root',
password: process.env.DB_PASSWORD || 'aiotAiot123!',
database: process.env.DB_NAME || 'ningxia_zhengfu'
};
console.log('正在连接数据库...');
console.log('📋 数据库配置信息:');
console.log(` 主机: ${config.host}`);
console.log(` 端口: ${config.port}`);
console.log(` 数据库名: ${config.database}`);
console.log(` 用户名: ${config.user}`);
// 创建数据库连接
const connection = await mysql.createConnection(config);
console.log('✅ 政府端后端数据库连接成功');
// 查询数据库中的表
const [tables] = await connection.query(
"SELECT table_name FROM information_schema.tables WHERE table_schema = ?",
[config.database]
);
console.log(`📚 数据库表数量: ${tables.length}`);
// 关闭连接
await connection.end();
console.log('🔒 数据库连接已关闭');
process.exit(0);
} catch (error) {
console.error('❌ 政府端后端数据库连接失败:', error.message);
process.exit(1);
}
}
testConnection();