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.

221 lines
11 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

CREATE DATABASE IF NOT EXISTS lifanghe_education DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
USE lifanghe_education;
CREATE TABLE IF NOT EXISTS roles (
role VARCHAR(40) PRIMARY KEY,
name VARCHAR(80) NOT NULL,
permissions JSON NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS users (
id VARCHAR(40) PRIMARY KEY,
username VARCHAR(80) NOT NULL UNIQUE,
password_hash CHAR(64) NULL,
role VARCHAR(40) NOT NULL,
role_name VARCHAR(80) NOT NULL,
name VARCHAR(80) NOT NULL,
phone VARCHAR(30) NULL UNIQUE,
wechat_openid VARCHAR(80) NULL UNIQUE,
wechat_unionid VARCHAR(80) NULL UNIQUE,
wechat_nickname VARCHAR(80) NULL,
wechat_avatar VARCHAR(500) NULL,
login_provider VARCHAR(30) NOT NULL DEFAULT 'password',
phone_bound TINYINT(1) NOT NULL DEFAULT 1,
phone_bound_at VARCHAR(32) NULL,
wechat_bound_at VARCHAR(32) NULL,
status VARCHAR(20) NOT NULL DEFAULT 'active',
last_login_at VARCHAR(32) NULL,
inviter_code VARCHAR(40) NULL UNIQUE,
child_id VARCHAR(40) NULL,
child_name VARCHAR(80) NULL,
child_grade VARCHAR(40) NULL,
child_focus VARCHAR(80) NULL,
trial_booking_limit INT NOT NULL DEFAULT 1,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
INDEX idx_users_role (role),
INDEX idx_users_phone (phone),
INDEX idx_users_login_provider (login_provider),
CONSTRAINT fk_users_role FOREIGN KEY (role) REFERENCES roles(role)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS point_accounts (
user_id VARCHAR(40) PRIMARY KEY,
available INT NOT NULL DEFAULT 0,
pending INT NOT NULL DEFAULT 0,
frozen INT NOT NULL DEFAULT 0,
expiring INT NOT NULL DEFAULT 0,
CONSTRAINT fk_point_accounts_user FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS point_transactions (
id VARCHAR(40) PRIMARY KEY,
user_id VARCHAR(40) NOT NULL,
title VARCHAR(200) NOT NULL,
amount INT NOT NULL,
status VARCHAR(30) NOT NULL,
reference_type VARCHAR(40) NULL,
reference_id VARCHAR(60) NULL,
created_at VARCHAR(32) NOT NULL,
INDEX idx_point_transactions_user (user_id),
INDEX idx_point_transactions_reference (reference_type, reference_id),
CONSTRAINT fk_point_transactions_user FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS point_expiry_rule (
id INT PRIMARY KEY DEFAULT 1,
title VARCHAR(100) NOT NULL,
valid_days INT NOT NULL,
description VARCHAR(500) NOT NULL,
reminder VARCHAR(500) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS point_expiry_schedules (
id VARCHAR(40) PRIMARY KEY,
user_id VARCHAR(40) NOT NULL,
points INT NOT NULL,
expire_at VARCHAR(32) NOT NULL,
source VARCHAR(200) NOT NULL,
INDEX idx_point_expiry_user (user_id),
CONSTRAINT fk_point_expiry_user FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS referral_rules (
event VARCHAR(40) PRIMARY KEY,
title VARCHAR(100) NOT NULL,
inviter INT NOT NULL,
invitee INT NOT NULL,
sort_order INT NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS referrals (
id VARCHAR(40) PRIMARY KEY,
inviter_id VARCHAR(40) NOT NULL,
invitee_id VARCHAR(40) NULL,
name VARCHAR(80) NOT NULL,
phone VARCHAR(30) NOT NULL,
child_grade VARCHAR(40) NOT NULL,
status VARCHAR(40) NOT NULL,
reward INT NOT NULL DEFAULT 0,
channel VARCHAR(80) NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
INDEX idx_referrals_inviter (inviter_id),
CONSTRAINT fk_referrals_inviter FOREIGN KEY (inviter_id) REFERENCES users(id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS courses (
id VARCHAR(40) PRIMARY KEY,
name VARCHAR(120) NOT NULL,
tags JSON NOT NULL,
next_time VARCHAR(32) NOT NULL,
points_back INT NOT NULL DEFAULT 0,
seats INT NOT NULL DEFAULT 0,
campus VARCHAR(80) NOT NULL,
teacher VARCHAR(80) NOT NULL,
trial_minutes INT NOT NULL DEFAULT 45,
status VARCHAR(30) NOT NULL DEFAULT 'active',
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS appointments (
id VARCHAR(40) PRIMARY KEY,
user_id VARCHAR(40) NOT NULL,
child_id VARCHAR(40) NULL,
course_id VARCHAR(40) NOT NULL,
status VARCHAR(30) NOT NULL,
created_at VARCHAR(40) NOT NULL,
INDEX idx_appointments_user (user_id),
INDEX idx_appointments_course (course_id),
CONSTRAINT fk_appointments_user FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
CONSTRAINT fk_appointments_course FOREIGN KEY (course_id) REFERENCES courses(id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS rewards (
id VARCHAR(40) PRIMARY KEY,
name VARCHAR(120) NOT NULL,
cost INT NOT NULL,
type VARCHAR(60) NOT NULL,
stock INT NOT NULL DEFAULT 0,
description VARCHAR(500) NOT NULL DEFAULT ''
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS redemption_orders (
id VARCHAR(40) PRIMARY KEY,
user_id VARCHAR(40) NOT NULL,
item_id VARCHAR(40) NOT NULL,
status VARCHAR(40) NOT NULL,
cost_points INT NOT NULL DEFAULT 0,
voucher_code VARCHAR(60) NULL UNIQUE,
voucher_status VARCHAR(40) NOT NULL DEFAULT 'not_issued',
created_at VARCHAR(40) NOT NULL,
reviewed_by VARCHAR(40) NULL,
reviewed_at VARCHAR(40) NULL,
rejected_reason VARCHAR(255) NULL,
expire_at VARCHAR(40) NULL,
used_at VARCHAR(40) NULL,
used_by VARCHAR(40) NULL,
verify_note VARCHAR(255) NULL,
INDEX idx_redemption_user (user_id),
INDEX idx_redemption_status (status),
INDEX idx_redemption_voucher (voucher_code),
CONSTRAINT fk_redemption_user FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
CONSTRAINT fk_redemption_reward FOREIGN KEY (item_id) REFERENCES rewards(id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS leads (
id VARCHAR(40) PRIMARY KEY,
referral_id VARCHAR(40) NULL,
invitee_id VARCHAR(40) NULL,
parent VARCHAR(80) NOT NULL,
source VARCHAR(100) NOT NULL,
stage VARCHAR(40) NOT NULL,
advisor VARCHAR(80) NOT NULL,
risk VARCHAR(40) NOT NULL DEFAULT '正常',
channel VARCHAR(80) NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
INDEX idx_leads_referral (referral_id),
INDEX idx_leads_invitee (invitee_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS channel_stats (
channel VARCHAR(80) PRIMARY KEY,
leads INT NOT NULL DEFAULT 0,
attended INT NOT NULL DEFAULT 0,
purchased INT NOT NULL DEFAULT 0
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
INSERT INTO roles (role, name, permissions) VALUES
('parent', '家长', JSON_ARRAY()),
('super_admin', '超级管理员', JSON_ARRAY('*:*:*')),
('campus_admin', '校区管理员', JSON_ARRAY('dashboard:overview:view', 'system:user:view', 'system:role:view', 'leads:referral:view', 'leads:referral:advance', 'points:account:view', 'points:rule:edit', 'points:redemption:view', 'points:redemption:review', 'points:voucher:verify', 'courses:trial:view', 'courses:trial:add', 'courses:trial:edit', 'statistics:channel:view')),
('advisor', '课程顾问', JSON_ARRAY('dashboard:overview:view', 'leads:referral:view', 'leads:referral:advance', 'courses:trial:view', 'points:account:view', 'points:redemption:view')),
('teacher', '老师', JSON_ARRAY('dashboard:overview:view', 'leads:referral:view', 'courses:trial:view')),
('finance', '财务', JSON_ARRAY('dashboard:overview:view', 'points:account:view', 'points:account:adjust', 'points:rule:edit', 'points:reward:edit', 'points:redemption:view', 'points:redemption:review', 'points:voucher:verify', 'statistics:channel:view'))
ON DUPLICATE KEY UPDATE name = VALUES(name), permissions = VALUES(permissions);
INSERT INTO users (
id, username, password_hash, role, role_name, name, phone,
wechat_openid, wechat_unionid, wechat_nickname, wechat_avatar,
login_provider, phone_bound, phone_bound_at, wechat_bound_at,
status, last_login_at, inviter_code, child_id, child_name, child_grade, child_focus
) VALUES
('admin_001', 'admin', '240be518fabd2724ddb6f04eeb1da5967448d7e831c08c8fa822809f74c720a9', 'super_admin', '超级管理员', '系统管理员', '13800009999', NULL, NULL, NULL, NULL, 'password', 1, NULL, NULL, 'active', NULL, NULL, NULL, NULL, NULL, NULL)
ON DUPLICATE KEY UPDATE username = VALUES(username), password_hash = VALUES(password_hash), role = VALUES(role), role_name = VALUES(role_name), name = VALUES(name), phone = VALUES(phone), login_provider = VALUES(login_provider), phone_bound = VALUES(phone_bound), status = VALUES(status);
INSERT INTO point_expiry_rule (id, title, valid_days, description, reminder) VALUES
(1, '积分有效期说明', 180, '积分自实际到账日起 180 天内有效,仅可兑换课程、测评和学习服务权益,不可提现或转赠。', '系统会在到期前 30 天进入“将过期”口径,运营可通过积分管理页提醒家长尽快兑换。')
ON DUPLICATE KEY UPDATE title = VALUES(title), valid_days = VALUES(valid_days), description = VALUES(description), reminder = VALUES(reminder);
INSERT INTO referral_rules (event, title, inviter, invitee, sort_order) VALUES
('registered', '新家长注册', 20, 20, 1),
('booked', '预约试听', 50, 50, 2),
('attended', '确认到课', 150, 100, 3),
('purchased', '报名正价课', 800, 500, 4)
ON DUPLICATE KEY UPDATE title = VALUES(title), inviter = VALUES(inviter), invitee = VALUES(invitee), sort_order = VALUES(sort_order);
INSERT INTO rewards (id, name, cost, type, stock, description) VALUES
('reward_001', '精品体验课 1 次', 800, '课程权益', 30, '适用于校区公开试听课审核通过后生成课程券码30 天内到店核销。'),
('reward_002', '学习规划咨询', 500, '服务权益', 50, '由课程顾问提供一次学习规划沟通,适合新生测评后使用。'),
('reward_003', '正价课抵扣券 100 元', 1000, '抵扣券', 20, '报名正价课程时抵扣 100 元,不可叠加现金活动使用。'),
('reward_004', '阶段测评报告', 300, '测评', 80, '兑换后安排一次阶段测评报告解读,帮助家长了解学习状态。')
ON DUPLICATE KEY UPDATE name = VALUES(name), cost = VALUES(cost), type = VALUES(type), stock = VALUES(stock), description = VALUES(description);