添加银行政府后端接口

This commit is contained in:
2025-09-25 15:53:44 +08:00
parent b17bdcc24c
commit 5b6b7e0a96
60 changed files with 5345 additions and 1920 deletions

View File

@@ -37,6 +37,7 @@ 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.use('/api/government', require('./routes/government'));
// 健康检查
app.get('/health', (req, res) => {

View File

@@ -0,0 +1,599 @@
const { Op } = require('sequelize');
const Department = require('../models/Department');
const Position = require('../models/Position');
const AdminStaff = require('../models/AdminStaff');
// 获取数据中心统计数据
const getDataCenterStats = async (req, res) => {
try {
// Mock data based on frontend analysis
const stats = {
totalFarmers: 128,
totalAnimals: 8056,
totalTransactions: 61,
activeUsers: 1,
monthlyTrends: [
{ month: '1月', value: 120 },
{ month: '2月', value: 180 },
{ month: '3月', value: 150 },
{ month: '4月', value: 200 },
{ month: '5月', value: 250 },
{ month: '6月', value: 220 },
{ month: '7月', value: 300 },
{ month: '8月', value: 280 },
{ month: '9月', value: 350 },
{ month: '10月', value: 400 },
{ month: '11月', value: 380 },
{ month: '12月', value: 450 }
],
categoryDistribution: [
{ value: 335, name: '西门塔尔牛' },
{ value: 310, name: '夏洛莱牛' },
{ value: 234, name: '安格斯牛' },
{ value: 135, name: '利木赞牛' },
{ value: 548, name: '其他' }
],
regionDistribution: [
{ value: 1548, name: '扎鲁特旗' },
{ value: 735, name: '科尔沁区' },
{ value: 510, name: '霍林郭勒市' },
{ value: 434, name: '开鲁县' },
{ value: 335, name: '库伦旗' }
],
scaleDistribution: [
{ value: 40, name: '1-10头' },
{ value: 30, name: '11-50头' },
{ value: 20, name: '51-100头' },
{ value: 10, name: '100头以上' }
],
updates: [
{ time: '2023-10-27 10:30', content: '数据更新-养殖户数据' },
{ time: '2023-10-27 10:30', content: '数据更新-存栏数据' },
{ time: '2023-10-27 10:30', content: '数据更新-交易数据' },
{ time: '2023-10-27 10:30', content: '数据更新-用户数据' }
]
};
res.json(stats);
} catch (error) {
res.status(500).json({ message: error.message });
}
};
// 获取市场价格信息
const getMarketPrice = async (req, res) => {
try {
const { type = 'beef' } = req.query;
let priceData = {};
// 繁殖牛数据
if (type === 'beef') {
priceData = {
type: 'beef',
typeText: '繁殖牛',
currentPrice: '38.50',
priceChange: '-0.20',
priceChangePercent: '-0.52%',
priceDate: '2025-01-01',
priceTrend: [
{ date: '2024-12-19', price: 38.50 },
{ date: '2024-12-20', price: 36.90 },
{ date: '2024-12-21', price: 39.50 },
{ date: '2024-12-22', price: 37.80 },
{ date: '2024-12-23', price: 38.40 },
{ date: '2024-12-24', price: 40.20 },
{ date: '2024-12-25', price: 39.10 },
{ date: '2024-12-26', price: 37.50 },
{ date: '2024-12-27', price: 36.20 },
{ date: '2024-12-28', price: 39.90 },
{ date: '2024-12-29', price: 39.30 },
{ date: '2024-12-30', price: 36.60 },
{ date: '2024-12-31', price: 38.70 },
{ date: '2025-01-01', price: 38.30 }
],
provincePrices: [
{ province: '上海市', price: 40 },
{ province: '云南省', price: 38.85 },
{ province: '内蒙古自治区', price: 38.85 },
{ province: '北京市', price: 40.7 },
{ province: '吉林省', price: 38.26 },
{ province: '四川省', price: 39.9 },
{ province: '天津市', price: 40.4 },
{ province: '宁夏回族自治区', price: 41.51 },
{ province: '安徽省', price: 38.5 },
{ province: '山东省', price: 40.4 },
{ province: '山西省', price: 40.8 },
{ province: '广东省', price: 40.3 },
{ province: '广西壮族自治区', price: 37.6 },
{ province: '新疆维吾尔自治区', price: 40.8 },
{ province: '江苏省', price: 39.1 },
{ province: '江西省', price: 40.2 },
{ province: '河北省', price: 38.2 },
{ province: '河南省', price: 41 },
{ province: '浙江省', price: 40 },
{ province: '海南省', price: 40.4 },
{ province: '湖北省', price: 37 },
{ province: '湖南省', price: 38.2 },
{ province: '甘肃省', price: 39.8 },
{ province: '福建省', price: 37.86 },
{ province: '贵州省', price: 37.7 },
{ province: '辽宁省', price: 38 },
{ province: '重庆市', price: 37.8 },
{ province: '陕西省', price: 38.4 },
{ province: '青海省', price: 38 },
{ province: '黑龙江省', price: 40.4 }
]
};
}
// 奶牛数据
else if (type === 'milk') {
priceData = {
type: 'milk',
typeText: '奶牛',
currentPrice: '32.80',
priceChange: '+0.15',
priceChangePercent: '+0.46%',
priceDate: '2025-01-01',
priceTrend: [
{ date: '2024-12-19', price: 32.80 },
{ date: '2024-12-20', price: 30.90 },
{ date: '2024-12-21', price: 33.50 },
{ date: '2024-12-22', price: 31.80 },
{ date: '2024-12-23', price: 32.40 },
{ date: '2024-12-24', price: 34.20 },
{ date: '2024-12-25', price: 33.10 },
{ date: '2024-12-26', price: 31.50 },
{ date: '2024-12-27', price: 30.20 },
{ date: '2024-12-28', price: 33.90 },
{ date: '2024-12-29', price: 33.30 },
{ date: '2024-12-30', price: 30.60 },
{ date: '2024-12-31', price: 32.70 },
{ date: '2025-01-01', price: 32.30 }
],
provincePrices: [
{ province: '上海市', price: 45 },
{ province: '云南省', price: 43.85 },
{ province: '内蒙古自治区', price: 43.85 },
{ province: '北京市', price: 44.7 },
{ province: '吉林省', price: 42.26 },
{ province: '四川省', price: 43.9 },
{ province: '天津市', price: 44.4 },
{ province: '宁夏回族自治区', price: 45.51 },
{ province: '安徽省', price: 42.5 },
{ province: '山东省', price: 44.4 },
{ province: '山西省', price: 44.8 },
{ province: '广东省', price: 44.3 },
{ province: '广西壮族自治区', price: 41.6 },
{ province: '新疆维吾尔自治区', price: 44.8 },
{ province: '江苏省', price: 43.1 },
{ province: '江西省', price: 44.2 },
{ province: '河北省', price: 42.2 },
{ province: '河南省', price: 45 },
{ province: '浙江省', price: 44 },
{ province: '海南省', price: 44.4 },
{ province: '湖北省', price: 41 },
{ province: '湖南省', price: 42.2 },
{ province: '甘肃省', price: 43.8 },
{ province: '福建省', price: 41.86 },
{ province: '贵州省', price: 41.7 },
{ province: '辽宁省', price: 42 },
{ province: '重庆市', price: 41.8 },
{ province: '陕西省', price: 42.4 },
{ province: '青海省', price: 42 },
{ province: '黑龙江省', price: 44.4 }
]
};
}
res.json(priceData);
} catch (error) {
res.status(500).json({ message: error.message });
}
};
// 获取所有部门及其岗位
const getDepartments = async (req, res) => {
try {
const departments = await Department.findAll({
include: [
{
model: Position,
as: 'positions'
}
]
});
// 转换数据格式以便前端使用
const formattedData = departments.map(dept => ({
id: dept.id,
name: dept.name,
description: dept.description,
positions: dept.positions.map(pos => ({
id: pos.id,
name: pos.name,
permission: pos.has_permission ? '已设置权限' : '未设置权限',
permission_details: pos.permission_details
}))
}));
res.json(formattedData);
} catch (error) {
res.status(500).json({ message: error.message });
}
};
// 新增部门
const createDepartment = async (req, res) => {
try {
const { name, description } = req.body;
const department = await Department.create({
name,
description,
created_by: req.user?.id || null,
updated_by: req.user?.id || null
});
res.status(201).json(department);
} catch (error) {
res.status(500).json({ message: error.message });
}
};
// 编辑部门
const updateDepartment = async (req, res) => {
try {
const { id } = req.params;
const { name, description } = req.body;
const department = await Department.findByPk(id);
if (!department) {
return res.status(404).json({ message: '部门不存在' });
}
department.name = name;
department.description = description;
department.updated_by = req.user?.id || null;
await department.save();
res.json(department);
} catch (error) {
res.status(500).json({ message: error.message });
}
};
// 删除部门
const deleteDepartment = async (req, res) => {
try {
const { id } = req.params;
const department = await Department.findByPk(id);
if (!department) {
return res.status(404).json({ message: '部门不存在' });
}
// 先删除该部门下的所有岗位
await Position.destroy({
where: { department_id: id }
});
// 再删除部门
await department.destroy();
res.json({ message: '部门删除成功' });
} catch (error) {
res.status(500).json({ message: error.message });
}
};
// 新增岗位
const createPosition = async (req, res) => {
try {
const { department_id } = req.params;
const { name } = req.body;
// 检查部门是否存在
const department = await Department.findByPk(department_id);
if (!department) {
return res.status(404).json({ message: '部门不存在' });
}
const position = await Position.create({
department_id,
name,
has_permission: false,
created_by: req.user?.id || null,
updated_by: req.user?.id || null
});
res.status(201).json({
id: position.id,
name: position.name,
permission: '未设置权限',
permission_details: position.permission_details
});
} catch (error) {
res.status(500).json({ message: error.message });
}
};
// 编辑岗位
const updatePosition = async (req, res) => {
try {
const { id } = req.params;
const { name } = req.body;
const position = await Position.findByPk(id);
if (!position) {
return res.status(404).json({ message: '岗位不存在' });
}
position.name = name;
position.updated_by = req.user?.id || null;
await position.save();
res.json({
id: position.id,
name: position.name,
permission: position.has_permission ? '已设置权限' : '未设置权限',
permission_details: position.permission_details
});
} catch (error) {
res.status(500).json({ message: error.message });
}
};
// 删除岗位
const deletePosition = async (req, res) => {
try {
const { id } = req.params;
const position = await Position.findByPk(id);
if (!position) {
return res.status(404).json({ message: '岗位不存在' });
}
await position.destroy();
res.json({ message: '岗位删除成功' });
} catch (error) {
res.status(500).json({ message: error.message });
}
};
// 设置岗位权限
const setPositionPermission = async (req, res) => {
try {
const { id } = req.params;
const { permission_details } = req.body;
const position = await Position.findByPk(id);
if (!position) {
return res.status(404).json({ message: '岗位不存在' });
}
position.has_permission = true;
position.permission_details = permission_details;
position.updated_by = req.user?.id || null;
await position.save();
res.json({
id: position.id,
name: position.name,
permission: '已设置权限',
permission_details: position.permission_details
});
} catch (error) {
res.status(500).json({ message: error.message });
}
};
// 行政人员相关接口
// 获取行政人员列表
const getAdminStaff = async (req, res) => {
try {
const { page = 1, pageSize = 10, search = '' } = req.query;
const whereCondition = {};
if (search) {
whereCondition.name = {
[Op.like]: `%${search}%`
};
}
const offset = (page - 1) * pageSize;
const { count, rows } = await AdminStaff.findAndCountAll({
where: whereCondition,
include: [
{
model: Department,
as: 'department',
attributes: ['name']
},
{
model: Position,
as: 'position',
attributes: ['name']
}
],
offset,
limit: parseInt(pageSize),
order: [['createdAt', 'DESC']]
});
// 格式化数据以便前端使用
const formattedData = rows.map(staff => ({
id: staff.id,
key: staff.id.toString(),
name: staff.name,
department: staff.department?.name || '',
position: staff.position?.name || '',
phone: staff.phone,
idCard: staff.id_card || '--',
status: staff.status,
createdAt: staff.createdAt.toLocaleString('zh-CN')
}));
res.json({
data: formattedData,
total: count,
page: parseInt(page),
pageSize: parseInt(pageSize)
});
} catch (error) {
console.error('获取行政人员列表失败:', error);
res.status(500).json({ message: error.message });
}
};
// 新增行政人员
const createAdminStaff = async (req, res) => {
try {
const { name, department_id, position_id, phone, id_card, status } = req.body;
const staff = await AdminStaff.create({
name,
department_id,
position_id,
phone,
id_card,
status: status !== undefined ? status : true
});
res.status(201).json({
success: true,
message: '行政人员创建成功',
data: staff
});
} catch (error) {
console.error('创建行政人员失败:', error);
res.status(500).json({ message: error.message });
}
};
// 编辑行政人员
const updateAdminStaff = async (req, res) => {
try {
const { id } = req.params;
const { name, department_id, position_id, phone, id_card, status } = req.body;
const staff = await AdminStaff.findByPk(id);
if (!staff) {
return res.status(404).json({ message: '行政人员不存在' });
}
await staff.update({
name,
department_id,
position_id,
phone,
id_card,
status
});
res.json({
success: true,
message: '行政人员更新成功',
data: staff
});
} catch (error) {
console.error('更新行政人员失败:', error);
res.status(500).json({ message: error.message });
}
};
// 删除行政人员
const deleteAdminStaff = async (req, res) => {
try {
const { id } = req.params;
const staff = await AdminStaff.findByPk(id);
if (!staff) {
return res.status(404).json({ message: '行政人员不存在' });
}
await staff.destroy();
res.json({
success: true,
message: '行政人员删除成功'
});
} catch (error) {
console.error('删除行政人员失败:', error);
res.status(500).json({ message: error.message });
}
};
// 重置行政人员密码
const resetAdminStaffPassword = async (req, res) => {
try {
const { id } = req.params;
const staff = await AdminStaff.findByPk(id);
if (!staff) {
return res.status(404).json({ message: '行政人员不存在' });
}
// 在实际应用中,这里应该生成一个临时密码并发送给用户
// 为了演示,我们只返回成功信息
res.json({
success: true,
message: '密码重置成功,新密码已发送到用户手机'
});
} catch (error) {
console.error('重置密码失败:', error);
res.status(500).json({ message: error.message });
}
};
// 获取所有岗位列表
const getPositions = async (req, res) => {
try {
const positions = await Position.findAll({
include: [
{
model: Department,
as: 'department'
}
]
});
// 转换数据格式以便前端使用
const formattedData = positions.map(pos => ({
id: pos.id,
name: pos.name,
department_id: pos.department_id,
department_name: pos.department?.name || '',
permission: pos.has_permission ? '已设置权限' : '未设置权限',
permission_details: pos.permission_details
}));
res.json(formattedData);
} catch (error) {
res.status(500).json({ message: error.message });
}
};
// 导出模块
module.exports = {
getDataCenterStats,
getMarketPrice,
getDepartments,
getPositions,
createDepartment,
updateDepartment,
deleteDepartment,
createPosition,
updatePosition,
deletePosition,
setPositionPermission,
getAdminStaff,
createAdminStaff,
updateAdminStaff,
deleteAdminStaff,
resetAdminStaffPassword
};

View File

@@ -0,0 +1,96 @@
// 完整模型测试脚本
const sequelize = require('./config/database');
// 确保先导入所有依赖模型
const Department = require('./models/Department');
const Position = require('./models/Position');
const AdminStaff = require('./models/AdminStaff');
async function fullModelTest() {
try {
console.log('开始完整模型测试...');
// 测试数据库连接
await sequelize.authenticate();
console.log('✅ 数据库连接成功');
// 检查模型是否被正确导入
console.log('\n检查模型导入状态:');
console.log('Department 模型:', Department ? '✅ 已导入' : '❌ 未导入');
console.log('Position 模型:', Position ? '✅ 已导入' : '❌ 未导入');
console.log('AdminStaff 模型:', AdminStaff ? '✅ 已导入' : '❌ 未导入');
// 测试基本的查询功能
console.log('\n测试基本查询功能:');
// 查询部门表
console.log('\n查询部门表:');
try {
const departments = await Department.findAll({ limit: 5 });
console.log(`找到 ${departments.length} 个部门`);
if (departments.length > 0) {
console.log('示例部门:', departments[0].dataValues);
}
} catch (error) {
console.error('部门查询失败:', error.message);
}
// 查询岗位表
console.log('\n查询岗位表:');
try {
const positions = await Position.findAll({ limit: 5 });
console.log(`找到 ${positions.length} 个岗位`);
if (positions.length > 0) {
console.log('示例岗位:', positions[0].dataValues);
}
} catch (error) {
console.error('岗位查询失败:', error.message);
}
// 查询行政人员表
console.log('\n查询行政人员表:');
try {
const adminStaffs = await AdminStaff.findAll({ limit: 5 });
console.log(`找到 ${adminStaffs.length} 个行政人员`);
if (adminStaffs.length > 0) {
console.log('示例行政人员:', adminStaffs[0].dataValues);
}
} catch (error) {
console.error('行政人员查询失败:', error.message);
console.error('错误详情:', error);
}
// 测试关联查询
console.log('\n测试关联查询:');
try {
const adminStaffWithRelations = await AdminStaff.findAll({
include: [
{ model: Department, as: 'department' },
{ model: Position, as: 'position' }
],
limit: 1
});
console.log('关联查询结果数量:', adminStaffWithRelations.length);
if (adminStaffWithRelations.length > 0) {
console.log('关联查询成功,已获取到关联数据');
// 只打印部分数据以避免输出过多
const staff = adminStaffWithRelations[0];
console.log('姓名:', staff.name);
console.log('部门:', staff.department?.name || '未知');
console.log('岗位:', staff.position?.name || '未知');
}
} catch (error) {
console.error('关联查询失败:', error.message);
console.error('错误详情:', error);
}
console.log('\n✅ 完整模型测试完成');
} catch (error) {
console.error('❌ 完整模型测试失败:', error.message);
console.error('错误详情:', error);
} finally {
await sequelize.close();
}
}
fullModelTest();

View File

@@ -0,0 +1,99 @@
// 模型导入测试脚本
const sequelize = require('./config/database');
const { DataTypes } = require('sequelize');
async function modelImportTest() {
try {
console.log('开始模型导入测试...');
// 测试数据库连接
await sequelize.authenticate();
console.log('✅ 数据库连接成功');
// 测试直接导入模型
console.log('\n测试直接导入模型:');
// 先测试 Department 模型
console.log('\n测试 Department 模型导入:');
try {
const Department = require('./models/Department');
console.log('Department 模型导入:', Department ? '✅ 成功' : '❌ 失败');
// 测试 Department 模型的结构
if (Department) {
console.log('Department 模型是否有 define 方法:', typeof Department.define === 'function' ? '✅ 是' : '❌ 否');
console.log('Department 模型的 tableName:', Department.tableName || Department.options?.tableName || '未定义');
}
} catch (error) {
console.error('Department 模型导入失败:', error.message);
}
// 测试 Position 模型
console.log('\n测试 Position 模型导入:');
try {
const Position = require('./models/Position');
console.log('Position 模型导入:', Position ? '✅ 成功' : '❌ 失败');
// 测试 Position 模型的结构
if (Position) {
console.log('Position 模型是否有 define 方法:', typeof Position.define === 'function' ? '✅ 是' : '❌ 否');
console.log('Position 模型的 tableName:', Position.tableName || Position.options?.tableName || '未定义');
}
} catch (error) {
console.error('Position 模型导入失败:', error.message);
}
// 测试 AdminStaff 模型
console.log('\n测试 AdminStaff 模型导入:');
try {
// 先导入依赖模型
require('./models/Department');
require('./models/Position');
const AdminStaff = require('./models/AdminStaff');
console.log('AdminStaff 模型导入:', AdminStaff ? '✅ 成功' : '❌ 失败');
// 测试 AdminStaff 模型的结构
if (AdminStaff) {
console.log('AdminStaff 模型是否有 define 方法:', typeof AdminStaff.define === 'function' ? '✅ 是' : '❌ 否');
console.log('AdminStaff 模型的 tableName:', AdminStaff.tableName || AdminStaff.options?.tableName || '未定义');
}
} catch (error) {
console.error('AdminStaff 模型导入失败:', error.message);
console.error('错误详情:', error);
}
// 测试创建一个简单的新模型
console.log('\n测试创建新模型:');
try {
const TestModel = sequelize.define('TestModel', {
id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
},
name: {
type: DataTypes.STRING,
allowNull: false
}
}, {
tableName: 'test_models',
timestamps: false,
paranoid: false
});
console.log('新模型创建:', TestModel ? '✅ 成功' : '❌ 失败');
} catch (error) {
console.error('新模型创建失败:', error.message);
}
console.log('\n✅ 模型导入测试完成');
} catch (error) {
console.error('❌ 模型导入测试失败:', error.message);
console.error('错误详情:', error);
} finally {
await sequelize.close();
}
}
modelImportTest();

View File

@@ -0,0 +1,85 @@
const sequelize = require('../config/database');
const { DataTypes } = require('sequelize');
const Department = require('./Department');
const Position = require('./Position');
const AdminStaff = sequelize.define('AdminStaff', {
id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
},
name: {
type: DataTypes.STRING,
allowNull: false,
comment: '员工姓名'
},
department_id: {
type: DataTypes.INTEGER,
allowNull: false,
references: {
model: Department,
key: 'id'
},
comment: '所属部门ID'
},
position_id: {
type: DataTypes.INTEGER,
allowNull: false,
references: {
model: Position,
key: 'id'
},
comment: '任职岗位ID'
},
phone: {
type: DataTypes.STRING,
allowNull: false,
unique: true,
comment: '联系电话'
},
id_card: {
type: DataTypes.STRING,
allowNull: true,
comment: '身份证号码'
},
status: {
type: DataTypes.BOOLEAN,
allowNull: false,
defaultValue: true,
comment: '账号使用状态'
}
}, {
tableName: 'government_admin_staff',
indexes: [
{
name: 'idx_admin_staff_department_id',
fields: ['department_id']
},
{
name: 'idx_admin_staff_position_id',
fields: ['position_id']
},
{
name: 'idx_admin_staff_name',
fields: ['name']
},
{
name: 'idx_admin_staff_phone',
fields: ['phone']
}
]
});
// 建立关联关系
AdminStaff.belongsTo(Department, {
foreignKey: 'department_id',
as: 'department'
});
AdminStaff.belongsTo(Position, {
foreignKey: 'position_id',
as: 'position'
});
module.exports = AdminStaff;

