Files
jurong_circle_black/config/database-init.js

1105 lines
46 KiB
JavaScript
Raw Normal View History

2025-08-26 10:06:23 +08:00
const mysql = require('mysql2/promise');
const bcrypt = require('bcryptjs');
const { initDB, getDB, dbConfig } = require('../database');
/**
* 数据库初始化函数
* 创建所有必要的表结构和初始数据
*/
async function initDatabase() {
try {
// 首先创建数据库(如果不存在)
const tempConnection = await mysql.createConnection({
host: dbConfig.host,
user: dbConfig.user,
password: dbConfig.password
});
// 创建数据库
await tempConnection.execute(`CREATE DATABASE IF NOT EXISTS ${dbConfig.database} CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci`);
await tempConnection.end();
// 初始化数据库连接池
await initDB();
console.log('数据库连接池初始化成功');
// 创建所有表
await createTables();
// 添加字段(处理表结构升级)
await addMissingFields();
// 创建默认数据
await createDefaultData();
console.log('数据库初始化完成');
} catch (error) {
console.error('数据库初始化失败:', error);
throw error;
}
}
/**
* 创建所有数据库表
*/
async function createTables() {
// 用户表
await getDB().execute(`
CREATE TABLE IF NOT EXISTS users (
id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) UNIQUE NOT NULL,
phone VARCHAR(20) UNIQUE,
password VARCHAR(255) NOT NULL,
role ENUM('user', 'admin') DEFAULT 'user',
avatar VARCHAR(255),
points INT DEFAULT 0,
2025-09-02 09:29:20 +08:00
rongdou INT DEFAULT 0,
2025-08-26 10:06:23 +08:00
balance DECIMAL(10,2) DEFAULT 0.00,
real_name VARCHAR(100),
id_card VARCHAR(18),
wechat_qr VARCHAR(255),
alipay_qr VARCHAR(255),
bank_card VARCHAR(30),
unionpay_qr VARCHAR(255),
business_license VARCHAR(500),
id_card_front VARCHAR(500),
id_card_back VARCHAR(500),
audit_status ENUM('pending', 'approved', 'rejected') DEFAULT 'pending',
audit_note TEXT,
audited_by INT,
audited_at TIMESTAMP NULL,
city VARCHAR(50),
district_id INT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
FOREIGN KEY (audited_by) REFERENCES users(id),
FOREIGN KEY (district_id) REFERENCES zhejiang_regions(id)
)
`);
// 商品表
await getDB().execute(`
CREATE TABLE IF NOT EXISTS products (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255) NOT NULL,
description TEXT,
price INT NOT NULL,
points_price INT NOT NULL,
2025-08-28 09:14:56 +08:00
rongdou_price INT NOT NULL DEFAULT 0,
2025-08-26 10:06:23 +08:00
original_price INT,
stock INT DEFAULT 0,
sales INT DEFAULT 0,
rating DECIMAL(3,2) DEFAULT 5.00,
category VARCHAR(100),
image_url VARCHAR(500),
images JSON,
2025-08-28 09:14:56 +08:00
videos JSON,
2025-08-26 10:06:23 +08:00
details TEXT,
2025-08-28 09:14:56 +08:00
shop_name VARCHAR(255),
shop_avatar VARCHAR(500),
payment_methods JSON,
2025-08-26 10:06:23 +08:00
status ENUM('active', 'inactive') DEFAULT 'active',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
)
`);
// 订单表
await getDB().execute(`
CREATE TABLE IF NOT EXISTS orders (
id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT NOT NULL,
order_no VARCHAR(50) UNIQUE NOT NULL,
total_amount INT NOT NULL,
total_points INT NOT NULL,
2025-09-02 09:29:20 +08:00
total_rongdou INT NOT NULL DEFAULT 0,
status ENUM('pending', 'paid', 'shipped', 'delivered', 'cancelled', 'pre_order') DEFAULT 'pending',
2025-08-26 10:06:23 +08:00
address JSON,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users(id)
)
`);
// 创建转账记录表
await getDB().execute(`
CREATE TABLE IF NOT EXISTS transfers (
id INT AUTO_INCREMENT PRIMARY KEY,
from_user_id INT NULL,
to_user_id INT NOT NULL,
amount DECIMAL(10,2) NOT NULL,
transfer_type ENUM('initial', 'return', 'user_to_user', 'system_to_user', 'user_to_system') DEFAULT 'user_to_user',
status ENUM('pending', 'confirmed', 'rejected', 'received', 'not_received') DEFAULT 'pending',
voucher_url VARCHAR(500),
description TEXT,
batch_id VARCHAR(50),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
FOREIGN KEY (from_user_id) REFERENCES users(id) ON DELETE CASCADE,
FOREIGN KEY (to_user_id) REFERENCES users(id) ON DELETE CASCADE
)
`);
// 创建转账确认表
await getDB().execute(`
CREATE TABLE IF NOT EXISTS transfer_confirmations (
id INT AUTO_INCREMENT PRIMARY KEY,
transfer_id INT NOT NULL,
confirmer_id INT NOT NULL,
action ENUM('confirm', 'reject') NOT NULL,
note TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (transfer_id) REFERENCES transfers(id) ON DELETE CASCADE,
FOREIGN KEY (confirmer_id) REFERENCES users(id) ON DELETE CASCADE
)
`);
// 订单商品表
await getDB().execute(`
CREATE TABLE IF NOT EXISTS order_items (
id INT AUTO_INCREMENT PRIMARY KEY,
order_id INT NOT NULL,
product_id INT NOT NULL,
2025-09-02 09:29:20 +08:00
spec_combination_id INT NULL COMMENT '规格组合ID',
2025-08-26 10:06:23 +08:00
quantity INT NOT NULL,
price INT NOT NULL,
points INT NOT NULL,
2025-09-02 09:29:20 +08:00
points_price INT NOT NULL DEFAULT 0,
rongdou INT DEFAULT 0 COMMENT '融豆价格',
rongdou_price INT NOT NULL DEFAULT 0,
spec_info JSON COMMENT '规格信息快照',
2025-08-26 10:06:23 +08:00
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (order_id) REFERENCES orders(id),
2025-09-02 09:29:20 +08:00
FOREIGN KEY (product_id) REFERENCES products(id),
FOREIGN KEY (spec_combination_id) REFERENCES product_spec_combinations(id) ON DELETE SET NULL
2025-08-26 10:06:23 +08:00
)
`);
// 积分记录表
await getDB().execute(`
CREATE TABLE IF NOT EXISTS points_history (
id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT NOT NULL,
type ENUM('earn', 'spend') NOT NULL,
amount INT NOT NULL,
description VARCHAR(255),
order_id INT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users(id),
FOREIGN KEY (order_id) REFERENCES orders(id)
)
`);
2025-09-02 09:29:20 +08:00
// 融豆记录表
await getDB().execute(`
CREATE TABLE IF NOT EXISTS rongdou_history (
id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT NOT NULL,
type ENUM('earn', 'spend') NOT NULL,
amount INT NOT NULL,
description VARCHAR(255),
order_id INT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users(id),
FOREIGN KEY (order_id) REFERENCES orders(id)
)
`);
2025-08-26 10:06:23 +08:00
// 管理员操作日志表
await getDB().execute(`
CREATE TABLE IF NOT EXISTS admin_operation_logs (
id INT AUTO_INCREMENT PRIMARY KEY,
admin_id INT NOT NULL,
operation_type VARCHAR(50) NOT NULL,
target_type VARCHAR(50) NOT NULL,
target_id INT NOT NULL,
description TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (admin_id) REFERENCES users(id) ON DELETE CASCADE
)
`);
// 商品评价表
await getDB().execute(`
CREATE TABLE IF NOT EXISTS product_reviews (
id INT AUTO_INCREMENT PRIMARY KEY,
product_id INT NOT NULL,
user_id INT NOT NULL,
order_id INT NOT NULL,
rating INT NOT NULL,
comment TEXT,
images JSON,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (product_id) REFERENCES products(id),
FOREIGN KEY (user_id) REFERENCES users(id),
FOREIGN KEY (order_id) REFERENCES orders(id)
)
`);
2025-09-02 09:29:20 +08:00
// 规格名称表(规格维度)
2025-08-28 09:14:56 +08:00
await getDB().execute(`
2025-09-02 09:29:20 +08:00
CREATE TABLE IF NOT EXISTS spec_names (
2025-08-28 09:14:56 +08:00
id INT AUTO_INCREMENT PRIMARY KEY,
2025-09-02 09:29:20 +08:00
name VARCHAR(100) NOT NULL COMMENT '规格名称,如:颜色、尺寸、材质',
display_name VARCHAR(100) NOT NULL COMMENT '显示名称',
sort_order INT DEFAULT 0 COMMENT '排序',
2025-08-28 09:14:56 +08:00
status ENUM('active', 'inactive') DEFAULT 'active',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
2025-09-02 09:29:20 +08:00
UNIQUE KEY unique_name (name)
)
`);
// 规格值表
await getDB().execute(`
CREATE TABLE IF NOT EXISTS spec_values (
id INT AUTO_INCREMENT PRIMARY KEY,
spec_name_id INT NOT NULL COMMENT '规格名称ID',
value VARCHAR(100) NOT NULL COMMENT '规格值红色、XL、棉质',
display_value VARCHAR(100) NOT NULL COMMENT '显示值',
color_code VARCHAR(20) COMMENT '颜色代码(仅颜色规格使用)',
image_url VARCHAR(500) COMMENT '规格图片',
sort_order INT DEFAULT 0 COMMENT '排序',
status ENUM('active', 'inactive') DEFAULT 'active',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
FOREIGN KEY (spec_name_id) REFERENCES spec_names(id) ON DELETE CASCADE,
UNIQUE KEY unique_spec_value (spec_name_id, value)
)
`);
// 商品规格组合表(笛卡尔积结果)
await getDB().execute(`
CREATE TABLE IF NOT EXISTS product_spec_combinations (
id INT AUTO_INCREMENT PRIMARY KEY,
product_id INT NOT NULL COMMENT '商品ID',
combination_key VARCHAR(255) NOT NULL COMMENT '组合键color_1-size_2-material_3',
spec_values JSON NOT NULL COMMENT '规格值组合存储spec_value_id数组',
price_adjustment INT DEFAULT 0 COMMENT '价格调整',
points_adjustment INT DEFAULT 0 COMMENT '积分调整',
rongdou_adjustment INT DEFAULT 0 COMMENT '融豆调整',
stock INT DEFAULT 0 COMMENT '库存',
sku_code VARCHAR(100) COMMENT 'SKU编码',
barcode VARCHAR(100) COMMENT '条形码',
weight DECIMAL(8,3) COMMENT '重量kg',
volume DECIMAL(10,3) COMMENT '体积cm³',
status ENUM('active', 'inactive') DEFAULT 'active',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
FOREIGN KEY (product_id) REFERENCES products(id) ON DELETE CASCADE,
UNIQUE KEY unique_product_combination (product_id, combination_key),
INDEX idx_product_status (product_id, status),
INDEX idx_sku_code (sku_code)
)
`);
// 商品规格关联表(定义商品使用哪些规格维度)
await getDB().execute(`
CREATE TABLE IF NOT EXISTS product_spec_names (
id INT AUTO_INCREMENT PRIMARY KEY,
product_id INT NOT NULL COMMENT '商品ID',
spec_name_id INT NOT NULL COMMENT '规格名称ID',
is_required BOOLEAN DEFAULT TRUE COMMENT '是否必选规格',
sort_order INT DEFAULT 0 COMMENT '排序',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (product_id) REFERENCES products(id) ON DELETE CASCADE,
FOREIGN KEY (spec_name_id) REFERENCES spec_names(id) ON DELETE CASCADE,
UNIQUE KEY unique_product_spec_name (product_id, spec_name_id)
2025-08-28 09:14:56 +08:00
)
`);
// 商品属性表
await getDB().execute(`
CREATE TABLE IF NOT EXISTS product_attributes (
id INT AUTO_INCREMENT PRIMARY KEY,
product_id INT NOT NULL,
attribute_key VARCHAR(100) NOT NULL,
attribute_value TEXT NOT NULL,
sort_order INT DEFAULT 0,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
FOREIGN KEY (product_id) REFERENCES products(id) ON DELETE CASCADE
)
`);
// 商品收藏表
await getDB().execute(`
CREATE TABLE IF NOT EXISTS product_favorites (
id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT NOT NULL,
product_id INT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
FOREIGN KEY (product_id) REFERENCES products(id) ON DELETE CASCADE,
UNIQUE KEY unique_user_product (user_id, product_id)
)
`);
2025-09-02 09:29:20 +08:00
// 购物车表
await getDB().execute(`
CREATE TABLE IF NOT EXISTS cart_items (
id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT NOT NULL,
product_id INT NOT NULL,
quantity INT NOT NULL DEFAULT 1,
spec_combination_id INT NULL COMMENT '规格组合ID',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
FOREIGN KEY (product_id) REFERENCES products(id) ON DELETE CASCADE,
FOREIGN KEY (spec_combination_id) REFERENCES product_spec_combinations(id) ON DELETE CASCADE,
UNIQUE KEY unique_user_product_spec (user_id, product_id, spec_combination_id)
)
`);
2025-08-28 09:14:56 +08:00
// 用户收货地址表
await getDB().execute(`
CREATE TABLE IF NOT EXISTS user_addresses (
id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT NOT NULL,
recipient_name VARCHAR(100) NOT NULL,
phone VARCHAR(20) NOT NULL,
province_code VARCHAR(20),
province_name VARCHAR(50) NOT NULL,
city_code VARCHAR(20),
city_name VARCHAR(50) NOT NULL,
district_code VARCHAR(20),
district_name VARCHAR(50) NOT NULL,
detailed_address TEXT NOT NULL,
postal_code VARCHAR(10),
label_id INT,
is_default BOOLEAN DEFAULT FALSE,
deleted_at TIMESTAMP NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
FOREIGN KEY (label_id) REFERENCES address_labels(id) ON DELETE SET NULL
)
`);
// 地址标签表
await getDB().execute(`
CREATE TABLE IF NOT EXISTS address_labels (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(50) NOT NULL,
color VARCHAR(20) DEFAULT '#1890ff',
user_id INT NULL COMMENT '用户IDNULL表示系统标签',
is_system BOOLEAN DEFAULT FALSE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
)
`);
// 全国省市区表
await getDB().execute(`
CREATE TABLE IF NOT EXISTS china_regions (
id INT AUTO_INCREMENT PRIMARY KEY,
code VARCHAR(20) NOT NULL UNIQUE,
name VARCHAR(100) NOT NULL,
parent_code VARCHAR(20),
level TINYINT NOT NULL COMMENT '1:省 2:市 3:区',
sort_order INT DEFAULT 0,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
INDEX idx_parent_code (parent_code),
INDEX idx_level (level)
)
`);
2025-08-26 10:06:23 +08:00
// 匹配订单表
await getDB().execute(`
CREATE TABLE IF NOT EXISTS matching_orders (
id INT AUTO_INCREMENT PRIMARY KEY,
initiator_id INT NOT NULL,
amount DECIMAL(10,2) NOT NULL,
status ENUM('pending', 'matching', 'completed', 'cancelled') DEFAULT 'pending',
cycle_count INT DEFAULT 0,
max_cycles INT DEFAULT 3,
matching_type ENUM('small', 'large', 'system_reverse') DEFAULT 'small',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
FOREIGN KEY (initiator_id) REFERENCES users(id) ON DELETE CASCADE
)
`);
// 匹配订单分配表
await getDB().execute(`
CREATE TABLE IF NOT EXISTS order_allocations (
id INT AUTO_INCREMENT PRIMARY KEY,
matching_order_id INT NOT NULL,
from_user_id INT NOT NULL,
to_user_id INT NOT NULL,
amount DECIMAL(10,2) NOT NULL,
cycle_number INT NOT NULL,
status ENUM('pending', 'confirmed', 'rejected', 'completed') DEFAULT 'pending',
transfer_id INT,
outbound_date DATE,
return_date DATE,
can_return_after TIMESTAMP,
confirmed_at TIMESTAMP NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
FOREIGN KEY (matching_order_id) REFERENCES matching_orders(id) ON DELETE CASCADE,
FOREIGN KEY (from_user_id) REFERENCES users(id) ON DELETE CASCADE,
FOREIGN KEY (to_user_id) REFERENCES users(id) ON DELETE CASCADE,
FOREIGN KEY (transfer_id) REFERENCES transfers(id) ON DELETE SET NULL
)
`);
// 用户匹配池表
await getDB().execute(`
CREATE TABLE IF NOT EXISTS user_matching_pool (
id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT NOT NULL,
available_amount DECIMAL(10,2) DEFAULT 0.00,
is_active BOOLEAN DEFAULT TRUE,
last_matched_at TIMESTAMP NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
UNIQUE KEY unique_user (user_id)
)
`);
// 匹配记录表
await getDB().execute(`
CREATE TABLE IF NOT EXISTS matching_records (
id INT AUTO_INCREMENT PRIMARY KEY,
matching_order_id INT NOT NULL,
user_id INT NOT NULL,
action ENUM('join', 'confirm', 'reject', 'complete') NOT NULL,
amount DECIMAL(10,2),
note TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (matching_order_id) REFERENCES matching_orders(id) ON DELETE CASCADE,
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
)
`);
// 创建系统设置表
await getDB().execute(`
CREATE TABLE IF NOT EXISTS system_settings (
id INT AUTO_INCREMENT PRIMARY KEY,
setting_key VARCHAR(100) NOT NULL UNIQUE,
setting_value TEXT,
description VARCHAR(255),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
)
`);
// 创建激活码表
await getDB().execute(`
CREATE TABLE IF NOT EXISTS registration_codes (
id INT AUTO_INCREMENT PRIMARY KEY,
code VARCHAR(10) UNIQUE NOT NULL,
expires_at TIMESTAMP NOT NULL,
is_used BOOLEAN DEFAULT FALSE,
used_at TIMESTAMP NULL,
created_by_admin_id INT,
used_by_user_id INT,
agent_id INT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (created_by_admin_id) REFERENCES users(id) ON DELETE SET NULL,
FOREIGN KEY (used_by_user_id) REFERENCES users(id) ON DELETE SET NULL,
FOREIGN KEY (agent_id) REFERENCES users(id) ON DELETE SET NULL
)
`);
// 创建浙江省区域表
await getDB().execute(`
CREATE TABLE IF NOT EXISTS zhejiang_regions (
id INT AUTO_INCREMENT PRIMARY KEY,
city_name VARCHAR(50) NOT NULL,
district_name VARCHAR(50) NOT NULL,
region_code VARCHAR(20) UNIQUE NOT NULL,
is_available BOOLEAN DEFAULT TRUE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
UNIQUE KEY unique_region (city_name, district_name)
)
`);
// 创建区域代理表
await getDB().execute(`
CREATE TABLE IF NOT EXISTS regional_agents (
id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT NOT NULL,
region_id INT NOT NULL,
agent_code VARCHAR(20) UNIQUE NOT NULL,
status ENUM('pending', 'active', 'suspended', 'terminated') DEFAULT 'pending',
commission_rate DECIMAL(5,4) DEFAULT 0.1000,
total_earnings DECIMAL(10,2) DEFAULT 0.00,
recruited_merchants INT DEFAULT 0,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
FOREIGN KEY (region_id) REFERENCES zhejiang_regions(id) ON DELETE CASCADE,
UNIQUE KEY unique_agent_region (user_id, region_id)
)
`);
// 创建代理商户关系表
await getDB().execute(`
CREATE TABLE IF NOT EXISTS agent_merchants (
id INT AUTO_INCREMENT PRIMARY KEY,
agent_id INT NOT NULL,
merchant_id INT NOT NULL,
registration_code_id INT,
matching_count INT DEFAULT 0,
commission_earned DECIMAL(10,2) DEFAULT 0.00,
is_qualified BOOLEAN DEFAULT FALSE,
qualified_at TIMESTAMP NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
FOREIGN KEY (agent_id) REFERENCES regional_agents(id) ON DELETE CASCADE,
FOREIGN KEY (merchant_id) REFERENCES users(id) ON DELETE CASCADE,
FOREIGN KEY (registration_code_id) REFERENCES registration_codes(id) ON DELETE SET NULL,
UNIQUE KEY unique_agent_merchant (agent_id, merchant_id)
)
`);
// 创建代理佣金记录表
await getDB().execute(`
CREATE TABLE IF NOT EXISTS agent_commission_records (
id INT AUTO_INCREMENT PRIMARY KEY,
agent_id INT NOT NULL,
merchant_id INT NOT NULL,
order_id INT,
commission_amount DECIMAL(10,2) NOT NULL,
commission_type ENUM('registration', 'matching') DEFAULT 'matching',
description TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (agent_id) REFERENCES regional_agents(id) ON DELETE CASCADE,
FOREIGN KEY (merchant_id) REFERENCES users(id) ON DELETE CASCADE,
FOREIGN KEY (order_id) REFERENCES matching_orders(id) ON DELETE SET NULL
)
`);
}
/**
* 添加缺失的字段处理数据库升级
*/
async function addMissingFields() {
// 为现有的matching_orders表添加字段
const matchingOrderFields = [
{ name: 'matching_type', sql: 'ALTER TABLE matching_orders ADD COLUMN matching_type ENUM(\'small\', \'large\') DEFAULT \'small\'' },
{ name: 'is_system_reverse', sql: 'ALTER TABLE matching_orders ADD COLUMN is_system_reverse BOOLEAN DEFAULT FALSE' }
];
for (const field of matchingOrderFields) {
try {
await getDB().execute(field.sql);
} catch (error) {
if (!error.message.includes('Duplicate column name')) {
console.log(`添加${field.name}字段错误:`, error.message);
}
}
}
// 为现有的users表添加字段
const userFields = [
{ name: 'balance', sql: 'ALTER TABLE users ADD COLUMN balance DECIMAL(10,2) DEFAULT 0.00' },
{ name: 'is_system_account', sql: 'ALTER TABLE users ADD COLUMN is_system_account BOOLEAN DEFAULT FALSE' },
{ name: 'points', sql: 'ALTER TABLE users ADD COLUMN points INT DEFAULT 0' },
{ name: 'avatar', sql: 'ALTER TABLE users ADD COLUMN avatar VARCHAR(255)' },
{ name: 'real_name', sql: 'ALTER TABLE users ADD COLUMN real_name VARCHAR(100)' },
{ name: 'id_card', sql: 'ALTER TABLE users ADD COLUMN id_card VARCHAR(18)' },
{ name: 'wechat_qr', sql: 'ALTER TABLE users ADD COLUMN wechat_qr VARCHAR(255)' },
{ name: 'alipay_qr', sql: 'ALTER TABLE users ADD COLUMN alipay_qr VARCHAR(255)' },
{ name: 'bank_card', sql: 'ALTER TABLE users ADD COLUMN bank_card VARCHAR(30)' },
{ name: 'unionpay_qr', sql: 'ALTER TABLE users ADD COLUMN unionpay_qr VARCHAR(255)' },
{ name: 'phone', sql: 'ALTER TABLE users ADD COLUMN phone VARCHAR(20) UNIQUE' },
{ name: 'completed_withdrawals', sql: 'ALTER TABLE users ADD COLUMN completed_withdrawals INT DEFAULT 0' },
{ name: 'business_license', sql: 'ALTER TABLE users ADD COLUMN business_license VARCHAR(500)' },
{ name: 'id_card_front', sql: 'ALTER TABLE users ADD COLUMN id_card_front VARCHAR(500)' },
{ name: 'id_card_back', sql: 'ALTER TABLE users ADD COLUMN id_card_back VARCHAR(500)' },
{ name: 'audit_status', sql: 'ALTER TABLE users ADD COLUMN audit_status ENUM(\'pending\', \'approved\', \'rejected\') DEFAULT \'pending\'' },
{ name: 'audit_note', sql: 'ALTER TABLE users ADD COLUMN audit_note TEXT' },
{ name: 'audited_by', sql: 'ALTER TABLE users ADD COLUMN audited_by INT' },
{ name: 'audited_at', sql: 'ALTER TABLE users ADD COLUMN audited_at TIMESTAMP NULL' },
{ name: 'city', sql: 'ALTER TABLE users ADD COLUMN city VARCHAR(50)' },
{ name: 'district_id', sql: 'ALTER TABLE users ADD COLUMN district_id INT' }
];
for (const field of userFields) {
try {
await getDB().execute(field.sql);
} catch (error) {
if (!error.message.includes('Duplicate column name')) {
console.log(`添加用户表${field.name}字段错误:`, error.message);
}
}
}
// 为现有的products表添加字段
const productFields = [
{ name: 'points_price', sql: 'ALTER TABLE products ADD COLUMN points_price INT NOT NULL DEFAULT 0' },
2025-08-28 09:14:56 +08:00
{ name: 'rongdou_price', sql: 'ALTER TABLE products ADD COLUMN rongdou_price INT NOT NULL DEFAULT 0' },
2025-08-26 10:06:23 +08:00
{ name: 'image_url', sql: 'ALTER TABLE products ADD COLUMN image_url VARCHAR(500)' },
2025-08-28 09:14:56 +08:00
{ name: 'images', sql: 'ALTER TABLE products ADD COLUMN images JSON' },
{ name: 'videos', sql: 'ALTER TABLE products ADD COLUMN videos JSON' },
{ name: 'details', sql: 'ALTER TABLE products ADD COLUMN details TEXT' },
{ name: 'shop_name', sql: 'ALTER TABLE products ADD COLUMN shop_name VARCHAR(255)' },
{ name: 'shop_avatar', sql: 'ALTER TABLE products ADD COLUMN shop_avatar VARCHAR(500)' },
{ name: 'payment_methods', sql: 'ALTER TABLE products ADD COLUMN payment_methods JSON' }
2025-08-26 10:06:23 +08:00
];
for (const field of productFields) {
try {
await getDB().execute(field.sql);
} catch (error) {
if (!error.message.includes('Duplicate column name')) {
console.log(`添加商品表${field.name}字段错误:`, error.message);
}
}
}
// 为现有的transfers表添加字段
const transferFields = [
{ name: 'is_overdue', sql: 'ALTER TABLE transfers ADD COLUMN is_overdue BOOLEAN DEFAULT FALSE' },
{ name: 'is_bad_debt', sql: 'ALTER TABLE transfers ADD COLUMN is_bad_debt BOOLEAN DEFAULT FALSE' },
{ name: 'confirmed_at', sql: 'ALTER TABLE transfers ADD COLUMN confirmed_at TIMESTAMP NULL' },
{ name: 'deadline_at', sql: 'ALTER TABLE transfers ADD COLUMN deadline_at TIMESTAMP NULL' },
{ name: 'admin_note', sql: 'ALTER TABLE transfers ADD COLUMN admin_note TEXT' },
{ name: 'admin_modified_at', sql: 'ALTER TABLE transfers ADD COLUMN admin_modified_at TIMESTAMP NULL' },
{ name: 'admin_modified_by', sql: 'ALTER TABLE transfers ADD COLUMN admin_modified_by INT' }
];
for (const field of transferFields) {
try {
await getDB().execute(field.sql);
} catch (error) {
if (!error.message.includes('Duplicate column name')) {
console.log(`添加转账表${field.name}字段错误:`, error.message);
}
}
}
// 修改transfers表的字段类型
try {
await getDB().execute(`
ALTER TABLE transfers
MODIFY COLUMN status ENUM('pending', 'confirmed', 'rejected', 'received', 'not_received', 'cancelled') DEFAULT 'pending'
`);
} catch (error) {
console.log('修改transfers状态字段错误:', error.message);
}
try {
await getDB().execute(`
ALTER TABLE transfers
MODIFY COLUMN from_user_id INT NULL
`);
} catch (error) {
console.log('修改transfers from_user_id字段错误:', error.message);
}
try {
await getDB().execute(`
ALTER TABLE transfers
MODIFY COLUMN transfer_type ENUM('initial', 'return', 'user_to_user', 'system_to_user', 'user_to_system') DEFAULT 'user_to_user'
`);
} catch (error) {
console.log('修改transfers transfer_type字段错误:', error.message);
}
// 为现有的order_allocations表添加字段
const allocationFields = [
{ name: 'confirmed_at', sql: 'ALTER TABLE order_allocations ADD COLUMN confirmed_at TIMESTAMP NULL' },
{ name: 'outbound_date', sql: 'ALTER TABLE order_allocations ADD COLUMN outbound_date DATE' },
{ name: 'return_date', sql: 'ALTER TABLE order_allocations ADD COLUMN return_date DATE' },
{ name: 'can_return_after', sql: 'ALTER TABLE order_allocations ADD COLUMN can_return_after TIMESTAMP' }
];
for (const field of allocationFields) {
try {
await getDB().execute(field.sql);
} catch (error) {
if (!error.message.includes('Duplicate column name')) {
console.log(`添加分配表${field.name}字段错误:`, error.message);
}
}
}
// 为现有的regional_agents表添加字段
const agentFields = [
{ name: 'approved_at', sql: 'ALTER TABLE regional_agents ADD COLUMN approved_at TIMESTAMP NULL' },
{ name: 'approved_by_admin_id', sql: 'ALTER TABLE regional_agents ADD COLUMN approved_by_admin_id INT' },
// 提现相关字段
{ name: 'withdrawn_amount', sql: 'ALTER TABLE regional_agents ADD COLUMN withdrawn_amount DECIMAL(10,2) DEFAULT 0.00 COMMENT "已提现金额"' },
{ name: 'pending_withdrawal', sql: 'ALTER TABLE regional_agents ADD COLUMN pending_withdrawal DECIMAL(10,2) DEFAULT 0.00 COMMENT "待审核提现金额"' },
{ name: 'payment_type', sql: 'ALTER TABLE regional_agents ADD COLUMN payment_type ENUM("bank", "wechat", "alipay", "unionpay") DEFAULT "bank" COMMENT "收款方式类型"' },
{ name: 'bank_name', sql: 'ALTER TABLE regional_agents ADD COLUMN bank_name VARCHAR(100) COMMENT "银行名称"' },
{ name: 'account_number', sql: 'ALTER TABLE regional_agents ADD COLUMN account_number VARCHAR(50) COMMENT "账号/银行账号"' },
{ name: 'account_holder', sql: 'ALTER TABLE regional_agents ADD COLUMN account_holder VARCHAR(100) COMMENT "持有人姓名"' },
{ name: 'qr_code_url', sql: 'ALTER TABLE regional_agents ADD COLUMN qr_code_url VARCHAR(255) COMMENT "收款码图片URL"' },
{ name: 'bank_account', sql: 'ALTER TABLE regional_agents ADD COLUMN bank_account VARCHAR(50) COMMENT "银行账号(兼容旧版本)"' }
];
for (const field of agentFields) {
try {
await getDB().execute(field.sql);
} catch (error) {
if (!error.message.includes('Duplicate column name')) {
console.log(`添加代理表${field.name}字段错误:`, error.message);
}
}
}
// 为现有的registration_codes表添加字段
const registrationCodeFields = [
{ name: 'agent_id', sql: 'ALTER TABLE registration_codes ADD COLUMN agent_id INT NULL' }
];
for (const field of registrationCodeFields) {
try {
await getDB().execute(field.sql);
} catch (error) {
if (!error.message.includes('Duplicate column name')) {
console.log(`添加激活码表${field.name}字段错误:`, error.message);
}
}
}
// 为registration_codes表的agent_id字段添加外键约束
try {
await getDB().execute(`
ALTER TABLE registration_codes
ADD CONSTRAINT fk_registration_codes_agent_id
FOREIGN KEY (agent_id) REFERENCES users(id) ON DELETE SET NULL
`);
} catch (error) {
if (!error.message.includes('Duplicate foreign key constraint name')) {
console.log('添加激活码表agent_id外键约束错误:', error.message);
}
}
// 注意MySQL不支持带WHERE条件的唯一索引
// 区域激活代理的唯一性通过应用层验证来确保
// 每个区域只能有一个激活状态的代理,这在代理申请、审核和启用时都会进行验证
// 创建代理提现记录表
try {
await getDB().execute(`
CREATE TABLE IF NOT EXISTS agent_withdrawals (
id INT AUTO_INCREMENT PRIMARY KEY,
agent_id INT NOT NULL,
amount DECIMAL(10,2) NOT NULL,
payment_type ENUM('bank', 'wechat', 'alipay', 'unionpay') DEFAULT 'bank' COMMENT '收款方式类型',
bank_name VARCHAR(100) COMMENT '银行名称',
account_number VARCHAR(50) COMMENT '账号/银行账号',
account_holder VARCHAR(100) COMMENT '持有人姓名',
qr_code_url VARCHAR(255) COMMENT '收款码图片URL',
status ENUM('pending', 'approved', 'rejected', 'completed') DEFAULT 'pending',
apply_note TEXT,
admin_note TEXT,
processed_by INT NULL,
processed_at TIMESTAMP NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
bank_account VARCHAR(50) COMMENT '银行账号(兼容旧版本)',
FOREIGN KEY (agent_id) REFERENCES regional_agents(id) ON DELETE CASCADE,
FOREIGN KEY (processed_by) REFERENCES users(id) ON DELETE SET NULL
)
`);
console.log('代理提现记录表创建成功');
} catch (error) {
if (!error.message.includes('Table') || !error.message.includes('already exists')) {
console.log('创建代理提现记录表错误:', error.message);
}
}
}
/**
* 创建默认数据
*/
async function createDefaultData() {
// 创建默认管理员账号
const defaultPassword = await bcrypt.hash('admin123', 10);
try {
await getDB().execute(`
INSERT IGNORE INTO users (username, phone, password, role)
VALUES ('admin', '13800000000', ?, 'admin')
`, [defaultPassword]);
console.log('默认管理员账号已创建: 用户名: admin, 密码: admin123');
} catch (error) {
console.log('默认管理员账号已存在或创建失败:', error.message);
}
// 创建多个系统公户账号
const publicPassword = await bcrypt.hash('public123', 10);
const systemAccounts = [
{ username: 'merchant_001', phone: '13800000001', real_name: '优选商户' },
{ username: 'merchant_002', phone: '13800000002', real_name: '品质商家' },
{ username: 'merchant_003', phone: '13800000003', real_name: '信誉商户' },
{ username: 'merchant_004', phone: '13800000004', real_name: '金牌商家' },
{ username: 'merchant_005', phone: '13800000005', real_name: '钻石商户' }
];
for (const account of systemAccounts) {
try {
const [result] = await getDB().execute(`
INSERT IGNORE INTO users (username, phone, password, role, real_name, is_system_account)
VALUES (?, ?, ?, 'user', ?, TRUE)
`, [account.username, account.phone, publicPassword, account.real_name]);
if (result.affectedRows > 0) {
// 为新创建的系统账户设置初始余额
await getDB().execute(`
UPDATE users SET balance = 0.00 WHERE id = ?
`, [result.insertId]);
console.log(`系统账户已创建: ${account.real_name} (${account.username})`);
} else {
// 确保现有系统账户的is_system_account字段正确设置
await getDB().execute(`
UPDATE users SET is_system_account = TRUE WHERE username = ?
`, [account.username]);
}
} catch (error) {
console.log(`系统账户${account.username}已存在或创建失败:`, error.message);
}
}
// 初始化浙江省区域数据
await initializeZhejiangRegions();
2025-08-28 09:14:56 +08:00
// 初始化默认地址标签
await initializeDefaultAddressLabels();
// 初始化全国省市区数据
await initializeChinaRegions();
2025-08-26 10:06:23 +08:00
}
/**
* 初始化浙江省区域数据
*/
async function initializeZhejiangRegions() {
const zhejiangRegions = [
// 杭州市
{ city: '杭州市', district: '上城区', code: 'HZ_SC' },
{ city: '杭州市', district: '拱墅区', code: 'HZ_GS' },
{ city: '杭州市', district: '西湖区', code: 'HZ_XH' },
{ city: '杭州市', district: '滨江区', code: 'HZ_BJ' },
{ city: '杭州市', district: '萧山区', code: 'HZ_XS' },
{ city: '杭州市', district: '余杭区', code: 'HZ_YH' },
{ city: '杭州市', district: '临平区', code: 'HZ_LP' },
{ city: '杭州市', district: '钱塘区', code: 'HZ_QT' },
{ city: '杭州市', district: '富阳区', code: 'HZ_FY' },
{ city: '杭州市', district: '临安区', code: 'HZ_LA' },
{ city: '杭州市', district: '桐庐县', code: 'HZ_TL' },
{ city: '杭州市', district: '淳安县', code: 'HZ_CA' },
{ city: '杭州市', district: '建德市', code: 'HZ_JD' },
// 宁波市
{ city: '宁波市', district: '海曙区', code: 'NB_HS' },
{ city: '宁波市', district: '江北区', code: 'NB_JB' },
{ city: '宁波市', district: '北仑区', code: 'NB_BL' },
{ city: '宁波市', district: '镇海区', code: 'NB_ZH' },
{ city: '宁波市', district: '鄞州区', code: 'NB_YZ' },
{ city: '宁波市', district: '奉化区', code: 'NB_FH' },
{ city: '宁波市', district: '象山县', code: 'NB_XS' },
{ city: '宁波市', district: '宁海县', code: 'NB_NH' },
{ city: '宁波市', district: '余姚市', code: 'NB_YY' },
{ city: '宁波市', district: '慈溪市', code: 'NB_CX' },
// 温州市
{ city: '温州市', district: '鹿城区', code: 'WZ_LC' },
{ city: '温州市', district: '龙湾区', code: 'WZ_LW' },
{ city: '温州市', district: '瓯海区', code: 'WZ_OH' },
{ city: '温州市', district: '洞头区', code: 'WZ_DT' },
{ city: '温州市', district: '永嘉县', code: 'WZ_YJ' },
{ city: '温州市', district: '平阳县', code: 'WZ_PY' },
{ city: '温州市', district: '苍南县', code: 'WZ_CN' },
{ city: '温州市', district: '文成县', code: 'WZ_WC' },
{ city: '温州市', district: '泰顺县', code: 'WZ_TS' },
{ city: '温州市', district: '瑞安市', code: 'WZ_RA' },
{ city: '温州市', district: '乐清市', code: 'WZ_LQ' },
// 嘉兴市
{ city: '嘉兴市', district: '南湖区', code: 'JX_NH' },
{ city: '嘉兴市', district: '秀洲区', code: 'JX_XZ' },
{ city: '嘉兴市', district: '嘉善县', code: 'JX_JS' },
{ city: '嘉兴市', district: '海盐县', code: 'JX_HY' },
{ city: '嘉兴市', district: '海宁市', code: 'JX_HN' },
{ city: '嘉兴市', district: '平湖市', code: 'JX_PH' },
{ city: '嘉兴市', district: '桐乡市', code: 'JX_TX' },
// 湖州市
{ city: '湖州市', district: '吴兴区', code: 'HuZ_WX' },
{ city: '湖州市', district: '南浔区', code: 'HuZ_NX' },
{ city: '湖州市', district: '德清县', code: 'HuZ_DQ' },
{ city: '湖州市', district: '长兴县', code: 'HuZ_CX' },
{ city: '湖州市', district: '安吉县', code: 'HuZ_AJ' },
// 绍兴市
{ city: '绍兴市', district: '越城区', code: 'SX_YC' },
{ city: '绍兴市', district: '柯桥区', code: 'SX_KQ' },
{ city: '绍兴市', district: '上虞区', code: 'SX_SY' },
{ city: '绍兴市', district: '新昌县', code: 'SX_XC' },
{ city: '绍兴市', district: '诸暨市', code: 'SX_ZJ' },
{ city: '绍兴市', district: '嵊州市', code: 'SX_SZ' },
// 金华市
{ city: '金华市', district: '婺城区', code: 'JH_WC' },
{ city: '金华市', district: '金东区', code: 'JH_JD' },
{ city: '金华市', district: '武义县', code: 'JH_WY' },
{ city: '金华市', district: '浦江县', code: 'JH_PJ' },
{ city: '金华市', district: '磐安县', code: 'JH_PA' },
{ city: '金华市', district: '兰溪市', code: 'JH_LX' },
{ city: '金华市', district: '义乌市', code: 'JH_YW' },
{ city: '金华市', district: '东阳市', code: 'JH_DY' },
{ city: '金华市', district: '永康市', code: 'JH_YK' },
// 衢州市
{ city: '衢州市', district: '柯城区', code: 'QZ_KC' },
{ city: '衢州市', district: '衢江区', code: 'QZ_QJ' },
{ city: '衢州市', district: '常山县', code: 'QZ_CS' },
{ city: '衢州市', district: '开化县', code: 'QZ_KH' },
{ city: '衢州市', district: '龙游县', code: 'QZ_LY' },
{ city: '衢州市', district: '江山市', code: 'QZ_JS' },
// 舟山市
{ city: '舟山市', district: '定海区', code: 'ZS_DH' },
{ city: '舟山市', district: '普陀区', code: 'ZS_PT' },
{ city: '舟山市', district: '岱山县', code: 'ZS_DS' },
{ city: '舟山市', district: '嵊泗县', code: 'ZS_SS' },
// 台州市
{ city: '台州市', district: '椒江区', code: 'TZ_JJ' },
{ city: '台州市', district: '黄岩区', code: 'TZ_HY' },
{ city: '台州市', district: '路桥区', code: 'TZ_LQ' },
{ city: '台州市', district: '三门县', code: 'TZ_SM' },
{ city: '台州市', district: '天台县', code: 'TZ_TT' },
{ city: '台州市', district: '仙居县', code: 'TZ_XJ' },
{ city: '台州市', district: '温岭市', code: 'TZ_WL' },
{ city: '台州市', district: '临海市', code: 'TZ_LH' },
{ city: '台州市', district: '玉环市', code: 'TZ_YH' },
// 丽水市
{ city: '丽水市', district: '莲都区', code: 'LS_LD' },
{ city: '丽水市', district: '青田县', code: 'LS_QT' },
{ city: '丽水市', district: '缙云县', code: 'LS_JY' },
{ city: '丽水市', district: '遂昌县', code: 'LS_SC' },
{ city: '丽水市', district: '松阳县', code: 'LS_SY' },
{ city: '丽水市', district: '云和县', code: 'LS_YH' },
{ city: '丽水市', district: '庆元县', code: 'LS_QY' },
{ city: '丽水市', district: '景宁县', code: 'LS_JN' },
{ city: '丽水市', district: '龙泉市', code: 'LS_LQ' }
];
// 批量插入区域数据
for (const region of zhejiangRegions) {
try {
await getDB().execute(
'INSERT IGNORE INTO zhejiang_regions (city_name, district_name, region_code) VALUES (?, ?, ?)',
[region.city, region.district, region.code]
);
} catch (error) {
console.log(`插入区域数据失败: ${region.city} ${region.district}`, error.message);
}
}
}
2025-08-28 09:14:56 +08:00
/**
* 初始化默认地址标签
*/
async function initializeDefaultAddressLabels() {
const defaultLabels = [
{ name: '家', color: '#52c41a' },
{ name: '公司', color: '#1890ff' },
{ name: '学校', color: '#722ed1' }
];
for (const label of defaultLabels) {
try {
await getDB().execute(`
INSERT IGNORE INTO address_labels (name, color, user_id, is_system)
VALUES (?, ?, NULL, TRUE)
`, [label.name, label.color]);
} catch (error) {
console.log(`默认标签${label.name}创建失败:`, error.message);
}
}
console.log('默认地址标签初始化完成');
}
/**
* 初始化全国省市区数据
*/
async function initializeChinaRegions() {
const regions = [
// 省级
{ code: '110000', name: '北京市', parent_code: null, level: 1 },
{ code: '120000', name: '天津市', parent_code: null, level: 1 },
{ code: '130000', name: '河北省', parent_code: null, level: 1 },
{ code: '140000', name: '山西省', parent_code: null, level: 1 },
{ code: '150000', name: '内蒙古自治区', parent_code: null, level: 1 },
{ code: '210000', name: '辽宁省', parent_code: null, level: 1 },
{ code: '220000', name: '吉林省', parent_code: null, level: 1 },
{ code: '230000', name: '黑龙江省', parent_code: null, level: 1 },
{ code: '310000', name: '上海市', parent_code: null, level: 1 },
{ code: '320000', name: '江苏省', parent_code: null, level: 1 },
{ code: '330000', name: '浙江省', parent_code: null, level: 1 },
{ code: '340000', name: '安徽省', parent_code: null, level: 1 },
{ code: '350000', name: '福建省', parent_code: null, level: 1 },
{ code: '360000', name: '江西省', parent_code: null, level: 1 },
{ code: '370000', name: '山东省', parent_code: null, level: 1 },
{ code: '410000', name: '河南省', parent_code: null, level: 1 },
{ code: '420000', name: '湖北省', parent_code: null, level: 1 },
{ code: '430000', name: '湖南省', parent_code: null, level: 1 },
{ code: '440000', name: '广东省', parent_code: null, level: 1 },
{ code: '450000', name: '广西壮族自治区', parent_code: null, level: 1 },
{ code: '460000', name: '海南省', parent_code: null, level: 1 },
{ code: '500000', name: '重庆市', parent_code: null, level: 1 },
{ code: '510000', name: '四川省', parent_code: null, level: 1 },
{ code: '520000', name: '贵州省', parent_code: null, level: 1 },
{ code: '530000', name: '云南省', parent_code: null, level: 1 },
{ code: '540000', name: '西藏自治区', parent_code: null, level: 1 },
{ code: '610000', name: '陕西省', parent_code: null, level: 1 },
{ code: '620000', name: '甘肃省', parent_code: null, level: 1 },
{ code: '630000', name: '青海省', parent_code: null, level: 1 },
{ code: '640000', name: '宁夏回族自治区', parent_code: null, level: 1 },
{ code: '650000', name: '新疆维吾尔自治区', parent_code: null, level: 1 },
// 浙江省市级
{ code: '330100', name: '杭州市', parent_code: '330000', level: 2 },
{ code: '330200', name: '宁波市', parent_code: '330000', level: 2 },
{ code: '330300', name: '温州市', parent_code: '330000', level: 2 },
{ code: '330400', name: '嘉兴市', parent_code: '330000', level: 2 },
{ code: '330500', name: '湖州市', parent_code: '330000', level: 2 },
{ code: '330600', name: '绍兴市', parent_code: '330000', level: 2 },
{ code: '330700', name: '金华市', parent_code: '330000', level: 2 },
{ code: '330800', name: '衢州市', parent_code: '330000', level: 2 },
{ code: '330900', name: '舟山市', parent_code: '330000', level: 2 },
{ code: '331000', name: '台州市', parent_code: '330000', level: 2 },
{ code: '331100', name: '丽水市', parent_code: '330000', level: 2 },
// 杭州市区级
{ code: '330102', name: '上城区', parent_code: '330100', level: 3 },
{ code: '330105', name: '拱墅区', parent_code: '330100', level: 3 },
{ code: '330106', name: '西湖区', parent_code: '330100', level: 3 },
{ code: '330108', name: '滨江区', parent_code: '330100', level: 3 },
{ code: '330109', name: '萧山区', parent_code: '330100', level: 3 },
{ code: '330110', name: '余杭区', parent_code: '330100', level: 3 },
{ code: '330111', name: '富阳区', parent_code: '330100', level: 3 },
{ code: '330112', name: '临安区', parent_code: '330100', level: 3 },
{ code: '330113', name: '临平区', parent_code: '330100', level: 3 },
{ code: '330114', name: '钱塘区', parent_code: '330100', level: 3 },
{ code: '330122', name: '桐庐县', parent_code: '330100', level: 3 },
{ code: '330127', name: '淳安县', parent_code: '330100', level: 3 },
{ code: '330182', name: '建德市', parent_code: '330100', level: 3 }
];
for (const region of regions) {
try {
await getDB().execute(`
INSERT IGNORE INTO china_regions (code, name, parent_code, level)
VALUES (?, ?, ?, ?)
`, [region.code, region.name, region.parent_code, region.level]);
} catch (error) {
console.log(`区域${region.name}创建失败:`, error.message);
}
}
console.log('全国省市区数据初始化完成');
}
2025-08-26 10:06:23 +08:00
module.exports = {
initDatabase,
createTables,
addMissingFields,
createDefaultData,
2025-08-28 09:14:56 +08:00
initializeZhejiangRegions,
initializeDefaultAddressLabels,
initializeChinaRegions
2025-08-26 10:06:23 +08:00
};