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.
233 lines
8.0 KiB
233 lines
8.0 KiB
|
3 months ago
|
// 数据库服务
|
||
|
|
const mysql = require('mysql2/promise');
|
||
|
|
const config = require('../config/config');
|
||
|
|
|
||
|
|
class DatabaseService {
|
||
|
|
constructor() {
|
||
|
|
this.connection = null;
|
||
|
|
}
|
||
|
|
|
||
|
|
// 连接数据库
|
||
|
|
async connect() {
|
||
|
|
try {
|
||
|
|
this.connection = await mysql.createConnection({
|
||
|
|
host: config.db.host,
|
||
|
|
port: config.db.port,
|
||
|
|
user: config.db.user,
|
||
|
|
password: config.db.password,
|
||
|
|
database: config.db.database
|
||
|
|
});
|
||
|
|
console.log('数据库连接成功');
|
||
|
|
} catch (error) {
|
||
|
|
console.error('数据库连接失败:', error.message);
|
||
|
|
throw error;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// 断开数据库连接
|
||
|
|
async disconnect() {
|
||
|
|
if (this.connection) {
|
||
|
|
await this.connection.end();
|
||
|
|
console.log('数据库连接已断开');
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// 查询需要同步的数据
|
||
|
|
async getAllSyncData() {
|
||
|
|
try {
|
||
|
|
// 根据配置决定是查询所有数据还是仅未同步数据
|
||
|
|
let usersQuery = `SELECT ${config.tables.users.fields.id},
|
||
|
|
${config.tables.users.fields.userId},
|
||
|
|
${config.tables.users.fields.company},
|
||
|
|
${config.tables.users.fields.name},
|
||
|
|
${config.tables.users.fields.phoneNumber},
|
||
|
|
${config.tables.users.fields.type},
|
||
|
|
${config.tables.users.fields.city}
|
||
|
|
FROM ${config.tables.users.name}`;
|
||
|
|
|
||
|
|
// 如果是增量同步,只查询未同步的数据
|
||
|
|
if (config.sync.incremental) {
|
||
|
|
usersQuery += ` WHERE ${config.sync.statusField} = ${config.sync.unsyncedValue}`;
|
||
|
|
console.log('启用增量同步模式,只查询未同步的数据');
|
||
|
|
} else {
|
||
|
|
console.log('启用全量同步模式,查询所有数据');
|
||
|
|
}
|
||
|
|
|
||
|
|
console.log('执行查询:', usersQuery);
|
||
|
|
const [users] = await this.connection.execute(usersQuery);
|
||
|
|
console.log(`查询结果: 共找到 ${users.length} 条需要同步的用户数据`);
|
||
|
|
|
||
|
|
const syncData = [];
|
||
|
|
|
||
|
|
// 为每个用户查询对应的cart_items和products数据
|
||
|
|
for (const user of users) {
|
||
|
|
const userId = user[config.tables.users.fields.userId];
|
||
|
|
|
||
|
|
// 查询cart_items表(buyer数据)
|
||
|
|
const [cartItems] = await this.connection.execute(
|
||
|
|
`SELECT ${config.tables.cartItems.fields.productName},
|
||
|
|
${config.tables.cartItems.fields.specification},
|
||
|
|
${config.tables.cartItems.fields.quantity},
|
||
|
|
${config.tables.cartItems.fields.yolk}
|
||
|
|
FROM ${config.tables.cartItems.name}
|
||
|
|
WHERE ${config.tables.cartItems.fields.userId} = ?`,
|
||
|
|
[userId]
|
||
|
|
);
|
||
|
|
|
||
|
|
// 查询products表(sell数据)
|
||
|
|
const [products] = await this.connection.execute(
|
||
|
|
`SELECT ${config.tables.products.fields.productName},
|
||
|
|
${config.tables.products.fields.specification},
|
||
|
|
${config.tables.products.fields.quantity},
|
||
|
|
${config.tables.products.fields.yolk}
|
||
|
|
FROM ${config.tables.products.name}
|
||
|
|
WHERE ${config.tables.products.fields.sellerId} = ?`,
|
||
|
|
[userId]
|
||
|
|
);
|
||
|
|
|
||
|
|
syncData.push({
|
||
|
|
user,
|
||
|
|
cartItems,
|
||
|
|
products,
|
||
|
|
userId: userId // 保存用户ID,用于同步后更新状态
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
return syncData;
|
||
|
|
} catch (error) {
|
||
|
|
console.error('查询数据失败:', error.message);
|
||
|
|
throw error;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// 获取一条测试数据用于API测试
|
||
|
|
async getTestData() {
|
||
|
|
try {
|
||
|
|
// 获取一条用户数据
|
||
|
|
const [users] = await this.connection.execute(
|
||
|
|
`SELECT ${config.tables.users.fields.id},
|
||
|
|
${config.tables.users.fields.userId},
|
||
|
|
${config.tables.users.fields.company},
|
||
|
|
${config.tables.users.fields.name},
|
||
|
|
${config.tables.users.fields.phoneNumber},
|
||
|
|
${config.tables.users.fields.type},
|
||
|
|
${config.tables.users.fields.city}
|
||
|
|
FROM ${config.tables.users.name} LIMIT 1`
|
||
|
|
);
|
||
|
|
|
||
|
|
if (users.length === 0) {
|
||
|
|
console.error('没有找到用户数据');
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
|
||
|
|
const user = users[0];
|
||
|
|
const userId = user[config.tables.users.fields.id];
|
||
|
|
|
||
|
|
// 获取该用户的购物车数据
|
||
|
|
const [cartItems] = await this.connection.execute(
|
||
|
|
`SELECT ${config.tables.cartItems.fields.productName},
|
||
|
|
${config.tables.cartItems.fields.specification},
|
||
|
|
${config.tables.cartItems.fields.quantity},
|
||
|
|
${config.tables.cartItems.fields.yolk}
|
||
|
|
FROM ${config.tables.cartItems.name}
|
||
|
|
WHERE ${config.tables.cartItems.fields.userId} = ?`,
|
||
|
|
[userId]
|
||
|
|
);
|
||
|
|
|
||
|
|
// 获取该用户的产品数据
|
||
|
|
const [products] = await this.connection.execute(
|
||
|
|
`SELECT ${config.tables.products.fields.productName},
|
||
|
|
${config.tables.products.fields.specification},
|
||
|
|
${config.tables.products.fields.quantity},
|
||
|
|
${config.tables.products.fields.yolk}
|
||
|
|
FROM ${config.tables.products.name}
|
||
|
|
WHERE ${config.tables.products.fields.sellerId} = ?`,
|
||
|
|
[userId]
|
||
|
|
);
|
||
|
|
|
||
|
|
return {
|
||
|
|
user,
|
||
|
|
cartItems,
|
||
|
|
products
|
||
|
|
};
|
||
|
|
} catch (error) {
|
||
|
|
console.error('获取测试数据失败:', error.message);
|
||
|
|
throw error;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// 更新数据同步状态
|
||
|
|
async updateSyncStatus(userId, synced) {
|
||
|
|
try {
|
||
|
|
const statusValue = synced ? config.sync.syncedValue : config.sync.unsyncedValue;
|
||
|
|
const now = new Date();
|
||
|
|
|
||
|
|
await this.connection.execute(
|
||
|
|
`UPDATE ${config.tables.users.name}
|
||
|
|
SET ${config.sync.statusField} = ?, ${config.sync.timeField} = ?
|
||
|
|
WHERE ${config.tables.users.fields.userId} = ?`,
|
||
|
|
[statusValue, now, userId]
|
||
|
|
);
|
||
|
|
|
||
|
|
console.log(`用户 ${userId} 的同步状态已更新为: ${synced ? '已同步' : '未同步'}`);
|
||
|
|
} catch (error) {
|
||
|
|
console.error(`更新用户 ${userId} 同步状态失败:`, error.message);
|
||
|
|
throw error;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// 测试数据库连接和表结构
|
||
|
|
async testDatabaseConnection() {
|
||
|
|
try {
|
||
|
|
// 测试连接
|
||
|
|
await this.connect();
|
||
|
|
|
||
|
|
// 查询表结构
|
||
|
|
const tables = [config.tables.users.name, config.tables.cartItems.name, config.tables.products.name];
|
||
|
|
|
||
|
|
for (const table of tables) {
|
||
|
|
console.log(`\n--- 表 ${table} 结构 ---`);
|
||
|
|
const [columns] = await this.connection.execute(`DESCRIBE ${table}`);
|
||
|
|
columns.forEach(column => {
|
||
|
|
console.log(`${column.Field}: ${column.Type} ${column.Null === 'YES' ? '(允许为空)' : '(不允许为空)'} ${column.Key === 'PRI' ? '(主键)' : ''}`);
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
// 查询示例数据
|
||
|
|
console.log(`\n--- 示例数据 ---`);
|
||
|
|
const [usersSample] = await this.connection.execute(`SELECT * FROM ${config.tables.users.name} LIMIT 1`);
|
||
|
|
if (usersSample.length > 0) {
|
||
|
|
console.log('用户表示例数据:', usersSample[0]);
|
||
|
|
|
||
|
|
const userId = usersSample[0][config.tables.users.fields.id];
|
||
|
|
const [cartItemsSample] = await this.connection.execute(
|
||
|
|
`SELECT * FROM ${config.tables.cartItems.name} WHERE ${config.tables.cartItems.fields.userId} = ? LIMIT 1`,
|
||
|
|
[userId]
|
||
|
|
);
|
||
|
|
if (cartItemsSample.length > 0) {
|
||
|
|
console.log('购物车表示例数据:', cartItemsSample[0]);
|
||
|
|
}
|
||
|
|
|
||
|
|
const [productsSample] = await this.connection.execute(
|
||
|
|
`SELECT * FROM ${config.tables.products.name} WHERE ${config.tables.products.fields.sellerId} = ? LIMIT 1`,
|
||
|
|
[userId]
|
||
|
|
);
|
||
|
|
if (productsSample.length > 0) {
|
||
|
|
console.log('产品表示例数据:', productsSample[0]);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
await this.disconnect();
|
||
|
|
return true;
|
||
|
|
} catch (error) {
|
||
|
|
console.error('数据库测试失败:', error.message);
|
||
|
|
if (this.connection) {
|
||
|
|
await this.disconnect();
|
||
|
|
}
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
module.exports = new DatabaseService();
|