View File

@@ -0,0 +1,41 @@
const sequelize = require('../config/database');
const { DataTypes } = require('sequelize');
const Department = sequelize.define('Department', {
id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
},
name: {
type: DataTypes.STRING,
allowNull: false,
unique: true,
comment: '部门名称'
},
description: {
type: DataTypes.TEXT,
allowNull: true,
comment: '部门描述'
},
created_by: {
type: DataTypes.INTEGER,
allowNull: true,
comment: '创建人ID'
},
updated_by: {
type: DataTypes.INTEGER,
allowNull: true,
comment: '更新人ID'
}
}, {
tableName: 'government_departments',
indexes: [
{
name: 'idx_department_name',
fields: ['name']
}
]
});
module.exports = Department;

View File

@@ -0,0 +1,66 @@
const sequelize = require('../config/database');
const { DataTypes } = require('sequelize');
const Department = require('./Department');
const Position = sequelize.define('Position', {
id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
},
department_id: {
type: DataTypes.INTEGER,
allowNull: false,
references: {
model: Department,
key: 'id'
},
comment: '所属部门ID'
},
name: {
type: DataTypes.STRING,
allowNull: false,
comment: '岗位名称'
},
has_permission: {
type: DataTypes.BOOLEAN,
allowNull: false,
defaultValue: false,
comment: '是否已设置权限'
},
created_by: {
type: DataTypes.INTEGER,
allowNull: true,
comment: '创建人ID'
},
updated_by: {
type: DataTypes.INTEGER,
allowNull: true,
comment: '更新人ID'
}
}, {
tableName: 'government_positions',
indexes: [
{
name: 'idx_position_department_id',
fields: ['department_id']
},
{
name: 'idx_position_name',
fields: ['name']
}
]
});
// 定义关系
Department.hasMany(Position, {
foreignKey: 'department_id',
as: 'positions'
});
Position.belongsTo(Department, {
foreignKey: 'department_id',
as: 'department'
});
module.exports = Position;

