You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1369 lines
51 KiB
1369 lines
51 KiB
const express = require('express');
|
|
const bodyParser = require('body-parser');
|
|
const cors = require('cors');
|
|
const mysql = require('mysql2/promise');
|
|
const path = require('path');
|
|
const app = express();
|
|
const PORT = 3000;
|
|
|
|
// 配置CORS
|
|
app.use(cors());
|
|
app.use((req, res, next) => {
|
|
res.header('Access-Control-Allow-Origin', '*');
|
|
res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
|
|
res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization');
|
|
if (req.method === 'OPTIONS') {
|
|
res.status(200).end();
|
|
return;
|
|
}
|
|
next();
|
|
});
|
|
app.use(bodyParser.json({ limit: '10mb' }));
|
|
app.use(express.static(path.join(__dirname)));
|
|
|
|
// 数据库配置
|
|
const dbConfig = {
|
|
host: '1.95.162.61',
|
|
user: 'root',
|
|
password: 'schl@2025', // 请替换为实际的数据库密码
|
|
database: 'wechat_app', // 连接到wechat_app数据库
|
|
waitForConnections: true,
|
|
connectionLimit: 10,
|
|
queueLimit: 0
|
|
};
|
|
|
|
// userlogin数据库配置
|
|
const userLoginDbConfig = {
|
|
host: '1.95.162.61',
|
|
user: 'root',
|
|
password: 'schl@2025', // 请替换为实际的数据库密码
|
|
database: 'userlogin', // 连接到userlogin数据库
|
|
waitForConnections: true,
|
|
connectionLimit: 10,
|
|
queueLimit: 0
|
|
};
|
|
|
|
// 创建数据库连接池
|
|
let pool;
|
|
let userLoginPool;
|
|
|
|
// 初始化数据库连接
|
|
async function initDatabase() {
|
|
try {
|
|
pool = mysql.createPool(dbConfig);
|
|
console.log('wechat_app数据库连接池创建成功');
|
|
|
|
// 初始化userlogin数据库连接池
|
|
userLoginPool = mysql.createPool(userLoginDbConfig);
|
|
console.log('userlogin数据库连接池创建成功');
|
|
|
|
// 测试wechat_app连接
|
|
const connection = await pool.getConnection();
|
|
console.log('wechat_app数据库连接测试成功');
|
|
connection.release();
|
|
|
|
// 测试userlogin连接
|
|
const userLoginConnection = await userLoginPool.getConnection();
|
|
console.log('userlogin数据库连接测试成功');
|
|
userLoginConnection.release();
|
|
|
|
// 确保数据库结构
|
|
await ensureDatabaseSchema();
|
|
} catch (error) {
|
|
console.error('数据库初始化失败:', error.message);
|
|
console.error('错误详情:', error);
|
|
// 如果初始化失败,尝试重新初始化
|
|
setTimeout(() => {
|
|
console.log('尝试重新初始化数据库连接...');
|
|
initDatabase();
|
|
}, 5000);
|
|
}
|
|
}
|
|
|
|
// 通用响应函数
|
|
function sendResponse(res, success, data = null, message = '') {
|
|
res.json({
|
|
success,
|
|
data,
|
|
message
|
|
});
|
|
}
|
|
|
|
// 导出函数供测试使用
|
|
module.exports.sendResponse = sendResponse;
|
|
|
|
// 获取货源列表API
|
|
app.get('/api/supplies', async (req, res) => {
|
|
console.log('收到获取货源列表请求:', req.query);
|
|
try {
|
|
const connection = await pool.getConnection();
|
|
// 支持search和keyword两种参数名,确保兼容性
|
|
const { page = 1, pageSize = 10, search = '', keyword = '', status = '', phoneNumber = '' } = req.query;
|
|
// 如果提供了keyword参数,优先使用keyword
|
|
const actualSearch = keyword || search;
|
|
const offset = (page - 1) * pageSize;
|
|
|
|
// 构建基础查询,添加LEFT JOIN获取用户信息
|
|
let query = 'SELECT p.*, u.phoneNumber, u.nickName FROM products p LEFT JOIN users u ON p.sellerId = u.userId';
|
|
let countQuery = 'SELECT COUNT(*) as total FROM products p LEFT JOIN users u ON p.sellerId = u.userId';
|
|
let whereClause = '';
|
|
let params = [];
|
|
|
|
// 添加搜索条件
|
|
if (actualSearch) {
|
|
whereClause += ` WHERE (p.id LIKE ? OR p.productId LIKE ? OR p.productName LIKE ?)`;
|
|
params.push(`%${actualSearch}%`, `%${actualSearch}%`, `%${actualSearch}%`);
|
|
}
|
|
|
|
// 添加手机号搜索
|
|
if (phoneNumber) {
|
|
whereClause += actualSearch ? ' AND' : ' WHERE';
|
|
whereClause += ` u.phoneNumber LIKE ?`;
|
|
params.push(`%${phoneNumber}%`);
|
|
}
|
|
|
|
// 添加状态筛选
|
|
if (status) {
|
|
whereClause += (actualSearch || phoneNumber) ? ' AND' : ' WHERE';
|
|
whereClause += ` status = ?`;
|
|
params.push(status);
|
|
}
|
|
|
|
// 添加sellerId筛选,只返回指定用户的货源
|
|
const { sellerId } = req.query;
|
|
if (sellerId) {
|
|
whereClause += (actualSearch || phoneNumber || status) ? ' AND' : ' WHERE';
|
|
whereClause += ` p.sellerId = ?`;
|
|
params.push(sellerId);
|
|
}
|
|
|
|
// 执行查询
|
|
const [results] = await connection.query(
|
|
`${query}${whereClause} ORDER BY p.id DESC LIMIT ? OFFSET ?`,
|
|
[...params, parseInt(pageSize), offset]
|
|
);
|
|
|
|
// 获取总数
|
|
const [countResults] = await connection.query(
|
|
`${countQuery}${whereClause}`,
|
|
params
|
|
);
|
|
|
|
connection.release();
|
|
|
|
// 处理返回结果中的imageUrls字段
|
|
const processedResults = results.map(product => {
|
|
// 处理imageUrls字段
|
|
let imageUrls = [];
|
|
|
|
if (product.imageUrls) {
|
|
if (typeof product.imageUrls === 'string') {
|
|
// 尝试解析为JSON数组
|
|
try {
|
|
let parsedImages = JSON.parse(product.imageUrls);
|
|
|
|
// 检查是否是JSON字符串的字符串表示(转义的JSON)
|
|
if (typeof parsedImages === 'string' &&
|
|
(parsedImages.startsWith('[') || parsedImages.startsWith('{'))) {
|
|
// 进行第二次解析
|
|
parsedImages = JSON.parse(parsedImages);
|
|
}
|
|
|
|
if (Array.isArray(parsedImages)) {
|
|
imageUrls = parsedImages;
|
|
} else if (typeof parsedImages === 'string') {
|
|
// 如果解析结果是字符串,可能是单个URL
|
|
imageUrls = [parsedImages];
|
|
}
|
|
} catch (e) {
|
|
// 解析失败,尝试按逗号分隔
|
|
if (product.imageUrls.includes(',')) {
|
|
imageUrls = product.imageUrls.split(',').map(url => url.trim());
|
|
} else {
|
|
// 作为单个URL处理
|
|
imageUrls = [product.imageUrls.trim()];
|
|
}
|
|
}
|
|
} else if (Array.isArray(product.imageUrls)) {
|
|
// 已经是数组,直接使用
|
|
imageUrls = product.imageUrls;
|
|
} else {
|
|
// 其他类型,转换为字符串数组
|
|
imageUrls = [String(product.imageUrls)];
|
|
}
|
|
}
|
|
|
|
// 过滤并处理无效的URL:移除反引号并验证
|
|
imageUrls = imageUrls
|
|
.filter(url => {
|
|
if (!url) return false;
|
|
const processedUrl = url.replace(/`/g, '').trim();
|
|
return processedUrl.startsWith('http://') || processedUrl.startsWith('https://');
|
|
})
|
|
// 对每个有效URL进行处理,移除反引号
|
|
.map(url => url.replace(/`/g, '').trim());
|
|
|
|
return {
|
|
...product,
|
|
imageUrls
|
|
};
|
|
});
|
|
|
|
// 返回结果
|
|
sendResponse(res, true, {
|
|
list: processedResults,
|
|
total: countResults[0].total,
|
|
page: parseInt(page),
|
|
pageSize: parseInt(pageSize)
|
|
}, '获取货源列表成功');
|
|
} catch (error) {
|
|
console.error('获取货源列表失败:', error.message);
|
|
console.error('错误详情:', error);
|
|
sendResponse(res, false, null, '获取货源列表失败');
|
|
}
|
|
});
|
|
|
|
// 审核通过API
|
|
app.post('/api/supplies/:id/approve', async (req, res) => {
|
|
console.log('收到审核通过请求:', req.params.id, req.body);
|
|
try {
|
|
const connection = await pool.getConnection();
|
|
const { remark = '' } = req.body;
|
|
const productId = req.params.id;
|
|
|
|
// 开始事务
|
|
await connection.beginTransaction();
|
|
|
|
// 检查当前状态
|
|
const [currentProduct] = await connection.query(
|
|
'SELECT status FROM products WHERE id = ?',
|
|
[productId]
|
|
);
|
|
|
|
if (currentProduct.length === 0) {
|
|
await connection.rollback();
|
|
connection.release();
|
|
return sendResponse(res, false, null, '货源不存在');
|
|
}
|
|
|
|
// 检查状态是否可审核,只允许审核中的状态进行审核操作
|
|
if (!['pending_review'].includes(currentProduct[0].status)) {
|
|
await connection.rollback();
|
|
connection.release();
|
|
return sendResponse(res, false, null, '该货源已审核,无需重复操作');
|
|
}
|
|
|
|
// 更新状态为已审核
|
|
await connection.query(
|
|
'UPDATE products SET status = ?, audit_time = ? WHERE id = ?',
|
|
['published', new Date(), productId]
|
|
);
|
|
|
|
// 记录日志
|
|
await connection.query(
|
|
'INSERT INTO audit_logs (supply_id, action, user_id, remark, created_at) VALUES (?, ?, ?, ?, ?)',
|
|
[productId, 'approve', 'system', remark, new Date()]
|
|
);
|
|
|
|
// 提交事务
|
|
await connection.commit();
|
|
connection.release();
|
|
|
|
sendResponse(res, true, null, '审核通过成功');
|
|
} catch (error) {
|
|
console.error('审核通过失败:', error.message);
|
|
console.error('错误详情:', error);
|
|
sendResponse(res, false, null, '审核通过失败');
|
|
}
|
|
});
|
|
|
|
console.log('正在注册拒绝审核API路由: /api/supplies/:id/reject');
|
|
|
|
// 审核拒绝API
|
|
app.post('/api/supplies/:id/reject', async (req, res) => {
|
|
console.log('收到审核拒绝请求:', req.params.id, req.body);
|
|
try {
|
|
const connection = await pool.getConnection();
|
|
// 同时支持reason和rejectReason参数,保持向后兼容
|
|
const { reason, rejectReason = '', remark = '' } = req.body;
|
|
// 如果有reason参数,则使用reason,否则使用rejectReason
|
|
const actualRejectReason = reason || rejectReason;
|
|
const productId = req.params.id;
|
|
|
|
// 开始事务
|
|
await connection.beginTransaction();
|
|
|
|
// 检查当前状态
|
|
const [currentProduct] = await connection.query(
|
|
'SELECT status FROM products WHERE id = ?',
|
|
[productId]
|
|
);
|
|
|
|
if (currentProduct.length === 0) {
|
|
await connection.rollback();
|
|
connection.release();
|
|
return sendResponse(res, false, null, '货源不存在');
|
|
}
|
|
|
|
// 检查状态是否可审核,只允许审核中的状态进行审核操作
|
|
if (!['pending_review'].includes(currentProduct[0].status)) {
|
|
await connection.rollback();
|
|
connection.release();
|
|
return sendResponse(res, false, null, '当前状态不允许审核拒绝');
|
|
}
|
|
|
|
// 更新状态和拒绝理由
|
|
await connection.query(
|
|
'UPDATE products SET status = ?, rejectReason = ?, audit_time = ? WHERE id = ?',
|
|
['rejected', actualRejectReason, new Date(), productId]
|
|
);
|
|
|
|
// 记录日志
|
|
await connection.query(
|
|
'INSERT INTO audit_logs (supply_id, action, user_id, remark, created_at) VALUES (?, ?, ?, ?, ?)',
|
|
[productId, 'reject', 'system', remark, new Date()]
|
|
);
|
|
|
|
// 提交事务
|
|
await connection.commit();
|
|
connection.release();
|
|
|
|
sendResponse(res, true, null, '审核拒绝成功');
|
|
} catch (error) {
|
|
console.error('审核拒绝失败:', error.message);
|
|
console.error('错误详情:', error);
|
|
sendResponse(res, false, null, '审核拒绝失败');
|
|
}
|
|
});
|
|
|
|
// 获取供应商列表API已删除
|
|
|
|
// 供应商审核通过API已删除
|
|
|
|
// 供应商审核拒绝API已删除
|
|
|
|
// 供应商开始合作API已删除
|
|
|
|
// 供应商终止合作API已删除
|
|
|
|
console.log('正在注册测试API路由: /api/test-db');
|
|
|
|
// 测试数据库连接API
|
|
app.get('/api/test-db', async (req, res) => {
|
|
console.log('收到数据库连接测试请求');
|
|
try {
|
|
const connection = await pool.getConnection();
|
|
const [results] = await connection.query('SELECT 1 + 1 as solution');
|
|
connection.release();
|
|
sendResponse(res, true, results[0], '数据库连接成功');
|
|
} catch (error) {
|
|
console.error('数据库连接测试失败:', error.message);
|
|
console.error('错误详情:', error);
|
|
sendResponse(res, false, null, '数据库连接测试失败');
|
|
}
|
|
});
|
|
|
|
// 登录API
|
|
app.post('/api/login', async (req, res) => {
|
|
try {
|
|
const { projectName, userName, password } = req.body;
|
|
|
|
// 验证参数
|
|
if (!projectName || !userName || !password) {
|
|
return sendResponse(res, false, null, '职位名称、用户名和密码不能为空');
|
|
}
|
|
|
|
// 1. 在login表中验证登录信息
|
|
const userLoginConnection = await userLoginPool.getConnection();
|
|
const [loginResult] = await userLoginConnection.query(
|
|
'SELECT id, projectName, userName, managerId FROM login WHERE projectName = ? AND userName = ? AND password = ?',
|
|
[projectName, userName, password]
|
|
);
|
|
|
|
if (loginResult.length === 0) {
|
|
userLoginConnection.release();
|
|
return sendResponse(res, false, null, '职位名称、用户名或密码错误');
|
|
}
|
|
|
|
const loginInfo = loginResult[0];
|
|
const { managerId } = loginInfo;
|
|
|
|
// 2. 在personnel表中查询手机号码
|
|
const [personnelResult] = await userLoginConnection.query(
|
|
'SELECT phoneNumber, name FROM personnel WHERE managerId = ?',
|
|
[managerId]
|
|
);
|
|
userLoginConnection.release();
|
|
|
|
if (personnelResult.length === 0) {
|
|
return sendResponse(res, false, null, '未找到对应的员工信息');
|
|
}
|
|
|
|
const { phoneNumber, name } = personnelResult[0];
|
|
|
|
// 3. 在users表中查询userId
|
|
const connection = await pool.getConnection();
|
|
const [userResult] = await connection.query(
|
|
'SELECT userId FROM users WHERE phoneNumber = ?',
|
|
[phoneNumber]
|
|
);
|
|
connection.release();
|
|
|
|
let userId = null;
|
|
if (userResult.length > 0) {
|
|
userId = userResult[0].userId;
|
|
}
|
|
|
|
// 4. 生成token(简单实现,实际项目中应使用JWT等安全机制)
|
|
const token = `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
|
|
|
// 5. 返回登录结果
|
|
const userInfo = {
|
|
id: loginInfo.id,
|
|
projectName: loginInfo.projectName,
|
|
userName: loginInfo.userName,
|
|
managerId: loginInfo.managerId,
|
|
name: name,
|
|
phoneNumber: phoneNumber,
|
|
userId: userId
|
|
};
|
|
|
|
sendResponse(res, true, { userInfo, token }, '登录成功');
|
|
} catch (error) {
|
|
console.error('登录失败:', error.message);
|
|
console.error('错误详情:', error);
|
|
sendResponse(res, false, null, '登录失败,请稍后重试');
|
|
}
|
|
});
|
|
|
|
// 获取联系人数据API
|
|
app.get('/api/contacts', async (req, res) => {
|
|
try {
|
|
// 直接从userlogin数据库的Personnel表查询联系人信息,只查询工位名为销售员的联系人
|
|
const userLoginConnection = await userLoginPool.getConnection();
|
|
const [personnelData] = await userLoginConnection.query(
|
|
'SELECT projectName, alias, phoneNumber FROM Personnel WHERE projectName = "销售员" AND phoneNumber IS NOT NULL AND phoneNumber != ""'
|
|
);
|
|
userLoginConnection.release();
|
|
|
|
if (personnelData.length === 0) {
|
|
sendResponse(res, true, [], '没有找到联系人信息');
|
|
return;
|
|
}
|
|
|
|
// 创建联系人数据数组,保持与原API相同的返回格式
|
|
const contacts = personnelData.map((person, index) => ({
|
|
id: index + 1,
|
|
salesPerson: person.projectName, // 销售员
|
|
name: person.alias, // 联系人别名
|
|
phoneNumber: person.phoneNumber // 电话号码
|
|
}));
|
|
|
|
sendResponse(res, true, contacts, '联系人数据获取成功');
|
|
} catch (error) {
|
|
console.error('获取联系人数据失败:', error.message);
|
|
console.error('错误详情:', error);
|
|
sendResponse(res, false, null, '获取联系人数据失败');
|
|
}
|
|
});
|
|
|
|
// 更新产品联系人API
|
|
app.put('/api/supplies/:id/contact', async (req, res) => {
|
|
try {
|
|
const { id } = req.params;
|
|
const { productContact, contactPhone } = req.body;
|
|
|
|
// 移除"联系人"前缀和"销售员 - "前缀
|
|
const processedProductContact = productContact.replace(/^(联系人|销售员\s*-\s*)/g, '').trim();
|
|
|
|
const connection = await pool.getConnection();
|
|
|
|
// 更新产品的联系人信息
|
|
const [result] = await connection.query(
|
|
'UPDATE products SET product_contact = ?, contact_phone = ? WHERE id = ?',
|
|
[processedProductContact, contactPhone, id]
|
|
);
|
|
|
|
connection.release();
|
|
|
|
if (result.affectedRows === 0) {
|
|
sendResponse(res, false, null, '未找到指定的产品');
|
|
return;
|
|
}
|
|
|
|
sendResponse(res, true, null, '产品联系人信息更新成功');
|
|
} catch (error) {
|
|
console.error('更新产品联系人信息失败:', error.message);
|
|
console.error('错误详情:', error);
|
|
sendResponse(res, false, null, '更新产品联系人信息失败');
|
|
}
|
|
});
|
|
|
|
// 供应商审核通过API - /api/suppliers/:id/approve
|
|
console.log('正在注册供应商审核通过API路由: /api/suppliers/:id/approve');
|
|
app.post('/api/suppliers/:id/approve', async (req, res) => {
|
|
console.log('收到供应商审核通过请求:', req.params);
|
|
try {
|
|
const connection = await pool.getConnection();
|
|
const userId = req.params.id;
|
|
|
|
if (!userId) {
|
|
connection.release();
|
|
return sendResponse(res, false, null, '用户ID不能为空');
|
|
}
|
|
|
|
// 开始事务
|
|
await connection.beginTransaction();
|
|
|
|
// 检查当前状态
|
|
const [currentUser] = await connection.query(
|
|
'SELECT partnerstatus FROM users WHERE userId = ?',
|
|
[userId]
|
|
);
|
|
|
|
if (currentUser.length === 0) {
|
|
await connection.rollback();
|
|
connection.release();
|
|
return sendResponse(res, false, null, '供应商不存在');
|
|
}
|
|
|
|
if (currentUser[0].partnerstatus !== 'underreview') {
|
|
await connection.rollback();
|
|
connection.release();
|
|
return sendResponse(res, false, null, '当前状态不允许审核通过');
|
|
}
|
|
|
|
// 更新状态和审核时间
|
|
await connection.query(
|
|
'UPDATE users SET partnerstatus = ?, audit_time = ? WHERE userId = ?',
|
|
['approved', new Date(), userId]
|
|
);
|
|
|
|
// 提交事务
|
|
await connection.commit();
|
|
connection.release();
|
|
|
|
sendResponse(res, true, null, '供应商审核通过成功');
|
|
} catch (error) {
|
|
console.error('供应商审核通过失败:', error.message);
|
|
console.error('错误详情:', error);
|
|
sendResponse(res, false, null, '供应商审核通过失败');
|
|
}
|
|
});
|
|
|
|
// 供应商审核拒绝API - /api/suppliers/:id/reject
|
|
console.log('正在注册供应商审核拒绝API路由: /api/suppliers/:id/reject');
|
|
app.post('/api/suppliers/:id/reject', async (req, res) => {
|
|
console.log('收到供应商审核拒绝请求:', req.params, req.body);
|
|
try {
|
|
const connection = await pool.getConnection();
|
|
const userId = req.params.id;
|
|
const { rejectReason } = req.body;
|
|
|
|
if (!userId) {
|
|
connection.release();
|
|
return sendResponse(res, false, null, '用户ID不能为空');
|
|
}
|
|
|
|
if (!rejectReason) {
|
|
connection.release();
|
|
return sendResponse(res, false, null, '审核失败原因不能为空');
|
|
}
|
|
|
|
// 开始事务
|
|
await connection.beginTransaction();
|
|
|
|
// 检查当前状态
|
|
const [currentUser] = await connection.query(
|
|
'SELECT partnerstatus FROM users WHERE userId = ?',
|
|
[userId]
|
|
);
|
|
|
|
if (currentUser.length === 0) {
|
|
await connection.rollback();
|
|
connection.release();
|
|
return sendResponse(res, false, null, '供应商不存在');
|
|
}
|
|
|
|
if (currentUser[0].partnerstatus !== 'underreview') {
|
|
await connection.rollback();
|
|
connection.release();
|
|
return sendResponse(res, false, null, '当前状态不允许审核拒绝');
|
|
}
|
|
|
|
// 更新状态、审核失败原因和审核时间
|
|
await connection.query(
|
|
'UPDATE users SET partnerstatus = ?, reasonforfailure = ?, audit_time = ? WHERE userId = ?',
|
|
['reviewfailed', rejectReason, new Date(), userId]
|
|
);
|
|
|
|
// 提交事务
|
|
await connection.commit();
|
|
connection.release();
|
|
|
|
sendResponse(res, true, null, '供应商审核拒绝成功');
|
|
} catch (error) {
|
|
console.error('供应商审核拒绝失败:', error.message);
|
|
console.error('错误详情:', error);
|
|
sendResponse(res, false, null, '供应商审核拒绝失败');
|
|
}
|
|
});
|
|
|
|
// 供应商开始合作API - /api/suppliers/:id/cooperate
|
|
console.log('正在注册供应商开始合作API路由: /api/suppliers/:id/cooperate');
|
|
app.post('/api/suppliers/:id/cooperate', async (req, res) => {
|
|
console.log('收到供应商开始合作请求:', req.params);
|
|
try {
|
|
const connection = await pool.getConnection();
|
|
const userId = req.params.id;
|
|
|
|
if (!userId) {
|
|
connection.release();
|
|
return sendResponse(res, false, null, '用户ID不能为空');
|
|
}
|
|
|
|
// 开始事务
|
|
await connection.beginTransaction();
|
|
|
|
// 检查当前状态
|
|
const [currentUser] = await connection.query(
|
|
'SELECT partnerstatus FROM users WHERE userId = ?',
|
|
[userId]
|
|
);
|
|
|
|
if (currentUser.length === 0) {
|
|
await connection.rollback();
|
|
connection.release();
|
|
return sendResponse(res, false, null, '供应商不存在');
|
|
}
|
|
|
|
if (currentUser[0].partnerstatus !== 'approved') {
|
|
await connection.rollback();
|
|
connection.release();
|
|
return sendResponse(res, false, null, '只有审核通过的供应商才能开始合作');
|
|
}
|
|
|
|
// 更新状态
|
|
await connection.query(
|
|
'UPDATE users SET partnerstatus = ? WHERE userId = ?',
|
|
['incooperation', userId]
|
|
);
|
|
|
|
// 提交事务
|
|
await connection.commit();
|
|
connection.release();
|
|
|
|
sendResponse(res, true, null, '供应商开始合作成功');
|
|
} catch (error) {
|
|
console.error('供应商开始合作失败:', error.message);
|
|
console.error('错误详情:', error);
|
|
sendResponse(res, false, null, '供应商开始合作失败');
|
|
}
|
|
});
|
|
|
|
// 供应商终止合作API - /api/suppliers/:id/terminate
|
|
console.log('正在注册供应商终止合作API路由: /api/suppliers/:id/terminate');
|
|
app.post('/api/suppliers/:id/terminate', async (req, res) => {
|
|
console.log('收到供应商终止合作请求:', req.params, req.body);
|
|
try {
|
|
const connection = await pool.getConnection();
|
|
const userId = req.params.id;
|
|
const { reason } = req.body;
|
|
|
|
if (!userId) {
|
|
connection.release();
|
|
return sendResponse(res, false, null, '用户ID不能为空');
|
|
}
|
|
|
|
// 开始事务
|
|
await connection.beginTransaction();
|
|
|
|
// 检查当前状态
|
|
const [currentUser] = await connection.query(
|
|
'SELECT partnerstatus FROM users WHERE userId = ?',
|
|
[userId]
|
|
);
|
|
|
|
if (currentUser.length === 0) {
|
|
await connection.rollback();
|
|
connection.release();
|
|
return sendResponse(res, false, null, '供应商不存在');
|
|
}
|
|
|
|
if (currentUser[0].partnerstatus !== 'approved' && currentUser[0].partnerstatus !== 'incooperation') {
|
|
await connection.rollback();
|
|
connection.release();
|
|
return sendResponse(res, false, null, '只有审核通过或合作中的供应商才能终止合作');
|
|
}
|
|
|
|
// 更新状态和终止原因
|
|
await connection.query(
|
|
'UPDATE users SET partnerstatus = ?, terminate_reason = ? WHERE userId = ?',
|
|
['notcooperative', reason, userId]
|
|
);
|
|
|
|
// 提交事务
|
|
await connection.commit();
|
|
connection.release();
|
|
|
|
sendResponse(res, true, null, '供应商终止合作成功');
|
|
} catch (error) {
|
|
console.error('供应商终止合作失败:', error.message);
|
|
console.error('错误详情:', error);
|
|
sendResponse(res, false, null, '供应商终止合作失败');
|
|
}
|
|
});
|
|
|
|
// 导入OSS上传工具
|
|
const OssUploader = require('./oss-uploader');
|
|
// 导入图片处理工具
|
|
const ImageProcessor = require('./image-processor');
|
|
|
|
// 创建货源API - /api/supplies/create
|
|
console.log('正在注册创建货源API路由: /api/supplies/create');
|
|
app.post('/api/supplies/create', async (req, res) => {
|
|
console.log('收到创建货源请求:', req.body);
|
|
let connection;
|
|
try {
|
|
connection = await pool.getConnection();
|
|
const { productName, price, quantity, grossWeight, yolk, specification, quality, region, imageUrls, sellerId, supplyStatus, description, sourceType, contactId, category } = req.body;
|
|
|
|
// 开始事务
|
|
await connection.beginTransaction();
|
|
|
|
// 验证必填字段
|
|
if (!productName || !price || !quantity || !supplyStatus || !sourceType) {
|
|
connection.release();
|
|
return sendResponse(res, false, null, '商品名称、价格、最小起订量、货源状态和货源类型不能为空');
|
|
}
|
|
|
|
// 如果sellerId为空,设置一个默认值
|
|
if (!sellerId) {
|
|
sellerId = 'default_seller';
|
|
}
|
|
|
|
// 处理联系人信息
|
|
let productContact = '';
|
|
let contactPhone = '';
|
|
if (contactId) {
|
|
console.log('开始处理联系人信息,contactId:', contactId);
|
|
// 从userlogin数据库获取联系人信息
|
|
const userLoginConnection = await userLoginPool.getConnection();
|
|
const [personnelData] = await userLoginConnection.query(
|
|
'SELECT alias, phoneNumber FROM Personnel WHERE projectName = "销售员" AND phoneNumber IS NOT NULL AND phoneNumber != "" AND id = ?',
|
|
[parseInt(contactId)] // 使用contactId直接查询对应的联系人
|
|
);
|
|
userLoginConnection.release();
|
|
|
|
console.log('查询到的联系人数据:', personnelData);
|
|
if (personnelData && personnelData.length > 0) {
|
|
productContact = personnelData[0].alias || '';
|
|
contactPhone = personnelData[0].phoneNumber || '';
|
|
console.log('获取到的联系人信息:', productContact, contactPhone);
|
|
}
|
|
}
|
|
|
|
console.log('准备插入的联系人信息:', productContact, contactPhone);
|
|
|
|
// 生成唯一的productId
|
|
const productId = `product_${Date.now()}_${Math.floor(Math.random() * 1000)}`;
|
|
|
|
// 处理图片上传
|
|
let uploadedImageUrls = [];
|
|
if (Array.isArray(imageUrls) && imageUrls.length > 0) {
|
|
console.log('开始处理图片上传,共', imageUrls.length, '张图片');
|
|
|
|
for (const imageUrl of imageUrls) {
|
|
if (imageUrl.startsWith('data:image/')) {
|
|
// 处理DataURL
|
|
const base64Data = imageUrl.replace(/^data:image\/(png|jpeg|jpg|gif);base64,/, '');
|
|
let buffer = Buffer.from(base64Data, 'base64');
|
|
const ext = imageUrl.match(/^data:image\/(png|jpeg|jpg|gif);base64,/)?.[1] || 'png';
|
|
const filename = `${Date.now()}-${Math.random().toString(36).substr(2, 9)}.${ext}`;
|
|
|
|
try {
|
|
// 不再添加水印,前端已处理
|
|
console.log('【水印处理】前端已添加水印,跳过后端水印处理');
|
|
|
|
// 使用OSS上传带水印的图片
|
|
const ossUrl = await OssUploader.uploadBuffer(buffer, filename, `products/${productName || 'general'}`, 'image');
|
|
uploadedImageUrls.push(ossUrl);
|
|
console.log('图片上传成功:', ossUrl);
|
|
} catch (uploadError) {
|
|
console.error('图片上传失败:', uploadError.message);
|
|
// 继续上传其他图片,不中断流程
|
|
}
|
|
} else {
|
|
// 已经是URL,直接使用
|
|
uploadedImageUrls.push(imageUrl);
|
|
}
|
|
}
|
|
console.log('图片处理完成,成功上传', uploadedImageUrls.length, '张图片');
|
|
}
|
|
|
|
// 创建商品数据
|
|
const productData = {
|
|
productId,
|
|
sellerId: sellerId, // 使用前端传入的sellerId
|
|
productName,
|
|
category: category || '', // 添加种类
|
|
price: price.toString(), // 确保是varchar类型
|
|
quantity: parseInt(quantity),
|
|
grossWeight,
|
|
yolk,
|
|
specification,
|
|
quality,
|
|
region,
|
|
status: 'published', // 直接上架,而不是审核中
|
|
supplyStatus: supplyStatus || '', // 预售/现货
|
|
sourceType: sourceType || '', // 平台货源/三方认证/三方未认证
|
|
description: description || '',
|
|
rejectReason: '',
|
|
imageUrls: uploadedImageUrls.length > 0 ? JSON.stringify(uploadedImageUrls) : '[]',
|
|
created_at: new Date(),
|
|
product_contact: productContact, // 添加联系人名称
|
|
contact_phone: contactPhone // 添加联系人电话
|
|
};
|
|
|
|
// 插入商品数据
|
|
let result;
|
|
try {
|
|
// 检查products表是否有quality字段
|
|
const [columns] = await connection.query('SHOW COLUMNS FROM products LIKE ?', ['quality']);
|
|
let insertQuery;
|
|
let insertParams;
|
|
|
|
if (columns.length === 0) {
|
|
// 没有quality字段,不包含quality字段的插入
|
|
insertQuery = 'INSERT INTO products (productId, sellerId, productName, category, price, quantity, grossWeight, yolk, specification, region, status, supplyStatus, sourceType, description, rejectReason, imageUrls, created_at, audit_time, product_contact, contact_phone) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)';
|
|
insertParams = [
|
|
productId, productData.sellerId, productName, category || '', price.toString(), parseInt(quantity), grossWeight,
|
|
yolk, specification, region, productData.status, productData.supplyStatus, productData.sourceType,
|
|
productData.description, productData.rejectReason, productData.imageUrls, new Date(), new Date(),
|
|
productContact, contactPhone // 添加联系人信息
|
|
];
|
|
} else {
|
|
// 有quality字段,包含quality字段的插入
|
|
insertQuery = 'INSERT INTO products (productId, sellerId, productName, category, price, quantity, grossWeight, yolk, specification, quality, region, status, supplyStatus, sourceType, description, rejectReason, imageUrls, created_at, audit_time, product_contact, contact_phone) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)';
|
|
insertParams = [
|
|
productId, productData.sellerId, productName, category || '', price.toString(), parseInt(quantity), grossWeight,
|
|
yolk, specification, quality, region, productData.status, productData.supplyStatus,
|
|
productData.sourceType, productData.description, productData.rejectReason, productData.imageUrls,
|
|
new Date(), new Date(), productContact, contactPhone // 添加联系人信息
|
|
];
|
|
}
|
|
|
|
result = await connection.query(insertQuery, insertParams);
|
|
} catch (insertError) {
|
|
await connection.rollback();
|
|
connection.release();
|
|
console.error('插入商品数据失败:', insertError.message);
|
|
console.error('SQL错误:', insertError.sqlMessage);
|
|
return sendResponse(res, false, null, `创建货源失败: ${insertError.sqlMessage}`);
|
|
}
|
|
|
|
// 提交事务
|
|
await connection.commit();
|
|
connection.release();
|
|
|
|
sendResponse(res, true, { productId: result.insertId }, '货源创建成功');
|
|
} catch (error) {
|
|
if (connection) {
|
|
try {
|
|
await connection.rollback();
|
|
connection.release();
|
|
} catch (rollbackError) {
|
|
console.error('回滚失败:', rollbackError.message);
|
|
}
|
|
}
|
|
console.error('创建货源失败:', error.message);
|
|
console.error('错误详情:', error);
|
|
sendResponse(res, false, null, `创建货源失败: ${error.message}`);
|
|
}
|
|
});
|
|
|
|
// 图片上传API - /api/upload-image
|
|
console.log('正在注册图片上传API路由: /api/upload-image');
|
|
app.post('/api/upload-image', async (req, res) => {
|
|
console.log('收到图片上传请求');
|
|
// 注意:这里需要实现实际的图片上传逻辑,包括OSS配置
|
|
// 由于当前缺少OSS配置,返回模拟数据
|
|
sendResponse(res, true, {
|
|
imageUrl: 'https://example.com/image.jpg',
|
|
message: '图片上传成功'
|
|
}, '图片上传成功');
|
|
});
|
|
|
|
// 获取审核失败原因API - /api/supplies/:id/reject-reason
|
|
console.log('正在注册获取审核失败原因API路由: /api/supplies/:id/reject-reason');
|
|
app.get('/api/supplies/:id/reject-reason', async (req, res) => {
|
|
console.log('收到获取审核失败原因请求:', req.params.id);
|
|
try {
|
|
const connection = await pool.getConnection();
|
|
const supplyId = req.params.id;
|
|
|
|
// 查询该货源的拒绝原因
|
|
const [supply] = await connection.query(
|
|
'SELECT rejectReason FROM products WHERE id = ?',
|
|
[supplyId]
|
|
);
|
|
|
|
connection.release();
|
|
|
|
if (supply.length === 0) {
|
|
return sendResponse(res, false, null, '货源不存在');
|
|
}
|
|
|
|
sendResponse(res, true, {
|
|
rejectReason: supply[0].rejectReason
|
|
}, '获取审核失败原因成功');
|
|
} catch (error) {
|
|
console.error('获取审核失败原因失败:', error.message);
|
|
sendResponse(res, false, null, '获取审核失败原因失败');
|
|
}
|
|
});
|
|
|
|
// 下架货源API - /api/supplies/:id/unpublish
|
|
console.log('正在注册下架货源API路由: /api/supplies/:id/unpublish');
|
|
app.post('/api/supplies/:id/unpublish', async (req, res) => {
|
|
console.log('收到下架货源请求:', req.params.id);
|
|
try {
|
|
const connection = await pool.getConnection();
|
|
const productId = req.params.id;
|
|
|
|
// 开始事务
|
|
await connection.beginTransaction();
|
|
|
|
// 检查当前状态
|
|
const [currentProduct] = await connection.query(
|
|
'SELECT status FROM products WHERE id = ?',
|
|
[productId]
|
|
);
|
|
|
|
if (currentProduct.length === 0) {
|
|
await connection.rollback();
|
|
connection.release();
|
|
return sendResponse(res, false, null, '货源不存在');
|
|
}
|
|
|
|
// 更新状态为下架
|
|
await connection.query(
|
|
'UPDATE products SET status = ? WHERE id = ?',
|
|
['hidden', productId]
|
|
);
|
|
|
|
// 提交事务
|
|
await connection.commit();
|
|
connection.release();
|
|
|
|
sendResponse(res, true, null, '货源下架成功');
|
|
} catch (error) {
|
|
console.error('下架货源失败:', error.message);
|
|
console.error('错误详情:', error);
|
|
sendResponse(res, false, null, '货源下架失败');
|
|
}
|
|
});
|
|
|
|
// 上架货源API - /api/supplies/:id/publish
|
|
console.log('正在注册上架货源API路由: /api/supplies/:id/publish');
|
|
app.post('/api/supplies/:id/publish', async (req, res) => {
|
|
console.log('收到上架货源请求:', req.params.id);
|
|
try {
|
|
const connection = await pool.getConnection();
|
|
const productId = req.params.id;
|
|
|
|
// 开始事务
|
|
await connection.beginTransaction();
|
|
|
|
// 检查当前状态
|
|
const [currentProduct] = await connection.query(
|
|
'SELECT status FROM products WHERE id = ?',
|
|
[productId]
|
|
);
|
|
|
|
if (currentProduct.length === 0) {
|
|
await connection.rollback();
|
|
connection.release();
|
|
return sendResponse(res, false, null, '货源不存在');
|
|
}
|
|
|
|
// 更新状态为审核中
|
|
await connection.query(
|
|
'UPDATE products SET status = ? WHERE id = ?',
|
|
['pending_review', productId]
|
|
);
|
|
|
|
// 提交事务
|
|
await connection.commit();
|
|
connection.release();
|
|
|
|
sendResponse(res, true, null, '货源已提交审核');
|
|
} catch (error) {
|
|
console.error('上架货源失败:', error.message);
|
|
console.error('错误详情:', error);
|
|
sendResponse(res, false, null, '货源上架失败');
|
|
}
|
|
});
|
|
|
|
// 删除货源API - /api/supplies/:id/delete
|
|
console.log('正在注册删除货源API路由: /api/supplies/:id/delete');
|
|
app.post('/api/supplies/:id/delete', async (req, res) => {
|
|
console.log('收到删除货源请求:', req.params.id);
|
|
try {
|
|
const connection = await pool.getConnection();
|
|
const productId = req.params.id;
|
|
|
|
// 开始事务
|
|
await connection.beginTransaction();
|
|
|
|
// 检查当前状态
|
|
const [currentProduct] = await connection.query(
|
|
'SELECT status FROM products WHERE id = ?',
|
|
[productId]
|
|
);
|
|
|
|
if (currentProduct.length === 0) {
|
|
await connection.rollback();
|
|
connection.release();
|
|
return sendResponse(res, false, null, '货源不存在');
|
|
}
|
|
|
|
// 删除货源
|
|
await connection.query(
|
|
'DELETE FROM products WHERE id = ?',
|
|
[productId]
|
|
);
|
|
|
|
// 提交事务
|
|
await connection.commit();
|
|
connection.release();
|
|
|
|
sendResponse(res, true, null, '货源删除成功');
|
|
} catch (error) {
|
|
console.error('删除货源失败:', error.message);
|
|
console.error('错误详情:', error);
|
|
sendResponse(res, false, null, '货源删除失败');
|
|
}
|
|
});
|
|
|
|
// 编辑货源API - /api/supplies/:id/edit
|
|
console.log('正在注册编辑货源API路由: /api/supplies/:id/edit');
|
|
app.put('/api/supplies/:id/edit', async (req, res) => {
|
|
console.log('收到编辑货源请求:', req.params.id, req.body);
|
|
try {
|
|
const connection = await pool.getConnection();
|
|
const productId = req.params.id;
|
|
const { productName, price, quantity, grossWeight, yolk, specification, supplyStatus, description, region, contactId } = req.body;
|
|
|
|
// 开始事务
|
|
await connection.beginTransaction();
|
|
|
|
// 检查当前状态
|
|
const [currentProduct] = await connection.query(
|
|
'SELECT status FROM products WHERE id = ?',
|
|
[productId]
|
|
);
|
|
|
|
if (currentProduct.length === 0) {
|
|
await connection.rollback();
|
|
connection.release();
|
|
return sendResponse(res, false, null, '货源不存在');
|
|
}
|
|
|
|
// 处理联系人信息
|
|
let productContact = '';
|
|
let contactPhone = '';
|
|
if (contactId) {
|
|
// 从userlogin数据库获取联系人信息
|
|
const userLoginConnection = await userLoginPool.getConnection();
|
|
const [personnelData] = await userLoginConnection.query(
|
|
'SELECT alias, phoneNumber FROM Personnel WHERE projectName = "销售员" AND phoneNumber IS NOT NULL AND phoneNumber != "" AND id = ?',
|
|
[parseInt(contactId)] // 使用contactId直接查询对应的联系人
|
|
);
|
|
userLoginConnection.release();
|
|
|
|
if (personnelData && personnelData.length > 0) {
|
|
productContact = personnelData[0].alias || '';
|
|
contactPhone = personnelData[0].phoneNumber || '';
|
|
}
|
|
}
|
|
|
|
// 更新货源信息
|
|
const updateQuery = `
|
|
UPDATE products
|
|
SET productName = ?, price = ?, quantity = ?, grossWeight = ?,
|
|
yolk = ?, specification = ?, supplyStatus = ?, description = ?, region = ?,
|
|
product_contact = ?, contact_phone = ?
|
|
WHERE id = ?
|
|
`;
|
|
|
|
await connection.query(updateQuery, [
|
|
productName, price.toString(), parseInt(quantity), grossWeight,
|
|
yolk, specification, supplyStatus, description, region,
|
|
productContact, contactPhone, productId
|
|
]);
|
|
|
|
// 提交事务
|
|
await connection.commit();
|
|
connection.release();
|
|
|
|
sendResponse(res, true, null, '货源编辑成功');
|
|
} catch (error) {
|
|
console.error('编辑货源失败:', error.message);
|
|
console.error('错误详情:', error);
|
|
sendResponse(res, false, null, '货源编辑失败');
|
|
}
|
|
});
|
|
|
|
// 供应商列表查询API - /api/suppliers
|
|
console.log('正在注册供应商列表查询API路由: /api/suppliers');
|
|
app.get('/api/suppliers', async (req, res) => {
|
|
console.log('收到供应商列表查询请求:', req.query);
|
|
try {
|
|
const connection = await pool.getConnection();
|
|
const { page = 1, pageSize = 10, status = '', keyword = '', phoneNumber = '' } = req.query;
|
|
|
|
// 构建查询条件
|
|
let whereClause = '';
|
|
let params = [];
|
|
|
|
// 添加状态筛选
|
|
if (status) {
|
|
whereClause += ` WHERE partnerstatus = ?`;
|
|
params.push(status);
|
|
}
|
|
|
|
// 添加关键词搜索
|
|
if (keyword) {
|
|
whereClause += status ? ' AND' : ' WHERE';
|
|
whereClause += ` (username LIKE ? OR company LIKE ? OR phoneNumber LIKE ?)`;
|
|
params.push(`%${keyword}%`, `%${keyword}%`, `%${keyword}%`);
|
|
}
|
|
|
|
// 添加手机号搜索(优先级高于keyword中的手机号搜索)
|
|
if (phoneNumber) {
|
|
whereClause += (status || keyword) ? ' AND' : ' WHERE';
|
|
whereClause += ` phoneNumber LIKE ?`;
|
|
params.push(`%${phoneNumber}%`);
|
|
}
|
|
|
|
// 获取总数
|
|
const [totalResult] = await connection.query(
|
|
`SELECT COUNT(*) as total FROM users${whereClause}`,
|
|
params
|
|
);
|
|
const total = totalResult[0].total;
|
|
|
|
// 计算分页
|
|
const offset = (page - 1) * pageSize;
|
|
params.push(parseInt(pageSize), offset);
|
|
|
|
// 查询供应商列表
|
|
const [suppliers] = await connection.query(
|
|
`SELECT userId, phoneNumber, province, city, district, detailedaddress, company, collaborationid, cooperation, businesslicenseurl, proofurl, brandurl, partnerstatus, reasonforfailure, reject_reason, terminate_reason, audit_time
|
|
FROM users${whereClause}
|
|
ORDER BY audit_time DESC LIMIT ? OFFSET ?`,
|
|
params
|
|
);
|
|
|
|
connection.release();
|
|
|
|
sendResponse(res, true, {
|
|
list: suppliers,
|
|
total,
|
|
page: parseInt(page),
|
|
pageSize: parseInt(pageSize)
|
|
}, '查询成功');
|
|
} catch (error) {
|
|
console.error('供应商列表查询失败:', error.message);
|
|
console.error('错误详情:', error);
|
|
sendResponse(res, false, null, '供应商列表查询失败');
|
|
}
|
|
});
|
|
|
|
// 首页路由
|
|
app.get('/', (req, res) => {
|
|
res.sendFile(path.join(__dirname, 'Reject.html'));
|
|
});
|
|
|
|
// 错误处理中间件
|
|
app.use((err, req, res, next) => {
|
|
console.error('服务器错误:', err.message);
|
|
console.error('错误详情:', err);
|
|
res.status(500).json({
|
|
success: false,
|
|
message: '服务器内部错误'
|
|
});
|
|
});
|
|
|
|
// 启动服务器
|
|
async function startServer() {
|
|
try {
|
|
await initDatabase();
|
|
|
|
app.listen(PORT, () => {
|
|
console.log(`服务器已启动,监听端口 ${PORT}`);
|
|
console.log(`访问地址: http://localhost:${PORT}`);
|
|
});
|
|
} catch (error) {
|
|
console.error('服务器启动失败:', error.message);
|
|
console.error('错误详情:', error);
|
|
// 如果启动失败,尝试重新启动
|
|
setTimeout(() => {
|
|
console.log('尝试重新启动服务器...');
|
|
startServer();
|
|
}, 5000);
|
|
}
|
|
}
|
|
|
|
// 确保数据库结构
|
|
async function ensureDatabaseSchema() {
|
|
console.log('开始执行数据库结构检查...');
|
|
try {
|
|
const connection = await pool.getConnection();
|
|
console.log('获取数据库连接成功');
|
|
|
|
// 检查users表是否有必要的字段
|
|
console.log('检查users表是否有partnerstatus字段...');
|
|
const [partnerStatusColumns] = await connection.query(
|
|
'SHOW COLUMNS FROM `users` LIKE ?',
|
|
['partnerstatus']
|
|
);
|
|
console.log('检查表字段结果:', partnerStatusColumns.length > 0 ? '已存在' : '不存在');
|
|
|
|
if (partnerStatusColumns.length === 0) {
|
|
console.log('添加partnerstatus字段到users表...');
|
|
await connection.query(
|
|
'ALTER TABLE `users` ADD COLUMN partnerstatus VARCHAR(50) DEFAULT "underreview" COMMENT "合作商状态"'
|
|
);
|
|
console.log('partnerstatus字段添加成功');
|
|
}
|
|
|
|
console.log('检查users表是否有reject_reason字段...');
|
|
const [rejectReasonColumns] = await connection.query(
|
|
'SHOW COLUMNS FROM `users` LIKE ?',
|
|
['reject_reason']
|
|
);
|
|
console.log('检查表字段结果:', rejectReasonColumns.length > 0 ? '已存在' : '不存在');
|
|
|
|
if (rejectReasonColumns.length === 0) {
|
|
console.log('添加reject_reason字段到users表...');
|
|
await connection.query(
|
|
'ALTER TABLE `users` ADD COLUMN reject_reason TEXT COMMENT "拒绝理由"'
|
|
);
|
|
console.log('reject_reason字段添加成功');
|
|
}
|
|
|
|
console.log('检查users表是否有terminate_reason字段...');
|
|
const [terminateReasonColumns] = await connection.query(
|
|
'SHOW COLUMNS FROM `users` LIKE ?',
|
|
['terminate_reason']
|
|
);
|
|
console.log('检查表字段结果:', terminateReasonColumns.length > 0 ? '已存在' : '不存在');
|
|
|
|
if (terminateReasonColumns.length === 0) {
|
|
console.log('添加terminate_reason字段到users表...');
|
|
await connection.query(
|
|
'ALTER TABLE `users` ADD COLUMN terminate_reason TEXT COMMENT "终止合作理由"'
|
|
);
|
|
console.log('terminate_reason字段添加成功');
|
|
}
|
|
|
|
console.log('检查users表是否有audit_time字段...');
|
|
const [userAuditTimeColumns] = await connection.query(
|
|
'SHOW COLUMNS FROM `users` LIKE ?',
|
|
['audit_time']
|
|
);
|
|
console.log('检查表字段结果:', userAuditTimeColumns.length > 0 ? '已存在' : '不存在');
|
|
|
|
if (userAuditTimeColumns.length === 0) {
|
|
console.log('添加audit_time字段到users表...');
|
|
await connection.query(
|
|
'ALTER TABLE `users` ADD COLUMN audit_time DATETIME COMMENT "审核时间"'
|
|
);
|
|
console.log('audit_time字段添加成功');
|
|
}
|
|
|
|
// 检查表是否有rejectReason字段
|
|
console.log('检查表products是否有rejectReason字段...');
|
|
const [columns] = await connection.query(
|
|
'SHOW COLUMNS FROM `products` LIKE ?',
|
|
['rejectReason']
|
|
);
|
|
console.log('检查表字段结果:', columns.length > 0 ? '已存在' : '不存在');
|
|
|
|
if (columns.length === 0) {
|
|
console.log('添加rejectReason字段到products表...');
|
|
await connection.query(
|
|
'ALTER TABLE `products` ADD COLUMN rejectReason TEXT COMMENT "拒绝理由"'
|
|
);
|
|
console.log('rejectReason字段添加成功');
|
|
}
|
|
|
|
// 检查表是否有audit_time字段
|
|
console.log('检查表products是否有audit_time字段...');
|
|
const [auditTimeColumns] = await connection.query(
|
|
'SHOW COLUMNS FROM `products` LIKE ?',
|
|
['audit_time']
|
|
);
|
|
console.log('检查表字段结果:', auditTimeColumns.length > 0 ? '已存在' : '不存在');
|
|
|
|
if (auditTimeColumns.length === 0) {
|
|
console.log('添加audit_time字段到products表...');
|
|
await connection.query(
|
|
'ALTER TABLE `products` ADD COLUMN audit_time DATETIME COMMENT "审核时间"'
|
|
);
|
|
console.log('audit_time字段添加成功');
|
|
}
|
|
|
|
// 检查audit_logs表是否存在,如果不存在则创建
|
|
console.log('检查audit_logs表是否存在...');
|
|
const [tables] = await connection.query(
|
|
"SHOW TABLES LIKE 'audit_logs'"
|
|
);
|
|
console.log('检查表存在性结果:', tables.length > 0 ? '已存在' : '不存在');
|
|
|
|
if (tables.length === 0) {
|
|
console.log('创建audit_logs表...');
|
|
await connection.query(`
|
|
CREATE TABLE audit_logs (
|
|
id INT AUTO_INCREMENT PRIMARY KEY,
|
|
supply_id VARCHAR(50) NOT NULL,
|
|
action VARCHAR(20) NOT NULL COMMENT 'approve或reject',
|
|
user_id VARCHAR(50) NOT NULL COMMENT '操作人ID',
|
|
remark TEXT COMMENT '备注信息',
|
|
created_at DATETIME NOT NULL,
|
|
INDEX idx_supply_id (supply_id),
|
|
INDEX idx_created_at (created_at)
|
|
) COMMENT '审核操作日志表'
|
|
`);
|
|
console.log('audit_logs表创建成功');
|
|
}
|
|
|
|
connection.release();
|
|
console.log('数据库结构检查完成');
|
|
} catch (error) {
|
|
console.error('数据库结构检查失败:', error.message);
|
|
console.error('错误详情:', error);
|
|
}
|
|
}
|
|
|
|
// 启动服务器
|
|
startServer();
|
|
|
|
// 优雅关闭
|
|
process.on('SIGINT', async () => {
|
|
console.log('正在关闭服务器...');
|
|
if (pool) {
|
|
try {
|
|
await pool.end();
|
|
console.log('数据库连接池已关闭');
|
|
} catch (error) {
|
|
console.error('关闭数据库连接池失败:', error.message);
|
|
}
|
|
}
|
|
console.log('服务器已关闭');
|
|
process.exit(0);
|
|
});
|
|
|
|
module.exports = app;
|