文件
shanghaipeiwan/server/src/db/mysql.ts

945 行
51 KiB
TypeScript

此文件含有模棱两可的 Unicode 字符

此文件含有可能会与其他字符混淆的 Unicode 字符。 如果您是想特意这样的,可以安全地忽略该警告。 使用 Escape 按钮显示他们。

import 'dotenv/config';
import mysql, { Pool } from 'mysql2/promise';
export const dbConfig = {
host: process.env.MYSQL_HOST || '127.0.0.1',
port: Number(process.env.MYSQL_PORT) || 3306,
user: process.env.MYSQL_USER || 'root',
password: process.env.MYSQL_PASSWORD || '123456',
database: process.env.MYSQL_DATABASE || 'peiwan',
charset: 'utf8mb4',
waitForConnections: true,
connectionLimit: 10,
queueLimit: 0,
};
export const pool: Pool = mysql.createPool(dbConfig);
// 初始化所有核心数据表与种子数据
export async function initDatabase(): Promise<void> {
const conn = await pool.getConnection();
try {
// 1. 活动表
await conn.query(`
CREATE TABLE IF NOT EXISTS activities (
id VARCHAR(64) PRIMARY KEY,
creator_id INT NOT NULL,
title VARCHAR(255) NOT NULL,
game_category VARCHAR(64) NOT NULL,
location VARCHAR(255),
pay_type INT NOT NULL DEFAULT 1,
total_fee_cents INT DEFAULT 0,
per_person_fee_cents INT DEFAULT 0,
max_participants INT DEFAULT 4,
allow_dynamic_price TINYINT DEFAULT 1,
price_adjust_rule VARCHAR(32) DEFAULT 'UNIFIED_HIGH',
status VARCHAR(32) DEFAULT 'RECRUITING',
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
`);
try {
await conn.query(`ALTER TABLE activities ADD COLUMN status VARCHAR(32) DEFAULT 'RECRUITING' AFTER price_adjust_rule`);
} catch (_) {
// 字段已存在忽略
}
// 2. 参与者与4位纯数字核销码表
await conn.query(`
CREATE TABLE IF NOT EXISTS participants (
id VARCHAR(64) PRIMARY KEY,
activity_id VARCHAR(64) NOT NULL,
user_id INT NOT NULL,
pay_amount_cents INT NOT NULL,
verify_code VARCHAR(4) NOT NULL,
checkin_status TINYINT DEFAULT 0,
verified_at DATETIME NULL,
verified_by INT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
INDEX idx_activity (activity_id),
INDEX idx_verify_code (verify_code)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
`);
// 3. 陪玩大神档案表
await conn.query(`
CREATE TABLE IF NOT EXISTS companions (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(64) NOT NULL,
avatar TEXT,
gender VARCHAR(10),
age INT,
track VARCHAR(64) NOT NULL,
rank_name VARCHAR(64),
hourly_rate INT NOT NULL,
voice_duration INT DEFAULT 15,
voice_title VARCHAR(128),
rating DECIMAL(3,2) DEFAULT 4.90,
order_count INT DEFAULT 0,
status VARCHAR(32) DEFAULT '接单中',
audit_status VARCHAR(32) DEFAULT '已通过',
id_card_masked VARCHAR(32),
tags JSON,
apply_time DATETIME DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
`);
// 动态为 companions 增加 tags 字段 (若历史表已存在)
try {
await conn.query('ALTER TABLE companions ADD COLUMN tags JSON AFTER id_card_masked');
} catch (_) {}
// 4. 订单表
await conn.query(`
CREATE TABLE IF NOT EXISTS orders (
id VARCHAR(64) PRIMARY KEY,
buyer_id INT DEFAULT 1001,
expert_id INT DEFAULT 101,
order_no VARCHAR(64) UNIQUE NOT NULL,
client_name VARCHAR(64) NOT NULL,
companion_name VARCHAR(64) NOT NULL,
expert_avatar TEXT,
track VARCHAR(64) NOT NULL,
service_title VARCHAR(255) DEFAULT '同城陪伴服务',
expense_burden VARCHAR(32) DEFAULT '客户全包',
hourly_rate INT NOT NULL,
duration_hours INT NOT NULL DEFAULT 2,
amount DECIMAL(10,2) NOT NULL,
location VARCHAR(255),
verify_code VARCHAR(8),
remark VARCHAR(255),
status VARCHAR(32) NOT NULL DEFAULT '待支付',
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
`);
// 动态增加移动端所需的扩展字段 (若历史表已存在则执行防断裂补丁)
const extraOrderCols = [
"ALTER TABLE orders ADD COLUMN buyer_id INT DEFAULT 1001 AFTER id",
"ALTER TABLE orders ADD COLUMN expert_id INT DEFAULT 101 AFTER buyer_id",
"ALTER TABLE orders ADD COLUMN expert_avatar TEXT AFTER companion_name",
"ALTER TABLE orders ADD COLUMN service_title VARCHAR(255) DEFAULT '同城陪伴服务' AFTER track",
"ALTER TABLE orders ADD COLUMN verify_code VARCHAR(8) AFTER location",
"ALTER TABLE orders ADD COLUMN remark VARCHAR(255) AFTER verify_code",
"ALTER TABLE orders ADD COLUMN pay_type VARCHAR(32) DEFAULT 'WECHAT' AFTER status",
"ALTER TABLE orders ADD COLUMN coupon_discount DECIMAL(10,2) DEFAULT 0.00 AFTER amount"
];
for (const colSql of extraOrderCols) {
try {
await conn.query(colSql);
} catch (_) {
// 字段已存在则忽略
}
}
// 5. 争议仲裁表
await conn.query(`
CREATE TABLE IF NOT EXISTS arbitrations (
id VARCHAR(64) PRIMARY KEY,
order_id VARCHAR(64) NOT NULL,
order_no VARCHAR(64) NOT NULL,
client_name VARCHAR(64) NOT NULL,
companion_name VARCHAR(64) NOT NULL,
reason VARCHAR(255) NOT NULL,
user_evidence TEXT,
status VARCHAR(32) NOT NULL DEFAULT '待平台仲裁',
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
`);
// 6. 资金财务流水表
await conn.query(`
CREATE TABLE IF NOT EXISTS finance_records (
id VARCHAR(64) PRIMARY KEY,
record_no VARCHAR(64) UNIQUE NOT NULL,
user_id INT,
type VARCHAR(64) NOT NULL,
amount DECIMAL(10,2) NOT NULL,
direction VARCHAR(8) NOT NULL DEFAULT 'IN',
counterparty VARCHAR(64),
related_id VARCHAR(64),
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
`);
try {
await conn.query('ALTER TABLE finance_records ADD COLUMN user_id INT AFTER record_no');
} catch (_) {}
// 7. 提现申请表
await conn.query(`
CREATE TABLE IF NOT EXISTS withdrawals (
id VARCHAR(64) PRIMARY KEY,
withdraw_no VARCHAR(64) UNIQUE NOT NULL,
companion_name VARCHAR(64) NOT NULL,
companion_id INT NOT NULL,
amount DECIMAL(10,2) NOT NULL,
balance DECIMAL(10,2) NOT NULL,
channel VARCHAR(64) DEFAULT '微信商户零钱',
status VARCHAR(32) DEFAULT '待审核',
apply_time DATETIME DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
`);
try {
await conn.query('ALTER TABLE withdrawals ADD COLUMN reason VARCHAR(255) DEFAULT ""');
} catch (_) {}
// 8. 线下合规场所库
await conn.query(`
CREATE TABLE IF NOT EXISTS safety_places (
id VARCHAR(64) PRIMARY KEY,
name VARCHAR(128) NOT NULL,
area VARCHAR(128) NOT NULL,
category VARCHAR(64) NOT NULL,
safety_level VARCHAR(64) DEFAULT 'AAA级合规认证',
status VARCHAR(32) DEFAULT '正常营业',
approved TINYINT DEFAULT 1
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
`);
// 9. 风控拦截日志表
await conn.query(`
CREATE TABLE IF NOT EXISTS safety_audit_logs (
id VARCHAR(64) PRIMARY KEY,
timestamp_str VARCHAR(64) NOT NULL,
user_id INT NOT NULL,
type VARCHAR(64) NOT NULL,
content TEXT NOT NULL,
action TEXT NOT NULL,
status VARCHAR(32) DEFAULT '已处置',
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
`);
// 10. 财务抽成与分销配置表
await conn.query(`
CREATE TABLE IF NOT EXISTS finance_config (
id INT PRIMARY KEY DEFAULT 1,
platform_rate_percent DECIMAL(5,2) DEFAULT 10.0,
first_referral_percent DECIMAL(5,2) DEFAULT 5.0,
second_referral_percent DECIMAL(5,2) DEFAULT 2.0,
min_withdraw_amount INT DEFAULT 50,
max_withdraw_amount INT DEFAULT 20000,
withdraw_fee_percent DECIMAL(5,2) DEFAULT 0.0
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
`);
// 11. 全平台注册用户表 (普通玩家/认证大神/房主)
await conn.query(`
CREATE TABLE IF NOT EXISTS users (
id INT PRIMARY KEY AUTO_INCREMENT,
user_no VARCHAR(32) UNIQUE NOT NULL,
nickname VARCHAR(64) NOT NULL,
avatar TEXT,
phone VARCHAR(32) NOT NULL,
gender VARCHAR(10) DEFAULT '保密',
role VARCHAR(32) NOT NULL DEFAULT '普通玩家',
balance DECIMAL(10,2) DEFAULT 0.00,
order_count INT DEFAULT 0,
activity_count INT DEFAULT 0,
status VARCHAR(32) DEFAULT '正常',
wechat_openid VARCHAR(64),
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
`);
// 12. 友圈动态表
await conn.query(`
CREATE TABLE IF NOT EXISTS posts (
id VARCHAR(64) PRIMARY KEY,
user_id INT NOT NULL DEFAULT 1001,
author VARCHAR(64) NOT NULL,
avatar TEXT,
tag VARCHAR(64) DEFAULT '同城搭子',
tag_type VARCHAR(32) DEFAULT 'warm-tag',
location VARCHAR(255) DEFAULT '北京市公开商圈',
distance VARCHAR(64) DEFAULT '100m内',
content TEXT NOT NULL,
topics JSON,
images JSON,
action_text VARCHAR(32) DEFAULT '加入车队',
likes INT DEFAULT 0,
comments INT DEFAULT 0,
views INT DEFAULT 1,
category VARCHAR(32) NOT NULL DEFAULT 'partner',
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
`);
// 13. 订单真实评价与评分表
await conn.query(`
CREATE TABLE IF NOT EXISTS order_reviews (
id VARCHAR(64) PRIMARY KEY,
order_id VARCHAR(64) NOT NULL,
expert_id INT NOT NULL,
user_id INT NOT NULL DEFAULT 1001,
user_nickname VARCHAR(64) NOT NULL DEFAULT '买家用户',
user_avatar TEXT,
rating INT NOT NULL DEFAULT 5,
tags JSON,
content TEXT,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
INDEX idx_order (order_id),
INDEX idx_expert (expert_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
`);
// 14. 友圈动态互动评论表
await conn.query(`
CREATE TABLE IF NOT EXISTS post_comments (
id VARCHAR(64) PRIMARY KEY,
post_id VARCHAR(64) NOT NULL,
user_id INT NOT NULL DEFAULT 1001,
author VARCHAR(64) NOT NULL DEFAULT '热心搭子',
avatar TEXT,
content TEXT NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
INDEX idx_post (post_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
`);
// 15. 友圈搭子互动约伴上车申请表
await conn.query(`
CREATE TABLE IF NOT EXISTS post_applies (
id VARCHAR(64) PRIMARY KEY,
post_id VARCHAR(64) NOT NULL,
applicant_id INT NOT NULL DEFAULT 1001,
applicant_name VARCHAR(64) NOT NULL DEFAULT '搭子玩家',
applicant_avatar TEXT,
status VARCHAR(32) NOT NULL DEFAULT 'PENDING',
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
INDEX idx_post_applies (post_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
`);
// 16. 首页轮播图运营配置表
await conn.query(`
CREATE TABLE IF NOT EXISTS banners (
id INT PRIMARY KEY AUTO_INCREMENT,
title VARCHAR(128) NOT NULL,
subtitle VARCHAR(255) DEFAULT '',
tag VARCHAR(64) DEFAULT '热门活动',
badge VARCHAR(64) DEFAULT 'HOT 热门组局',
badge_type VARCHAR(64) DEFAULT 'badge-hot',
bg VARCHAR(255) DEFAULT 'linear-gradient(135deg, #F43F5E 0%, #FB7185 100%)',
image TEXT,
link VARCHAR(255) DEFAULT '/pages/activity/list',
sort_order INT DEFAULT 0,
status TINYINT DEFAULT 1,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
INDEX idx_sort (sort_order),
INDEX idx_status (status)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
`);
// 17. 首页金刚区活动品类导航配置表
await conn.query(`
CREATE TABLE IF NOT EXISTS nav_categories (
id INT PRIMARY KEY AUTO_INCREMENT,
code VARCHAR(64) UNIQUE NOT NULL,
name VARCHAR(64) NOT NULL,
icon TEXT NOT NULL,
bg_class VARCHAR(64) DEFAULT 'bg-indigo',
cat VARCHAR(64) DEFAULT 'all',
target_url VARCHAR(255) NOT NULL DEFAULT '/pages/activity/list?category=ALL',
badge_text VARCHAR(32) DEFAULT '',
sort_order INT DEFAULT 0,
status TINYINT DEFAULT 1,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
INDEX idx_sort (sort_order),
INDEX idx_status (status)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
`);
// 18. 钱包充值阶梯与赠送配置表
await conn.query(`
CREATE TABLE IF NOT EXISTS recharge_tiers (
id INT PRIMARY KEY AUTO_INCREMENT,
amount DECIMAL(10,2) NOT NULL,
bonus_amount DECIMAL(10,2) DEFAULT 0.00,
tag VARCHAR(32) DEFAULT '',
sort_order INT DEFAULT 0,
status TINYINT DEFAULT 1,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
INDEX idx_sort (sort_order),
INDEX idx_status (status)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
`);
// 19. 平台营销优惠券配置与发放表
await conn.query(`
CREATE TABLE IF NOT EXISTS coupons (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(64) NOT NULL,
discount_amount DECIMAL(10,2) NOT NULL,
min_spend DECIMAL(10,2) NOT NULL DEFAULT 0.00,
valid_days INT NOT NULL DEFAULT 7,
total_count INT NOT NULL DEFAULT 1000,
received_count INT NOT NULL DEFAULT 0,
category_limit VARCHAR(64) DEFAULT 'ALL',
description VARCHAR(255) DEFAULT '',
status TINYINT DEFAULT 1,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
INDEX idx_status (status)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
`);
// 20. 平台官方客服、公告及服务协议通用配置表
await conn.query(`
CREATE TABLE IF NOT EXISTS platform_configs (
id INT PRIMARY KEY AUTO_INCREMENT,
config_key VARCHAR(64) UNIQUE NOT NULL,
name VARCHAR(128) NOT NULL,
value_json JSON NOT NULL,
description VARCHAR(255) DEFAULT '',
status TINYINT DEFAULT 1,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
INDEX idx_key (config_key)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
`);
// 初始化配置单条记录
const [cfgRows]: any = await conn.query('SELECT COUNT(*) as count FROM finance_config WHERE id = 1');
if (cfgRows[0].count === 0) {
await conn.query(`
INSERT INTO finance_config (id, platform_rate_percent, first_referral_percent, second_referral_percent, min_withdraw_amount, max_withdraw_amount, withdraw_fee_percent)
VALUES (1, 10.0, 5.0, 2.0, 50, 20000, 0.0);
`);
}
// 扩展 users 表结构: commission, invited_count
try {
await conn.query('ALTER TABLE users ADD COLUMN commission DECIMAL(10,2) DEFAULT 0.00');
} catch (_) {}
try {
await conn.query('ALTER TABLE users ADD COLUMN invited_count INT DEFAULT 0');
} catch (_) {}
try {
await conn.query('UPDATE users SET commission = 128.50, invited_count = 8 WHERE id = 1001 AND (commission IS NULL OR commission = 0)');
} catch (_) {}
// 扩展 users 表结构: 个性签名
try {
await conn.query("ALTER TABLE users ADD COLUMN signature VARCHAR(64) DEFAULT ''");
} catch (_) {}
// 确保存在 demo 账号 101 (金牌陪伴师/认证大神体验账号)
try {
await conn.query(`
INSERT INTO users (id, user_no, nickname, avatar, phone, gender, role, balance, commission, invited_count, order_count, activity_count, status, wechat_openid, signature)
VALUES (101, 'U101', '糖心小糯米', 'https://images.unsplash.com/photo-1494790108377-be9c29b29330?w=200', '138****0101', '女', '认证大神', 2580.00, 128.50, 6, 88, 16, '正常', 'wx_openid_101', '人美声甜,擅长各类同城陪伴与开黑互动')
ON DUPLICATE KEY UPDATE nickname = VALUES(nickname)
`);
} catch (_) {}
// 21. 用户举报工单表 (涉黄/涉赌/线下欺诈等不良陪玩举报)
await conn.query(`
CREATE TABLE IF NOT EXISTS reports (
id VARCHAR(64) PRIMARY KEY,
reporter_id INT NOT NULL,
target_type VARCHAR(32) NOT NULL DEFAULT 'EXPERT',
target_id VARCHAR(64) NOT NULL,
target_name VARCHAR(64) DEFAULT '',
reason VARCHAR(64) NOT NULL,
description VARCHAR(500) DEFAULT '',
evidence JSON,
status VARCHAR(32) NOT NULL DEFAULT '待处理',
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
INDEX idx_target (target_type, target_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
`);
// 22. 陪玩收藏表 (收藏喜欢的陪玩,实时高亮在接单状态)
await conn.query(`
CREATE TABLE IF NOT EXISTS favorites (
id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT NOT NULL,
expert_id INT NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
UNIQUE KEY uk_user_expert (user_id, expert_id),
INDEX idx_user (user_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
`);
// 23. 分销体系扩展 (下级团队与佣金订单记录)
try {
await conn.query('ALTER TABLE users ADD COLUMN inviter_id INT DEFAULT NULL');
} catch (_) {}
await conn.query(`
CREATE TABLE IF NOT EXISTS distribution_records (
id VARCHAR(64) PRIMARY KEY,
user_id INT NOT NULL,
from_user_id INT NOT NULL,
from_user_name VARCHAR(64) NOT NULL,
order_no VARCHAR(64) NOT NULL,
order_amount DECIMAL(10,2) NOT NULL,
commission DECIMAL(10,2) NOT NULL,
level INT NOT NULL DEFAULT 1,
rate_percent DECIMAL(5,2) NOT NULL,
status VARCHAR(32) NOT NULL DEFAULT '已入账',
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
INDEX idx_dist_user (user_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
`);
// 检查并插入初始种子数据(若表为空)
await seedInitialDataIfEmpty(conn);
console.log('[MySQL] peiwan 数据库核心表及种子数据已完整就绪');
} finally {
conn.release();
}
}
async function seedInitialDataIfEmpty(conn: any): Promise<void> {
// 1. 种子活动
const [actRows]: any = await conn.query('SELECT COUNT(*) as count FROM activities');
if (actRows[0].count === 0) {
await conn.query(`
INSERT INTO activities (id, creator_id, title, game_category, location, pay_type, total_fee_cents, per_person_fee_cents, max_participants, allow_dynamic_price, price_adjust_rule)
VALUES
('act_101', 1001, '三里屯铜锅涮肉AA探店 · 8人热烈局', '同城陪吃', '北京市朝阳区三里屯聚宝源铜锅涮肉', 1, 40000, 5000, 4, 1, 'UNIFIED_HIGH'),
('act_102', 1002, '工体纯KTV沉浸式麦霸欢唱 · 寻找甜美副唱', '同城陪唱', '工体西路8号纯KTV 888包厢', 2, 240000, 80000, 3, 1, 'UNIFIED_HIGH'),
('act_103', 1003, '望京合生麒麟社微醺清吧精酿品鉴', '同城陪喝', '望京街道合生麒麟社地库跳海酒馆', 1, 39600, 19800, 4, 1, 'UNIFIED_HIGH');
`);
// 种子参与者与4位核销码
await conn.query(`
INSERT INTO participants (id, activity_id, user_id, pay_amount_cents, verify_code, checkin_status, verified_at, verified_by)
VALUES
('pt_101', 'act_101', 2001, 5000, '8392', 1, NOW(), 1001),
('pt_102', 'act_101', 2002, 5000, '5419', 0, NULL, NULL),
('pt_103', 'act_101', 2003, 5000, '7260', 0, NULL, NULL),
('pt_104', 'act_102', 2004, 80000, '9031', 0, NULL, NULL),
('pt_105', 'act_103', 2005, 19800, '6184', 0, NULL, NULL);
`);
}
// 2. 种子大神档案
const [compRows]: any = await conn.query('SELECT COUNT(*) as count FROM companions');
if (compRows[0].count === 0) {
await conn.query(`
INSERT INTO companions (name, avatar, gender, age, track, rank_name, hourly_rate, voice_duration, voice_title, rating, order_count, status, audit_status, id_card_masked)
VALUES
('苏苏学姐', 'https://images.unsplash.com/photo-1534528741775-53994a69daeb?w=120', '女', 22, '同城陪吃', '金牌探店官', 158, 18, '甜美学姐元气语音条', 4.95, 382, '接单中', '已通过', '110105********3821'),
('林深见鹿', 'https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=120', '男', 24, 'KTV陪唱', '十佳青年歌手', 288, 25, '清澈烟嗓流行情歌试听', 4.98, 512, '接单中', '已通过', '310115********1028'),
('小鱼泡泡', 'https://images.unsplash.com/photo-1517841905240-472988babdf9?w=120', '女', 21, '同城陪喝', '精酿侍酒达人', 198, 14, '微醺甜美随和聊天', 4.88, 194, '休息中', '已通过', '440301********7824'),
('顾北辰', 'https://images.unsplash.com/photo-1500648767791-00dcc994a43e?w=120', '男', 23, '线上电竞', '百星王者国服第一射手', 88, 12, '低沉磁性指挥型男音', 4.92, 680, '接单中', '已通过', '510107********4419'),
('可可奶芙', 'https://images.unsplash.com/photo-1494790108377-be9c29b29330?w=120', '女', 20, '同城陪吃', '美食品鉴官', 168, 16, '软糯元气自我介绍', 4.85, 42, '待审核', '待审核', '320106********9124'),
('夜风沉醉', 'https://images.unsplash.com/photo-1522075469751-3a6694fb2f61?w=120', '男', 25, 'KTV陪唱', '摇滚乐队副主唱', 220, 22, '摇滚副歌现场高音试听', 4.75, 18, '待审核', '待审核', '330104********2816');
`);
}
// 3. 种子订单
const [ordRows]: any = await conn.query('SELECT COUNT(*) as count FROM orders');
if (ordRows[0].count === 0) {
await conn.query(`
INSERT INTO orders (id, order_no, client_name, companion_name, track, expense_burden, hourly_rate, duration_hours, amount, location, status)
VALUES
('ord_01', 'PW202609280001', '赵公子', '苏苏学姐', '同城陪吃', '客户全包', 158, 2, 316.00, '朝阳区大悦城 太二酸菜鱼', '已到场核销'),
('ord_02', 'PW202609280002', '钱老板', '林深见鹿', 'KTV陪唱', '客户全包', 288, 3, 864.00, '工体西路8号纯KTV 888包厢', '履约中'),
('ord_03', 'PW202609280003', '孙先生', '小鱼泡泡', '同城陪喝', '费用AA', 198, 2, 396.00, '望京合生麒麟社跳海酒馆', '待支付'),
('ord_04', 'PW202609280004', '李小姐', '顾北辰', '线上电竞', '无需承担', 88, 4, 352.00, '线上语音频道 #9021', '已完成'),
('ord_05', 'PW202609280005', '周先生', '林深见鹿', 'KTV陪唱', '客户全包', 288, 2, 576.00, '海淀中关村好乐迪KTV', '争议仲裁中');
`);
}
// 4. 种子仲裁
const [arbRows]: any = await conn.query('SELECT COUNT(*) as count FROM arbitrations');
if (arbRows[0].count === 0) {
await conn.query(`
INSERT INTO arbitrations (id, order_id, order_no, client_name, companion_name, reason, user_evidence, status)
VALUES
('arb_001', 'ord_05', 'PW202609280005', '周先生', '林深见鹿', '未准时到场且提前离场', '大神迟到了35分钟,且中途以有急事为由提前40分钟离开,实际服务仅45分钟。现场有微信沟通记录与到场照片。', '待平台仲裁');
`);
}
// 5. 种子财务流水
const [finRows]: any = await conn.query('SELECT COUNT(*) as count FROM finance_records');
if (finRows[0].count === 0) {
await conn.query(`
INSERT INTO finance_records (id, record_no, type, amount, direction, counterparty, related_id)
VALUES
('fin_001', 'TR20260928001', '活动报名入账', 50.00, 'IN', '用户 2001', 'act_101'),
('fin_002', 'TR20260928002', '活动报名入账', 50.00, 'IN', '用户 2002', 'act_101'),
('fin_003', 'TR20260928003', '大神订单全款', 316.00, 'IN', '客户 赵公子', 'ord_01'),
('fin_004', 'TR20260928004', '平台抽成 (10%)', 31.60, 'IN', '系统结算', 'ord_01'),
('fin_005', 'TR20260928005', '一级分销佣金 (5%)', 15.80, 'OUT', '推荐人 张三', 'ord_01'),
('fin_006', 'TR20260928006', '房主追加赏金差额退补', 300.00, 'IN', '房主 1001', 'act_101');
`);
}
// 6. 种子提现
const [wdRows]: any = await conn.query('SELECT COUNT(*) as count FROM withdrawals');
if (wdRows[0].count === 0) {
await conn.query(`
INSERT INTO withdrawals (id, withdraw_no, companion_name, companion_id, amount, balance, channel, status)
VALUES
('wd_001', 'TX20260928001', '苏苏学姐', 101, 1250.00, 4890.00, '微信商户零钱', '待审核'),
('wd_002', 'TX20260928002', '顾北辰', 104, 2800.00, 6200.00, '银联企业直连', '已打款');
`);
}
// 7. 种子场所
const [placeRows]: any = await conn.query('SELECT COUNT(*) as count FROM safety_places');
if (placeRows[0].count === 0) {
await conn.query(`
INSERT INTO safety_places (id, name, area, category, safety_level, status, approved)
VALUES
('place_001', '三里屯聚宝源铜锅涮肉', '朝阳区三里屯商圈', '餐饮美食', 'AAA级合规认证', '正常营业', 1),
('place_002', '工体纯KTV', '朝阳区工人体育场商圈', '量贩KTV', 'AAA级合规认证', '正常营业', 1),
('place_003', '望京合生麒麟社跳海酒馆', '朝阳区望京商圈', '商圈清吧', 'AA级合规认证', '正常营业', 1),
('place_004', '朝阳大悦城太二酸菜鱼', '朝阳区青年路大悦城', '餐饮美食', 'AAA级合规认证', '正常营业', 1);
`);
}
// 8. 种子风控拦截日志
const [secRows]: any = await conn.query('SELECT COUNT(*) as count FROM safety_audit_logs');
if (secRows[0].count === 0) {
await conn.query(`
INSERT INTO safety_audit_logs (id, timestamp_str, user_id, type, content, action, status)
VALUES
('sec_001', '2026-09-28 14:12:05', 2088, '违规场所拦截', '用户尝试将线下陪吃地点填写为:某某苑4号楼2单元501室(私人住宅)', '系统自动阻断下单,弹出公共商圈合规红线告警', '已处置'),
('sec_002', '2026-09-28 11:35:20', 2095, '违规场所拦截', '用户尝试将线下陪唱地点填写为:某某精品快捷酒店308客房', '系统拦截并强制要求修改为正规商业量贩KTV', '已处置'),
('sec_003', '2026-09-27 21:04:18', 2012, '敏感词过滤', '组局留言中出现敏感违规引流词汇汇款、加私微等', '关键词自动打码屏蔽,并记录账号风控提示分', '已处置');
`);
}
// 9. 种子全平台注册用户
const [userRows]: any = await conn.query('SELECT COUNT(*) as count FROM users');
if (userRows[0].count === 0) {
await conn.query(`
INSERT INTO users (id, user_no, nickname, avatar, phone, gender, role, balance, order_count, activity_count, status, wechat_openid, created_at)
VALUES
(1001, 'U1001', '同城局长', 'https://images.unsplash.com/photo-1535713875002-d1d0cf377fde?w=120', '138****1001', '男', '同城房主', 1880.00, 8, 12, '正常', 'wx_openid_1001', '2026-09-01 10:00:00'),
(2001, 'U2001', '涮肉小行家', 'https://images.unsplash.com/photo-1534528741775-53994a69daeb?w=120', '139****2001', '女', '普通玩家', 260.00, 15, 6, '正常', 'wx_openid_2001', '2026-09-05 14:20:00'),
(2002, 'U2002', '吃货小张', 'https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=120', '136****2002', '男', '普通玩家', 120.00, 6, 2, '正常', 'wx_openid_2002', '2026-09-10 11:15:00'),
(2003, 'U2003', 'K歌达人阿伟', 'https://images.unsplash.com/photo-1500648767791-00dcc994a43e?w=120', '137****2003', '男', '普通玩家', 350.00, 21, 9, '正常', 'wx_openid_2003', '2026-09-12 18:30:00'),
(2004, 'U2004', '电竞刺客', 'https://images.unsplash.com/photo-1517841905240-472988babdf9?w=120', '135****2004', '男', '普通玩家', 50.00, 9, 3, '正常', 'wx_openid_2004', '2026-09-15 20:00:00'),
(2005, 'U2005', '橙子小七', 'https://images.unsplash.com/photo-1534528741775-53994a69daeb?w=120', '138****2005', '女', '认证大神', 4280.00, 420, 28, '正常', 'wx_openid_2005', '2026-09-02 09:00:00'),
(2006, 'U2006', '苏苏学姐', 'https://images.unsplash.com/photo-1524504388940-b1c1722653e1?w=120', '139****2006', '女', '认证大神', 5690.00, 560, 35, '正常', 'wx_openid_2006', '2026-09-03 16:45:00'),
(2007, 'U2007', '莫吉托学长', 'https://images.unsplash.com/photo-1506794778202-cad84cf45f1d?w=120', '137****2007', '男', '认证大神', 3100.00, 310, 18, '正常', 'wx_openid_2007', '2026-09-08 12:20:00'),
(2008, 'U2008', '测试玩家小李', 'https://images.unsplash.com/photo-1535713875002-d1d0cf377fde?w=120', '188****2008', '男', '普通玩家', 88.00, 2, 1, '正常', 'wx_openid_2008', '2026-09-28 10:10:00'),
(2009, 'U2009', '风险异常号', 'https://images.unsplash.com/photo-1492562080023-ab3db95bfbce?w=120', '131****2009', '未知', '普通玩家', 0.00, 0, 0, '已封禁', 'wx_openid_2009', '2026-09-27 15:30:00');
`);
}
// 10. 种子友圈动态
const [postRows]: any = await conn.query('SELECT COUNT(*) as count FROM posts');
if (postRows[0].count === 0) {
await conn.query(`
INSERT INTO posts (id, user_id, author, avatar, tag, tag_type, location, distance, content, topics, images, action_text, likes, comments, views, category, created_at)
VALUES
('post_1', 2005, '小甜橙', 'https://images.unsplash.com/photo-1534528741775-53994a69daeb?w=150', '火锅达人', 'warm-tag', '朝阳区 · 三里屯太古里', '800m', '今晚7点半有没有在三里屯附近的小伙伴一起去吃铜锅涮肉?已预订包间,目前已有2人,再来2个饭搭子AA!吃完还可以顺路去清吧听歌放松~', '["三里屯探店", "铜锅涮肉AA", "饭搭子招募"]', '["https://images.unsplash.com/photo-1555396273-367ea4eb4db5?w=500", "https://images.unsplash.com/photo-1517248135467-4c7edcad34c4?w=500"]', '加入车队', 42, 8, 310, 'partner', NOW() - INTERVAL 15 MINUTE),
('post_2', 2004, '暗影刺客 (省一李白)', 'https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=150', '国服大神', 'cool-tag', '海淀区 · 五道口', '3.5km', '今晚王者荣耀荣耀王者冲分车队!目前缺一个听指挥的中单或者软辅妹子,全程开麦包赢不保段包赔,想上星的速速滴我!', '["王者荣耀", "荣耀车队", "连胜冲分"]', '["https://images.unsplash.com/photo-1542751371-adc38448a05e?w=500"]', '立即上车', 76, 15, 680, 'game', NOW() - INTERVAL 40 MINUTE),
('post_3', 2006, '苏苏学姐', 'https://images.unsplash.com/photo-1517841905240-472988babdf9?w=150', '金牌麦霸', 'gold-tag', '朝阳区 · 工体商业街', '1.2km', '工体纯K量贩欢唱局!甜美情歌、粤语老歌、摇滚气氛拉满。现场备有精美果盘与特饮,今晚欢唱不嗨不散,还有专属歌声试听哦!', '["KTV欢唱", "量贩陪唱", "同城聚会"]', '["https://images.unsplash.com/photo-1516450360452-9312f5e86fc7?w=500"]', '报名同去', 58, 11, 520, 'partner', NOW() - INTERVAL 1 HOUR);
`);
}
// 11. 种子订单真实评价
const [revRows]: any = await conn.query('SELECT COUNT(*) as count FROM order_reviews');
if (revRows[0].count === 0) {
await conn.query(`
INSERT INTO order_reviews (id, order_id, expert_id, user_id, user_nickname, user_avatar, rating, tags, content, created_at)
VALUES
('rev_101', 'ord_04', 104, 1001, '李小姐', 'https://images.unsplash.com/photo-1534528741775-53994a69daeb?w=120', 5, '["技术过硬", "耐心温柔", "连胜吃鸡"]', '北辰大神意识太好了,几波团战残血反杀,全程听指挥轻轻松松上大分!', NOW() - INTERVAL 1 DAY),
('rev_102', 'ord_01', 101, 2001, '赵公子', 'https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=120', 5, '["随和健谈", "品味极佳", "准时守约"]', '苏苏学姐推荐的涮肉店真的一绝,性格温柔幽默,聚餐氛围特别好!', NOW() - INTERVAL 2 DAY);
`);
}
// 12. 种子友圈动态评论
const [cmtRows]: any = await conn.query('SELECT COUNT(*) as count FROM post_comments');
if (cmtRows[0].count === 0) {
await conn.query(`
INSERT INTO post_comments (id, post_id, user_id, author, avatar, content, created_at)
VALUES
('cmt_1', 'post_1', 2002, '吃货小张', 'https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=120', '三里屯聚宝源吗?这家手切羊肉超棒,已报名+1!', NOW() - INTERVAL 10 MINUTE),
('cmt_2', 'post_1', 2006, '苏苏学姐', 'https://images.unsplash.com/photo-1524504388940-b1c1722653e1?w=120', '吃完可以去附近跳海酒馆坐坐,环境很舒服~', NOW() - INTERVAL 5 MINUTE),
('cmt_3', 'post_2', 2001, '涮肉小行家', 'https://images.unsplash.com/photo-1534528741775-53994a69daeb?w=120', '国服李白太强了!主玩大乔和张飞,晚上可以一起开黑吗?', NOW() - INTERVAL 25 MINUTE);
`);
}
// 13. 种子轮播图
const [bnrRows]: any = await conn.query('SELECT COUNT(*) as count FROM banners');
if (bnrRows[0].count === 0) {
await conn.query(`
INSERT INTO banners (id, title, subtitle, tag, badge, badge_type, bg, image, link, sort_order, status)
VALUES
(1, '同城聚会狂欢 | 网红火锅探店与量贩KTV嗨唱', 'AA制铜锅涮肉 · 8人热烈局', '热门陪伴', 'HOT 热门组局', 'badge-hot', 'linear-gradient(135deg, #F43F5E 0%, #FB7185 100%)', 'https://images.unsplash.com/photo-1555396273-367ea4eb4db5?w=800', '/pages/activity/detail?id=act_101', 1, 1),
(2, '量贩KTV麦霸沉浸欢唱 | 音乐达人歌声试听', '工体纯K 888豪华包厢', 'K歌对唱', '同城陪唱', 'badge-ktv', 'linear-gradient(135deg, #7C3AED 0%, #6366F1 100%)', 'https://images.unsplash.com/photo-1516450360452-9312f5e86fc7?w=800', '/pages/activity/detail?id=act_102', 2, 1),
(3, '精酿清吧微醺畅聊 | 线下陪吃陪喝立减30元', '望京跳海酒馆 · 慢调交友', '同城陪喝', '同城陪喝', 'badge-bar', 'linear-gradient(135deg, #059669 0%, #10B981 100%)', 'https://images.unsplash.com/photo-1517248135467-4c7edcad34c4?w=800', '/pages/activity/detail?id=act_103', 3, 1);
`);
}
// 14. 种子金刚区活动品类导航
const [navRows]: any = await conn.query('SELECT COUNT(*) as count FROM nav_categories');
if (navRows[0].count === 0) {
await conn.query(`
INSERT INTO nav_categories (id, code, name, icon, bg_class, cat, target_url, badge_text, sort_order, status)
VALUES
(1, 'esports', '电子竞技', 'gameAll', 'bg-indigo', 'all', '/pages/activity/list?category=ALL', 'HOT', 1, 1),
(2, 'meal', '美食探店', 'utensils', 'bg-amber', 'offline_meal', '/pages/activity/list?category=MEAL', 'AA制', 2, 1),
(3, 'sing', 'KTV嗨唱', 'micVocal', 'bg-rose', 'offline_sing', '/pages/activity/list?category=SING', '热度高', 3, 1),
(4, 'billiards', '同城台球', 'billiards', 'bg-sky', 'offline_play', '/pages/activity/list?category=ALL', '', 4, 1),
(5, 'hiking', '户外爬山', 'mountain', 'bg-emerald', 'offline_play', '/pages/activity/list?category=ALL', '周末', 5, 1),
(6, 'drink', '下午茶歇', 'coffee', 'bg-teal', 'offline_drink', '/pages/activity/list?category=DRINK', '', 6, 1),
(7, 'boardgame', '剧本桌游', 'dice', 'bg-purple', 'offline_play', '/pages/activity/list?category=ALL', '', 7, 1),
(8, 'fitness', '运动健身', 'fitness', 'bg-orange', 'offline_play', '/pages/activity/list?category=ALL', '', 8, 1),
(9, 'bar', '同城微醺', 'warmFlame', 'bg-rose', 'offline_drink', '/pages/activity/list?category=DRINK', '清吧', 9, 1),
(10, 'more', '全部活动', 'gridAll', 'bg-blue', 'all', '/pages/activity/list?category=ALL', '', 10, 1);
`);
}
// 15. 种子充值阶梯
const [tierRows]: any = await conn.query('SELECT COUNT(*) as count FROM recharge_tiers');
if (tierRows[0].count === 0) {
await conn.query(`
INSERT INTO recharge_tiers (id, amount, bonus_amount, tag, sort_order, status)
VALUES
(1, 50.00, 0.00, '基础充值', 1, 1),
(2, 100.00, 5.00, '热门畅享', 2, 1),
(3, 200.00, 15.00, '超值加赠', 3, 1),
(4, 500.00, 50.00, '尊享特惠', 4, 1),
(5, 1000.00, 120.00, '土豪专享', 5, 1);
`);
}
// 16. 种子平台优惠券
const [cpnRows]: any = await conn.query('SELECT COUNT(*) as count FROM coupons');
if (cpnRows[0].count === 0) {
await conn.query(`
INSERT INTO coupons (id, name, discount_amount, min_spend, valid_days, total_count, received_count, category_limit, description, status)
VALUES
(1, '新用户注册专享立减券', 20.00, 50.00, 15, 2000, 128, 'ALL', '全品类陪玩及同城组局满50可用', 1),
(2, '周末同城聚会AA抵扣券', 15.00, 80.00, 7, 1000, 85, 'MEAL', '仅限同城美食探店组局活动使用', 1),
(3, '工体K歌麦霸欢唱减免券', 30.00, 120.00, 10, 800, 62, 'SING', '仅限KTV陪唱预约与活动使用', 1),
(4, '电竞开黑连胜冲星券', 10.00, 30.00, 30, 5000, 340, 'ALL', '线上游戏陪玩下单立减', 1);
`);
}
// 17. 种子平台通用配置(官方客服、履约公告指引、规范协议、话题、公告、FAQ)
const communityTopicsVal = JSON.stringify([
{ id: 'top_1', name: '三里屯探店', hot: true, postsCount: 1280 },
{ id: 'top_2', name: '铜锅涮肉AA', hot: true, postsCount: 890 },
{ id: 'top_3', name: '工体纯K麦霸', hot: false, postsCount: 650 },
{ id: 'top_4', name: '国服上分车队', hot: true, postsCount: 2310 },
{ id: 'top_5', name: '望京跳海微醺', hot: false, postsCount: 420 },
{ id: 'top_6', name: '同城搭子招募', hot: true, postsCount: 3100 }
]);
const communityNoticeVal = JSON.stringify({
title: '友圈同城互动与公约置顶',
content: '欢迎来到同城搭子友圈!文明交友,发布真实组局诉求;平台全天候对动态与评论实施微信官方内容安全过滤,严禁广告引流及私下交易。',
tag: '置顶推荐',
showInBanner: true
});
const faqListVal = JSON.stringify([
{
id: 'faq_1',
category: '新手预约与组局',
question: '什么是4位纯数字核销码?',
answer: '为确保搭子碰面和订单真实履约,下单成功或报名组局后系统自动生成专属4位防伪数字码,到达公开活动现场后出示给陪伴师或房主签到核销。'
},
{
id: 'faq_2',
category: '新手预约与组局',
question: 'AA制拼桌与房主请客有什么区别?',
answer: '【AA制拼桌】由参与人员平摊费用,报名时支付人均分摊金额;【房主请客/项目制】由发起房主全额买单,且房主可随时追加赏金或提高出价。'
},
{
id: 'faq_3',
category: '资金与退款',
question: '如何申请退款与争议仲裁?',
answer: '在订单【待接单】或【待付款】状态可随时取消全额退款;在【服务中】或遇违约可在订单详情点击【发起争议仲裁】,由平台官方运营人工介入判定。'
},
{
id: 'faq_4',
category: '大神与收益',
question: '成为陪玩大神有什么资质要求?',
answer: '需在小程序个人中心提交实名认证与技能资质,通过平台运营团队人工审核后,即可解锁接单工作台与附近雷达扫单功能。'
}
]);
const securityWordsVal = JSON.stringify([
'加微信私聊', '私下走微信', '走线下免佣金', '线下给现金', '私下单',
'联系方式v', 'vx号', '微信转账', '私加好友', '线下私约'
]);
const homePopupVal = JSON.stringify({
enabled: true,
title: '新人专享同城陪伴好礼',
subtitle: '注册即送20元无门槛立减券,首单专享特惠',
imageUrl: 'https://images.unsplash.com/photo-1511671782779-c97d3d27a1d4?w=800',
link: '/pages/activity/list',
btnText: '立即领券组局',
frequency: 'once_daily' // once_daily | always | once_ever
});
const expertRulesVal = JSON.stringify({
minHourlyRate: 30,
maxHourlyRate: 500,
defaultHourlyRate: 88,
requireRealName: true,
allowCustomTags: true,
maxTagsCount: 6,
candidateTags: [
'国服王者', '声优达人', '幽默风趣', '随叫随到', '暖心倾听',
'百星野王', '金牌探店', '量贩麦霸', '微醺搭子', '绅士礼貌',
'活力开朗', '耐心教学', '高胜率车头', '拍照好看'
]
});
const financeRulesVal = JSON.stringify({
platformRatePercent: 10.0,
firstReferralPercent: 5.0,
secondReferralPercent: 2.0,
minWithdrawAmount: 50,
maxWithdrawAmount: 20000,
withdrawFeePercent: 0.0,
withdrawDesc: '提现将自动发起微信企业付款打款至微信零钱,工作日预计2小时内到账。'
});
const activityRulesVal = JSON.stringify({
minParticipants: 2,
maxParticipants: 10,
defaultParticipants: 4,
presetPerPersonFees: [200, 300, 500, 800, 1000],
presetTotalFees: [500, 1000, 2000, 3000, 5000],
defaultAaFee: 50
});
const [cfgItemRows]: any = await conn.query('SELECT COUNT(*) as count FROM platform_configs');
if (cfgItemRows[0].count === 0) {
const customerServiceVal = JSON.stringify({
hotline: '400-888-6666',
hotlineDesc: '7x24h 官方客服服务热线',
wechat: 'peiwan_vip_kefu',
wechatDesc: '官方 VIP 客服微信号',
workHours: '周一至周日 00:00 - 24:00'
});
const safetyNoticeVal = JSON.stringify({
title: '平台官方公告与指引',
points: [
'【安全履约须知】为保障搭子与陪伴师人身与财产安全,线下约局须在合规公开商业街区进行。',
'【现场核销】现场碰面后请出示 4 位数字核销码进行签到确认。',
'【平台兜底】平台提供 7x24 小时争议仲裁与资金托管保障服务,严禁脱离平台私下交易。'
],
noticePopup: false
});
const protocolVal = JSON.stringify({
title: '用户服务协议与隐私规范',
summary: '严禁发布任何违规言论及低俗诈骗行为,平台全面遵循微信内容安全风控与用户隐私保护标准。',
userAgreementTitle: '用户服务协议',
userAgreementContent: '1. 账号使用规范:用户注册与使用同城生活陪伴服务须符合国家法律法规,严禁利用平台从事任何违法违规行为。\n2. 资金与交易保障:平台提供全额担保交易,订单完成前款项由官方账户托管,碰面出示4位核销码确认后自动结算至大神钱包。\n3. 履约安全守则:所有同城活动须在合规公开商业街区进行,严禁私下导流与脱离平台交易。\n4. 争议与售后仲裁:若遇服务不符或搭子违约,可随时在订单中发起申诉,由平台运营仲裁专员裁决。',
privacyPolicyTitle: '隐私保护指引',
privacyPolicyContent: '1. 信息收集范围:为保障同城陪玩交易安全与现场4位核销码核验,平台在获得您授权后会依法收集手机号与必要位置信息。\n2. 数据加密保护:平台全面接入微信小程序官方安全风控规范,所有用户数据均实施高强度加密脱敏存储。\n3. 权限撤回与管理:您可随时在小程序系统设置中撤回位置或通讯授权,平台未经您的明确许可绝不会向任何第三方泄露您的隐私数据。',
content: '1. 账号使用规范:用户注册与使用陪玩服务须符合国家法律法规,严禁利用平台从事违法违规行为。\n2. 资金与交易保障:平台提供全额担保交易,订单完成前款项由官方账户托管,核销确认后自动结算至大神钱包。\n3. 争议与售后:若遇服务不符或搭子违约,可随时提交争议仲裁由运营平台人工介入裁决。'
});
await conn.query(`
INSERT INTO platform_configs (config_key, name, value_json, description, status)
VALUES
('customer_service', '官方在线客服与服务热线', ?, '小程序端个人中心客服联系方式', 1),
('safety_notice', '安全履约须知与官方公告', ?, '小程序端官方指引与安全红线弹窗', 1),
('platform_protocol', '平台服务协议与合规规范', ?, '小程序端服务协议与隐私政策详情', 1),
('community_topics', '友圈热门推荐话题库', ?, '友圈广场发帖推荐话题与热门标签', 1),
('community_notice', '友圈社区置顶头条公告', ?, '友圈广场顶部置顶横幅公告与社区公约', 1),
('faq_list', '帮助中心与常见问题FAQ', ?, '小程序端帮助中心常见问答与指引', 1),
('security_words', '私下引流与违规自定义敏感词库', ?, '全平台发帖、评论及订单防私下交易关键词实时过滤', 1),
('home_popup', '小程序首页运营全局弹窗', ?, '节日活动推广、新用户专享首单优惠全局浮层弹窗', 1),
('expert_rules', '大神技能标签库与定价区间规范', ?, '陪玩大神入驻审核、定价上下限限制与官方推荐技能标签库', 1),
('finance_rules', '平台抽成与推广分销规则', ?, '平台佣金抽成比例、二级分销返润与佣金提现门槛限制', 1),
('activity_rules', '同城组局发单与预算预设规范', ?, '招募席位上下限、快捷单人赏金预设与包场预算梯队', 1);
`, [
customerServiceVal, safetyNoticeVal, protocolVal,
communityTopicsVal, communityNoticeVal, faqListVal,
securityWordsVal, homePopupVal, expertRulesVal,
financeRulesVal, activityRulesVal
]);
} else {
// 增量保证各核心配置项完整就绪
const [existingRows]: any = await conn.query('SELECT config_key FROM platform_configs');
const existingKeys = new Set(existingRows.map((r: any) => r.config_key));
if (!existingKeys.has('community_topics')) {
await conn.query(`
INSERT INTO platform_configs (config_key, name, value_json, description, status)
VALUES ('community_topics', '友圈热门推荐话题库', ?, '友圈广场发帖推荐话题与热门标签', 1)
`, [communityTopicsVal]);
}
if (!existingKeys.has('community_notice')) {
await conn.query(`
INSERT INTO platform_configs (config_key, name, value_json, description, status)
VALUES ('community_notice', '友圈社区置顶头条公告', ?, '友圈广场顶部置顶横幅公告与社区公约', 1)
`, [communityNoticeVal]);
}
if (!existingKeys.has('faq_list')) {
await conn.query(`
INSERT INTO platform_configs (config_key, name, value_json, description, status)
VALUES ('faq_list', '帮助中心与常见问题FAQ', ?, '小程序端帮助中心常见问答与指引', 1)
`, [faqListVal]);
}
if (!existingKeys.has('security_words')) {
await conn.query(`
INSERT INTO platform_configs (config_key, name, value_json, description, status)
VALUES ('security_words', '私下引流与违规自定义敏感词库', ?, '全平台发帖、评论及订单防私下交易关键词实时过滤', 1)
`, [securityWordsVal]);
}
if (!existingKeys.has('home_popup')) {
await conn.query(`
INSERT INTO platform_configs (config_key, name, value_json, description, status)
VALUES ('home_popup', '小程序首页运营全局弹窗', ?, '节日活动推广、新用户专享首单优惠全局浮层弹窗', 1)
`, [homePopupVal]);
}
if (!existingKeys.has('expert_rules')) {
await conn.query(`
INSERT INTO platform_configs (config_key, name, value_json, description, status)
VALUES ('expert_rules', '大神技能标签库与定价区间规范', ?, '陪玩大神入驻审核、定价上下限限制与官方推荐技能标签库', 1)
`, [expertRulesVal]);
}
if (!existingKeys.has('finance_rules')) {
await conn.query(`
INSERT INTO platform_configs (config_key, name, value_json, description, status)
VALUES ('finance_rules', '平台抽成与推广分销规则', ?, '平台佣金抽成比例、二级分销返润与佣金提现门槛限制', 1)
`, [financeRulesVal]);
}
if (!existingKeys.has('activity_rules')) {
await conn.query(`
INSERT INTO platform_configs (config_key, name, value_json, description, status)
VALUES ('activity_rules', '同城组局发单与预算预设规范', ?, '招募席位上下限、快捷单人赏金预设与包场预算梯队', 1)
`, [activityRulesVal]);
}
if (existingKeys.has('platform_protocol')) {
const [protoRows]: any = await conn.query("SELECT value_json FROM platform_configs WHERE config_key = 'platform_protocol'");
if (protoRows && protoRows.length > 0) {
let curVal = protoRows[0].value_json;
if (typeof curVal === 'string') {
try { curVal = JSON.parse(curVal); } catch (_) {}
}
if (curVal && (!curVal.userAgreementContent || !curVal.privacyPolicyContent)) {
const defaultProto = {
userAgreementTitle: '用户服务协议',
userAgreementContent: '1. 账号使用规范:用户注册与使用同城生活陪伴服务须符合国家法律法规,严禁利用平台从事任何违法违规行为。\n2. 资金与交易保障:平台提供全额担保交易,订单完成前款项由官方账户托管,碰面出示4位核销码确认后自动结算至大神钱包。\n3. 履约安全守则:所有同城活动须在合规公开商业街区进行,严禁私下导流与脱离平台交易。\n4. 争议与售后仲裁:若遇服务不符或搭子违约,可随时在订单中发起申诉,由平台运营仲裁专员裁决。',
privacyPolicyTitle: '隐私保护指引',
privacyPolicyContent: '1. 信息收集范围:为保障同城陪玩交易安全与现场4位核销码核验,平台在获得您授权后会依法收集手机号与必要位置信息。\n2. 数据加密保护:平台全面接入微信小程序官方安全风控规范,所有用户数据均实施高强度加密脱敏存储。\n3. 权限撤回与管理:您可随时在小程序系统设置中撤回位置或通讯授权,平台未经您的明确许可绝不会向任何第三方泄露您的隐私数据。'
};
const mergedProto = {
...defaultProto,
...curVal
};
if (!mergedProto.userAgreementContent) mergedProto.userAgreementContent = defaultProto.userAgreementContent;
if (!mergedProto.privacyPolicyContent) mergedProto.privacyPolicyContent = defaultProto.privacyPolicyContent;
await conn.query("UPDATE platform_configs SET value_json = ? WHERE config_key = 'platform_protocol'", [JSON.stringify(mergedProto)]);
}
}
}
}
}