View File

@@ -0,0 +1,55 @@
const express = require('express');
const router = express.Router();
const governmentController = require('../controllers/governmentController');
// 数据览仓接口
router.get('/data-center', governmentController.getDataCenterStats);
// 市场价格接口
router.get('/market-price', governmentController.getMarketPrice);
// 行政部门管理接口
// 获取所有部门及其岗位
router.get('/departments', governmentController.getDepartments);
// 新增部门
router.post('/departments', governmentController.createDepartment);
// 编辑部门
router.put('/departments/:id', governmentController.updateDepartment);
// 删除部门
router.delete('/departments/:id', governmentController.deleteDepartment);
// 获取所有岗位列表
router.get('/positions', governmentController.getPositions);
// 在指定部门下新增岗位
router.post('/departments/:id/positions', governmentController.createPosition);
// 编辑岗位
router.put('/positions/:id', governmentController.updatePosition);
// 删除岗位
router.delete('/positions/:id', governmentController.deletePosition);
// 设置岗位权限
router.post('/positions/:id/permission', governmentController.setPositionPermission);
// 行政人员管理接口
// 获取行政人员列表
router.get('/admin-staff', governmentController.getAdminStaff);
// 新增行政人员
router.post('/admin-staff', governmentController.createAdminStaff);
// 编辑行政人员
router.put('/admin-staff/:id', governmentController.updateAdminStaff);
// 删除行政人员
router.delete('/admin-staff/:id', governmentController.deleteAdminStaff);
// 重置行政人员密码
router.post('/admin-staff/:id/reset-password', governmentController.resetAdminStaffPassword);
module.exports = router;

View File

@@ -0,0 +1,43 @@
const Department = require('../models/Department');
const Position = require('../models/Position');
const sequelize = require('../config/database');
// 查看数据库中的部门和岗位
async function checkData() {
try {
console.log('连接数据库...');
// 获取所有部门
console.log('\n查询所有部门...');
const departments = await Department.findAll();
console.log(`找到 ${departments.length} 个部门:`);
departments.forEach(dept => {
console.log(`- ID: ${dept.id}, 名称: ${dept.name}, 描述: ${dept.description}`);
});
// 获取所有岗位
console.log('\n查询所有岗位...');
const positions = await Position.findAll({
include: [
{
model: Department,
as: 'department',
attributes: ['name']
}
]
});
console.log(`找到 ${positions.length} 个岗位:`);
positions.forEach(pos => {
console.log(`- ID: ${pos.id}, 名称: ${pos.name}, 部门ID: ${pos.department_id}, 部门名称: ${pos.department?.name || '未知'}`);
});
console.log('\n查询完成');
process.exit(0);
} catch (error) {
console.error('查询数据失败:', error);
process.exit(1);
}
}
// 执行查询
checkData();

View File

@@ -0,0 +1,86 @@
const sequelize = require('../config/database');
const Department = require('../models/Department');
const Position = require('../models/Position');
// 测试数据
const departments = [
{
name: '防疫部门',
description: '负责动物防疫工作的部门',
positions: [
{ name: '防疫员', has_permission: true, permission_details: { basic: ['view', 'edit'], advanced: ['delete'] } },
{ name: '防疫管理员', has_permission: true, permission_details: { basic: ['view', 'edit', 'add', 'delete'], advanced: ['admin'] } }
]
},
{
name: '检疫部门',
description: '负责动物检疫工作的部门',
positions: [
{ name: '检疫员', has_permission: false, permission_details: null }
]
},
{
name: '冷配管理部门',
description: '负责动物冷配管理工作的部门',
positions: [
{ name: '冷配员', has_permission: true, permission_details: { basic: ['view', 'edit'], advanced: [] } }
]
},
{
name: '测试部门',
description: '用于系统测试的部门',
positions: [
{ name: '内部测试账号', has_permission: true, permission_details: { basic: ['view', 'edit', 'add', 'delete'], advanced: ['admin', 'debug'] } }
]
}
];
// 初始化数据库表并插入测试数据
async function seedDatabase() {
try {
console.log('开始同步数据库表结构...');
// 同步数据库表结构
await sequelize.sync({ alter: true });
console.log('数据库表结构同步完成!');
console.log('开始插入测试数据...');
// 逐个创建部门及其岗位
for (const deptData of departments) {
// 创建部门
const department = await Department.create({
name: deptData.name,
description: deptData.description,
created_by: 1,
updated_by: 1
});
console.log(`已创建部门: ${department.name}`);
// 创建该部门下的岗位
for (const posData of deptData.positions) {
const position = await Position.create({
department_id: department.id,
name: posData.name,
has_permission: posData.has_permission,
permission_details: posData.permission_details,
created_by: 1,
updated_by: 1
});
console.log(` - 已创建岗位: ${position.name} (权限: ${position.has_permission ? '已设置' : '未设置'})`);
}
}
console.log('测试数据插入完成!');
} catch (error) {
console.error('数据库初始化失败:', error);
process.exit(1);
} finally {
// 关闭数据库连接
await sequelize.close();
}
}
// 执行播种函数
seedDatabase();

View File

@@ -0,0 +1,181 @@
const Department = require('../models/Department');
const Position = require('../models/Position');
const AdminStaff = require('../models/AdminStaff');
const sequelize = require('../config/database');
// 测试数据
const departmentsData = [
{
name: '防疫部门',
description: '负责疫情防控和动物健康监测'
},
{
name: '行政管理部门',
description: '负责日常行政事务管理'
},
{
name: '数据分析部门',
description: '负责数据收集、分析和报告'
},
{
name: '市场监管部门',
description: '负责市场价格监管和交易监督'
}
];
const positionsData = [
{ name: '部门主管', has_permission: true },
{ name: '防疫专员', has_permission: false },
{ name: '行政主管', has_permission: true },
{ name: '行政助理', has_permission: false },
{ name: '数据分析主管', has_permission: true },
{ name: '数据分析师', has_permission: false },
{ name: '市场监管主管', has_permission: true },
{ name: '市场监管员', has_permission: false }
];
const adminStaffData = [
{
name: '张三',
phone: '13800138001',
id_card: '110101199003070010',
status: true
},
{
name: '李四',
phone: '13800138002',
id_card: '110101199104150020',
status: true
},
{
name: '王五',
phone: '13800138003',
id_card: '110101199205200030',
status: true
},
{
name: '赵六',
phone: '13800138004',
id_card: '110101199306250040',
status: true
},
{
name: '孙七',
phone: '13800138005',
id_card: '110101199407300050',
status: true
},
{
name: '周八',
phone: '13800138006',
id_card: '110101199508310060',
status: false
},
{
name: '吴九',
phone: '13800138007',
id_card: '110101199609150070',
status: true
},
{
name: '郑十',
phone: '13800138008',
id_card: '110101199710200080',
status: true
}
];
// 添加测试数据到数据库
async function seedData() {
try {
console.log('开始添加测试数据...');
// 先检查是否已有行政人员数据
const existingStaffCount = await AdminStaff.count();
if (existingStaffCount > 0) {
console.log(`数据库中已有 ${existingStaffCount} 个行政人员数据,跳过所有数据添加`);
process.exit(0);
}
// 开始事务
await sequelize.transaction(async (transaction) => {
// 先删除可能存在的软删除数据
await AdminStaff.destroy({ where: {}, force: true, transaction });
await Position.destroy({ where: {}, force: true, transaction });
await Department.destroy({ where: {}, force: true, transaction });
console.log('已清空所有表数据(包括软删除的数据)');
// 添加部门数据
console.log('添加部门数据...');
const departments = await Department.bulkCreate(departmentsData, {
transaction,
ignoreDuplicates: true
});
console.log(`成功添加 ${departments.length} 个部门`);
// 添加岗位数据,为每个部门添加相应的岗位
console.log('添加岗位数据...');
let positionId = 1;
const createdPositions = [];
for (let i = 0; i < departments.length; i++) {
const deptId = departments[i].id;
// 每个部门添加2个岗位
for (let j = 0; j < 2; j++) {
const posIndex = i * 2 + j;
if (posIndex < positionsData.length) {
const position = await Position.create({
department_id: deptId,
name: positionsData[posIndex].name,
has_permission: positionsData[posIndex].has_permission
}, {
transaction
});
createdPositions.push(position);
console.log(` 添加岗位: ${position.name} (ID: ${position.id}, 部门ID: ${deptId})`);
}
}
}
console.log(`总共添加了 ${createdPositions.length} 个岗位`);
// 添加行政人员数据,关联到实际创建的部门和岗位
console.log('添加行政人员数据...');
const createdStaff = [];
for (let i = 0; i < adminStaffData.length; i++) {
const staffData = adminStaffData[i];
// 根据索引分配部门和岗位
const deptIndex = Math.floor(i / 2); // 每2个人员属于同一个部门
const posIndex = i;
if (deptIndex < departments.length && posIndex < createdPositions.length) {
const staff = await AdminStaff.create({
name: staffData.name,
department_id: departments[deptIndex].id,
position_id: createdPositions[posIndex].id,
phone: staffData.phone,
id_card: staffData.id_card,
status: staffData.status
}, {
transaction
});
createdStaff.push(staff);
console.log(` 添加行政人员: ${staff.name} (ID: ${staff.id}, 部门: ${departments[deptIndex].name})`);
}
}
console.log(`总共添加了 ${createdStaff.length} 个行政人员`);
});
console.log('所有测试数据添加完成!');
process.exit(0);
} catch (error) {
console.error('添加测试数据失败:', error);
process.exit(1);
}
}
// 执行数据添加
seedData();

View File

@@ -0,0 +1,37 @@
// 简单测试脚本
const sequelize = require('./config/database');
const { DataTypes } = require('sequelize');
async function simpleTest() {
try {
console.log('开始简单测试...');
// 测试数据库连接
await sequelize.authenticate();
console.log('✅ 数据库连接成功');
// 测试DataTypes是否可用
console.log('\n测试DataTypes:');
console.log('DataTypes.INTEGER:', DataTypes.INTEGER ? '✅ 可用' : '❌ 不可用');
console.log('DataTypes.STRING:', DataTypes.STRING ? '✅ 可用' : '❌ 不可用');
console.log('DataTypes.BOOLEAN:', DataTypes.BOOLEAN ? '✅ 可用' : '❌ 不可用');
// 测试sequelize实例是否可用
console.log('\n测试sequelize实例:');
console.log('sequelize实例:', sequelize ? '✅ 可用' : '❌ 不可用');
// 测试直接查询数据库
console.log('\n测试直接查询数据库:');
const [results] = await sequelize.query('SELECT 1+1 AS result');
console.log('查询结果:', results);
console.log('\n✅ 简单测试完成');
} catch (error) {
console.error('❌ 简单测试失败:', error.message);
console.error('错误详情:', error);
} finally {
await sequelize.close();
}
}
simpleTest();

View File

@@ -0,0 +1,74 @@
// 测试模型文件
const sequelize = require('./config/database');
const AdminStaff = require('./models/AdminStaff');
const Department = require('./models/Department');
const Position = require('./models/Position');
async function testModels() {
try {
console.log('开始测试模型...');
// 测试数据库连接
await sequelize.authenticate();
console.log('✅ 数据库连接成功');
// 测试模型关系
console.log('\n测试模型关系:');
console.log('AdminStaff关联Department:', AdminStaff.associations.department ? '✅' : '❌');
console.log('AdminStaff关联Position:', AdminStaff.associations.position ? '✅' : '❌');
console.log('Department关联Position:', Department.associations.positions ? '✅' : '❌');
console.log('Position关联Department:', Position.associations.department ? '✅' : '❌');
// 尝试获取行政人员数据
console.log('\n尝试获取行政人员数据:');
const adminStaffs = await AdminStaff.findAll({
include: [
{ model: Department, as: 'department' },
{ model: Position, as: 'position' }
],
limit: 5
});
if (adminStaffs.length > 0) {
console.log(`✅ 成功获取${adminStaffs.length}条行政人员数据`);
console.log('示例数据:', adminStaffs[0].dataValues);
} else {
console.log('⚠️ 未找到行政人员数据');
}
// 尝试获取部门数据
console.log('\n尝试获取部门数据:');
const departments = await Department.findAll({
limit: 5
});
if (departments.length > 0) {
console.log(`✅ 成功获取${departments.length}条部门数据`);
console.log('示例数据:', departments[0].dataValues);
} else {
console.log('⚠️ 未找到部门数据');
}
// 尝试获取岗位数据
console.log('\n尝试获取岗位数据:');
const positions = await Position.findAll({
include: [{ model: Department, as: 'department' }],
limit: 5
});
if (positions.length > 0) {
console.log(`✅ 成功获取${positions.length}条岗位数据`);
console.log('示例数据:', positions[0].dataValues);
} else {
console.log('⚠️ 未找到岗位数据');
}
console.log('\n✅ 模型测试完成');
} catch (error) {
console.error('❌ 模型测试失败:', error);
} finally {
await sequelize.close();
}
}
testModels();