完善业务闭环,实现对轮播图的管理,优化数据库表文件

This commit is contained in:
2026-07-18 16:21:40 +08:00
parent feaf014b4a
commit 97a5eff678
78 changed files with 3210 additions and 100 deletions
@@ -0,0 +1,73 @@
package cn.novalon.gym.manage.db.converter;
import cn.novalon.gym.manage.notify.core.domain.Banner;
import cn.novalon.gym.manage.db.entity.BannerEntity;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.stream.Collectors;
/**
* 轮播图实体转换器
*
* @author 张翔
* @date 2026-07-18
*/
@Component
public class BannerConverter {
public Banner toDomain(BannerEntity entity) {
if (entity == null) {
return null;
}
Banner domain = new Banner();
domain.setId(entity.getId());
domain.setImageUrl(entity.getImageUrl());
domain.setTitle(entity.getTitle());
domain.setSubtitle(entity.getSubtitle());
domain.setSortOrder(entity.getSortOrder());
domain.setIsActive(entity.getIsActive());
domain.setLinkUrl(entity.getLinkUrl());
domain.setCreatedAt(entity.getCreatedAt());
domain.setUpdatedAt(entity.getUpdatedAt());
domain.setDeletedAt(entity.getDeletedAt());
return domain;
}
public BannerEntity toEntity(Banner domain) {
if (domain == null) {
return null;
}
BannerEntity entity = new BannerEntity();
entity.setId(domain.getId());
entity.setImageUrl(domain.getImageUrl());
entity.setTitle(domain.getTitle());
entity.setSubtitle(domain.getSubtitle());
entity.setSortOrder(domain.getSortOrder());
entity.setIsActive(domain.getIsActive());
entity.setLinkUrl(domain.getLinkUrl());
entity.setCreatedAt(domain.getCreatedAt());
entity.setUpdatedAt(domain.getUpdatedAt());
entity.setDeletedAt(domain.getDeletedAt());
return entity;
}
public List<Banner> toDomainList(List<BannerEntity> entities) {
if (entities == null) {
return null;
}
return entities.stream()
.map(this::toDomain)
.collect(Collectors.toList());
}
public List<BannerEntity> toEntityList(List<Banner> domains) {
if (domains == null) {
return null;
}
return domains.stream()
.map(this::toEntity)
.collect(Collectors.toList());
}
}
@@ -0,0 +1,22 @@
package cn.novalon.gym.manage.db.dao;
import cn.novalon.gym.manage.db.entity.BannerEntity;
import org.springframework.data.domain.Sort;
import org.springframework.data.r2dbc.repository.Query;
import org.springframework.data.r2dbc.repository.R2dbcRepository;
import org.springframework.stereotype.Repository;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
@Repository
public interface BannerDao extends R2dbcRepository<BannerEntity, Long> {
Flux<BannerEntity> findByDeletedAtIsNull();
Flux<BannerEntity> findByDeletedAtIsNull(Sort sort);
@Query("SELECT * FROM banner WHERE deleted_at IS NULL ORDER BY sort_order ASC")
Flux<BannerEntity> findActiveBanners();
Mono<Void> deleteByIdAndDeletedAtIsNull(Long id);
}
@@ -0,0 +1,127 @@
package cn.novalon.gym.manage.db.entity;
import org.springframework.data.annotation.Id;
import org.springframework.data.relational.core.mapping.Column;
import org.springframework.data.relational.core.mapping.Table;
import java.time.LocalDateTime;
/**
* 轮播图数据库实体类
*
* @author 张翔
* @date 2026-07-18
*/
@Table("banner")
public class BannerEntity {
@Id
private Long id;
@Column("image_url")
private String imageUrl;
@Column("title")
private String title;
@Column("subtitle")
private String subtitle;
@Column("sort_order")
private Integer sortOrder;
@Column("is_active")
private String isActive;
@Column("link_url")
private String linkUrl;
@Column("created_at")
private LocalDateTime createdAt;
@Column("updated_at")
private LocalDateTime updatedAt;
@Column("deleted_at")
private LocalDateTime deletedAt;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getImageUrl() {
return imageUrl;
}
public void setImageUrl(String imageUrl) {
this.imageUrl = imageUrl;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getSubtitle() {
return subtitle;
}
public void setSubtitle(String subtitle) {
this.subtitle = subtitle;
}
public Integer getSortOrder() {
return sortOrder;
}
public void setSortOrder(Integer sortOrder) {
this.sortOrder = sortOrder;
}
public String getIsActive() {
return isActive;
}
public void setIsActive(String isActive) {
this.isActive = isActive;
}
public String getLinkUrl() {
return linkUrl;
}
public void setLinkUrl(String linkUrl) {
this.linkUrl = linkUrl;
}
public LocalDateTime getCreatedAt() {
return createdAt;
}
public void setCreatedAt(LocalDateTime createdAt) {
this.createdAt = createdAt;
}
public LocalDateTime getUpdatedAt() {
return updatedAt;
}
public void setUpdatedAt(LocalDateTime updatedAt) {
this.updatedAt = updatedAt;
}
public LocalDateTime getDeletedAt() {
return deletedAt;
}
public void setDeletedAt(LocalDateTime deletedAt) {
this.deletedAt = deletedAt;
}
}
@@ -0,0 +1,59 @@
package cn.novalon.gym.manage.db.repository;
import cn.novalon.gym.manage.notify.core.domain.Banner;
import cn.novalon.gym.manage.notify.core.repository.IBannerRepository;
import cn.novalon.gym.manage.db.converter.BannerConverter;
import cn.novalon.gym.manage.db.dao.BannerDao;
import cn.novalon.gym.manage.db.entity.BannerEntity;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Repository;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
/**
* 轮播图仓储实现类
*
* @author 张翔
* @date 2026-07-18
*/
@Repository
public class BannerRepository implements IBannerRepository {
private final BannerDao bannerDao;
private final BannerConverter bannerConverter;
public BannerRepository(BannerDao bannerDao, BannerConverter bannerConverter) {
this.bannerDao = bannerDao;
this.bannerConverter = bannerConverter;
}
@Override
public Flux<Banner> findByDeletedAtIsNull() {
return bannerDao.findByDeletedAtIsNull(Sort.by(Sort.Direction.ASC, "sortOrder"))
.map(bannerConverter::toDomain);
}
@Override
public Flux<Banner> findActiveBanners() {
return bannerDao.findActiveBanners()
.map(bannerConverter::toDomain);
}
@Override
public Mono<Banner> findById(Long id) {
return bannerDao.findById(id)
.map(bannerConverter::toDomain);
}
@Override
public Mono<Banner> save(Banner banner) {
BannerEntity entity = bannerConverter.toEntity(banner);
return bannerDao.save(entity)
.map(bannerConverter::toDomain);
}
@Override
public Mono<Void> deleteByIdAndDeletedAtIsNull(Long id) {
return bannerDao.deleteByIdAndDeletedAtIsNull(id);
}
}
@@ -1,76 +0,0 @@
-- ============================================
-- 团课类型表
-- ============================================
-- 团课类型表
CREATE TABLE IF NOT EXISTS group_course_type (
id BIGSERIAL PRIMARY KEY,
type_name VARCHAR(100) NOT NULL,
base_difficulty INTEGER DEFAULT 1,
description TEXT,
category VARCHAR(50),
create_by VARCHAR(50),
update_by VARCHAR(50),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
deleted_at TIMESTAMP
);
COMMENT ON TABLE group_course_type IS '团课类型表';
COMMENT ON COLUMN group_course_type.id IS '主键ID';
COMMENT ON COLUMN group_course_type.type_name IS '类型名称';
COMMENT ON COLUMN group_course_type.base_difficulty IS '基础难度(1-10';
COMMENT ON COLUMN group_course_type.description IS '类型描述';
COMMENT ON COLUMN group_course_type.category IS '分类(如:有氧、力量、柔韧等)';
COMMENT ON COLUMN group_course_type.create_by IS '创建人';
COMMENT ON COLUMN group_course_type.update_by IS '更新人';
COMMENT ON COLUMN group_course_type.created_at IS '创建时间';
COMMENT ON COLUMN group_course_type.updated_at IS '更新时间';
COMMENT ON COLUMN group_course_type.deleted_at IS '删除时间(软删除)';
-- 创建索引
CREATE INDEX idx_group_course_type_type_name ON group_course_type(type_name);
CREATE INDEX idx_group_course_type_category ON group_course_type(category);
-- 插入初始团课类型数据(参考exmp.txt)
INSERT INTO group_course_type (type_name, base_difficulty, description, category) VALUES
('慢走/椭圆机轻松模式', 1, '几乎无难度,适合所有人', '基础有氧与热身'),
('固定自行车(低阻力)', 2, '注意座椅高度调节即可', '基础有氧与热身'),
('跑步机慢跑', 3, '需要基本协调性,膝盖有压力', '基础有氧与热身'),
('跳绳(连续基础跳)', 3, '需要手脚配合,心肺要求明显', '基础有氧与热身'),
('坐姿腿屈伸/腿弯举', 2, '很容易找到发力感', '固定器械训练'),
('坐姿推胸机', 3, '需注意肩胛后收,避免耸肩', '固定器械训练'),
('高位下拉(坐姿)', 3, '需控制不要过度后仰', '固定器械训练'),
('史密斯机深蹲', 4, '轨迹固定,但需保持核心稳定', '固定器械训练'),
('蝴蝶机夹胸', 3, '易用肘关节代偿,需锁定肩关节', '固定器械训练'),
('平板支撑', 3, '耐力考验,技巧低', '自重基础动作'),
('跪姿俯卧撑', 3, '上肢力量较弱者首选', '自重基础动作'),
('标准俯卧撑', 5, '需核心收紧,身体成直线', '自重基础动作'),
('引体向上(弹力带辅助)', 6, '背部和手臂力量要求高', '自重基础动作'),
('标准引体向上', 8, '力量-体重比极高,多数男性无法完成1次', '自重基础动作'),
('徒手深蹲', 3, '注意膝盖方向与背部直立', '自重基础动作'),
('单腿深蹲(手枪蹲)', 8, '需要极高下肢力量、柔韧性和平衡', '自重基础动作'),
('哑铃二头弯举', 4, '容易晃动借力,但较安全', '自由重量杠铃/哑铃'),
('哑铃侧平举', 5, '极易用斜方肌代偿,真正练到三角肌中束很难', '自由重量杠铃/哑铃'),
('杠铃卧推', 7, '肩关节压力大,起桥、沉肩、稳定手腕均有技巧,有压伤风险', '自由重量杠铃/哑铃'),
('杠铃深蹲(颈后)', 8, '全身协调性、核心抗压、杠位放置、呼吸模式,学习曲线陡峭', '自由重量杠铃/哑铃'),
('传统硬拉', 9, '风险极高,需要精确的脊柱中立、髋铰链、背阔肌收紧,错误时伤腰', '自由重量杠铃/哑铃'),
('高翻/抓举(奥运举重)', 10, '需要爆发力、柔韧、精准衔接,非数月训练不能掌握', '自由重量杠铃/哑铃'),
('波比跳(标准版)', 6, '连续做时心肺压力极大', '高强度与爆发力'),
('冲刺跑(短跑)', 7, '对腘绳肌和脚踝爆发力要求高', '高强度与爆发力'),
('跳箱(合理高度)', 6, '需要落地缓冲技巧', '高强度与爆发力'),
('负重雪橇推', 6, '主要考验腿部耐力和意志力', '高强度与爆发力'),
('双力臂(引体向上后翻腕上杠)', 9, '需要爆发引体 + 极高相对力量', '高强度与爆发力'),
('静态拉伸(坐姿体前屈)', 2, '无风险,但需要坚持', '柔韧与平衡类'),
('瑜伽下犬式', 3, '常见,但需背部与手臂对齐', '柔韧与平衡类'),
('单腿罗马尼亚硬拉(徒手)', 6, '极考验平衡和髋稳定', '柔韧与平衡类'),
('全深蹲(脚跟贴地,亚洲蹲)', 5, '踝关节灵活度限制多数人', '柔韧与平衡类'),
('竖叉/横叉', 8, '需要数月甚至数年拉伸', '柔韧与平衡类'),
('瑜伽入门', 2, '适合初学者的瑜伽课程,注重基础体式', '柔韧与平衡类'),
('瑜伽进阶', 5, '针对有一定基础的学员,包含更复杂体式', '柔韧与平衡类'),
('普拉提', 4, '注重核心力量和身体控制', '柔韧与平衡类'),
('动感单车', 4, '高强度有氧运动,节奏感强', '基础有氧与热身'),
('搏击操', 5, '结合拳击动作的有氧运动', '高强度与爆发力'),
('HIIT训练', 7, '高强度间歇训练,对心肺要求极高', '高强度与爆发力'),
('核心训练', 4, '针对核心肌群的专项训练', '自重基础动作')
ON CONFLICT DO NOTHING;
@@ -1,8 +1,9 @@
-- ============================================
-- 团课推荐表
-- 版本: V10
-- 描述: 创建团课推荐表,用于首页推荐团课展示
-- ============================================
-- 团课推荐表
CREATE TABLE IF NOT EXISTS group_course_recommend (
id BIGSERIAL PRIMARY KEY,
course_id BIGINT NOT NULL,
@@ -18,7 +19,6 @@ CREATE TABLE IF NOT EXISTS group_course_recommend (
deleted_at TIMESTAMP
);
-- 创建索引
CREATE INDEX IF NOT EXISTS idx_group_course_recommend_course_id ON group_course_recommend(course_id);
CREATE INDEX IF NOT EXISTS idx_group_course_recommend_priority ON group_course_recommend(priority);
CREATE INDEX IF NOT EXISTS idx_group_course_recommend_is_active ON group_course_recommend(is_active);
@@ -35,4 +35,4 @@ COMMENT ON COLUMN group_course_recommend.create_by IS '创建人';
COMMENT ON COLUMN group_course_recommend.update_by IS '更新人';
COMMENT ON COLUMN group_course_recommend.created_at IS '创建时间';
COMMENT ON COLUMN group_course_recommend.updated_at IS '更新时间';
COMMENT ON COLUMN group_course_recommend.deleted_at IS '删除时间(软删除)';
COMMENT ON COLUMN group_course_recommend.deleted_at IS '删除时间(软删除)';
@@ -1,9 +1,9 @@
-- ============================================
-- 为团课表添加二维码路径字段
-- 版本: V11
-- 描述: 添加团课二维码路径,用于扫码签到
-- ============================================
-- 添加二维码路径字段
ALTER TABLE group_course ADD COLUMN qr_code_path VARCHAR(500);
ALTER TABLE group_course ADD COLUMN IF NOT EXISTS qr_code_path VARCHAR(500);
-- 添加字段注释
COMMENT ON COLUMN group_course.qr_code_path IS '二维码图片路径';
COMMENT ON COLUMN group_course.qr_code_path IS '二维码图片路径';
@@ -1,6 +1,7 @@
-- ============================================
-- V20: 为 member_user 表添加 deleted_at 字段
-- 原因:BaseEntity 已映射该字段,但 member_user 表缺失
-- 为 member_user 表添加 deleted_at 字段
-- 版本: V12
-- 描述: 补充软删除时间字段,与BaseEntity映射对齐
-- ============================================
ALTER TABLE member_user
@@ -1,6 +1,7 @@
-- ============================================
-- V21: 为 member_card_transactions 表添加 updated_at 字段
-- 原因:MemberCardTransaction 继承 BaseEntity 已映射该字段,但表缺失
-- 为 member_card_transactions 表添加 updated_at 字段
-- 版本: V13
-- 描述: 补充更新时间字段,与BaseEntity映射对齐
-- ============================================
ALTER TABLE member_card_transactions
@@ -1,342 +0,0 @@
-- ============================================================
-- V13: 整合所有测试数据(基于 2026-07-14
-- 说明: 系统初始数据由 V2 处理,本文件仅包含业务测试数据
-- 所有时间相关字段已更新为基于 2026-07-14
-- ============================================================
-- ============================================================
-- Section B: 团课类型数据(来源 V15)
-- ============================================================
INSERT INTO group_course_type (type_name, base_difficulty, description, category) VALUES
('慢走/椭圆机轻松模式', 1, '几乎无难度,适合所有人', '基础有氧与热身'),
('固定自行车(低阻力)', 2, '注意座椅高度调节即可', '基础有氧与热身'),
('跑步机慢跑', 3, '需要基本协调性,膝盖有压力', '基础有氧与热身'),
('跳绳(连续基础跳)', 3, '需要手脚配合,心肺要求明显', '基础有氧与热身'),
('坐姿腿屈伸/腿弯举', 2, '很容易找到发力感', '固定器械训练'),
('坐姿推胸机', 3, '需注意肩胛后收,避免耸肩', '固定器械训练'),
('高位下拉(坐姿)', 3, '需控制不要过度后仰', '固定器械训练'),
('史密斯机深蹲', 4, '轨迹固定,但需保持核心稳定', '固定器械训练'),
('蝴蝶机夹胸', 3, '易用肘关节代偿,需锁定肩关节', '固定器械训练'),
('平板支撑', 3, '耐力考验,技巧低', '自重基础动作'),
('跪姿俯卧撑', 3, '上肢力量较弱者首选', '自重基础动作'),
('标准俯卧撑', 5, '需核心收紧,身体成直线', '自重基础动作'),
('引体向上(弹力带辅助)', 6, '背部和手臂力量要求高', '自重基础动作'),
('标准引体向上', 8, '力量-体重比极高,多数男性无法完成1次', '自重基础动作'),
('徒手深蹲', 3, '注意膝盖方向与背部直立', '自重基础动作'),
('单腿深蹲(手枪蹲)', 8, '需要极高下肢力量、柔韧性和平衡', '自重基础动作'),
('哑铃二头弯举', 4, '容易晃动借力,但较安全', '自由重量杠铃/哑铃'),
('哑铃侧平举', 5, '极易用斜方肌代偿,真正练到三角肌中束很难', '自由重量杠铃/哑铃'),
('杠铃卧推', 7, '肩关节压力大,起桥、沉肩、稳定手腕均有技巧,有压伤风险', '自由重量杠铃/哑铃'),
('杠铃深蹲(颈后)', 8, '全身协调性、核心抗压、杠位放置、呼吸模式,学习曲线陡峭', '自由重量杠铃/哑铃'),
('传统硬拉', 9, '风险极高,需要精确的脊柱中立、髋铰链、背阔肌收紧,错误时伤腰', '自由重量杠铃/哑铃'),
('高翻/抓举(奥运举重)', 10, '需要爆发力、柔韧、精准衔接,非数月训练不能掌握', '自由重量杠铃/哑铃'),
('波比跳(标准版)', 6, '连续做时心肺压力极大', '高强度与爆发力'),
('冲刺跑(短跑)', 7, '对腘绳肌和脚踝爆发力要求高', '高强度与爆发力'),
('跳箱(合理高度)', 6, '需要落地缓冲技巧', '高强度与爆发力'),
('负重雪橇推', 6, '主要考验腿部耐力和意志力', '高强度与爆发力'),
('双力臂(引体向上后翻腕上杠)', 9, '需要爆发引体 + 极高相对力量', '高强度与爆发力'),
('静态拉伸(坐姿体前屈)', 2, '无风险,但需要坚持', '柔韧与平衡类'),
('瑜伽下犬式', 3, '常见,但需背部与手臂对齐', '柔韧与平衡类'),
('单腿罗马尼亚硬拉(徒手)', 6, '极考验平衡和髋稳定', '柔韧与平衡类'),
('全深蹲(脚跟贴地,亚洲蹲)', 5, '踝关节灵活度限制多数人', '柔韧与平衡类'),
('竖叉/横叉', 8, '需要数月甚至数年拉伸', '柔韧与平衡类'),
('瑜伽入门', 2, '适合初学者的瑜伽课程,注重基础体式', '柔韧与平衡类'),
('瑜伽进阶', 5, '针对有一定基础的学员,包含更复杂体式', '柔韧与平衡类'),
('普拉提', 4, '注重核心力量和身体控制', '柔韧与平衡类'),
('动感单车', 4, '高强度有氧运动,节奏感强', '基础有氧与热身'),
('搏击操', 5, '结合拳击动作的有氧运动', '高强度与爆发力'),
('HIIT训练', 7, '高强度间歇训练,对心肺要求极高', '高强度与爆发力'),
('核心训练', 4, '针对核心肌群的专项训练', '自重基础动作');
-- ============================================================
-- Section C: 团课标签数据(来源 V16)
-- ============================================================
INSERT INTO course_label (label_name, color, description) VALUES
('适合新手', '#52c41a', '适合健身初学者'),
('中级过渡', '#faad14', '适合有一定基础的学员'),
('高级进阶', '#f5222d', '适合高级学员'),
('减脂塑形', '#722ed1', '有助于减脂塑形'),
('增肌强化', '#13c2c2', '有助于增肌强化'),
('柔韧性训练', '#eb2f96', '注重柔韧性提升'),
('核心训练', '#1890ff', '注重核心力量'),
('心肺训练', '#fa8c16', '提升心肺功能'),
('低冲击', '#52c41a', '低冲击运动,适合关节保护'),
('高强度', '#f5222d', '高强度间歇训练'),
('团体互动', '#722ed1', '注重团队协作'),
('私教推荐', '#13c2c2', '私教推荐课程'),
('热门课程', '#ff1493', '人气较高的课程'),
('新课上线', '#00ced1', '新上线的课程');
-- ============================================================
-- Section D: 会员卡类型(来源 V10 / V11,已去重合并)
-- ============================================================
INSERT INTO member_card (member_card_name, member_card_type, member_card_price, member_card_validity_days, member_card_total_times, member_card_amount, member_card_status, extra_config, created_at, updated_at) VALUES
('30天时长卡', 'TIME_CARD', 299.00, 30, NULL, NULL, 1, '{}', '2026-01-01 00:00:00', '2026-01-01 00:00:00'),
('10次卡', 'COUNT_CARD', 499.00, NULL, 10, NULL, 1, '{}', '2026-01-01 00:00:00', '2026-01-01 00:00:00'),
('储值卡500', 'STORED_VALUE_CARD', 500.00, NULL, NULL, 500.00, 1, '{}', '2026-01-01 00:00:00', '2026-01-01 00:00:00');
-- ============================================================
-- Section E: 测试会员(来源 V10 / V11 / V12 / V14
-- ============================================================
-- E1: 数据统计测试会员(V14,显式 ID 1001-1012
INSERT INTO member_user (id, member_no, nickname, phone, created_at, updated_at, is_deleted) VALUES
(1001, 'M20260714001', '张三', '13800138001', '2026-07-14 08:00:00', '2026-07-14 08:00:00', false),
(1002, 'M20260714002', '李四', '13800138002', '2026-07-14 09:00:00', '2026-07-14 09:00:00', false),
(1003, 'M20260713003', '王五', '13800138003', '2026-07-13 10:00:00', '2026-07-13 10:00:00', false),
(1004, 'M20260712004', '赵六', '13800138004', '2026-07-12 11:00:00', '2026-07-12 11:00:00', false),
(1005, 'M20260714005', '钱七', '13800138005', '2026-07-14 08:00:00', '2026-07-14 08:00:00', false),
(1006, 'M20260714006', '孙八', '13800138006', '2026-07-14 09:00:00', '2026-07-14 09:00:00', false),
(1007, 'M20260714007', '周九', '13800138007', '2026-07-14 10:00:00', '2026-07-14 10:00:00', false),
(1008, 'M20260711008', '吴十', '13800138008', '2026-07-11 14:00:00', '2026-07-11 14:00:00', false),
(1009, 'M20260710009', '郑十一', '13800138009', '2026-07-10 15:00:00', '2026-07-10 15:00:00', false),
(1010, 'M20260709010', '王十二', '13800138010', '2026-07-09 16:00:00', '2026-07-09 16:00:00', false),
(1011, 'M20260708011', '陈十三', '13800138011', '2026-07-08 17:00:00', '2026-07-08 17:00:00', false),
(1012, 'M20260707012', '刘十四', '13800138012', '2026-07-07 18:00:00', '2026-07-07 18:00:00', false);
-- E2: 预约场景测试会员(V10: A-G)
INSERT INTO member_user (member_no, nickname, phone, gender, is_deleted, created_at, updated_at) VALUES
('MEM_TEST_A', '用户A_无卡新用户', '13800001001', 1, false, '2026-07-14 10:00:00', '2026-07-14 10:00:00'),
('MEM_TEST_B', '用户B_过期时长卡', '13800001002', 1, false, '2026-07-13 10:00:00', '2026-07-13 10:00:00'),
('MEM_TEST_C', '会员C_有效时长卡', '13800001003', 2, false, '2026-07-13 10:00:00', '2026-07-13 10:00:00'),
('MEM_TEST_D', '会员D_次数用尽', '13800001004', 1, false, '2026-07-13 10:00:00', '2026-07-13 10:00:00'),
('MEM_TEST_E', '会员E_次数充足', '13800001005', 2, false, '2026-07-13 10:00:00', '2026-07-13 10:00:00'),
('MEM_TEST_F', '会员F_储值卡余额不足', '13800001006', 1, false, '2026-07-13 10:00:00', '2026-07-13 10:00:00'),
('MEM_TEST_G', '会员G_储值卡余额充足', '13800001007', 2, false, '2026-07-13 10:00:00', '2026-07-13 10:00:00');
-- E3: 取消预约测试会员(V11: 张三/李四/王五)
INSERT INTO member_user (member_no, nickname, phone, gender, is_deleted, created_at, updated_at) VALUES
('MEM_TEST_ZHANG', '张三_时长卡用户', '13800002001', 1, false, '2026-07-13 10:00:00', '2026-07-13 10:00:00'),
('MEM_TEST_LI', '李四_次数卡用户', '13800002002', 1, false, '2026-07-13 10:00:00', '2026-07-13 10:00:00'),
('MEM_TEST_WANG', '王五_储值卡用户', '13800002003', 2, false, '2026-07-13 10:00:00', '2026-07-13 10:00:00');
-- E4: 时间冲突测试会员(V12)
INSERT INTO member_user (member_no, nickname, phone, gender, is_deleted, created_at, updated_at) VALUES
('MEM_TIME_CONFLICT', '时间冲突测试会员', '13800009999', 1, false, '2026-07-13 10:00:00', '2026-07-13 10:00:00');
-- ============================================================
-- Section F: 会员卡记录
-- ============================================================
-- F1: V10 预约场景 - 6条会员卡记录
INSERT INTO member_card_record (member_id, member_card_id, status, remaining_times, remaining_amount, expire_time, purchase_time, version, card_composition, created_at, updated_at) VALUES
((SELECT id FROM member_user WHERE member_no = 'MEM_TEST_B'), (SELECT member_card_id FROM member_card WHERE member_card_name = '30天时长卡'), 'EXPIRED', 0, 0.00, '2026-07-13 23:59:59', '2026-06-13 10:00:00', 0, '{}', '2026-06-13 10:00:00', '2026-07-14 10:00:00');
INSERT INTO member_card_record (member_id, member_card_id, status, remaining_times, remaining_amount, expire_time, purchase_time, version, card_composition, created_at, updated_at) VALUES
((SELECT id FROM member_user WHERE member_no = 'MEM_TEST_C'), (SELECT member_card_id FROM member_card WHERE member_card_name = '30天时长卡'), 'ACTIVE', 0, 0.00, '2026-08-13 23:59:59', '2026-07-14 10:00:00', 0, '{}', '2026-07-14 10:00:00', '2026-07-14 10:00:00');
INSERT INTO member_card_record (member_id, member_card_id, status, remaining_times, remaining_amount, expire_time, purchase_time, version, card_composition, created_at, updated_at) VALUES
((SELECT id FROM member_user WHERE member_no = 'MEM_TEST_D'), (SELECT member_card_id FROM member_card WHERE member_card_name = '10次卡'), 'ACTIVE', 0, 0.00, '2026-12-31 23:59:59', '2026-06-13 10:00:00', 0, '{}', '2026-06-13 10:00:00', '2026-07-14 10:00:00');
INSERT INTO member_card_record (member_id, member_card_id, status, remaining_times, remaining_amount, expire_time, purchase_time, version, card_composition, created_at, updated_at) VALUES
((SELECT id FROM member_user WHERE member_no = 'MEM_TEST_E'), (SELECT member_card_id FROM member_card WHERE member_card_name = '10次卡'), 'ACTIVE', 5, 0.00, '2026-12-31 23:59:59', '2026-06-13 10:00:00', 0, '{}', '2026-06-13 10:00:00', '2026-07-14 10:00:00');
INSERT INTO member_card_record (member_id, member_card_id, status, remaining_times, remaining_amount, expire_time, purchase_time, version, card_composition, created_at, updated_at) VALUES
((SELECT id FROM member_user WHERE member_no = 'MEM_TEST_F'), (SELECT member_card_id FROM member_card WHERE member_card_name = '储值卡500'), 'ACTIVE', 0, 30.00, '2027-07-14 23:59:59', '2026-06-13 10:00:00', 0, '{}', '2026-06-13 10:00:00', '2026-07-14 10:00:00');
INSERT INTO member_card_record (member_id, member_card_id, status, remaining_times, remaining_amount, expire_time, purchase_time, version, card_composition, created_at, updated_at) VALUES
((SELECT id FROM member_user WHERE member_no = 'MEM_TEST_G'), (SELECT member_card_id FROM member_card WHERE member_card_name = '储值卡500'), 'ACTIVE', 0, 200.00, '2027-07-14 23:59:59', '2026-06-13 10:00:00', 0, '{}', '2026-06-13 10:00:00', '2026-07-14 10:00:00');
-- F2: V11 取消预约场景 - 3条
INSERT INTO member_card_record (member_id, member_card_id, status, remaining_times, remaining_amount, expire_time, purchase_time, version, card_composition, created_at, updated_at) VALUES
((SELECT id FROM member_user WHERE member_no = 'MEM_TEST_ZHANG'), (SELECT member_card_id FROM member_card WHERE member_card_name = '30天时长卡'), 'ACTIVE', 0, 0.00, '2026-08-13 23:59:59', '2026-07-14 10:00:00', 0, '{}', '2026-07-14 10:00:00', '2026-07-14 10:00:00'),
((SELECT id FROM member_user WHERE member_no = 'MEM_TEST_LI'), (SELECT member_card_id FROM member_card WHERE member_card_name = '10次卡'), 'ACTIVE', 5, 0.00, '2026-12-31 23:59:59', '2026-06-13 10:00:00', 0, '{}', '2026-06-13 10:00:00', '2026-07-14 10:00:00'),
((SELECT id FROM member_user WHERE member_no = 'MEM_TEST_WANG'), (SELECT member_card_id FROM member_card WHERE member_card_name = '储值卡500'), 'ACTIVE', 0, 200.00, '2027-07-14 23:59:59', '2026-06-13 10:00:00', 0, '{}', '2026-06-13 10:00:00', '2026-07-14 10:00:00');
-- F3: V12 时间冲突场景 - 1条
INSERT INTO member_card_record (member_id, member_card_id, status, remaining_times, remaining_amount, expire_time, purchase_time, version, card_composition, created_at, updated_at) VALUES
((SELECT id FROM member_user WHERE member_no = 'MEM_TIME_CONFLICT'), (SELECT member_card_id FROM member_card WHERE member_card_name = '10次卡'), 'ACTIVE', 10, 0.00, '2026-12-31 23:59:59', '2026-07-14 10:00:00', 0, '{}', '2026-07-14 10:00:00', '2026-07-14 10:00:00');
-- ============================================================
-- Section G: 团课课程(来源 V7 / V10 / V11 / V12 / V14,基于 2026-07-14
-- ============================================================
-- G1: V7 - 7种场景团课
INSERT INTO group_course (course_name, coach_id, course_type, start_time, end_time, max_members, current_members, status, location, cover_image, description, stored_value_amount, create_by, created_at, updated_at) VALUES
('极速燃脂单车', 104, 2, '2026-07-15 16:45:00', '2026-07-15 20:20:00', 25, 0, 0, '单车房', '/images/spinning.jpg', '跟随音乐节奏变换阻力和速度,体验爬坡与冲刺的快感。', 50.00, 'admin', '2026-07-14 10:00:00', '2026-07-14 10:00:00'),
('清晨流瑜伽', 101, 1, '2026-07-18 09:00:00', '2026-07-18 10:30:00', 15, 5, 0, 'A座3楼瑜伽教室', '/images/yoga_flow.jpg', '适合有一定基础的学员,通过流畅的体式连接呼吸。', 50.00, 'admin', '2026-07-14 10:00:00', '2026-07-14 10:00:00'),
('燃脂搏击', 102, 2, '2026-07-16 18:30:00', '2026-07-16 19:30:00', 20, 20, 0, '综合训练区', '/images/kickboxing.jpg', '高强度间歇训练,名额已满。', 50.00, 'coach_zhang', '2026-07-14 14:30:00', '2026-07-14 14:30:00'),
('哈他瑜伽', 101, 1, '2026-07-14 17:45:00', '2026-07-14 18:50:00', 12, 3, 0, '瑜伽教室B', '/images/hatha_yoga.jpg', '基础哈他瑜伽,距开始不足30分钟,已停止预约。', 50.00, 'coach_li', '2026-07-14 08:00:00', '2026-07-14 08:00:00'),
('周末冥想修复', 101, 1, '2026-07-26 15:00:00', '2026-07-26 16:00:00', 12, 3, 1, '冥想室', '/images/meditation.jpg', '通过呼吸和正念冥想,该课程已被取消。', 50.00, 'coach_wang', '2026-07-14 08:00:00', '2026-07-14 08:00:00'),
('蜜桃臀塑造', 103, 3, '2026-07-08 19:00:00', '2026-07-08 20:00:00', 10, 8, 2, '私教专区', '/images/glute.jpg', '针对性训练臀部肌肉群,课程已结束。', 50.00, 'coach_li', '2026-07-08 09:15:00', '2026-07-08 09:15:00'),
('午间冥想放松', 101, 1, '2026-07-10 12:00:00', '2026-07-10 13:00:00', 15, 6, 2, '冥想室', '/images/meditation_noon.jpg', '午间冥想课程,已结束。', 50.00, 'admin', '2026-07-10 09:00:00', '2026-07-10 09:00:00');
-- G2: V10 预约场景(已取消次数卡支付,仅保留储值卡)
INSERT INTO group_course (course_name, coach_id, course_type, start_time, end_time, max_members, current_members, status, location, description, stored_value_amount, create_by, created_at, updated_at) VALUES
('燃脂搏击_储值测试', 102, 2, '2026-07-16 19:30:00', '2026-07-16 20:30:00', 20, 0, 0, '综合训练区', '消耗储值50元', 50.00, 'admin', '2026-07-14 10:00:00', '2026-07-14 10:00:00'),
('高端普拉提_储值卡课程', 103, 1, '2026-07-17 19:00:00', '2026-07-17 20:00:00', 15, 0, 0, '普拉提教室', '消耗储值20元', 20.00, 'admin', '2026-07-14 10:00:00', '2026-07-14 10:00:00');
-- G3: V11 取消预约场景
INSERT INTO group_course (course_name, coach_id, course_type, start_time, end_time, max_members, current_members, status, location, description, stored_value_amount, create_by, created_at, updated_at) VALUES
('晚间瑜伽_取消测试', 101, 1, '2026-07-17 19:00:00', '2026-07-17 20:00:00', 20, 0, 0, '瑜伽教室', '用于测试取消预约功能', 30.00, 'admin', '2026-07-14 10:00:00', '2026-07-14 10:00:00');
-- G4: V12 时间冲突场景
INSERT INTO group_course (course_name, coach_id, course_type, start_time, end_time, max_members, current_members, status, location, description, stored_value_amount, create_by, created_at, updated_at) VALUES
('时间冲突测试_A_13点-15点', 102, 2, '2026-07-16 13:00:00', '2026-07-16 15:00:00', 20, 0, 0, '综合训练区', '测试用团课A', 50.00, 'admin', '2026-07-14 10:00:00', '2026-07-14 10:00:00'),
('时间冲突测试_B_14点-16点', 103, 1, '2026-07-16 14:00:00', '2026-07-16 16:00:00', 15, 0, 0, '普拉提教室', '与团课A时间重叠', 50.00, 'admin', '2026-07-14 10:00:00', '2026-07-14 10:00:00'),
('时间冲突测试_C_10点-12点', 101, 1, '2026-07-16 10:00:00', '2026-07-16 12:00:00', 15, 0, 0, '瑜伽教室', '与A/B不冲突', 50.00, 'admin', '2026-07-14 10:00:00', '2026-07-14 10:00:00');
-- G5: V14 数据统计场景(今天 2026-07-14
INSERT INTO group_course (id, course_name, coach_id, course_type, start_time, end_time, max_members, current_members, status, location, cover_image, description, stored_value_amount, created_at, updated_at) VALUES
(3001, '瑜伽入门', 1, 1, '2026-07-14 08:00:00', '2026-07-14 09:00:00', 20, 15, 0, '健身房A区', 'https://example.com/yoga.jpg', '适合初学者的瑜伽课程', 50.00, '2026-07-14 10:00:00', '2026-07-14 10:00:00'),
(3002, '动感单车', 2, 2, '2026-07-14 09:30:00', '2026-07-14 10:30:00', 25, 20, 0, '健身房B区', 'https://example.com/spinning.jpg', '高强度有氧运动', 50.00, '2026-07-14 11:00:00', '2026-07-14 11:00:00'),
(3003, '普拉提', 3, 1, '2026-07-14 14:00:00', '2026-07-14 15:00:00', 15, 10, 0, '健身房C区', 'https://example.com/pilates.jpg', '核心力量训练', 50.00, '2026-07-14 12:00:00', '2026-07-14 12:00:00');
-- ============================================================
-- Section H: 团课预约记录
-- ============================================================
-- H1: V11 取消预约测试
INSERT INTO group_course_booking (course_id, member_id, member_card_id, booking_time, status, course_name, course_start_time, course_end_time, location, created_at, updated_at) VALUES
((SELECT id FROM group_course WHERE course_name = '晚间瑜伽_取消测试'), (SELECT id FROM member_user WHERE member_no = 'MEM_TEST_ZHANG'), (SELECT id FROM member_card_record WHERE member_id = (SELECT id FROM member_user WHERE member_no = 'MEM_TEST_ZHANG')), '2026-07-14 11:00:00', '0', '晚间瑜伽_取消测试', '2026-07-17 19:00:00', '2026-07-17 20:00:00', '瑜伽教室', '2026-07-14 11:00:00', '2026-07-14 11:00:00'),
((SELECT id FROM group_course WHERE course_name = '晚间瑜伽_取消测试'), (SELECT id FROM member_user WHERE member_no = 'MEM_TEST_LI'), (SELECT id FROM member_card_record WHERE member_id = (SELECT id FROM member_user WHERE member_no = 'MEM_TEST_LI')), '2026-07-14 11:30:00', '0', '晚间瑜伽_取消测试', '2026-07-17 19:00:00', '2026-07-17 20:00:00', '瑜伽教室', '2026-07-14 11:30:00', '2026-07-14 11:30:00'),
((SELECT id FROM group_course WHERE course_name = '晚间瑜伽_取消测试'), (SELECT id FROM member_user WHERE member_no = 'MEM_TEST_WANG'), (SELECT id FROM member_card_record WHERE member_id = (SELECT id FROM member_user WHERE member_no = 'MEM_TEST_WANG')), '2026-07-14 12:00:00', '0', '晚间瑜伽_取消测试', '2026-07-17 19:00:00', '2026-07-17 20:00:00', '瑜伽教室', '2026-07-14 12:00:00', '2026-07-14 12:00:00');
UPDATE group_course SET current_members = current_members + 3 WHERE course_name = '晚间瑜伽_取消测试';
-- H2: V14 数据统计预约 - 今天(7月14日)
INSERT INTO group_course_booking (id, member_id, member_card_id, course_id, booking_time, status, created_at, updated_at) VALUES
(4001, 1001, 1, 3001, '2026-07-14 08:00:00', '2', '2026-07-08 20:00:00', '2026-07-14 08:30:00'),
(4002, 1002, 2, 3001, '2026-07-14 08:00:00', '2', '2026-07-08 21:00:00', '2026-07-14 08:30:00'),
(4003, 1003, 3, 3001, '2026-07-14 08:00:00', '3', '2026-07-08 22:00:00', '2026-07-14 09:00:00'),
(4004, 1004, 4, 3002, '2026-07-14 09:30:00', '2', '2026-07-08 19:00:00', '2026-07-14 09:30:00'),
(4005, 1005, 5, 3002, '2026-07-14 09:30:00', '1', '2026-07-08 20:30:00', '2026-07-14 09:00:00'),
(4006, 1006, 6, 3002, '2026-07-14 09:30:00', '2', '2026-07-08 21:30:00', '2026-07-14 09:30:00'),
(4007, 1007, 7, 3003, '2026-07-14 14:00:00', '2', '2026-07-08 22:30:00', '2026-07-14 14:00:00'),
(4008, 1008, 8, 3003, '2026-07-14 14:00:00', '3', '2026-07-14 08:00:00', '2026-07-14 14:00:00'),
(4009, 1009, 9, 3003, '2026-07-14 14:00:00', '2', '2026-07-14 09:00:00', '2026-07-14 14:00:00'),
(4010, 1010, 10, 3001, '2026-07-14 08:00:00', '2', '2026-07-14 07:00:00', '2026-07-14 08:00:00'),
(4011, 1011, 11, 3002, '2026-07-14 09:30:00', '1', '2026-07-14 08:30:00', '2026-07-14 09:00:00'),
(4012, 1012, 12, 3003, '2026-07-14 14:00:00', '2', '2026-07-14 10:00:00', '2026-07-14 14:00:00');
-- H3: V14 数据统计预约 - 昨天(7月13日)
INSERT INTO group_course_booking (id, member_id, member_card_id, course_id, booking_time, status, created_at, updated_at) VALUES
(4013, 1001, 1, 3001, '2026-07-08 08:00:00', '2', '2026-07-07 20:00:00', '2026-07-08 08:30:00'),
(4014, 1002, 2, 3001, '2026-07-08 08:00:00', '2', '2026-07-07 21:00:00', '2026-07-08 08:30:00'),
(4015, 1003, 3, 3002, '2026-07-08 09:30:00', '3', '2026-07-07 22:00:00', '2026-07-08 09:30:00'),
(4016, 1004, 4, 3002, '2026-07-08 09:30:00', '2', '2026-07-07 19:00:00', '2026-07-08 09:30:00'),
(4017, 1005, 5, 3003, '2026-07-08 14:00:00', '1', '2026-07-07 20:30:00', '2026-07-08 13:00:00'),
(4018, 1006, 6, 3003, '2026-07-08 14:00:00', '2', '2026-07-07 21:30:00', '2026-07-08 14:00:00');
-- H4: V14 数据统计预约 - 前天(7月12日)
INSERT INTO group_course_booking (id, member_id, member_card_id, course_id, booking_time, status, created_at, updated_at) VALUES
(4019, 1001, 1, 3002, '2026-07-07 09:30:00', '2', '2026-07-06 20:00:00', '2026-07-07 09:30:00'),
(4020, 1002, 2, 3002, '2026-07-07 09:30:00', '2', '2026-07-06 21:00:00', '2026-07-07 09:30:00'),
(4021, 1003, 3, 3003, '2026-07-07 14:00:00', '2', '2026-07-06 22:00:00', '2026-07-07 14:00:00'),
(4022, 1004, 4, 3003, '2026-07-07 14:00:00', '3', '2026-07-06 19:00:00', '2026-07-07 14:00:00');
-- ============================================================
-- Section I: 签到记录(来源 V14,基于 2026-07-14
-- ============================================================
INSERT INTO sign_in_record (id, member_id, sign_in_time, sign_in_type, sign_in_status, source, is_delete) VALUES
(2001, 1001, '2026-07-14 08:00:00', 'QR_CODE', 'SUCCESS', 'MINI_PROGRAM', false),
(2002, 1002, '2026-07-14 08:15:00', 'MANUAL', 'SUCCESS', 'PC_BACKEND', false),
(2003, 1003, '2026-07-14 08:30:00', 'FACE', 'SUCCESS', 'MINI_PROGRAM', false),
(2004, 1004, '2026-07-14 09:00:00', 'QR_CODE', 'SUCCESS', 'MINI_PROGRAM', false),
(2005, 1005, '2026-07-14 09:15:00', 'MANUAL', 'SUCCESS', 'PC_BACKEND', false),
(2006, 1006, '2026-07-14 09:30:00', 'QR_CODE', 'SUCCESS', 'MINI_PROGRAM', false),
(2007, 1007, '2026-07-14 10:00:00', 'FACE', 'SUCCESS', 'MINI_PROGRAM', false),
(2008, 1008, '2026-07-14 10:15:00', 'QR_CODE', 'SUCCESS', 'MINI_PROGRAM', false),
(2009, 1009, '2026-07-14 10:30:00', 'MANUAL', 'SUCCESS', 'PC_BACKEND', false),
(2010, 1010, '2026-07-14 11:00:00', 'QR_CODE', 'SUCCESS', 'MINI_PROGRAM', false),
(2011, 1011, '2026-07-14 11:15:00', 'FACE', 'FAIL', 'MINI_PROGRAM', false),
(2012, 1012, '2026-07-14 11:30:00', 'MANUAL', 'SUCCESS', 'PC_BACKEND', false);
INSERT INTO sign_in_record (id, member_id, sign_in_time, sign_in_type, sign_in_status, source, is_delete) VALUES
(2013, 1001, '2026-07-08 07:30:00', 'QR_CODE', 'SUCCESS', 'MINI_PROGRAM', false),
(2014, 1002, '2026-07-08 08:00:00', 'MANUAL', 'SUCCESS', 'PC_BACKEND', false),
(2015, 1003, '2026-07-08 08:30:00', 'FACE', 'SUCCESS', 'MINI_PROGRAM', false),
(2016, 1004, '2026-07-08 09:00:00', 'QR_CODE', 'SUCCESS', 'MINI_PROGRAM', false),
(2017, 1005, '2026-07-08 09:30:00', 'MANUAL', 'SUCCESS', 'PC_BACKEND', false),
(2018, 1006, '2026-07-08 10:00:00', 'QR_CODE', 'SUCCESS', 'MINI_PROGRAM', false),
(2019, 1007, '2026-07-08 10:30:00', 'FACE', 'SUCCESS', 'MINI_PROGRAM', false),
(2020, 1008, '2026-07-08 11:00:00', 'QR_CODE', 'SUCCESS', 'MINI_PROGRAM', false);
INSERT INTO sign_in_record (id, member_id, sign_in_time, sign_in_type, sign_in_status, source, is_delete) VALUES
(2021, 1001, '2026-07-07 07:00:00', 'QR_CODE', 'SUCCESS', 'MINI_PROGRAM', false),
(2022, 1002, '2026-07-07 07:30:00', 'MANUAL', 'SUCCESS', 'PC_BACKEND', false),
(2023, 1003, '2026-07-07 08:00:00', 'FACE', 'FAIL', 'MINI_PROGRAM', false),
(2024, 1004, '2026-07-07 08:30:00', 'QR_CODE', 'SUCCESS', 'MINI_PROGRAM', false),
(2025, 1005, '2026-07-07 09:00:00', 'MANUAL', 'SUCCESS', 'PC_BACKEND', false);
-- ============================================================
-- Section J: 团课推荐测试数据(来源 V18,基于 2026-07-14
-- ============================================================
INSERT INTO group_course_recommend (course_id, recommend_title, recommend_content, recommend_reason, priority, is_active, create_by, created_at, updated_at) VALUES
((SELECT id FROM group_course WHERE course_name = '极速燃脂单车'), '本周热门推荐', '极速燃脂单车课程,跟随音乐节奏变换阻力和速度,体验爬坡与冲刺的快感,一节课消耗800大卡!', '教练专业,课程内容丰富,深受学员喜爱,燃脂效果显著', 20, true, 'admin', '2026-07-14 10:00:00', '2026-07-14 10:00:00');
INSERT INTO group_course_recommend (course_id, recommend_title, recommend_content, recommend_reason, priority, is_active, create_by, created_at, updated_at) VALUES
((SELECT id FROM group_course WHERE course_name = '清晨流瑜伽'), '新手友好推荐', '清晨流瑜伽课程,适合有一定基础的学员,通过流畅的体式连接呼吸,唤醒身体能量。', '适合新手入门,教练耐心指导,课程节奏适中', 15, true, 'admin', '2026-07-14 11:00:00', '2026-07-14 11:00:00');
INSERT INTO group_course_recommend (course_id, recommend_title, recommend_content, recommend_reason, priority, is_active, create_by, created_at, updated_at) VALUES
((SELECT id FROM group_course WHERE course_name = '燃脂搏击'), '高强度燃脂', '燃脂搏击课程,高强度间歇训练,配合音乐快速燃脂,释放压力。', '高强度训练,适合进阶学员,快速燃脂塑形', 10, false, 'admin', '2026-07-14 12:00:00', '2026-07-14 12:00:00');
INSERT INTO group_course_recommend (course_id, recommend_title, recommend_content, recommend_reason, priority, is_active, create_by, created_at, updated_at) VALUES
((SELECT id FROM group_course WHERE course_name = '哈他瑜伽'), '基础瑜伽推荐', '基础哈他瑜伽课程,适合所有级别学员,通过基础体式练习提升身体柔韧性和平衡能力。', '零基础友好,适合所有健身水平,放松身心', 12, true, 'coach_li', '2026-07-14 13:00:00', '2026-07-14 13:00:00');
INSERT INTO group_course_recommend (course_id, recommend_title, recommend_content, recommend_reason, priority, is_active, create_by, created_at, updated_at) VALUES
((SELECT id FROM group_course WHERE course_name = '蜜桃臀塑造'), '塑形热门课程', '蜜桃臀塑造课程,针对性训练臀部肌肉群,打造完美曲线。', '专业私教指导,动作标准,效果显著,深受女性学员喜爱', 18, true, 'coach_li', '2026-07-14 09:15:00', '2026-07-14 09:15:00');
INSERT INTO group_course_recommend (course_id, recommend_title, recommend_content, recommend_reason, priority, is_active, create_by, created_at, updated_at) VALUES
((SELECT id FROM group_course WHERE course_name = '午间冥想放松'), '午间放松推荐', '午间冥想放松课程,通过呼吸和正念冥想,深度放松身心,缓解工作压力。', '适合上班族,午间放松充电,提升下午工作效率', 8, true, 'admin', '2026-07-14 09:00:00', '2026-07-14 09:00:00');
INSERT INTO group_course_recommend (course_id, recommend_title, recommend_content, recommend_reason, priority, is_active, create_by, created_at, updated_at) VALUES
((SELECT id FROM group_course WHERE course_name = '极速燃脂单车'), '减脂首选课程', '想要快速减脂?极速燃脂单车是你的最佳选择!专业教练带领,科学训练计划。', '减脂效果最佳,课程强度适中,适合想要快速瘦身的学员', 16, true, 'coach_zhang', '2026-07-14 14:00:00', '2026-07-14 14:00:00');
INSERT INTO group_course_recommend (course_id, recommend_title, recommend_content, recommend_reason, priority, is_active, create_by, created_at, updated_at) VALUES
((SELECT id FROM group_course WHERE course_name = '清晨流瑜伽'), '晨练优选', '清晨流瑜伽,唤醒身体能量,开启活力一天!适合晨练爱好者。', '晨练最佳选择,提升身体活力,改善精神状态', 14, true, 'coach_wang', '2026-07-14 15:00:00', '2026-07-14 15:00:00');
INSERT INTO group_course_recommend (course_id, recommend_title, recommend_content, recommend_reason, priority, is_active, create_by, created_at, updated_at) VALUES
((SELECT id FROM group_course WHERE course_name = '哈他瑜伽'), '身心平衡推荐', '哈他瑜伽课程,通过体式练习和呼吸控制,达到身心平衡,提升整体健康水平。', '改善身体柔韧性,增强核心力量,提升身体协调性', 11, true, 'coach_li', '2026-07-14 16:00:00', '2026-07-14 16:00:00');
INSERT INTO group_course_recommend (course_id, recommend_title, recommend_content, recommend_reason, priority, is_active, create_by, created_at, updated_at) VALUES
((SELECT id FROM group_course WHERE course_name = '午间冥想放松'), '职场减压课程', '午间冥想放松,专为职场人士设计,快速缓解工作压力,提升工作状态。', '职场减压首选,课程时间短,效果显著', 9, false, 'admin', '2026-07-14 10:00:00', '2026-07-14 10:00:00');
-- ============================================================
-- Section K: 统计说明
-- ============================================================
-- 今日(2026-07-14)统计预期:
-- 新增会员: 3 (1005, 1006, 1007)
-- 签到会员: 12
-- 预约总数: 12 (4001-4012),取消: 2,出席: 8,缺席: 2
-- 签到总数: 12,成功: 11,失败: 1
-- ============================================================
-- Section L: 测试场景汇总
-- ============================================================
-- 1. V7 团课预约场景:
-- - 极速燃脂单车: 明天(6/25),0人,可预约
-- - 清晨流瑜伽: 6月28日,5/15人,可预约
-- - 燃脂搏击: 6月26日,满员,不可预约
-- - 哈他瑜伽: 6/24 17:45,距开始<30min,不可预约
-- - 周末冥想修复: 7月6日,已取消(status=1)
-- - 蜜桃臀塑造: 6月18日,已结束(status=2)
-- - 午间冥想放松: 6月20日,已结束(status=2)
--
-- 2. V10 会员卡预约资格校验:
-- - 用户A: 无会员卡 → "无可用会员卡"
-- - 用户B: 时长卡过期 → "会员卡已过期"
-- - 会员C: 时长卡有效 → 可正常预约
-- - 会员D: 次数为0 → "剩余次数不足"
-- - 会员E: 次数充足 → 不可用次数卡预约团课(仅支持储值卡)
-- - 会员F: 储值卡30元,课程需50元 → 余额不足
-- - 会员G: 储值卡200元,课程需50元 → 可正常预约
--
-- 3. V11 取消预约:
-- - 张三(时长卡)、李四(储值卡)、王五(储值卡) 预约了晚间瑜伽_取消测试
-- - 取消后应恢复对应卡状态,释放课程名额
--
-- 4. V12 时间冲突检测:
-- - 团课A: 6/26 13:00-15:00, 团课B: 6/26 14:00-16:00 → 时间重叠
-- - 团课C: 6/26 10:00-12:00 → 与A/B不冲突
--
-- 5. V14 数据统计:
-- - 3天签到/预约数据,覆盖今天/昨天/前天
--
-- 6. V18 团课推荐:
-- - 10条推荐记录,覆盖不同优先级和启用状态
@@ -0,0 +1,63 @@
-- ============================================
-- 支付订单表
-- 版本: V14
-- 描述: 创建支付订单表,用于记录支付交易信息
-- ============================================
CREATE TABLE IF NOT EXISTS payment_order (
id BIGSERIAL PRIMARY KEY,
order_no VARCHAR(64) NOT NULL UNIQUE,
member_id BIGINT,
order_type VARCHAR(32),
goods_desc VARCHAR(256),
trans_amt DECIMAL(12, 2),
trade_type VARCHAR(32),
pay_status VARCHAR(16) DEFAULT 'PENDING',
huifu_id VARCHAR(64),
req_seq_id VARCHAR(64),
req_date VARCHAR(16),
hf_seq_id VARCHAR(64),
pay_info TEXT,
qr_code TEXT,
pay_url TEXT,
remark VARCHAR(512),
notify_url VARCHAR(512),
pay_time TIMESTAMP,
expire_time TIMESTAMP,
error_code VARCHAR(64),
error_msg VARCHAR(512),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
deleted_at TIMESTAMP
);
CREATE INDEX IF NOT EXISTS idx_payment_order_order_no ON payment_order(order_no);
CREATE INDEX IF NOT EXISTS idx_payment_order_member_id ON payment_order(member_id);
CREATE INDEX IF NOT EXISTS idx_payment_order_req_seq_id ON payment_order(req_seq_id);
CREATE INDEX IF NOT EXISTS idx_payment_order_status ON payment_order(pay_status);
CREATE INDEX IF NOT EXISTS idx_payment_order_expire_time ON payment_order(expire_time);
COMMENT ON TABLE payment_order IS '支付订单表';
COMMENT ON COLUMN payment_order.order_no IS '订单号';
COMMENT ON COLUMN payment_order.member_id IS '会员ID';
COMMENT ON COLUMN payment_order.order_type IS '订单类型';
COMMENT ON COLUMN payment_order.goods_desc IS '商品描述';
COMMENT ON COLUMN payment_order.trans_amt IS '交易金额';
COMMENT ON COLUMN payment_order.trade_type IS '交易类型';
COMMENT ON COLUMN payment_order.pay_status IS '支付状态:PENDING-待支付,SUCCESS-成功,FAILED-失败';
COMMENT ON COLUMN payment_order.huifu_id IS '汇付商户ID';
COMMENT ON COLUMN payment_order.req_seq_id IS '请求流水号';
COMMENT ON COLUMN payment_order.req_date IS '请求日期';
COMMENT ON COLUMN payment_order.hf_seq_id IS '汇付流水号';
COMMENT ON COLUMN payment_order.pay_info IS '支付信息';
COMMENT ON COLUMN payment_order.qr_code IS '二维码';
COMMENT ON COLUMN payment_order.pay_url IS '支付链接';
COMMENT ON COLUMN payment_order.remark IS '备注';
COMMENT ON COLUMN payment_order.notify_url IS '通知地址';
COMMENT ON COLUMN payment_order.pay_time IS '支付时间';
COMMENT ON COLUMN payment_order.expire_time IS '过期时间';
COMMENT ON COLUMN payment_order.error_code IS '错误码';
COMMENT ON COLUMN payment_order.error_msg IS '错误信息';
COMMENT ON COLUMN payment_order.created_at IS '创建时间';
COMMENT ON COLUMN payment_order.updated_at IS '更新时间';
COMMENT ON COLUMN payment_order.deleted_at IS '删除时间';
@@ -0,0 +1,9 @@
-- ============================================
-- 支付订单表添加 party_order_id 字段
-- 版本: V15
-- 描述: 添加汇付支付返回的商户订单号
-- ============================================
ALTER TABLE payment_order ADD COLUMN IF NOT EXISTS party_order_id VARCHAR(64);
COMMENT ON COLUMN payment_order.party_order_id IS '汇付商户订单号';
@@ -1,6 +1,10 @@
-- 创建储值卡表(包含支付密码)
-- 每个会员只有一张储值卡,支付密码也在同一张表中
-- ============================================
-- 储值卡相关表
-- 版本: V16
-- 描述: 创建储值卡表和充值记录表,每个会员只有一张储值卡
-- ============================================
-- 储值卡表(包含支付密码)
CREATE TABLE IF NOT EXISTS member_stored_card (
id BIGSERIAL PRIMARY KEY,
member_id BIGINT NOT NULL,
@@ -14,10 +18,8 @@ CREATE TABLE IF NOT EXISTS member_stored_card (
deleted_at TIMESTAMP
);
-- 创建唯一索引,每个会员只能有一张储值卡
CREATE UNIQUE INDEX IF NOT EXISTS idx_member_stored_card_member_id ON member_stored_card(member_id) WHERE deleted_at IS NULL;
-- 添加注释
COMMENT ON TABLE member_stored_card IS '储值卡表,每个会员只有一张储值卡,包含支付密码';
COMMENT ON COLUMN member_stored_card.member_id IS '会员用户ID';
COMMENT ON COLUMN member_stored_card.balance IS '储值卡余额';
@@ -26,7 +28,7 @@ COMMENT ON COLUMN member_stored_card.total_consume IS '累计消费金额';
COMMENT ON COLUMN member_stored_card.pay_password IS '支付密码(BCrypt加密)';
COMMENT ON COLUMN member_stored_card.is_pay_password_set IS '是否已设置支付密码';
-- 创建储值卡充值记录表
-- 储值卡充值记录表
CREATE TABLE IF NOT EXISTS member_stored_card_recharge (
id BIGSERIAL PRIMARY KEY,
member_id BIGINT NOT NULL,
@@ -42,11 +44,9 @@ CREATE TABLE IF NOT EXISTS member_stored_card_recharge (
deleted_at TIMESTAMP
);
-- 创建索引
CREATE INDEX IF NOT EXISTS idx_stored_card_recharge_member_id ON member_stored_card_recharge(member_id) WHERE deleted_at IS NULL;
CREATE UNIQUE INDEX IF NOT EXISTS idx_stored_card_recharge_order_no ON member_stored_card_recharge(order_no) WHERE deleted_at IS NULL;
-- 添加注释
COMMENT ON TABLE member_stored_card_recharge IS '储值卡充值记录表';
COMMENT ON COLUMN member_stored_card_recharge.member_id IS '会员用户ID';
COMMENT ON COLUMN member_stored_card_recharge.order_no IS '订单号';
@@ -0,0 +1,8 @@
-- ============================================
-- 将 group_course_booking 表的 member_card_id 改为可空
-- 版本: V17
-- 描述: 预约团课不再需要会员卡,member_card_id 允许为空
-- ============================================
ALTER TABLE group_course_booking
ALTER COLUMN member_card_id DROP NOT NULL;
@@ -0,0 +1,209 @@
-- ============================================
-- 团课测试数据
-- 版本: V18
-- 描述: 插入团课标签、类型、关联关系及课程数据
-- 5个团课类型,14个标签,每类型3个标签,每类型5个团课
-- ============================================
-- ============================================
-- 1. 团课标签数据(14个)
-- ============================================
INSERT INTO course_label (label_name, color, description) VALUES
('适合新手', '#52c41a', '适合健身初学者,动作简单易学'),
('中级过渡', '#faad14', '适合有一定基础的学员,逐步提升难度'),
('高级进阶', '#f5222d', '适合高级学员,强度和技巧要求较高'),
('减脂塑形', '#722ed1', '高效燃烧卡路里,助力减脂和体型塑造'),
('增肌强化', '#13c2c2', '注重肌肉力量和围度增长'),
('柔韧性训练', '#eb2f96', '提升身体柔韧性和关节活动度'),
('核心训练', '#1890ff', '强化核心肌群,改善身体稳定性'),
('心肺训练', '#fa8c16', '提升心肺功能和耐力水平'),
('低冲击', '#52c41a', '低冲击运动,对关节友好'),
('高强度', '#f5222d', '高强度训练,短时间内最大化训练效果'),
('团体互动', '#722ed1', '注重团队协作和互动氛围'),
('私教推荐', '#13c2c2', '私教推荐的高效训练课程'),
('热门课程', '#ff1493', '人气较高,广受学员欢迎'),
('新课上线', '#00ced1', '新上线课程,欢迎尝鲜体验')
ON CONFLICT DO NOTHING;
-- ============================================
-- 2. 团课类型数据(5个)
-- ============================================
INSERT INTO group_course_type (type_name, base_difficulty, description, category) VALUES
('瑜伽', 3, '通过呼吸调控与体式练习,提升身体柔韧性、力量与心灵平静,适合各年龄段人群', '柔韧与平衡类'),
('动感单车', 5, '伴随动感音乐节奏进行室内骑行,高效燃烧卡路里,释放压力,体验极速快感', '基础有氧与热身'),
('HIIT训练', 8, '高强度间歇训练,通过短时爆发动作与间歇休息交替,短时间内达到最大燃脂效果', '高强度与爆发力'),
('普拉提', 4, '注重核心肌群控制、脊柱对齐和呼吸配合,有效改善体态,预防运动损伤', '柔韧与平衡类'),
('搏击操', 6, '融合拳击、踢腿、格斗动作的有氧运动,宣泄压力同时高效塑形,增强协调性', '高强度与爆发力')
ON CONFLICT DO NOTHING;
-- ============================================
-- 3. 类型-标签关联数据(每类型3个标签,共15条)
-- ============================================
INSERT INTO course_type_label (type_id, label_id)
SELECT gt.id, cl.id FROM group_course_type gt, course_label cl
WHERE gt.type_name = '瑜伽' AND cl.label_name = '柔韧性训练'
OR gt.type_name = '瑜伽' AND cl.label_name = '低冲击'
OR gt.type_name = '瑜伽' AND cl.label_name = '适合新手'
OR gt.type_name = '动感单车' AND cl.label_name = '心肺训练'
OR gt.type_name = '动感单车' AND cl.label_name = '热门课程'
OR gt.type_name = '动感单车' AND cl.label_name = '中级过渡'
OR gt.type_name = 'HIIT训练' AND cl.label_name = '高强度'
OR gt.type_name = 'HIIT训练' AND cl.label_name = '减脂塑形'
OR gt.type_name = 'HIIT训练' AND cl.label_name = '高级进阶'
OR gt.type_name = '普拉提' AND cl.label_name = '核心训练'
OR gt.type_name = '普拉提' AND cl.label_name = '柔韧性训练'
OR gt.type_name = '普拉提' AND cl.label_name = '适合新手'
OR gt.type_name = '搏击操' AND cl.label_name = '高强度'
OR gt.type_name = '搏击操' AND cl.label_name = '减脂塑形'
OR gt.type_name = '搏击操' AND cl.label_name = '心肺训练'
ON CONFLICT DO NOTHING;
-- ============================================
-- 4. 团课课程数据(5个类型 × 5个课程 = 25个)
-- start_time / end_time 分布在 2026-07-20 至 2026-08-02
-- ============================================
-- ---------- 瑜伽课程(5个)----------
INSERT INTO group_course (course_name, course_type, start_time, end_time, max_members, current_members, status, location, cover_image, description, stored_value_amount, create_by)
SELECT '哈他瑜伽入门', gt.id, '2026-07-20 08:00:00'::TIMESTAMP, '2026-07-20 09:00:00'::TIMESTAMP, 25, 12, '0', '瑜伽室A', '/static/course/yoga_hatha.jpg', '经典哈他瑜伽,从基础体式入手,配合呼吸引导,帮助初学者建立正确的瑜伽练习基础,感受身心的和谐统一。', 88.00, 'system'
FROM group_course_type gt WHERE gt.type_name = '瑜伽';
INSERT INTO group_course (course_name, course_type, start_time, end_time, max_members, current_members, status, location, cover_image, description, stored_value_amount, create_by)
SELECT '流瑜伽', gt.id, '2026-07-22 10:00:00'::TIMESTAMP, '2026-07-22 11:00:00'::TIMESTAMP, 20, 18, '0', '瑜伽室A', '/static/course/yoga_flow.jpg', '体式之间流畅串联,如行云流水般一气呵成。以拜日式为根基,结合站姿、平衡和扭转,提升力量与柔韧的整合能力。', 98.00, 'system'
FROM group_course_type gt WHERE gt.type_name = '瑜伽';
INSERT INTO group_course (course_name, course_type, start_time, end_time, max_members, current_members, status, location, cover_image, description, stored_value_amount, create_by)
SELECT '阴瑜伽', gt.id, '2026-07-24 18:00:00'::TIMESTAMP, '2026-07-24 19:15:00'::TIMESTAMP, 20, 8, '0', '瑜伽室B', '/static/course/yoga_yin.jpg', '阴瑜伽以长时间保持体式为特点,深度伸展筋膜和结缔组织,帮助你释放身体深层紧张,缓解一周的工作疲劳。适合所有级别。', 88.00, 'system'
FROM group_course_type gt WHERE gt.type_name = '瑜伽';
INSERT INTO group_course (course_name, course_type, start_time, end_time, max_members, current_members, status, location, cover_image, description, stored_value_amount, create_by)
SELECT '阿斯汤加瑜伽', gt.id, '2026-07-21 07:00:00'::TIMESTAMP, '2026-07-21 08:30:00'::TIMESTAMP, 15, 10, '0', '瑜伽室A', '/static/course/yoga_ashtanga.jpg', '阿斯汤加瑜伽以固定的体式序列和独特的呼吸法为核心,节奏紧凑,强度较高,能有效提升力量、柔韧和专注力。建议有一定瑜伽基础者参加。', 128.00, 'system'
FROM group_course_type gt WHERE gt.type_name = '瑜伽';
INSERT INTO group_course (course_name, course_type, start_time, end_time, max_members, current_members, status, location, cover_image, description, stored_value_amount, create_by)
SELECT '空中瑜伽', gt.id, '2026-07-23 19:00:00'::TIMESTAMP, '2026-07-23 20:00:00'::TIMESTAMP, 12, 12, '0', '瑜伽室B', '/static/course/yoga_aerial.jpg', '利用悬挂的瑜伽吊床完成各种体式,借助重力让脊柱自然延展,体验"飞翔"般的自由感。深受女性学员喜爱,名额有限请提前预约。', 128.00, 'system'
FROM group_course_type gt WHERE gt.type_name = '瑜伽';
-- ---------- 动感单车课程(5个)----------
INSERT INTO group_course (course_name, course_type, start_time, end_time, max_members, current_members, status, location, cover_image, description, stored_value_amount, create_by)
SELECT '初级燃脂骑行', gt.id, '2026-07-20 19:00:00'::TIMESTAMP, '2026-07-20 19:45:00'::TIMESTAMP, 30, 22, '0', '单车房', '/static/course/spin_beginner.jpg', '适合新手的入门级骑行课程,教练将带领你掌握正确的骑行姿势和阻力调节技巧。在动感音乐中轻松燃烧300-400卡路里。', 58.00, 'system'
FROM group_course_type gt WHERE gt.type_name = '动感单车';
INSERT INTO group_course (course_name, course_type, start_time, end_time, max_members, current_members, status, location, cover_image, description, stored_value_amount, create_by)
SELECT '节奏爬坡', gt.id, '2026-07-22 18:30:00'::TIMESTAMP, '2026-07-22 19:15:00'::TIMESTAMP, 30, 15, '0', '单车房', '/static/course/spin_climb.jpg', '模拟山路爬坡骑行,通过逐渐增加阻力来挑战你的耐力和意志力。每一段爬坡后都有短暂的平路冲刺,节奏感十足,大汗淋漓的畅快体验。', 68.00, 'system'
FROM group_course_type gt WHERE gt.type_name = '动感单车';
INSERT INTO group_course (course_name, course_type, start_time, end_time, max_members, current_members, status, location, cover_image, description, stored_value_amount, create_by)
SELECT '极速冲刺', gt.id, '2026-07-24 20:00:00'::TIMESTAMP, '2026-07-24 20:45:00'::TIMESTAMP, 25, 25, '0', '单车房', '/static/course/spin_sprint.jpg', '高强度冲刺为主题的骑行课,多组30秒极限冲刺搭配短暂恢复,彻底引爆你的心肺极限。周五夜间的爆款课程,约满速度极快!', 68.00, 'system'
FROM group_course_type gt WHERE gt.type_name = '动感单车';
INSERT INTO group_course (course_name, course_type, start_time, end_time, max_members, current_members, status, location, cover_image, description, stored_value_amount, create_by)
SELECT '耐力骑行', gt.id, '2026-07-25 10:00:00'::TIMESTAMP, '2026-07-25 11:00:00'::TIMESTAMP, 30, 18, '0', '单车房', '/static/course/spin_endurance.jpg', '60分钟中低强度耐力骑行,适合周末早晨唤醒身体。在稳定的节奏中持续燃脂,配以舒缓的收尾拉伸,开启元气满满的周末。', 58.00, 'system'
FROM group_course_type gt WHERE gt.type_name = '动感单车';
INSERT INTO group_course (course_name, course_type, start_time, end_time, max_members, current_members, status, location, cover_image, description, stored_value_amount, create_by)
SELECT '音乐主题骑行', gt.id, '2026-07-21 19:30:00'::TIMESTAMP, '2026-07-21 20:15:00'::TIMESTAMP, 30, 20, '0', '单车房', '/static/course/spin_music.jpg', '以热门流行音乐为主题的骑行派对!每首歌曲对应一套骑行组合,跟着节拍加速、爬坡、冲刺,在音乐中忘记疲惫。', 68.00, 'system'
FROM group_course_type gt WHERE gt.type_name = '动感单车';
-- ---------- HIIT训练课程(5个)----------
INSERT INTO group_course (course_name, course_type, start_time, end_time, max_members, current_members, status, location, cover_image, description, stored_value_amount, create_by)
SELECT 'Tabata燃脂', gt.id, '2026-07-20 07:00:00'::TIMESTAMP, '2026-07-20 07:30:00'::TIMESTAMP, 15, 8, '0', '多功能训练区', '/static/course/hiit_tabata.jpg', '经典的Tabata模式:20秒全力运动 + 10秒休息,循环8轮共4分钟,搭配热身和拉伸,30分钟全身燃爆。早晨空腹训练燃脂效果加倍!', 98.00, 'system'
FROM group_course_type gt WHERE gt.type_name = 'HIIT训练';
INSERT INTO group_course (course_name, course_type, start_time, end_time, max_members, current_members, status, location, cover_image, description, stored_value_amount, create_by)
SELECT '全身循环训练', gt.id, '2026-07-22 12:00:00'::TIMESTAMP, '2026-07-22 12:45:00'::TIMESTAMP, 15, 12, '0', '多功能训练区', '/static/course/hiit_circuit.jpg', '午间燃脂利器!8个动作站点轮流进行,涵盖深蹲跳、波比跳、壶铃摇摆、登山跑等,每个动作45秒,休息15秒,3轮循环让你全身湿透。', 98.00, 'system'
FROM group_course_type gt WHERE gt.type_name = 'HIIT训练';
INSERT INTO group_course (course_name, course_type, start_time, end_time, max_members, current_members, status, location, cover_image, description, stored_value_amount, create_by)
SELECT '核心爆发力', gt.id, '2026-07-24 17:30:00'::TIMESTAMP, '2026-07-24 18:15:00'::TIMESTAMP, 12, 5, '0', '多功能训练区', '/static/course/hiit_core.jpg', '专注于核心肌群的HIIT训练,结合药球砸地、悬垂举腿、俄罗斯转体和平板支撑变式,打造钢铁般的核心力量,提升所有运动表现。', 108.00, 'system'
FROM group_course_type gt WHERE gt.type_name = 'HIIT训练';
INSERT INTO group_course (course_name, course_type, start_time, end_time, max_members, current_members, status, location, cover_image, description, stored_value_amount, create_by)
SELECT '战绳挑战', gt.id, '2026-07-25 08:00:00'::TIMESTAMP, '2026-07-25 08:45:00'::TIMESTAMP, 10, 10, '0', '户外训练区', '/static/course/hiit_battle.jpg', '风靡全球的战绳训练!通过波浪、猛击、旋转等动作模式激活全身肌群,30秒一组高强度间歇,燃脂同时雕刻上肢线条。名额有限,已约满!', 128.00, 'system'
FROM group_course_type gt WHERE gt.type_name = 'HIIT训练';
INSERT INTO group_course (course_name, course_type, start_time, end_time, max_members, current_members, status, location, cover_image, description, stored_value_amount, create_by)
SELECT '药球HIIT', gt.id, '2026-07-26 10:00:00'::TIMESTAMP, '2026-07-26 10:45:00'::TIMESTAMP, 12, 6, '0', '多功能训练区', '/static/course/hiit_medball.jpg', '以药球为主要工具的HIIT训练。药球砸地、旋转投掷、过头抛接等动作兼具力量和爆发力训练,动作多样不枯燥,周日上午的爆汗之选。', 108.00, 'system'
FROM group_course_type gt WHERE gt.type_name = 'HIIT训练';
-- ---------- 普拉提课程(5个)----------
INSERT INTO group_course (course_name, course_type, start_time, end_time, max_members, current_members, status, location, cover_image, description, stored_value_amount, create_by)
SELECT '垫上普拉提', gt.id, '2026-07-21 10:00:00'::TIMESTAMP, '2026-07-21 11:00:00'::TIMESTAMP, 20, 14, '0', '普拉提室', '/static/course/pilates_mat.jpg', '经典垫上普拉提,通过精准的动作控制激活深层核心肌群。从呼吸到骨盆稳定,从脊柱逐节卷动到四肢协调,一节课改善你的身体感知。', 108.00, 'system'
FROM group_course_type gt WHERE gt.type_name = '普拉提';
INSERT INTO group_course (course_name, course_type, start_time, end_time, max_members, current_members, status, location, cover_image, description, stored_value_amount, create_by)
SELECT '器械普拉提', gt.id, '2026-07-23 09:00:00'::TIMESTAMP, '2026-07-23 10:00:00'::TIMESTAMP, 10, 8, '0', '普拉提室', '/static/course/pilates_reformer.jpg', '使用专业普拉提核心床(Reformer)进行训练,弹簧阻力提供精准的负荷控制,适合需要针对性改善体态、康复训练或追求高效塑形的学员。', 158.00, 'system'
FROM group_course_type gt WHERE gt.type_name = '普拉提';
INSERT INTO group_course (course_name, course_type, start_time, end_time, max_members, current_members, status, location, cover_image, description, stored_value_amount, create_by)
SELECT '核心塑形', gt.id, '2026-07-25 14:00:00'::TIMESTAMP, '2026-07-25 15:00:00'::TIMESTAMP, 15, 9, '0', '普拉提室', '/static/course/pilates_sculpt.jpg', '专注于腹部、腰部和臀部的普拉提塑形课程。百次拍击、剪刀腿、肩桥等经典动作持续刺激目标肌群,打造紧致核心线条。', 128.00, 'system'
FROM group_course_type gt WHERE gt.type_name = '普拉提';
INSERT INTO group_course (course_name, course_type, start_time, end_time, max_members, current_members, status, location, cover_image, description, stored_value_amount, create_by)
SELECT '脊柱健康', gt.id, '2026-07-20 16:00:00'::TIMESTAMP, '2026-07-20 17:00:00'::TIMESTAMP, 15, 6, '0', '普拉提室', '/static/course/pilates_spine.jpg', '专为久坐办公人群设计,通过普拉提脊柱逐节运动改善驼背、圆肩等不良体态。融合猫牛式、脊柱旋转和游泳式,给你的脊柱一次深度保养。', 108.00, 'system'
FROM group_course_type gt WHERE gt.type_name = '普拉提';
INSERT INTO group_course (course_name, course_type, start_time, end_time, max_members, current_members, status, location, cover_image, description, stored_value_amount, create_by)
SELECT '产后恢复普拉提', gt.id, '2026-07-22 11:00:00'::TIMESTAMP, '2026-07-22 12:00:00'::TIMESTAMP, 10, 4, '0', '普拉提室', '/static/course/pilates_postnatal.jpg', '专为产后妈妈设计的温和修复课程,重点激活盆底肌和腹横肌,循序渐进恢复核心力量。小班教学,教练一对一关注每位学员的姿势质量。', 158.00, 'system'
FROM group_course_type gt WHERE gt.type_name = '普拉提';
-- ---------- 搏击操课程(5个)----------
INSERT INTO group_course (course_name, course_type, start_time, end_time, max_members, current_members, status, location, cover_image, description, stored_value_amount, create_by)
SELECT '有氧搏击基础', gt.id, '2026-07-21 18:00:00'::TIMESTAMP, '2026-07-21 19:00:00'::TIMESTAMP, 25, 20, '0', '操厅A', '/static/course/boxing_basic.jpg', '零基础友好的搏击操入门课。从直拳、摆拳、勾拳到前踢、侧踹,教练分步讲解每个动作的要领,配合动感音乐串联成完整的搏击组合。', 68.00, 'system'
FROM group_course_type gt WHERE gt.type_name = '搏击操';
INSERT INTO group_course (course_name, course_type, start_time, end_time, max_members, current_members, status, location, cover_image, description, stored_value_amount, create_by)
SELECT 'Kickboxing进阶', gt.id, '2026-07-23 19:00:00'::TIMESTAMP, '2026-07-23 20:00:00'::TIMESTAMP, 20, 15, '0', '操厅A', '/static/course/boxing_kickboxing.jpg', '融合踢拳技术的进阶搏击课程,增加连击组合、闪躲步法和膝肘技术。强度较基础课明显提升,汗如雨下的同时释放工作压力,宣泄效果一流。', 88.00, 'system'
FROM group_course_type gt WHERE gt.type_name = '搏击操';
INSERT INTO group_course (course_name, course_type, start_time, end_time, max_members, current_members, status, location, cover_image, description, stored_value_amount, create_by)
SELECT '综合格斗体能', gt.id, '2026-07-25 16:00:00'::TIMESTAMP, '2026-07-25 17:00:00'::TIMESTAMP, 20, 12, '0', '操厅A', '/static/course/boxing_mma.jpg', '融合拳击、泰拳、摔跤元素的综合体能训练。沙袋击打、地面对抗和爆发力训练交替进行,全面提升力量、速度和耐力。周六下午的硬核之选!', 98.00, 'system'
FROM group_course_type gt WHERE gt.type_name = '搏击操';
INSERT INTO group_course (course_name, course_type, start_time, end_time, max_members, current_members, status, location, cover_image, description, stored_value_amount, create_by)
SELECT '燃脂拳击', gt.id, '2026-07-20 12:00:00'::TIMESTAMP, '2026-07-20 13:00:00'::TIMESTAMP, 25, 16, '0', '操厅A', '/static/course/boxing_fatburn.jpg', '午间燃脂拳击课。空击组合与沙袋击打间歇进行,心率维持在高燃脂区间。一节课可消耗500-700卡路里,中午来打拳比喝咖啡更提神!', 68.00, 'system'
FROM group_course_type gt WHERE gt.type_name = '搏击操';
INSERT INTO group_course (course_name, course_type, start_time, end_time, max_members, current_members, status, location, cover_image, description, stored_value_amount, create_by)
SELECT '泰拳基础', gt.id, '2026-07-26 15:00:00'::TIMESTAMP, '2026-07-26 16:00:00'::TIMESTAMP, 15, 7, '0', '操厅A', '/static/course/boxing_muaythai.jpg', '学习泰拳的八肢艺术(双拳、双腿、双膝、双肘),从基本站架到肘膝组合,感受泰拳的刚猛魅力。小班教学保证动作纠正质量。', 98.00, 'system'
FROM group_course_type gt WHERE gt.type_name = '搏击操';
-- ============================================
-- 5. 团课推荐数据(每类型推荐1个热门课程,共5条)
-- ============================================
INSERT INTO group_course_recommend (course_id, recommend_title, recommend_content, recommend_reason, priority, is_active)
SELECT gc.id, '清晨之选 - 哈他瑜伽入门', '周一早晨8点,用温和的瑜伽唤醒身体,开启高效一周', '最受欢迎的入门瑜伽课,教练耐心细致', 5, TRUE
FROM group_course gc WHERE gc.course_name = '哈他瑜伽入门';
INSERT INTO group_course_recommend (course_id, recommend_title, recommend_content, recommend_reason, priority, is_active)
SELECT gc.id, '周五狂欢 - 极速冲刺', '周五晚8点,用极速骑行释放一周的疲惫与压力', '单车房王牌课程,周周爆满,燃烧500+卡路里', 4, TRUE
FROM group_course gc WHERE gc.course_name = '极速冲刺';
INSERT INTO group_course_recommend (course_id, recommend_title, recommend_content, recommend_reason, priority, is_active)
SELECT gc.id, '午间爆汗 - 全身循环训练', '午休45分钟,8个站点循环,高效利用碎片时间燃脂', '午间最受欢迎的HIIT课,适合忙碌的上班族', 3, TRUE
FROM group_course gc WHERE gc.course_name = '全身循环训练';
INSERT INTO group_course_recommend (course_id, recommend_title, recommend_content, recommend_reason, priority, is_active)
SELECT gc.id, '久坐救星 - 脊柱健康普拉提', '专为久坐族设计的脊柱保养课,改善驼背圆肩', '全网好评,学员反馈"一节课腰就不疼了"', 2, TRUE
FROM group_course gc WHERE gc.course_name = '脊柱健康';
INSERT INTO group_course_recommend (course_id, recommend_title, recommend_content, recommend_reason, priority, is_active)
SELECT gc.id, '释压首选 - 有氧搏击基础', '零基础也能打!在拳拳到肉的快感中忘记烦恼', '新手友好,发泄压力效果拔群,超过200名学员推荐', 1, TRUE
FROM group_course gc WHERE gc.course_name = '有氧搏击基础';
@@ -0,0 +1,315 @@
-- ============================================
-- V19: 系统初始数据(角色/用户/权限/菜单/字典/配置)
-- 来源:合并原 V2 + V22 + V28 + V29 + V30 + V31
-- ============================================
-- ============================================
-- 1. 角色数据
-- ============================================
INSERT INTO sys_role (id, role_name, role_key, role_sort, status, create_by, update_by, created_at, updated_at)
VALUES
(1, '超级管理员', 'admin', 1, 1, 'system', 'system', NOW(), NOW()),
(2, '测试管理员', 'test_admin', 2, 1, 'system', 'system', NOW(), NOW()),
(3, '普通用户', 'normal_user', 3, 1, 'system', 'system', NOW(), NOW()),
(4, '访客', 'guest', 4, 1, 'system', 'system', NOW(), NOW());
SELECT setval('sys_role_id_seq', 4);
-- ============================================
-- 2. 用户数据(密码均为 Test@123)
-- ============================================
INSERT INTO sys_user (id, username, password, email, phone, nickname, status, create_by, update_by, created_at, updated_at)
VALUES
(1, 'admin', '$2a$12$nZ1EMUpZQljbnEdIKzH72eHlDJKUmHmHppnTTVth/SlHs5VpSAr8C', 'admin@novalon.com', '13800138000', '超级管理员', 1, 'system', 'system', NOW(), NOW()),
(2, 'user', '$2a$12$nZ1EMUpZQljbnEdIKzH72eHlDJKUmHmHppnTTVth/SlHs5VpSAr8C', 'user@novalon.com', '13800138001', '普通用户', 1, 'system', 'system', NOW(), NOW()),
(10,'e2e_test_user', '$2a$12$nZ1EMUpZQljbnEdIKzH72eHlDJKUmHmHppnTTVth/SlHs5VpSAr8C', 'e2e@test.com', '13900139000', 'E2E测试用户', 1, 'system', 'system', NOW(), NOW())
ON CONFLICT (username) DO UPDATE SET
password = EXCLUDED.password,
status = EXCLUDED.status;
SELECT setval('sys_user_id_seq', 10);
-- ============================================
-- 3. 用户角色关联
-- ============================================
INSERT INTO user_role (user_id, role_id, created_by, created_at)
VALUES
(1, 1, 'system', NOW()),
(2, 3, 'system', NOW()),
(10, 1, 'system', NOW())
ON CONFLICT (user_id, role_id) DO NOTHING;
-- ============================================
-- 4. 权限数据
-- ============================================
-- 4.1 系统管理权限
INSERT INTO sys_permission (permission_name, permission_code, resource, action, description, status, create_by, update_by, created_at, updated_at) VALUES
('用户查看', 'system:user:view', '/api/users', 'GET', '查看用户列表', 1, 'system', 'system', NOW(), NOW()),
('用户创建', 'system:user:create', '/api/users', 'POST', '创建用户', 1, 'system', 'system', NOW(), NOW()),
('用户编辑', 'system:user:edit', '/api/users', 'PUT', '编辑用户', 1, 'system', 'system', NOW(), NOW()),
('用户删除', 'system:user:delete', '/api/users', 'DELETE', '删除用户', 1, 'system', 'system', NOW(), NOW()),
('角色查看', 'system:role:view', '/api/roles', 'GET', '查看角色列表', 1, 'system', 'system', NOW(), NOW()),
('角色创建', 'system:role:create', '/api/roles', 'POST', '创建角色', 1, 'system', 'system', NOW(), NOW()),
('角色编辑', 'system:role:edit', '/api/roles', 'PUT', '编辑角色', 1, 'system', 'system', NOW(), NOW()),
('角色删除', 'system:role:delete', '/api/roles', 'DELETE', '删除角色', 1, 'system', 'system', NOW(), NOW()),
('角色分配权限', 'system:role:assign', '/api/roles/*/permissions', 'POST', '为角色分配权限', 1, 'system', 'system', NOW(), NOW()),
('权限查看', 'system:permission:view', '/api/permissions', 'GET', '查看权限列表', 1, 'system', 'system', NOW(), NOW()),
('权限创建', 'system:permission:create', '/api/permissions', 'POST', '创建权限', 1, 'system', 'system', NOW(), NOW()),
('权限编辑', 'system:permission:edit', '/api/permissions', 'PUT', '编辑权限', 1, 'system', 'system', NOW(), NOW()),
('权限删除', 'system:permission:delete', '/api/permissions', 'DELETE', '删除权限', 1, 'system', 'system', NOW(), NOW()),
('菜单查看', 'system:menu:view', '/api/menus', 'GET', '查看菜单列表', 1, 'system', 'system', NOW(), NOW()),
('菜单创建', 'system:menu:create', '/api/menus', 'POST', '创建菜单', 1, 'system', 'system', NOW(), NOW()),
('菜单编辑', 'system:menu:edit', '/api/menus', 'PUT', '编辑菜单', 1, 'system', 'system', NOW(), NOW()),
('菜单删除', 'system:menu:delete', '/api/menus', 'DELETE', '删除菜单', 1, 'system', 'system', NOW(), NOW()),
('字典查看', 'system:dict:view', '/api/dict', 'GET', '查看字典列表', 1, 'system', 'system', NOW(), NOW()),
('字典创建', 'system:dict:create', '/api/dict', 'POST', '创建字典', 1, 'system', 'system', NOW(), NOW()),
('字典编辑', 'system:dict:edit', '/api/dict', 'PUT', '编辑字典', 1, 'system', 'system', NOW(), NOW()),
('字典删除', 'system:dict:delete', '/api/dict', 'DELETE', '删除字典', 1, 'system', 'system', NOW(), NOW()),
('配置查看', 'system:config:view', '/api/config', 'GET', '查看系统配置', 1, 'system', 'system', NOW(), NOW()),
('配置创建', 'system:config:create', '/api/config', 'POST', '创建系统配置', 1, 'system', 'system', NOW(), NOW()),
('配置编辑', 'system:config:edit', '/api/config', 'PUT', '编辑系统配置', 1, 'system', 'system', NOW(), NOW()),
('配置删除', 'system:config:delete', '/api/config', 'DELETE', '删除系统配置', 1, 'system', 'system', NOW(), NOW()),
('日志查看', 'system:log:view', '/api/logs', 'GET', '查看日志', 1, 'system', 'system', NOW(), NOW()),
('文件上传', 'system:file:upload', '/api/files/upload', 'POST', '上传文件', 1, 'system', 'system', NOW(), NOW()),
('文件下载', 'system:file:download', '/api/files/download', 'GET', '下载文件', 1, 'system', 'system', NOW(), NOW()),
('文件删除', 'system:file:delete', '/api/files', 'DELETE', '删除文件', 1, 'system', 'system', NOW(), NOW()),
('公告查看', 'system:notice:view', '/api/notices', 'GET', '查看公告', 1, 'system', 'system', NOW(), NOW()),
('公告创建', 'system:notice:create', '/api/notices', 'POST', '创建公告', 1, 'system', 'system', NOW(), NOW()),
('公告编辑', 'system:notice:edit', '/api/notices', 'PUT', '编辑公告', 1, 'system', 'system', NOW(), NOW()),
('公告删除', 'system:notice:delete', '/api/notices', 'DELETE', '删除公告', 1, 'system', 'system', NOW(), NOW());
-- 4.2 业务模块权限
INSERT INTO sys_permission (permission_name, permission_code, resource, action, description, status, create_by, update_by, created_at, updated_at) VALUES
-- 会员管理
('会员查看', 'business:member:view', '/api/admin/members', 'GET', '查看会员列表及详情', 1, 'system', 'system', NOW(), NOW()),
('会员编辑', 'business:member:edit', '/api/admin/member', 'PUT', '编辑会员信息', 1, 'system', 'system', NOW(), NOW()),
('会员手机修改', 'business:member:phone', '/api/admin/member/phone', 'POST', '管理员修改会员手机号', 1, 'system', 'system', NOW(), NOW()),
-- 会员卡管理
('会员卡查看', 'business:memberCard:view', '/api/member-cards', 'GET', '查看会员卡列表及详情', 1, 'system', 'system', NOW(), NOW()),
('会员卡创建', 'business:memberCard:create', '/api/member-cards', 'POST', '创建会员卡类型', 1, 'system', 'system', NOW(), NOW()),
('会员卡编辑', 'business:memberCard:edit', '/api/member-cards', 'PUT', '编辑会员卡类型', 1, 'system', 'system', NOW(), NOW()),
('会员卡删除', 'business:memberCard:delete', '/api/member-cards', 'DELETE', '删除会员卡类型', 1, 'system', 'system', NOW(), NOW()),
('会员卡购买', 'business:memberCard:purchase', '/api/member-card-records/purchase', 'POST', '为会员购买/绑定会员卡', 1, 'system', 'system', NOW(), NOW()),
('会员卡退卡', 'business:memberCard:refund', '/api/member-card-records/refund', 'POST', '会员卡退卡/解绑', 1, 'system', 'system', NOW(), NOW()),
-- 团课管理
('团课查看', 'business:groupCourse:view', '/api/groupCourse', 'GET', '查看团课列表及详情', 1, 'system', 'system', NOW(), NOW()),
('团课创建', 'business:groupCourse:create', '/api/groupCourse', 'POST', '创建团课', 1, 'system', 'system', NOW(), NOW()),
('团课编辑', 'business:groupCourse:edit', '/api/groupCourse', 'PUT', '编辑团课信息', 1, 'system', 'system', NOW(), NOW()),
('团课删除', 'business:groupCourse:delete', '/api/groupCourse', 'DELETE', '删除团课', 1, 'system', 'system', NOW(), NOW()),
('团课取消', 'business:groupCourse:cancel', '/api/groupCourse/cancel', 'POST', '取消团课', 1, 'system', 'system', NOW(), NOW()),
-- 团课类型管理
('团课类型查看', 'business:groupCourseType:view', '/api/groupCourse/types', 'GET', '查看团课类型列表', 1, 'system', 'system', NOW(), NOW()),
('团课类型创建', 'business:groupCourseType:create', '/api/groupCourse/types', 'POST', '创建团课类型', 1, 'system', 'system', NOW(), NOW()),
('团课类型编辑', 'business:groupCourseType:edit', '/api/groupCourse/types', 'PUT', '编辑团课类型', 1, 'system', 'system', NOW(), NOW()),
('团课类型删除', 'business:groupCourseType:delete', '/api/groupCourse/types', 'DELETE', '删除团课类型', 1, 'system', 'system', NOW(), NOW()),
-- 团课推荐管理
('团课推荐查看', 'business:groupCourseRecommend:view', '/api/groupCourse/recommend', 'GET', '查看推荐团课列表', 1, 'system', 'system', NOW(), NOW()),
('团课推荐创建', 'business:groupCourseRecommend:create','/api/groupCourse/recommend', 'POST', '创建推荐团课', 1, 'system', 'system', NOW(), NOW()),
('团课推荐编辑', 'business:groupCourseRecommend:edit', '/api/groupCourse/recommend', 'PUT', '编辑推荐团课', 1, 'system', 'system', NOW(), NOW()),
('团课推荐删除', 'business:groupCourseRecommend:delete','/api/groupCourse/recommend', 'DELETE', '删除推荐团课', 1, 'system', 'system', NOW(), NOW()),
-- 团课预约管理
('团课预约查看', 'business:groupCourseBooking:view', '/api/groupCourse/bookings', 'GET', '查看团课预约记录', 1, 'system', 'system', NOW(), NOW()),
('团课预约创建', 'business:groupCourseBooking:create', '/api/groupCourse/book', 'POST', '预约团课', 1, 'system', 'system', NOW(), NOW()),
('团课预约取消', 'business:groupCourseBooking:cancel', '/api/groupCourse/booking/cancel', 'POST', '取消团课预约', 1, 'system', 'system', NOW(), NOW()),
-- 签到管理
('签到查看', 'business:checkIn:view', '/api/checkIn/records', 'GET', '查看签到记录', 1, 'system', 'system', NOW(), NOW()),
('签到操作', 'business:checkIn:create', '/api/checkIn', 'POST', '执行签到操作', 1, 'system', 'system', NOW(), NOW()),
('签到导出', 'business:checkIn:export', '/api/checkIn/records/export', 'GET', '导出签到记录', 1, 'system', 'system', NOW(), NOW()),
-- 数据统计
('数据统计查看', 'business:dataCount:view', '/api/datacount', 'GET', '查看数据统计报表', 1, 'system', 'system', NOW(), NOW()),
('数据统计导出', 'business:dataCount:export', '/api/datacount/export', 'GET', '导出统计报表', 1, 'system', 'system', NOW(), NOW()),
-- 员工管理
('员工查看', 'business:employee:view', '/api/employees/page', 'GET', '查看员工列表', 1, 'system', 'system', NOW(), NOW()),
('员工创建', 'business:employee:create', '/api/users', 'POST', '创建员工账号', 1, 'system', 'system', NOW(), NOW()),
('员工编辑', 'business:employee:edit', '/api/users', 'PUT', '编辑员工信息', 1, 'system', 'system', NOW(), NOW()),
('员工删除', 'business:employee:delete', '/api/users', 'DELETE', '删除/禁用员工账号', 1, 'system', 'system', NOW(), NOW()),
('员工分配角色', 'business:employee:assignRole', '/api/users/roles', 'POST', '为员工分配角色', 1, 'system', 'system', NOW(), NOW());
-- ============================================
-- 5. 为超级管理员角色分配所有权限
-- ============================================
INSERT INTO sys_role_permission (role_id, permission_id, create_by, update_by, created_at, updated_at)
SELECT 1, id, 'system', 'system', NOW(), NOW() FROM sys_permission WHERE status = 1
AND id NOT IN (SELECT permission_id FROM sys_role_permission WHERE role_id = 1);
-- ============================================
-- 6. 菜单数据
-- ============================================
-- 6.1 一级菜单
INSERT INTO sys_menu (id, menu_name, parent_id, order_num, menu_type, perms, component, status, created_at, updated_at) VALUES
(1, '系统管理', 0, 1, 'M', NULL, NULL, 1, NOW(), NOW()),
(2, '审计日志', 0, 2, 'M', NULL, NULL, 1, NOW(), NOW()),
(3, '系统监控', 0, 3, 'M', NULL, NULL, 1, NOW(), NOW()),
(400, '团课管理', 0, 4, 'M', NULL, NULL, 1, NOW(), NOW()),
(500, '会员管理', 0, 5, 'M', NULL, NULL, 1, NOW(), NOW()),
(502, '会员卡管理', 0, 6, 'M', NULL, NULL, 1, NOW(), NOW()),
(504, '数据统计', 0, 7, 'M', NULL, NULL, 1, NOW(), NOW());
-- 6.2 系统管理 - 子菜单
INSERT INTO sys_menu (id, menu_name, parent_id, order_num, menu_type, perms, component, status, created_at, updated_at) VALUES
(11, '用户管理', 1, 1, 'C', 'system:user:list', 'system/user/index', 1, NOW(), NOW()),
(12, '角色管理', 1, 2, 'C', 'system:role:list', 'system/role/index', 1, NOW(), NOW()),
(13, '菜单管理', 1, 3, 'C', 'system:menu:list', 'system/menu/index', 1, NOW(), NOW()),
(14, '部门管理', 1, 4, 'C', 'system:dept:list', 'system/dept/index', 1, NOW(), NOW()),
(15, '字典管理', 1, 5, 'C', 'system:dict:list', 'system/dict/index', 1, NOW(), NOW()),
(16, '参数管理', 1, 6, 'C', 'system:config:list', 'system/config/index', 1, NOW(), NOW()),
(17, '通知公告', 1, 7, 'C', 'system:notice:list', 'system/notice/index', 1, NOW(), NOW()),
(18, '文件管理', 1, 8, 'C', 'system:file:list', 'system/file/index', 1, NOW(), NOW()),
(19, '轮播图管理', 0, 8, 'C', 'system:banner:list', 'banner/index', 1, NOW(), NOW());
-- 6.3 系统管理 - 按钮权限
INSERT INTO sys_menu (id, menu_name, parent_id, order_num, menu_type, perms, component, status, created_at, updated_at) VALUES
-- 用户管理按钮
(111, '用户查询', 11, 1, 'F', 'system:user:query', NULL, 1, NOW(), NOW()),
(112, '用户新增', 11, 2, 'F', 'system:user:add', NULL, 1, NOW(), NOW()),
(113, '用户修改', 11, 3, 'F', 'system:user:edit', NULL, 1, NOW(), NOW()),
(114, '用户删除', 11, 4, 'F', 'system:user:remove', NULL, 1, NOW(), NOW()),
(115, '用户导出', 11, 5, 'F', 'system:user:export', NULL, 1, NOW(), NOW()),
(116, '用户导入', 11, 6, 'F', 'system:user:import', NULL, 1, NOW(), NOW()),
(117, '重置密码', 11, 7, 'F', 'system:user:resetPwd', NULL, 1, NOW(), NOW()),
-- 角色管理按钮
(121, '角色查询', 12, 1, 'F', 'system:role:query', NULL, 1, NOW(), NOW()),
(122, '角色新增', 12, 2, 'F', 'system:role:add', NULL, 1, NOW(), NOW()),
(123, '角色修改', 12, 3, 'F', 'system:role:edit', NULL, 1, NOW(), NOW()),
(124, '角色删除', 12, 4, 'F', 'system:role:remove', NULL, 1, NOW(), NOW()),
(125, '角色导出', 12, 5, 'F', 'system:role:export', NULL, 1, NOW(), NOW()),
-- 菜单管理按钮
(131, '菜单查询', 13, 1, 'F', 'system:menu:query', NULL, 1, NOW(), NOW()),
(132, '菜单新增', 13, 2, 'F', 'system:menu:add', NULL, 1, NOW(), NOW()),
(133, '菜单修改', 13, 3, 'F', 'system:menu:edit', NULL, 1, NOW(), NOW()),
(134, '菜单删除', 13, 4, 'F', 'system:menu:remove', NULL, 1, NOW(), NOW());
-- 6.4 审计日志 - 子菜单
INSERT INTO sys_menu (id, menu_name, parent_id, order_num, menu_type, perms, component, status, created_at, updated_at) VALUES
(21, '操作日志', 2, 1, 'C', 'audit:operation:list', 'audit/operation/index', 1, NOW(), NOW()),
(22, '登录日志', 2, 2, 'C', 'audit:login:list', 'audit/login/index', 1, NOW(), NOW()),
(23, '异常日志', 2, 3, 'C', 'audit:exception:list', 'audit/exception/index', 1, NOW(), NOW());
-- 6.5 审计日志 - 按钮权限
INSERT INTO sys_menu (id, menu_name, parent_id, order_num, menu_type, perms, component, status, created_at, updated_at) VALUES
(211, '操作查询', 21, 1, 'F', 'audit:operation:query', NULL, 1, NOW(), NOW()),
(212, '操作删除', 21, 2, 'F', 'audit:operation:remove', NULL, 1, NOW(), NOW()),
(213, '操作导出', 21, 3, 'F', 'audit:operation:export', NULL, 1, NOW(), NOW()),
(221, '登录查询', 22, 1, 'F', 'audit:login:query', NULL, 1, NOW(), NOW()),
(222, '登录删除', 22, 2, 'F', 'audit:login:remove', NULL, 1, NOW(), NOW()),
(223, '登录导出', 22, 3, 'F', 'audit:login:export', NULL, 1, NOW(), NOW()),
(231, '异常查询', 23, 1, 'F', 'audit:exception:query', NULL, 1, NOW(), NOW()),
(232, '异常删除', 23, 2, 'F', 'audit:exception:remove', NULL, 1, NOW(), NOW()),
(233, '异常导出', 23, 3, 'F', 'audit:exception:export', NULL, 1, NOW(), NOW());
-- 6.6 系统监控 - 子菜单
INSERT INTO sys_menu (id, menu_name, parent_id, order_num, menu_type, perms, component, status, created_at, updated_at) VALUES
(31, '在线用户', 3, 1, 'C', 'monitor:online:list', 'monitor/online/index', 1, NOW(), NOW()),
(32, '定时任务', 3, 2, 'C', 'monitor:job:list', 'monitor/job/index', 1, NOW(), NOW()),
(33, '数据监控', 3, 3, 'C', 'monitor:data:list', 'monitor/data/index', 1, NOW(), NOW()),
(34, '服务监控', 3, 4, 'C', 'monitor:server:list', 'monitor/server/index', 1, NOW(), NOW()),
(35, '缓存监控', 3, 5, 'C', 'monitor:cache:list', 'monitor/cache/index', 1, NOW(), NOW());
-- 6.7 系统监控 - 按钮权限
INSERT INTO sys_menu (id, menu_name, parent_id, order_num, menu_type, perms, component, status, created_at, updated_at) VALUES
(311, '在线查询', 31, 1, 'F', 'monitor:online:query', NULL, 1, NOW(), NOW()),
(312, '在线强退', 31, 2, 'F', 'monitor:online:forceLogout', NULL, 1, NOW(), NOW()),
(321, '任务查询', 32, 1, 'F', 'monitor:job:query', NULL, 1, NOW(), NOW()),
(322, '任务新增', 32, 2, 'F', 'monitor:job:add', NULL, 1, NOW(), NOW()),
(323, '任务修改', 32, 3, 'F', 'monitor:job:edit', NULL, 1, NOW(), NOW()),
(324, '任务删除', 32, 4, 'F', 'monitor:job:remove', NULL, 1, NOW(), NOW()),
(325, '任务执行', 32, 5, 'F', 'monitor:job:execute', NULL, 1, NOW(), NOW());
-- 6.8 团课管理 - 子菜单
INSERT INTO sys_menu (id, menu_name, parent_id, order_num, menu_type, perms, component, status, created_at, updated_at) VALUES
(401, '团课管理', 400, 1, 'C', 'business:groupCourse:list', 'gymCourse/course/index', 1, NOW(), NOW()),
(402, '团课类型', 400, 2, 'C', 'business:groupCourseType:list', 'gymCourse/type/index', 1, NOW(), NOW()),
(403, '类型标签', 400, 3, 'C', 'business:groupCourseLabel:list', 'gymCourse/label/index', 1, NOW(), NOW()),
(404, '团课推荐', 400, 4, 'C', 'business:groupCourseRecommend:list', 'gymCourse/recommend/index', 1, NOW(), NOW());
-- 6.9 团课管理 - 按钮权限
INSERT INTO sys_menu (id, menu_name, parent_id, order_num, menu_type, perms, component, status, created_at, updated_at) VALUES
(4011, '团课查询', 401, 1, 'F', 'business:groupCourse:query', NULL, 1, NOW(), NOW()),
(4012, '团课新增', 401, 2, 'F', 'business:groupCourse:add', NULL, 1, NOW(), NOW()),
(4013, '团课修改', 401, 3, 'F', 'business:groupCourse:edit', NULL, 1, NOW(), NOW()),
(4014, '团课删除', 401, 4, 'F', 'business:groupCourse:remove', NULL, 1, NOW(), NOW()),
(4015, '团课取消', 401, 5, 'F', 'business:groupCourse:cancel', NULL, 1, NOW(), NOW()),
(4021, '类型查询', 402, 1, 'F', 'business:groupCourseType:query', NULL, 1, NOW(), NOW()),
(4022, '类型新增', 402, 2, 'F', 'business:groupCourseType:add', NULL, 1, NOW(), NOW()),
(4023, '类型修改', 402, 3, 'F', 'business:groupCourseType:edit', NULL, 1, NOW(), NOW()),
(4024, '类型删除', 402, 4, 'F', 'business:groupCourseType:remove', NULL, 1, NOW(), NOW()),
(4031, '标签查询', 403, 1, 'F', 'business:groupCourseLabel:query', NULL, 1, NOW(), NOW()),
(4032, '标签新增', 403, 2, 'F', 'business:groupCourseLabel:add', NULL, 1, NOW(), NOW()),
(4033, '标签修改', 403, 3, 'F', 'business:groupCourseLabel:edit', NULL, 1, NOW(), NOW()),
(4034, '标签删除', 403, 4, 'F', 'business:groupCourseLabel:remove', NULL, 1, NOW(), NOW()),
(4041, '推荐查询', 404, 1, 'F', 'business:groupCourseRecommend:query', NULL, 1, NOW(), NOW()),
(4042, '推荐新增', 404, 2, 'F', 'business:groupCourseRecommend:add', NULL, 1, NOW(), NOW()),
(4043, '推荐修改', 404, 3, 'F', 'business:groupCourseRecommend:edit', NULL, 1, NOW(), NOW()),
(4044, '推荐删除', 404, 4, 'F', 'business:groupCourseRecommend:remove', NULL, 1, NOW(), NOW());
-- 6.10 会员管理 - 子菜单
INSERT INTO sys_menu (id, menu_name, parent_id, order_num, menu_type, perms, component, status, created_at, updated_at) VALUES
(501, '会员管理', 500, 1, 'C', 'business:member:list', 'member/member/index', 1, NOW(), NOW()),
(503, '会员卡管理', 502, 1, 'C', 'business:memberCard:list', 'member/card/index', 1, NOW(), NOW()),
(505, '数据统计看板', 504, 1, 'C', 'business:statistics:view', 'statistics/dashboard/index', 1, NOW(), NOW());
-- 6.11 会员管理 - 按钮权限
INSERT INTO sys_menu (id, menu_name, parent_id, order_num, menu_type, perms, component, status, created_at, updated_at) VALUES
(5011, '会员查询', 501, 1, 'F', 'business:member:query', NULL, 1, NOW(), NOW()),
(5012, '会员新增', 501, 2, 'F', 'business:member:add', NULL, 1, NOW(), NOW()),
(5013, '会员修改', 501, 3, 'F', 'business:member:edit', NULL, 1, NOW(), NOW()),
(5014, '会员删除', 501, 4, 'F', 'business:member:remove', NULL, 1, NOW(), NOW()),
(5015, '会员详情', 501, 5, 'F', 'business:member:detail', NULL, 1, NOW(), NOW()),
(5031, '会员卡查询', 503, 1, 'F', 'business:memberCard:query', NULL, 1, NOW(), NOW()),
(5032, '会员卡新增', 503, 2, 'F', 'business:memberCard:add', NULL, 1, NOW(), NOW()),
(5033, '会员卡修改', 503, 3, 'F', 'business:memberCard:edit', NULL, 1, NOW(), NOW()),
(5034, '会员卡删除', 503, 4, 'F', 'business:memberCard:remove', NULL, 1, NOW(), NOW()),
(5051, '数据统计导出', 505, 1, 'F', 'business:statistics:export', NULL, 1, NOW(), NOW());
-- ============================================
-- 7. 字典数据
-- ============================================
-- 7.1 字典类型
INSERT INTO sys_dict_type (dict_name, dict_type, status, remark, create_by, update_by, created_at, updated_at)
VALUES
('用户状态', 'user_status', '0', '用户状态列表', 'system', 'system', NOW(), NOW()),
('菜单状态', 'menu_status', '0', '菜单状态列表', 'system', 'system', NOW(), NOW()),
('角色状态', 'role_status', '0', '角色状态列表', 'system', 'system', NOW(), NOW()),
('系统开关', 'sys_normal_disable', '0', '系统开关列表', 'system', 'system', NOW(), NOW())
ON CONFLICT (dict_type) DO NOTHING;
-- 7.2 字典数据
INSERT INTO sys_dict_data (dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, status, create_by, update_by, created_at, updated_at)
VALUES
(1, '正常', '1', 'user_status', '', 'primary', 'Y', '0', 'system', 'system', NOW(), NOW()),
(2, '停用', '0', 'user_status', '', 'danger', 'N', '0', 'system', 'system', NOW(), NOW()),
(1, '正常', '0', 'menu_status', '', 'primary', 'Y', '0', 'system', 'system', NOW(), NOW()),
(2, '停用', '1', 'menu_status', '', 'danger', 'N', '0', 'system', 'system', NOW(), NOW()),
(1, '正常', '0', 'role_status', '', 'primary', 'Y', '0', 'system', 'system', NOW(), NOW()),
(2, '停用', '1', 'role_status', '', 'danger', 'N', '0', 'system', 'system', NOW(), NOW()),
(1, '正常', '0', 'sys_normal_disable', '', 'primary', 'Y', '0', 'system', 'system', NOW(), NOW()),
(2, '停用', '1', 'sys_normal_disable', '', 'danger', 'N', '0', 'system', 'system', NOW(), NOW());
-- ============================================
-- 8. 系统配置
-- ============================================
INSERT INTO sys_config (config_name, config_key, config_value, config_type, create_by, update_by, created_at, updated_at)
VALUES
('用户管理-用户初始密码', 'sys.user.initPassword', '123456', 'Y', 'system', 'system', NOW(), NOW()),
('主框架页-默认皮肤样式名称', 'sys.index.skinName', 'skin-blue','Y', 'system', 'system', NOW(), NOW()),
('用户自助-验证码开关', 'sys.account.captchaEnabled', 'true', 'Y', 'system', 'system', NOW(), NOW()),
('用户自助-是否开启用户注册功能', 'sys.account.registerUser', 'false', 'Y', 'system', 'system', NOW(), NOW()),
('账号自助-密码验证码', 'sys.account.pwdCaptchaEnabled','true', 'Y', 'system', 'system', NOW(), NOW()),
('团课-取消预约免手续费次数', 'group_course.cancel_free_limit','3', 'Y', 'system', 'system', NOW(), NOW())
ON CONFLICT (config_key) DO NOTHING;
-- ============================================
-- 9. 重置所有序列值
-- ============================================
SELECT setval('sys_user_id_seq', (SELECT COALESCE(MAX(id), 1) FROM sys_user));
SELECT setval('sys_role_id_seq', (SELECT COALESCE(MAX(id), 1) FROM sys_role));
SELECT setval('user_role_id_seq', (SELECT COALESCE(MAX(id), 1) FROM user_role));
SELECT setval('sys_permission_id_seq', (SELECT COALESCE(MAX(id), 1) FROM sys_permission));
SELECT setval('sys_role_permission_id_seq', (SELECT COALESCE(MAX(id), 1) FROM sys_role_permission));
SELECT setval('sys_menu_id_seq', (SELECT COALESCE(MAX(id), 1) FROM sys_menu));
SELECT setval('sys_dict_type_id_seq', (SELECT COALESCE(MAX(id), 1) FROM sys_dict_type));
SELECT setval('sys_dict_data_id_seq', (SELECT COALESCE(MAX(id), 1) FROM sys_dict_data));
SELECT setval('sys_config_id_seq', (SELECT COALESCE(MAX(id), 1) FROM sys_config));
@@ -1,6 +1,8 @@
-- ============================================
-- Novalon管理系统数据库初始化脚本
-- 版本: V1
-- 描述: 创建所有核心表结构(合并版)
-- 描述: 创建所有核心系统表结构
-- ============================================
-- ============================================
-- 用户与角色相关表
@@ -140,7 +142,7 @@ CREATE TABLE IF NOT EXISTS sys_dict_data (
deleted_at TIMESTAMP
);
-- 字典表(通用字典
-- 通用字典
CREATE TABLE IF NOT EXISTS sys_dictionary (
id BIGSERIAL PRIMARY KEY,
type VARCHAR(100) NOT NULL,
@@ -165,7 +167,7 @@ CREATE TABLE IF NOT EXISTS sys_config (
config_name VARCHAR(100) NOT NULL,
config_key VARCHAR(100) NOT NULL UNIQUE,
config_value VARCHAR(500) NOT NULL,
config_type VARCHAR(1) DEFAULT 'N',
config_type VARCHAR(1) DEFAULT 'Y',
create_by VARCHAR(50),
update_by VARCHAR(50),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
@@ -355,15 +357,6 @@ COMMENT ON TABLE sys_dict_data IS '字典数据表';
COMMENT ON TABLE sys_dictionary IS '通用字典表';
COMMENT ON TABLE sys_config IS '系统配置表';
COMMENT ON TABLE sys_login_log IS '登录日志表';
COMMENT ON TABLE sys_exception_log IS '异常日志表';
COMMENT ON TABLE operation_log IS '操作日志表';
COMMENT ON TABLE audit_log IS '审计日志表';
COMMENT ON TABLE audit_log_archive IS '审计日志归档表';
COMMENT ON TABLE sys_notice IS '系统公告表';
COMMENT ON TABLE sys_user_message IS '用户消息表';
COMMENT ON TABLE sys_file IS '文件管理表';
COMMENT ON TABLE oauth2_client IS 'OAuth2客户端表';
COMMENT ON TABLE sys_exception_log IS '异常日志表';
COMMENT ON COLUMN sys_exception_log.id IS '主键ID';
COMMENT ON COLUMN sys_exception_log.username IS '操作用户';
@@ -375,7 +368,22 @@ COMMENT ON COLUMN sys_exception_log.exception_msg IS '异常消息';
COMMENT ON COLUMN sys_exception_log.exception_stack IS '异常堆栈';
COMMENT ON COLUMN sys_exception_log.ip IS 'IP地址';
COMMENT ON COLUMN sys_exception_log.create_time IS '创建时间';
COMMENT ON TABLE operation_log IS '操作日志表';
COMMENT ON COLUMN operation_log.id IS '主键ID';
COMMENT ON COLUMN operation_log.username IS '操作用户';
COMMENT ON COLUMN operation_log.operation IS '操作描述';
COMMENT ON COLUMN operation_log.method IS '请求方法';
COMMENT ON COLUMN operation_log.params IS '请求参数';
COMMENT ON COLUMN operation_log.result IS '操作结果';
COMMENT ON COLUMN operation_log.ip IS 'IP地址';
COMMENT ON COLUMN operation_log.duration IS '执行时长(毫秒)';
COMMENT ON COLUMN operation_log.status IS '操作状态(0成功 1失败)';
COMMENT ON COLUMN operation_log.error_msg IS '错误消息';
COMMENT ON COLUMN operation_log.create_by IS '创建人';
COMMENT ON COLUMN operation_log.update_by IS '更新人';
COMMENT ON COLUMN operation_log.created_at IS '创建时间';
COMMENT ON COLUMN operation_log.updated_at IS '更新时间';
COMMENT ON COLUMN operation_log.deleted_at IS '删除时间';
COMMENT ON TABLE audit_log IS '审计日志表';
COMMENT ON COLUMN audit_log.id IS '主键ID';
COMMENT ON COLUMN audit_log.entity_type IS '实体类型(如User, Role等)';
@@ -389,7 +397,6 @@ COMMENT ON COLUMN audit_log.changed_fields IS '变更字段列表';
COMMENT ON COLUMN audit_log.ip_address IS 'IP地址';
COMMENT ON COLUMN audit_log.description IS '操作描述';
COMMENT ON COLUMN audit_log.created_at IS '记录创建时间';
COMMENT ON TABLE audit_log_archive IS '审计日志归档表';
COMMENT ON COLUMN audit_log_archive.id IS '主键ID';
COMMENT ON COLUMN audit_log_archive.entity_type IS '实体类型(如User, Role等)';
@@ -405,3 +412,7 @@ COMMENT ON COLUMN audit_log_archive.user_agent IS '用户代理';
COMMENT ON COLUMN audit_log_archive.description IS '操作描述';
COMMENT ON COLUMN audit_log_archive.created_at IS '记录创建时间';
COMMENT ON COLUMN audit_log_archive.archived_at IS '归档时间';
COMMENT ON TABLE sys_notice IS '系统公告表';
COMMENT ON TABLE sys_user_message IS '用户消息表';
COMMENT ON TABLE sys_file IS '文件管理表';
COMMENT ON TABLE oauth2_client IS 'OAuth2客户端表';
@@ -0,0 +1,18 @@
-- ============================================
-- V20: 新增轮播图管理菜单
-- 描述: 为首页轮播图管理功能创建菜单项
-- ============================================
-- 轮播图管理子菜单(页面),归属系统管理目录
INSERT INTO sys_menu (id, menu_name, parent_id, order_num, menu_type, perms, component, status, created_at, updated_at) VALUES
(19, '轮播图管理', 0, 8, 'C', 'system:banner:list', 'banner/index', 1, NOW(), NOW());
-- 轮播图管理按钮权限
INSERT INTO sys_menu (id, menu_name, parent_id, order_num, menu_type, perms, component, status, created_at, updated_at) VALUES
(191, '轮播图查询', 19, 1, 'F', 'system:banner:query', NULL, 1, NOW(), NOW()),
(192, '轮播图新增', 19, 2, 'F', 'system:banner:add', NULL, 1, NOW(), NOW()),
(193, '轮播图修改', 19, 3, 'F', 'system:banner:edit', NULL, 1, NOW(), NOW()),
(194, '轮播图删除', 19, 4, 'F', 'system:banner:remove', NULL, 1, NOW(), NOW());
-- 重置菜单序列
SELECT setval('sys_menu_id_seq', (SELECT COALESCE(MAX(id), 1) FROM sys_menu));
@@ -0,0 +1,20 @@
-- ============================================
-- V21: 创建轮播图表并更新菜单为顶级菜单
-- ============================================
-- 创建 banner 表
CREATE TABLE IF NOT EXISTS banner (
id BIGSERIAL PRIMARY KEY,
image_url VARCHAR(512) NOT NULL,
title VARCHAR(100) NOT NULL,
subtitle TEXT,
sort_order INT DEFAULT 0,
is_active VARCHAR(1) DEFAULT '1',
link_url VARCHAR(512),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
deleted_at TIMESTAMP
);
-- 将轮播图管理菜单从系统管理子菜单调整为顶级菜单(parent_id=0, sort=8
UPDATE sys_menu SET parent_id = 0, order_num = 8 WHERE id = 19;
@@ -1,100 +0,0 @@
-- ============================================
-- V22: 新增业务模块权限
-- 描述: 为会员、会员卡、团课、签到、数据统计、员工管理等业务模块创建权限
-- ============================================
-- ============================================
-- 会员管理权限
-- ============================================
INSERT INTO sys_permission (permission_name, permission_code, resource, action, description, status, create_by, update_by, created_at, updated_at) VALUES
('会员查看', 'business:member:view', '/api/admin/members', 'GET', '查看会员列表及详情', 1, 'system', 'system', NOW(), NOW()),
('会员编辑', 'business:member:edit', '/api/admin/member', 'PUT', '编辑会员信息', 1, 'system', 'system', NOW(), NOW()),
('会员手机修改', 'business:member:phone', '/api/admin/member/phone', 'POST', '管理员修改会员手机号', 1, 'system', 'system', NOW(), NOW());
-- ============================================
-- 会员卡管理权限
-- ============================================
INSERT INTO sys_permission (permission_name, permission_code, resource, action, description, status, create_by, update_by, created_at, updated_at) VALUES
('会员卡查看', 'business:memberCard:view', '/api/member-cards', 'GET', '查看会员卡列表及详情', 1, 'system', 'system', NOW(), NOW()),
('会员卡创建', 'business:memberCard:create', '/api/member-cards', 'POST', '创建会员卡类型', 1, 'system', 'system', NOW(), NOW()),
('会员卡编辑', 'business:memberCard:edit', '/api/member-cards', 'PUT', '编辑会员卡类型', 1, 'system', 'system', NOW(), NOW()),
('会员卡删除', 'business:memberCard:delete', '/api/member-cards', 'DELETE', '删除会员卡类型', 1, 'system', 'system', NOW(), NOW()),
('会员卡购买', 'business:memberCard:purchase', '/api/member-card-records/purchase', 'POST', '为会员购买/绑定会员卡', 1, 'system', 'system', NOW(), NOW()),
('会员卡退卡', 'business:memberCard:refund', '/api/member-card-records/refund', 'POST', '会员卡退卡/解绑', 1, 'system', 'system', NOW(), NOW());
-- ============================================
-- 团课管理权限
-- ============================================
INSERT INTO sys_permission (permission_name, permission_code, resource, action, description, status, create_by, update_by, created_at, updated_at) VALUES
('团课查看', 'business:groupCourse:view', '/api/groupCourse', 'GET', '查看团课列表及详情', 1, 'system', 'system', NOW(), NOW()),
('团课创建', 'business:groupCourse:create', '/api/groupCourse', 'POST', '创建团课', 1, 'system', 'system', NOW(), NOW()),
('团课编辑', 'business:groupCourse:edit', '/api/groupCourse', 'PUT', '编辑团课信息', 1, 'system', 'system', NOW(), NOW()),
('团课删除', 'business:groupCourse:delete', '/api/groupCourse', 'DELETE', '删除团课', 1, 'system', 'system', NOW(), NOW()),
('团课取消', 'business:groupCourse:cancel', '/api/groupCourse/cancel', 'POST', '取消团课', 1, 'system', 'system', NOW(), NOW());
-- ============================================
-- 团课类型管理权限
-- ============================================
INSERT INTO sys_permission (permission_name, permission_code, resource, action, description, status, create_by, update_by, created_at, updated_at) VALUES
('团课类型查看', 'business:groupCourseType:view', '/api/groupCourse/types', 'GET', '查看团课类型列表', 1, 'system', 'system', NOW(), NOW()),
('团课类型创建', 'business:groupCourseType:create', '/api/groupCourse/types', 'POST', '创建团课类型', 1, 'system', 'system', NOW(), NOW()),
('团课类型编辑', 'business:groupCourseType:edit', '/api/groupCourse/types', 'PUT', '编辑团课类型', 1, 'system', 'system', NOW(), NOW()),
('团课类型删除', 'business:groupCourseType:delete', '/api/groupCourse/types', 'DELETE', '删除团课类型', 1, 'system', 'system', NOW(), NOW());
-- ============================================
-- 团课推荐管理权限
-- ============================================
INSERT INTO sys_permission (permission_name, permission_code, resource, action, description, status, create_by, update_by, created_at, updated_at) VALUES
('团课推荐查看', 'business:groupCourseRecommend:view', '/api/groupCourse/recommend', 'GET', '查看推荐团课列表', 1, 'system', 'system', NOW(), NOW()),
('团课推荐创建', 'business:groupCourseRecommend:create', '/api/groupCourse/recommend', 'POST', '创建推荐团课', 1, 'system', 'system', NOW(), NOW()),
('团课推荐编辑', 'business:groupCourseRecommend:edit', '/api/groupCourse/recommend', 'PUT', '编辑推荐团课', 1, 'system', 'system', NOW(), NOW()),
('团课推荐删除', 'business:groupCourseRecommend:delete', '/api/groupCourse/recommend', 'DELETE', '删除推荐团课', 1, 'system', 'system', NOW(), NOW());
-- ============================================
-- 团课预约管理权限
-- ============================================
INSERT INTO sys_permission (permission_name, permission_code, resource, action, description, status, create_by, update_by, created_at, updated_at) VALUES
('团课预约查看', 'business:groupCourseBooking:view', '/api/groupCourse/bookings', 'GET', '查看团课预约记录', 1, 'system', 'system', NOW(), NOW()),
('团课预约创建', 'business:groupCourseBooking:create', '/api/groupCourse/book', 'POST', '预约团课', 1, 'system', 'system', NOW(), NOW()),
('团课预约取消', 'business:groupCourseBooking:cancel', '/api/groupCourse/booking/cancel', 'POST', '取消团课预约', 1, 'system', 'system', NOW(), NOW());
-- ============================================
-- 签到管理权限
-- ============================================
INSERT INTO sys_permission (permission_name, permission_code, resource, action, description, status, create_by, update_by, created_at, updated_at) VALUES
('签到查看', 'business:checkIn:view', '/api/checkIn/records', 'GET', '查看签到记录', 1, 'system', 'system', NOW(), NOW()),
('签到操作', 'business:checkIn:create', '/api/checkIn', 'POST', '执行签到操作', 1, 'system', 'system', NOW(), NOW()),
('签到导出', 'business:checkIn:export', '/api/checkIn/records/export', 'GET', '导出签到记录', 1, 'system', 'system', NOW(), NOW());
-- ============================================
-- 数据统计权限
-- ============================================
INSERT INTO sys_permission (permission_name, permission_code, resource, action, description, status, create_by, update_by, created_at, updated_at) VALUES
('数据统计查看', 'business:dataCount:view', '/api/datacount', 'GET', '查看数据统计报表', 1, 'system', 'system', NOW(), NOW()),
('数据统计导出', 'business:dataCount:export', '/api/datacount/export', 'GET', '导出统计报表', 1, 'system', 'system', NOW(), NOW());
-- ============================================
-- 员工管理权限
-- ============================================
INSERT INTO sys_permission (permission_name, permission_code, resource, action, description, status, create_by, update_by, created_at, updated_at) VALUES
('员工查看', 'business:employee:view', '/api/employees/page', 'GET', '查看员工列表', 1, 'system', 'system', NOW(), NOW()),
('员工创建', 'business:employee:create', '/api/users', 'POST', '创建员工账号', 1, 'system', 'system', NOW(), NOW()),
('员工编辑', 'business:employee:edit', '/api/users', 'PUT', '编辑员工信息', 1, 'system', 'system', NOW(), NOW()),
('员工删除', 'business:employee:delete', '/api/users', 'DELETE', '删除/禁用员工账号', 1, 'system', 'system', NOW(), NOW()),
('员工分配角色', 'business:employee:assignRole', '/api/users/roles', 'POST', '为员工分配角色', 1, 'system', 'system', NOW(), NOW());
-- ============================================
-- 为超级管理员角色分配所有业务权限
-- ============================================
INSERT INTO sys_role_permission (role_id, permission_id, create_by, update_by, created_at, updated_at)
SELECT 1, id, 'system', 'system', NOW(), NOW()
FROM sys_permission
WHERE permission_code LIKE 'business:%'
AND status = 1
AND id NOT IN (SELECT permission_id FROM sys_role_permission WHERE role_id = 1);
-- ============================================
-- 重置序列值
-- ============================================
SELECT setval('sys_permission_id_seq', (SELECT COALESCE(MAX(id), 1) FROM sys_permission));
SELECT setval('sys_role_permission_id_seq', (SELECT COALESCE(MAX(id), 1) FROM sys_role_permission));
@@ -1,93 +0,0 @@
-- ============================================================
-- V23: 教练账号测试数据
-- 描述: 创建教练角色、教练用户及相关团课测试数据
-- 日期: 2026-07-14
-- ============================================================
-- ============================================================
-- 1. 新增教练专属权限
-- 教练只能查看自己教授的团课/预约/签到信息,不能修改数据库
-- ============================================================
INSERT INTO sys_permission (permission_name, permission_code, resource, action, description, status, create_by, update_by, created_at, updated_at) VALUES
('查看自己的团课', 'coach:course:view', '/api/coach/courses', 'GET', '查看教练自己教授的团课列表及详情', 1, 'system', 'system', NOW(), NOW()),
('查看自己团课的预约', 'coach:booking:view', '/api/coach/bookings', 'GET', '查看教练自己团课的会员预约记录', 1, 'system', 'system', NOW(), NOW()),
('查看自己团课的签到', 'coach:signIn:view', '/api/coach/signins', 'GET', '查看教练自己团课的会员签到记录', 1, 'system', 'system', NOW(), NOW()),
('教练执行签到', 'coach:signIn:create', '/api/coach/signins', 'POST', '教练为自己团课的会员执行签到操作', 1, 'system', 'system', NOW(), NOW())
ON CONFLICT (permission_code) DO NOTHING;
-- ============================================================
-- 2. 教练角色
-- ============================================================
INSERT INTO sys_role (id, role_name, role_key, role_sort, status, create_by, update_by, created_at, updated_at)
VALUES (5, '教练', 'coach', 5, 1, 'system', 'system', NOW(), NOW())
ON CONFLICT (role_key) DO NOTHING;
-- ============================================================
-- 3. 教练用户(密码: Test@123
-- ============================================================
INSERT INTO sys_user (id, username, password, email, phone, nickname, status, create_by, update_by, created_at, updated_at)
VALUES (20, 'coach', '$2a$12$nZ1EMUpZQljbnEdIKzH72eHlDJKUmHmHppnTTVth/SlHs5VpSAr8C', 'coach@novalon.com', '13900000001', '张教练', 1, 'system', 'system', NOW(), NOW())
ON CONFLICT (username) DO NOTHING;
-- ============================================================
-- 4. 教练角色关联
-- ============================================================
INSERT INTO user_role (user_id, role_id, created_by, created_at)
VALUES (20, 5, 'system', NOW())
ON CONFLICT (user_id, role_id) DO NOTHING;
-- ============================================================
-- 5. 为教练角色分配有限权限
-- 教练只能查看自己教授的团课、查看自己团课的预约/签到信息、为自己团课的会员签到
-- 不能对数据库进行写操作(签到属于业务操作,非数据库直接写入)
-- ============================================================
INSERT INTO sys_role_permission (role_id, permission_id, create_by, update_by, created_at, updated_at)
SELECT 5, id, 'system', 'system', NOW(), NOW()
FROM sys_permission
WHERE permission_code IN (
'coach:course:view', -- 查看自己的团课
'coach:booking:view', -- 查看自己团课的预约信息
'coach:signIn:view', -- 查看自己团课的签到信息
'coach:signIn:create', -- 为自己团课的会员签到
'system:notice:view' -- 查看系统公告
)
AND NOT EXISTS (
SELECT 1 FROM sys_role_permission WHERE role_id = 5 AND permission_id = sys_permission.id
);
-- ============================================================
-- 6. 为教练分配今天的测试团课
-- ============================================================
INSERT INTO group_course (course_name, coach_id, course_type, start_time, end_time, max_members, current_members, status, location, description, stored_value_amount, create_by, created_at, updated_at)
VALUES
('核心力量训练', 20, (SELECT id FROM group_course_type WHERE type_name = '核心训练' LIMIT 1),
CURRENT_DATE + TIME '08:00', CURRENT_DATE + TIME '09:00', 15, 3, '0', '健身房B区', '针对核心肌群的专项训练,适合所有水平学员', 50.00, 'system', NOW(), NOW()),
('瑜伽入门', 20, (SELECT id FROM group_course_type WHERE type_name = '瑜伽入门' LIMIT 1),
CURRENT_DATE + TIME '10:00', CURRENT_DATE + TIME '11:00', 12, 5, '0', '瑜伽教室', '基础的瑜伽体式教学,新课上线欢迎参加', 50.00, 'system', NOW(), NOW()),
('动感单车', 20, (SELECT id FROM group_course_type WHERE type_name = '动感单车' LIMIT 1),
CURRENT_DATE + TIME '14:00', CURRENT_DATE + TIME '15:00', 20, 8, '0', '单车房', '高强度燃脂骑行,动感音乐带你飞', 50.00, 'system', NOW(), NOW()),
('晚间普拉提', 20, (SELECT id FROM group_course_type WHERE type_name = '普拉提' LIMIT 1),
CURRENT_DATE + TIME '18:00', CURRENT_DATE + TIME '19:00', 10, 2, '0', '普拉提教室', '注重核心力量和身体控制,放松一天疲劳', 50.00, 'system', NOW(), NOW());
-- ============================================================
-- 7. 为教练创建一个未来的团课(方便测试时间表)
-- ============================================================
INSERT INTO group_course (course_name, coach_id, course_type, start_time, end_time, max_members, current_members, status, location, description, stored_value_amount, create_by, created_at, updated_at)
VALUES
('HIIT燃脂训练', 20, (SELECT id FROM group_course_type WHERE type_name = 'HIIT训练' LIMIT 1),
CURRENT_DATE + INTERVAL '1 day' + TIME '08:00', CURRENT_DATE + INTERVAL '1 day' + TIME '09:00',
15, 0, '0', '综合训练区', '高强度间歇训练,挑战心肺极限', 50.00, 'system', NOW(), NOW()),
('周末瑜伽', 20, (SELECT id FROM group_course_type WHERE type_name = '瑜伽进阶' LIMIT 1),
CURRENT_DATE + INTERVAL '3 days' + TIME '09:00', CURRENT_DATE + INTERVAL '3 days' + TIME '10:30',
12, 0, '0', '瑜伽教室', '针对有基础的进阶瑜伽课程', 50.00, 'system', NOW(), NOW());
-- ============================================================
-- 8. 重置序列值
-- ============================================================
SELECT setval('sys_role_id_seq', GREATEST((SELECT COALESCE(MAX(id), 0) FROM sys_role), 5));
SELECT setval('sys_user_id_seq', GREATEST((SELECT COALESCE(MAX(id), 0) FROM sys_user), 20));
SELECT setval('group_course_id_seq', (SELECT COALESCE(MAX(id), 0) FROM group_course));
@@ -1,50 +0,0 @@
-- ============================================================
-- V24: 新增第二个测试教练账号(李教练)
-- 描述:
-- 1. 新增测试教练用户 coachli(李教练)
-- 2. 为李教练分配教练角色(继承教练的有限权限)
-- 3. 为李教练分配未来一周的测试团课
-- 日期: 2026-07-14
-- ============================================================
-- ============================================================
-- 1. 第二个测试教练账号(密码: Test@123)
-- ============================================================
INSERT INTO sys_user (id, username, password, email, phone, nickname, status, create_by, update_by, created_at, updated_at)
VALUES (21, 'coachli', '$2a$12$nZ1EMUpZQljbnEdIKzH72eHlDJKUmHmHppnTTVth/SlHs5VpSAr8C', 'coachli@novalon.com', '13900000002', '李教练', 1, 'system', 'system', NOW(), NOW())
ON CONFLICT (username) DO NOTHING;
-- ============================================================
-- 2. 为李教练分配教练角色(role_id=5)
-- 继承教练角色的所有有限权限
-- ============================================================
INSERT INTO user_role (user_id, role_id, created_by, created_at)
VALUES (21, 5, 'system', NOW())
ON CONFLICT (user_id, role_id) DO NOTHING;
-- ============================================================
-- 3. 为李教练分配测试团课(未来一周的课程)
-- ============================================================
INSERT INTO group_course (course_name, coach_id, course_type, start_time, end_time, max_members, current_members, status, location, description, stored_value_amount, create_by, created_at, updated_at)
VALUES
('入门瑜伽', 21, (SELECT id FROM group_course_type WHERE type_name = '瑜伽入门' LIMIT 1),
CURRENT_DATE + INTERVAL '2 days' + TIME '09:00', CURRENT_DATE + INTERVAL '2 days' + TIME '10:00',
15, 0, '0', '瑜伽教室', '适合零基础学员的入门瑜伽课程', 50.00, 'system', NOW(), NOW()),
('燃脂搏击', 21, (SELECT id FROM group_course_type WHERE type_name = '动感单车' LIMIT 1),
CURRENT_DATE + INTERVAL '2 days' + TIME '15:00', CURRENT_DATE + INTERVAL '2 days' + TIME '16:00',
20, 0, '0', '综合训练区', '高强度搏击操,燃烧卡路里', 50.00, 'system', NOW(), NOW()),
('肩颈理疗', 21, (SELECT id FROM group_course_type WHERE type_name = '普拉提' LIMIT 1),
CURRENT_DATE + INTERVAL '4 days' + TIME '10:00', CURRENT_DATE + INTERVAL '4 days' + TIME '11:00',
12, 0, '0', '普拉提教室', '针对久坐人群的肩颈放松课程', 50.00, 'system', NOW(), NOW()),
('晨间有氧', 21, (SELECT id FROM group_course_type WHERE type_name = 'HIIT训练' LIMIT 1),
CURRENT_DATE + INTERVAL '5 days' + TIME '07:00', CURRENT_DATE + INTERVAL '5 days' + TIME '08:00',
20, 0, '0', '有氧区', '清晨燃脂有氧训练,开启活力一天', 50.00, 'system', NOW(), NOW());
-- ============================================================
-- 4. 重置序列值
-- ============================================================
SELECT setval('sys_user_id_seq', GREATEST((SELECT COALESCE(MAX(id), 0) FROM sys_user), 21));
SELECT setval('group_course_id_seq', (SELECT COALESCE(MAX(id), 0) FROM group_course));
@@ -1,33 +0,0 @@
-- 支付订单表
CREATE TABLE IF NOT EXISTS payment_order (
id BIGSERIAL PRIMARY KEY,
order_no VARCHAR(64) NOT NULL UNIQUE,
member_id BIGINT,
order_type VARCHAR(32),
goods_desc VARCHAR(256),
trans_amt DECIMAL(12, 2),
trade_type VARCHAR(32),
pay_status VARCHAR(16) DEFAULT 'PENDING',
huifu_id VARCHAR(64),
req_seq_id VARCHAR(64),
req_date VARCHAR(16),
hf_seq_id VARCHAR(64),
pay_info TEXT,
qr_code TEXT,
pay_url TEXT,
remark VARCHAR(512),
notify_url VARCHAR(512),
pay_time TIMESTAMP,
expire_time TIMESTAMP,
error_code VARCHAR(64),
error_msg VARCHAR(512),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
deleted_at TIMESTAMP
);
CREATE INDEX IF NOT EXISTS idx_payment_order_order_no ON payment_order(order_no);
CREATE INDEX IF NOT EXISTS idx_payment_order_member_id ON payment_order(member_id);
CREATE INDEX IF NOT EXISTS idx_payment_order_req_seq_id ON payment_order(req_seq_id);
CREATE INDEX IF NOT EXISTS idx_payment_order_status ON payment_order(pay_status);
CREATE INDEX IF NOT EXISTS idx_payment_order_expire_time ON payment_order(expire_time);
@@ -1 +0,0 @@
ALTER TABLE payment_order ADD COLUMN IF NOT EXISTS party_order_id VARCHAR(64);
@@ -1,47 +0,0 @@
-- ============================================
-- V28: 新增业务模块菜单
-- 描述: 为团课管理、团课类型、团课标签、团课推荐创建菜单项
-- ============================================
-- 团课管理一级菜单(目录)
INSERT INTO sys_menu (id, menu_name, parent_id, order_num, menu_type, perms, component, status, created_at, updated_at) VALUES
(400, '团课管理', 0, 4, 'M', NULL, NULL, 1, NOW(), NOW());
-- 团课管理子菜单(页面)
INSERT INTO sys_menu (id, menu_name, parent_id, order_num, menu_type, perms, component, status, created_at, updated_at) VALUES
(401, '团课管理', 400, 1, 'C', 'business:groupCourse:list', 'gymCourse/course/index', 1, NOW(), NOW()),
(402, '团课类型', 400, 2, 'C', 'business:groupCourseType:list', 'gymCourse/type/index', 1, NOW(), NOW()),
(403, '类型标签', 400, 3, 'C', 'business:groupCourseLabel:list', 'gymCourse/label/index', 1, NOW(), NOW()),
(404, '团课推荐', 400, 4, 'C', 'business:groupCourseRecommend:list', 'gymCourse/recommend/index', 1, NOW(), NOW());
-- 团课管理按钮权限
INSERT INTO sys_menu (id, menu_name, parent_id, order_num, menu_type, perms, component, status, created_at, updated_at) VALUES
(4011, '团课查询', 401, 1, 'F', 'business:groupCourse:query', NULL, 1, NOW(), NOW()),
(4012, '团课新增', 401, 2, 'F', 'business:groupCourse:add', NULL, 1, NOW(), NOW()),
(4013, '团课修改', 401, 3, 'F', 'business:groupCourse:edit', NULL, 1, NOW(), NOW()),
(4014, '团课删除', 401, 4, 'F', 'business:groupCourse:remove', NULL, 1, NOW(), NOW()),
(4015, '团课取消', 401, 5, 'F', 'business:groupCourse:cancel', NULL, 1, NOW(), NOW());
-- 团课类型按钮权限
INSERT INTO sys_menu (id, menu_name, parent_id, order_num, menu_type, perms, component, status, created_at, updated_at) VALUES
(4021, '类型查询', 402, 1, 'F', 'business:groupCourseType:query', NULL, 1, NOW(), NOW()),
(4022, '类型新增', 402, 2, 'F', 'business:groupCourseType:add', NULL, 1, NOW(), NOW()),
(4023, '类型修改', 402, 3, 'F', 'business:groupCourseType:edit', NULL, 1, NOW(), NOW()),
(4024, '类型删除', 402, 4, 'F', 'business:groupCourseType:remove', NULL, 1, NOW(), NOW());
-- 团课标签按钮权限
INSERT INTO sys_menu (id, menu_name, parent_id, order_num, menu_type, perms, component, status, created_at, updated_at) VALUES
(4031, '标签查询', 403, 1, 'F', 'business:groupCourseLabel:query', NULL, 1, NOW(), NOW()),
(4032, '标签新增', 403, 2, 'F', 'business:groupCourseLabel:add', NULL, 1, NOW(), NOW()),
(4033, '标签修改', 403, 3, 'F', 'business:groupCourseLabel:edit', NULL, 1, NOW(), NOW()),
(4034, '标签删除', 403, 4, 'F', 'business:groupCourseLabel:remove', NULL, 1, NOW(), NOW());
-- 团课推荐按钮权限
INSERT INTO sys_menu (id, menu_name, parent_id, order_num, menu_type, perms, component, status, created_at, updated_at) VALUES
(4041, '推荐查询', 404, 1, 'F', 'business:groupCourseRecommend:query', NULL, 1, NOW(), NOW()),
(4042, '推荐新增', 404, 2, 'F', 'business:groupCourseRecommend:add', NULL, 1, NOW(), NOW()),
(4043, '推荐修改', 404, 3, 'F', 'business:groupCourseRecommend:edit', NULL, 1, NOW(), NOW()),
(4044, '推荐删除', 404, 4, 'F', 'business:groupCourseRecommend:remove', NULL, 1, NOW(), NOW());
-- 重置菜单序列
SELECT setval('sys_menu_id_seq', (SELECT COALESCE(MAX(id), 1) FROM sys_menu));
@@ -1,23 +0,0 @@
-- ============================================
-- V29: 新增会员管理菜单
-- 描述: 为会员管理功能创建菜单项
-- ============================================
-- 会员管理一级菜单(目录)
INSERT INTO sys_menu (id, menu_name, parent_id, order_num, menu_type, perms, component, status, created_at, updated_at) VALUES
(500, '会员管理', 0, 5, 'M', NULL, NULL, 1, NOW(), NOW());
-- 会员管理子菜单(页面)
INSERT INTO sys_menu (id, menu_name, parent_id, order_num, menu_type, perms, component, status, created_at, updated_at) VALUES
(501, '会员管理', 500, 1, 'C', 'business:member:list', 'member/member/index', 1, NOW(), NOW());
-- 会员管理按钮权限
INSERT INTO sys_menu (id, menu_name, parent_id, order_num, menu_type, perms, component, status, created_at, updated_at) VALUES
(5011, '会员查询', 501, 1, 'F', 'business:member:query', NULL, 1, NOW(), NOW()),
(5012, '会员新增', 501, 2, 'F', 'business:member:add', NULL, 1, NOW(), NOW()),
(5013, '会员修改', 501, 3, 'F', 'business:member:edit', NULL, 1, NOW(), NOW()),
(5014, '会员删除', 501, 4, 'F', 'business:member:remove', NULL, 1, NOW(), NOW()),
(5015, '会员详情', 501, 5, 'F', 'business:member:detail', NULL, 1, NOW(), NOW());
-- 重置菜单序列
SELECT setval('sys_menu_id_seq', (SELECT COALESCE(MAX(id), 1) FROM sys_menu));
@@ -1,6 +1,8 @@
-- ============================================
-- Novalon管理系统索引优化脚本
-- 版本: V3
-- 描述: 为表创建必要的索引以提升查询性能
-- 版本: V2
-- 描述: 为核心系统表创建必要的索引以提升查询性能
-- ============================================
-- ============================================
-- 用户与角色表索引
@@ -1,234 +0,0 @@
-- Novalon管理系统初始数据脚本
-- 版本: V2
-- 描述: 插入所有必要的初始数据(合并版)
-- ============================================
-- 角色数据
-- ============================================
INSERT INTO sys_role (id, role_name, role_key, role_sort, status, create_by, update_by, created_at, updated_at)
VALUES
(1, '超级管理员', 'admin', 1, 1, 'system', 'system', NOW(), NOW()),
(2, '测试管理员', 'test_admin', 2, 1, 'system', 'system', NOW(), NOW()),
(3, '普通用户', 'normal_user', 3, 1, 'system', 'system', NOW(), NOW()),
(4, '访客', 'guest', 4, 1, 'system', 'system', NOW(), NOW());
SELECT setval('sys_role_id_seq', 4);
-- ============================================
-- 用户数据
-- ============================================
-- 密码均为: Test@123 (BCrypt哈希)
INSERT INTO sys_user (id, username, password, email, phone, nickname, status, create_by, update_by, created_at, updated_at)
VALUES
(1, 'admin', '$2a$12$nZ1EMUpZQljbnEdIKzH72eHlDJKUmHmHppnTTVth/SlHs5VpSAr8C', 'admin@novalon.com', '13800138000', '超级管理员', 1, 'system', 'system', NOW(), NOW()),
(2, 'user', '$2a$12$nZ1EMUpZQljbnEdIKzH72eHlDJKUmHmHppnTTVth/SlHs5VpSAr8C', 'user@novalon.com', '13800138001', '普通用户', 1, 'system', 'system', NOW(), NOW()),
(10, 'e2e_test_user', '$2a$12$nZ1EMUpZQljbnEdIKzH72eHlDJKUmHmHppnTTVth/SlHs5VpSAr8C', 'e2e@test.com', '13900139000', 'E2E测试用户', 1, 'system', 'system', NOW(), NOW())
ON CONFLICT (username) DO UPDATE SET
password = EXCLUDED.password,
status = EXCLUDED.status;
SELECT setval('sys_user_id_seq', 10);
-- ============================================
-- 用户角色关联
-- ============================================
-- 为admin用户分配超级管理员角色
INSERT INTO user_role (user_id, role_id, created_by, created_at)
VALUES
(1, 1, 'system', NOW()),
(2, 3, 'system', NOW()),
(10, 1, 'system', NOW())
ON CONFLICT (user_id, role_id) DO NOTHING;
-- ============================================
-- 权限数据
-- ============================================
INSERT INTO sys_permission (permission_name, permission_code, resource, action, description, status, create_by, update_by, created_at, updated_at) VALUES
('用户查看', 'system:user:view', '/api/users', 'GET', '查看用户列表', 1, 'system', 'system', NOW(), NOW()),
('用户创建', 'system:user:create', '/api/users', 'POST', '创建用户', 1, 'system', 'system', NOW(), NOW()),
('用户编辑', 'system:user:edit', '/api/users', 'PUT', '编辑用户', 1, 'system', 'system', NOW(), NOW()),
('用户删除', 'system:user:delete', '/api/users', 'DELETE', '删除用户', 1, 'system', 'system', NOW(), NOW()),
('角色查看', 'system:role:view', '/api/roles', 'GET', '查看角色列表', 1, 'system', 'system', NOW(), NOW()),
('角色创建', 'system:role:create', '/api/roles', 'POST', '创建角色', 1, 'system', 'system', NOW(), NOW()),
('角色编辑', 'system:role:edit', '/api/roles', 'PUT', '编辑角色', 1, 'system', 'system', NOW(), NOW()),
('角色删除', 'system:role:delete', '/api/roles', 'DELETE', '删除角色', 1, 'system', 'system', NOW(), NOW()),
('角色分配权限', 'system:role:assign', '/api/roles/*/permissions', 'POST', '为角色分配权限', 1, 'system', 'system', NOW(), NOW()),
('权限查看', 'system:permission:view', '/api/permissions', 'GET', '查看权限列表', 1, 'system', 'system', NOW(), NOW()),
('权限创建', 'system:permission:create', '/api/permissions', 'POST', '创建权限', 1, 'system', 'system', NOW(), NOW()),
('权限编辑', 'system:permission:edit', '/api/permissions', 'PUT', '编辑权限', 1, 'system', 'system', NOW(), NOW()),
('权限删除', 'system:permission:delete', '/api/permissions', 'DELETE', '删除权限', 1, 'system', 'system', NOW(), NOW()),
('菜单查看', 'system:menu:view', '/api/menus', 'GET', '查看菜单列表', 1, 'system', 'system', NOW(), NOW()),
('菜单创建', 'system:menu:create', '/api/menus', 'POST', '创建菜单', 1, 'system', 'system', NOW(), NOW()),
('菜单编辑', 'system:menu:edit', '/api/menus', 'PUT', '编辑菜单', 1, 'system', 'system', NOW(), NOW()),
('菜单删除', 'system:menu:delete', '/api/menus', 'DELETE', '删除菜单', 1, 'system', 'system', NOW(), NOW()),
('字典查看', 'system:dict:view', '/api/dict', 'GET', '查看字典列表', 1, 'system', 'system', NOW(), NOW()),
('字典创建', 'system:dict:create', '/api/dict', 'POST', '创建字典', 1, 'system', 'system', NOW(), NOW()),
('字典编辑', 'system:dict:edit', '/api/dict', 'PUT', '编辑字典', 1, 'system', 'system', NOW(), NOW()),
('字典删除', 'system:dict:delete', '/api/dict', 'DELETE', '删除字典', 1, 'system', 'system', NOW(), NOW()),
('配置查看', 'system:config:view', '/api/config', 'GET', '查看系统配置', 1, 'system', 'system', NOW(), NOW()),
('配置创建', 'system:config:create', '/api/config', 'POST', '创建系统配置', 1, 'system', 'system', NOW(), NOW()),
('配置编辑', 'system:config:edit', '/api/config', 'PUT', '编辑系统配置', 1, 'system', 'system', NOW(), NOW()),
('配置删除', 'system:config:delete', '/api/config', 'DELETE', '删除系统配置', 1, 'system', 'system', NOW(), NOW()),
('日志查看', 'system:log:view', '/api/logs', 'GET', '查看日志', 1, 'system', 'system', NOW(), NOW()),
('文件上传', 'system:file:upload', '/api/files/upload', 'POST', '上传文件', 1, 'system', 'system', NOW(), NOW()),
('文件下载', 'system:file:download', '/api/files/download', 'GET', '下载文件', 1, 'system', 'system', NOW(), NOW()),
('文件删除', 'system:file:delete', '/api/files', 'DELETE', '删除文件', 1, 'system', 'system', NOW(), NOW()),
('公告查看', 'system:notice:view', '/api/notices', 'GET', '查看公告', 1, 'system', 'system', NOW(), NOW()),
('公告创建', 'system:notice:create', '/api/notices', 'POST', '创建公告', 1, 'system', 'system', NOW(), NOW()),
('公告编辑', 'system:notice:edit', '/api/notices', 'PUT', '编辑公告', 1, 'system', 'system', NOW(), NOW()),
('公告删除', 'system:notice:delete', '/api/notices', 'DELETE', '删除公告', 1, 'system', 'system', NOW(), NOW());
-- 为管理员角色分配所有权限
INSERT INTO sys_role_permission (role_id, permission_id, create_by, update_by, created_at, updated_at)
SELECT 1, id, 'system', 'system', NOW(), NOW() FROM sys_permission WHERE status = 1;
-- ============================================
-- 菜单数据
-- ============================================
-- 一级菜单
INSERT INTO sys_menu (id, menu_name, parent_id, order_num, menu_type, perms, component, status, created_at, updated_at) VALUES
(1, '系统管理', 0, 1, 'M', NULL, NULL, 1, NOW(), NOW()),
(2, '审计日志', 0, 2, 'M', NULL, NULL, 1, NOW(), NOW()),
(3, '系统监控', 0, 3, 'M', NULL, NULL, 1, NOW(), NOW());
-- 系统管理子菜单
INSERT INTO sys_menu (id, menu_name, parent_id, order_num, menu_type, perms, component, status, created_at, updated_at) VALUES
(11, '用户管理', 1, 1, 'C', 'system:user:list', 'system/user/index', 1, NOW(), NOW()),
(12, '角色管理', 1, 2, 'C', 'system:role:list', 'system/role/index', 1, NOW(), NOW()),
(13, '菜单管理', 1, 3, 'C', 'system:menu:list', 'system/menu/index', 1, NOW(), NOW()),
(14, '部门管理', 1, 4, 'C', 'system:dept:list', 'system/dept/index', 1, NOW(), NOW()),
(15, '字典管理', 1, 5, 'C', 'system:dict:list', 'system/dict/index', 1, NOW(), NOW()),
(16, '参数管理', 1, 6, 'C', 'system:config:list', 'system/config/index', 1, NOW(), NOW()),
(17, '通知公告', 1, 7, 'C', 'system:notice:list', 'system/notice/index', 1, NOW(), NOW()),
(18, '文件管理', 1, 8, 'C', 'system:file:list', 'system/file/index', 1, NOW(), NOW());
-- 用户管理按钮权限
INSERT INTO sys_menu (id, menu_name, parent_id, order_num, menu_type, perms, component, status, created_at, updated_at) VALUES
(111, '用户查询', 11, 1, 'F', 'system:user:query', NULL, 1, NOW(), NOW()),
(112, '用户新增', 11, 2, 'F', 'system:user:add', NULL, 1, NOW(), NOW()),
(113, '用户修改', 11, 3, 'F', 'system:user:edit', NULL, 1, NOW(), NOW()),
(114, '用户删除', 11, 4, 'F', 'system:user:remove', NULL, 1, NOW(), NOW()),
(115, '用户导出', 11, 5, 'F', 'system:user:export', NULL, 1, NOW(), NOW()),
(116, '用户导入', 11, 6, 'F', 'system:user:import', NULL, 1, NOW(), NOW()),
(117, '重置密码', 11, 7, 'F', 'system:user:resetPwd', NULL, 1, NOW(), NOW());
-- 角色管理按钮权限
INSERT INTO sys_menu (id, menu_name, parent_id, order_num, menu_type, perms, component, status, created_at, updated_at) VALUES
(121, '角色查询', 12, 1, 'F', 'system:role:query', NULL, 1, NOW(), NOW()),
(122, '角色新增', 12, 2, 'F', 'system:role:add', NULL, 1, NOW(), NOW()),
(123, '角色修改', 12, 3, 'F', 'system:role:edit', NULL, 1, NOW(), NOW()),
(124, '角色删除', 12, 4, 'F', 'system:role:remove', NULL, 1, NOW(), NOW()),
(125, '角色导出', 12, 5, 'F', 'system:role:export', NULL, 1, NOW(), NOW());
-- 菜单管理按钮权限
INSERT INTO sys_menu (id, menu_name, parent_id, order_num, menu_type, perms, component, status, created_at, updated_at) VALUES
(131, '菜单查询', 13, 1, 'F', 'system:menu:query', NULL, 1, NOW(), NOW()),
(132, '菜单新增', 13, 2, 'F', 'system:menu:add', NULL, 1, NOW(), NOW()),
(133, '菜单修改', 13, 3, 'F', 'system:menu:edit', NULL, 1, NOW(), NOW()),
(134, '菜单删除', 13, 4, 'F', 'system:menu:remove', NULL, 1, NOW(), NOW());
-- 审计日志子菜单
INSERT INTO sys_menu (id, menu_name, parent_id, order_num, menu_type, perms, component, status, created_at, updated_at) VALUES
(21, '操作日志', 2, 1, 'C', 'audit:operation:list', 'audit/operation/index', 1, NOW(), NOW()),
(22, '登录日志', 2, 2, 'C', 'audit:login:list', 'audit/login/index', 1, NOW(), NOW()),
(23, '异常日志', 2, 3, 'C', 'audit:exception:list', 'audit/exception/index', 1, NOW(), NOW());
-- 操作日志按钮权限
INSERT INTO sys_menu (id, menu_name, parent_id, order_num, menu_type, perms, component, status, created_at, updated_at) VALUES
(211, '操作查询', 21, 1, 'F', 'audit:operation:query', NULL, 1, NOW(), NOW()),
(212, '操作删除', 21, 2, 'F', 'audit:operation:remove', NULL, 1, NOW(), NOW()),
(213, '操作导出', 21, 3, 'F', 'audit:operation:export', NULL, 1, NOW(), NOW());
-- 登录日志按钮权限
INSERT INTO sys_menu (id, menu_name, parent_id, order_num, menu_type, perms, component, status, created_at, updated_at) VALUES
(221, '登录查询', 22, 1, 'F', 'audit:login:query', NULL, 1, NOW(), NOW()),
(222, '登录删除', 22, 2, 'F', 'audit:login:remove', NULL, 1, NOW(), NOW()),
(223, '登录导出', 22, 3, 'F', 'audit:login:export', NULL, 1, NOW(), NOW());
-- 异常日志按钮权限
INSERT INTO sys_menu (id, menu_name, parent_id, order_num, menu_type, perms, component, status, created_at, updated_at) VALUES
(231, '异常查询', 23, 1, 'F', 'audit:exception:query', NULL, 1, NOW(), NOW()),
(232, '异常删除', 23, 2, 'F', 'audit:exception:remove', NULL, 1, NOW(), NOW()),
(233, '异常导出', 23, 3, 'F', 'audit:exception:export', NULL, 1, NOW(), NOW());
-- 系统监控子菜单
INSERT INTO sys_menu (id, menu_name, parent_id, order_num, menu_type, perms, component, status, created_at, updated_at) VALUES
(31, '在线用户', 3, 1, 'C', 'monitor:online:list', 'monitor/online/index', 1, NOW(), NOW()),
(32, '定时任务', 3, 2, 'C', 'monitor:job:list', 'monitor/job/index', 1, NOW(), NOW()),
(33, '数据监控', 3, 3, 'C', 'monitor:data:list', 'monitor/data/index', 1, NOW(), NOW()),
(34, '服务监控', 3, 4, 'C', 'monitor:server:list', 'monitor/server/index', 1, NOW(), NOW()),
(35, '缓存监控', 3, 5, 'C', 'monitor:cache:list', 'monitor/cache/index', 1, NOW(), NOW());
-- 在线用户按钮权限
INSERT INTO sys_menu (id, menu_name, parent_id, order_num, menu_type, perms, component, status, created_at, updated_at) VALUES
(311, '在线查询', 31, 1, 'F', 'monitor:online:query', NULL, 1, NOW(), NOW()),
(312, '在线强退', 31, 2, 'F', 'monitor:online:forceLogout', NULL, 1, NOW(), NOW());
-- 定时任务按钮权限
INSERT INTO sys_menu (id, menu_name, parent_id, order_num, menu_type, perms, component, status, created_at, updated_at) VALUES
(321, '任务查询', 32, 1, 'F', 'monitor:job:query', NULL, 1, NOW(), NOW()),
(322, '任务新增', 32, 2, 'F', 'monitor:job:add', NULL, 1, NOW(), NOW()),
(323, '任务修改', 32, 3, 'F', 'monitor:job:edit', NULL, 1, NOW(), NOW()),
(324, '任务删除', 32, 4, 'F', 'monitor:job:remove', NULL, 1, NOW(), NOW()),
(325, '任务执行', 32, 5, 'F', 'monitor:job:execute', NULL, 1, NOW(), NOW());
SELECT setval('sys_menu_id_seq', 400);
-- ============================================
-- 字典数据
-- ============================================
-- 字典类型
INSERT INTO sys_dict_type (dict_name, dict_type, status, remark, create_by, update_by, created_at, updated_at)
VALUES
('用户状态', 'user_status', '0', '用户状态列表', 'system', 'system', NOW(), NOW()),
('菜单状态', 'menu_status', '0', '菜单状态列表', 'system', 'system', NOW(), NOW()),
('角色状态', 'role_status', '0', '角色状态列表', 'system', 'system', NOW(), NOW()),
('系统开关', 'sys_normal_disable', '0', '系统开关列表', 'system', 'system', NOW(), NOW())
ON CONFLICT (dict_type) DO NOTHING;
-- 字典数据
INSERT INTO sys_dict_data (dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, status, create_by, update_by, created_at, updated_at)
VALUES
-- 用户状态
(1, '正常', '1', 'user_status', '', 'primary', 'Y', '0', 'system', 'system', NOW(), NOW()),
(2, '停用', '0', 'user_status', '', 'danger', 'N', '0', 'system', 'system', NOW(), NOW()),
-- 菜单状态
(1, '正常', '0', 'menu_status', '', 'primary', 'Y', '0', 'system', 'system', NOW(), NOW()),
(2, '停用', '1', 'menu_status', '', 'danger', 'N', '0', 'system', 'system', NOW(), NOW()),
-- 角色状态
(1, '正常', '0', 'role_status', '', 'primary', 'Y', '0', 'system', 'system', NOW(), NOW()),
(2, '停用', '1', 'role_status', '', 'danger', 'N', '0', 'system', 'system', NOW(), NOW()),
-- 系统开关
(1, '正常', '0', 'sys_normal_disable', '', 'primary', 'Y', '0', 'system', 'system', NOW(), NOW()),
(2, '停用', '1', 'sys_normal_disable', '', 'danger', 'N', '0', 'system', 'system', NOW(), NOW());
-- ============================================
-- 系统配置
-- ============================================
INSERT INTO sys_config (config_name, config_key, config_value, config_type, create_by, update_by, created_at, updated_at)
VALUES
('用户管理-用户初始密码', 'sys.user.initPassword', '123456', 'Y', 'system', 'system', NOW(), NOW()),
('主框架页-默认皮肤样式名称', 'sys.index.skinName', 'skin-blue', 'Y', 'system', 'system', NOW(), NOW()),
('用户自助-验证码开关', 'sys.account.captchaEnabled', 'true', 'Y', 'system', 'system', NOW(), NOW()),
('用户自助-是否开启用户注册功能', 'sys.account.registerUser', 'false', 'Y', 'system', 'system', NOW(), NOW()),
('账号自助-密码验证码', 'sys.account.pwdCaptchaEnabled', 'true', 'Y', 'system', 'system', NOW(), NOW()),
('团课-取消预约免手续费次数', 'group_course.cancel_free_limit', '3', 'Y', 'system', 'system', NOW(), NOW())
ON CONFLICT (config_key) DO NOTHING;
-- ============================================
-- 重置序列值
-- ============================================
SELECT setval('sys_dict_type_id_seq', (SELECT COALESCE(MAX(id), 1) FROM sys_dict_type));
SELECT setval('sys_dict_data_id_seq', (SELECT COALESCE(MAX(id), 1) FROM sys_dict_data));
SELECT setval('sys_config_id_seq', (SELECT COALESCE(MAX(id), 1) FROM sys_config));
SELECT setval('sys_permission_id_seq', (SELECT COALESCE(MAX(id), 1) FROM sys_permission));
SELECT setval('sys_role_permission_id_seq', (SELECT COALESCE(MAX(id), 1) FROM sys_role_permission));
SELECT setval('user_role_id_seq', (SELECT COALESCE(MAX(id), 1) FROM user_role));
@@ -1,22 +0,0 @@
-- ============================================
-- V30: 新增会员卡管理菜单
-- 描述: 为会员卡管理功能创建菜单项
-- ============================================
-- 会员卡管理一级菜单(目录)
INSERT INTO sys_menu (id, menu_name, parent_id, order_num, menu_type, perms, component, status, created_at, updated_at) VALUES
(502, '会员卡管理', 0, 6, 'M', NULL, NULL, 1, NOW(), NOW());
-- 会员卡管理子菜单(页面)
INSERT INTO sys_menu (id, menu_name, parent_id, order_num, menu_type, perms, component, status, created_at, updated_at) VALUES
(503, '会员卡管理', 502, 1, 'C', 'business:memberCard:list', 'member/card/index', 1, NOW(), NOW());
-- 会员卡管理按钮权限
INSERT INTO sys_menu (id, menu_name, parent_id, order_num, menu_type, perms, component, status, created_at, updated_at) VALUES
(5031, '会员卡查询', 503, 1, 'F', 'business:memberCard:query', NULL, 1, NOW(), NOW()),
(5032, '会员卡新增', 503, 2, 'F', 'business:memberCard:add', NULL, 1, NOW(), NOW()),
(5033, '会员卡修改', 503, 3, 'F', 'business:memberCard:edit', NULL, 1, NOW(), NOW()),
(5034, '会员卡删除', 503, 4, 'F', 'business:memberCard:remove', NULL, 1, NOW(), NOW());
-- 重置菜单序列
SELECT setval('sys_menu_id_seq', (SELECT COALESCE(MAX(id), 1) FROM sys_menu));
@@ -1,19 +0,0 @@
-- ============================================
-- V31: 新增数据统计菜单
-- 描述: 为数据统计看板功能创建菜单项
-- ============================================
-- 数据统计一级菜单(目录)
INSERT INTO sys_menu (id, menu_name, parent_id, order_num, menu_type, perms, component, status, created_at, updated_at) VALUES
(504, '数据统计', 0, 7, 'M', NULL, NULL, 1, NOW(), NOW());
-- 数据统计子菜单(页面)
INSERT INTO sys_menu (id, menu_name, parent_id, order_num, menu_type, perms, component, status, created_at, updated_at) VALUES
(505, '数据统计看板', 504, 1, 'C', 'business:statistics:view', 'statistics/dashboard/index', 1, NOW(), NOW());
-- 数据统计按钮权限
INSERT INTO sys_menu (id, menu_name, parent_id, order_num, menu_type, perms, component, status, created_at, updated_at) VALUES
(5051, '数据统计导出', 505, 1, 'F', 'business:statistics:export', NULL, 1, NOW(), NOW());
-- 重置菜单序列
SELECT setval('sys_menu_id_seq', (SELECT COALESCE(MAX(id), 1) FROM sys_menu));
@@ -1,8 +0,0 @@
-- ============================================================
-- V32: 将 group_course_booking 表的 member_card_id 改为可空
-- 说明: 预约团课不再需要会员卡,member_card_id 允许为空
-- 日期: 2026-07-14
-- ============================================================
ALTER TABLE group_course_booking
ALTER COLUMN member_card_id DROP NOT NULL;
@@ -1,6 +1,8 @@
-- ============================================
-- Novalon管理系统权限授予脚本
-- 版本: V4
-- 版本: V3
-- 描述: 为novalon用户授予所有表的访问权限
-- ============================================
-- 授予所有表的SELECT, INSERT, UPDATE, DELETE权限
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO novalon;
@@ -1,63 +1,46 @@
-- ============================================
-- 会员相关表
-- 版本: V4
-- 描述: 创建会员、微信用户、会员卡类型、会员卡记录、交易流水、退款申请等表
-- ============================================
-- ============================================
-- 1. member_user 表(会员表)
-- ============================================
-- Step 1: 删除已存在的表(如果需要重建)
-- DROP TABLE IF EXISTS member_user CASCADE;
-- Step 2: 创建 member_user 表
CREATE TABLE IF NOT EXISTS member_user (
-- ========== 主键和基础字段(来自BaseEntity==========
id BIGSERIAL PRIMARY KEY, -- 主键ID,自增
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, -- 创建时间
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, -- 更新时间
id BIGSERIAL PRIMARY KEY,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
-- ========== 会员核心字段 ==========
member_no VARCHAR(50) NOT NULL UNIQUE, -- 会员编号(唯一)
nickname VARCHAR(100), -- 昵称
phone VARCHAR(255), -- 手机号(AES加密存储)
gender INTEGER DEFAULT 0, -- 性别:0-未知,1-男,2-女
birthday DATE, -- 生日
address VARCHAR(500), -- 地址
avatar VARCHAR(500), -- 头像URL
subscribed BOOLEAN DEFAULT FALSE, -- 是否关注服务号
last_login_at TIMESTAMP, -- 最后登录时间
member_no VARCHAR(50) NOT NULL UNIQUE,
nickname VARCHAR(100),
phone VARCHAR(255),
gender INTEGER DEFAULT 0,
birthday DATE,
address VARCHAR(500),
avatar VARCHAR(500),
subscribed BOOLEAN DEFAULT FALSE,
last_login_at TIMESTAMP,
-- ========== 微信相关字段 ==========
union_id VARCHAR(100), -- 微信UnionID(跨应用唯一标识)
miniapp_open_id VARCHAR(100), -- 小程序OpenID
official_open_id VARCHAR(100), -- 服务号OpenID
union_id VARCHAR(100),
miniapp_open_id VARCHAR(100),
official_open_id VARCHAR(100),
-- ========== 软删除字段 ==========
is_deleted BOOLEAN DEFAULT FALSE -- 是否删除(软删除标记)
);
is_deleted BOOLEAN DEFAULT FALSE
);
-- Step 3: 创建索引
-- 会员编号索引(唯一索引,加速查询)
CREATE UNIQUE INDEX IF NOT EXISTS idx_member_user_member_no ON member_user(member_no);
-- UnionID索引(加速跨平台用户查找)
CREATE INDEX IF NOT EXISTS idx_member_user_union_id ON member_user(union_id);
-- 小程序OpenID索引(加速小程序登录查询)
CREATE INDEX IF NOT EXISTS idx_member_user_miniapp_openid ON member_user(miniapp_open_id);
-- 服务号OpenID索引(加速服务号事件处理)
CREATE INDEX IF NOT EXISTS idx_member_user_official_openid ON member_user(official_open_id);
-- 手机号索引(加速手机号查询和去重)
CREATE INDEX IF NOT EXISTS idx_member_user_phone ON member_user(phone);
-- 软删除索引(加速查询未删除的记录)
CREATE INDEX IF NOT EXISTS idx_member_user_is_deleted ON member_user(is_deleted);
-- Step 4: 添加注释
COMMENT ON TABLE member_user IS '会员表';
COMMENT ON COLUMN member_user.id IS '主键ID';
COMMENT ON COLUMN member_user.created_at IS '创建时间';
COMMENT ON COLUMN member_user.updated_at IS '更新时间';
COMMENT ON COLUMN member_user.member_no IS '会员编号(唯一,格式:MEM + 8位随机字符)';
COMMENT ON COLUMN member_user.nickname IS '昵称';
COMMENT ON COLUMN member_user.phone IS '手机号(AES-128-CBC加密存储)';
@@ -67,88 +50,64 @@ COMMENT ON COLUMN member_user.address IS '地址';
COMMENT ON COLUMN member_user.avatar IS '头像URL';
COMMENT ON COLUMN member_user.subscribed IS '是否关注服务号:true-已关注,false-未关注';
COMMENT ON COLUMN member_user.last_login_at IS '最后登录时间';
COMMENT ON COLUMN member_user.union_id IS '微信UnionID(用户在开放平台的唯一标识,跨应用相同)';
COMMENT ON COLUMN member_user.miniapp_open_id IS '小程序OpenID(用户在当前小程序的唯一标识)';
COMMENT ON COLUMN member_user.official_open_id IS '服务号OpenID(用户在当前服务号的唯一标识)';
COMMENT ON COLUMN member_user.is_deleted IS '是否删除(软删除标记):false-正常,true-已删除';
-- ============================================
-- 2. wechat_user 表(微信用户表)
-- ============================================
-- Step 1: 删除已存在的表(如果需要重建)
-- DROP TABLE IF EXISTS wechat_user CASCADE;
-- Step 2: 创建 wechat_user 表
CREATE TABLE IF NOT EXISTS wechat_user (
-- ========== 主键和基础字段(来自BaseEntity==========
id BIGSERIAL PRIMARY KEY, -- 主键ID,自增
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, -- 创建时间
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, -- 更新时间
id BIGSERIAL PRIMARY KEY,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
-- ========== 关联字段 ==========
member_id BIGINT NOT NULL, -- 会员ID(外键)
member_id BIGINT NOT NULL,
-- ========== 微信标识字段 ==========
union_id VARCHAR(100), -- 微信UnionID
miniapp_openid VARCHAR(100), -- 小程序OpenID
mp_openid VARCHAR(100), -- 服务号OpenID
union_id VARCHAR(100),
miniapp_openid VARCHAR(100),
mp_openid VARCHAR(100),
-- ========== 关注状态字段 ==========
is_subscribed BOOLEAN DEFAULT FALSE, -- 是否关注服务号
subscribe_time TIMESTAMP, -- 首次关注时间
unsubscribe_time TIMESTAMP -- 最后一次取消关注时间
);
is_subscribed BOOLEAN DEFAULT FALSE,
subscribe_time TIMESTAMP,
unsubscribe_time TIMESTAMP
);
-- Step 3: 创建外键约束
ALTER TABLE wechat_user
ADD CONSTRAINT fk_wechat_user_member
FOREIGN KEY (member_id) REFERENCES member_user(id) ON DELETE CASCADE;
-- Step 4: 创建索引
-- UnionID索引(加速跨平台用户查找)
CREATE INDEX IF NOT EXISTS idx_wechat_user_union_id ON wechat_user(union_id);
-- 小程序OpenID索引(加速小程序登录查询)
CREATE INDEX IF NOT EXISTS idx_wechat_user_miniapp_openid ON wechat_user(miniapp_openid);
-- 服务号OpenID索引(加速服务号事件处理)
CREATE INDEX IF NOT EXISTS idx_wechat_user_mp_openid ON wechat_user(mp_openid);
-- 会员ID索引(加速关联查询)
CREATE INDEX IF NOT EXISTS idx_wechat_user_member_id ON wechat_user(member_id);
-- Step 5: 添加注释
COMMENT ON TABLE wechat_user IS '微信用户表';
COMMENT ON COLUMN wechat_user.id IS '主键ID';
COMMENT ON COLUMN wechat_user.created_at IS '创建时间';
COMMENT ON COLUMN wechat_user.updated_at IS '更新时间';
COMMENT ON COLUMN wechat_user.member_id IS '会员ID(关联 member_user 表的 id 字段)';
COMMENT ON COLUMN wechat_user.union_id IS '微信UnionID(用户在开放平台的唯一标识)';
COMMENT ON COLUMN wechat_user.miniapp_openid IS '小程序OpenID(用户在当前小程序的唯一标识)';
COMMENT ON COLUMN wechat_user.mp_openid IS '服务号OpenID(用户在当前服务号的唯一标识)';
COMMENT ON COLUMN wechat_user.is_subscribed IS '是否关注服务号:true-已关注,false-未关注';
COMMENT ON COLUMN wechat_user.subscribe_time IS '首次关注时间';
COMMENT ON COLUMN wechat_user.unsubscribe_time IS '最后一次取消关注时间';
-- ============================================
-- 3. member_card 表(会员卡类型表)
-- ============================================
CREATE TABLE IF NOT EXISTS member_card (
id BIGSERIAL PRIMARY KEY,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
deleted_at TIMESTAMP,
member_card_id BIGSERIAL,
member_card_name VARCHAR(100) NOT NULL,
CREATE TABLE IF NOT EXISTS member_card (
id BIGSERIAL PRIMARY KEY,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
deleted_at TIMESTAMP,
member_card_id BIGSERIAL,
member_card_name VARCHAR(100) NOT NULL,
member_card_type VARCHAR(20) NOT NULL,
member_card_price DECIMAL(10, 2) NOT NULL,
member_card_validity_days INTEGER,
@@ -156,7 +115,7 @@ CREATE TABLE IF NOT EXISTS member_card (
member_card_amount DECIMAL(10, 2),
member_card_status INTEGER DEFAULT 1 NOT NULL,
extra_config TEXT DEFAULT '{}'
);
);
COMMENT ON TABLE member_card IS '会员卡类型表';
COMMENT ON COLUMN member_card.member_card_id IS '会员卡ID';
@@ -169,20 +128,20 @@ COMMENT ON COLUMN member_card.member_card_amount IS '面额(储值卡用)';
COMMENT ON COLUMN member_card.member_card_status IS '状态:0-下架, 1-上架';
COMMENT ON COLUMN member_card.extra_config IS '扩展配置(JSON格式)';
-- ============================================
-- 4. member_card_record 表(会员卡记录表)
-- ============================================
CREATE TABLE IF NOT EXISTS member_card_record (
id BIGSERIAL PRIMARY KEY,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
deleted_at TIMESTAMP,
member_card_record_id BIGSERIAL,
member_id BIGINT NOT NULL,
member_card_id BIGINT NOT NULL,
status VARCHAR(20) NOT NULL DEFAULT 'ACTIVE',
CREATE TABLE IF NOT EXISTS member_card_record (
id BIGSERIAL PRIMARY KEY,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
deleted_at TIMESTAMP,
member_card_record_id BIGSERIAL,
member_id BIGINT NOT NULL,
member_card_id BIGINT NOT NULL,
status VARCHAR(20) NOT NULL DEFAULT 'ACTIVE',
remaining_times INTEGER DEFAULT 0,
remaining_amount DECIMAL(10, 2) DEFAULT 0.00,
expire_time TIMESTAMP,
@@ -190,9 +149,8 @@ CREATE TABLE IF NOT EXISTS member_card_record (
purchase_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
version INTEGER DEFAULT 0 NOT NULL,
card_composition TEXT
);
);
-- 索引优化
CREATE INDEX IF NOT EXISTS idx_member_card_record_member_id ON member_card_record(member_id);
CREATE INDEX IF NOT EXISTS idx_member_card_record_status ON member_card_record(status);
CREATE INDEX IF NOT EXISTS idx_member_card_record_expire_time ON member_card_record(expire_time);
@@ -213,18 +171,18 @@ COMMENT ON COLUMN member_card_record.purchase_time IS '购买时间';
COMMENT ON COLUMN member_card_record.version IS '乐观锁版本号';
COMMENT ON COLUMN member_card_record.card_composition IS '卡片组成(JSON格式,用于组合卡)';
-- ============================================
-- 5. member_card_transactions 表(会员卡交易流水表)
-- ============================================
CREATE TABLE IF NOT EXISTS member_card_transactions (
id BIGSERIAL PRIMARY KEY,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
member_card_record_id BIGINT NOT NULL,
member_id BIGINT NOT NULL,
member_card_id BIGINT NOT NULL,
operation_type VARCHAR(20) NOT NULL,
CREATE TABLE IF NOT EXISTS member_card_transactions (
id BIGSERIAL PRIMARY KEY,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
member_card_record_id BIGINT NOT NULL,
member_id BIGINT NOT NULL,
member_card_id BIGINT NOT NULL,
operation_type VARCHAR(20) NOT NULL,
change_amount INTEGER DEFAULT 0,
change_balance DECIMAL(10, 2) DEFAULT 0.00,
after_remaining_count INTEGER DEFAULT 0,
@@ -234,9 +192,8 @@ CREATE TABLE IF NOT EXISTS member_card_transactions (
remark VARCHAR(500),
is_archived BOOLEAN DEFAULT FALSE,
archived_at TIMESTAMP
);
);
-- 索引优化
CREATE INDEX IF NOT EXISTS idx_member_card_transactions_member_id ON member_card_transactions(member_id);
CREATE INDEX IF NOT EXISTS idx_member_card_transactions_record_id ON member_card_transactions(member_card_record_id);
CREATE INDEX IF NOT EXISTS idx_member_card_transactions_created_at ON member_card_transactions(created_at);
@@ -253,26 +210,26 @@ COMMENT ON COLUMN member_card_transactions.related_biz_type IS '关联业务类
COMMENT ON COLUMN member_card_transactions.is_archived IS '是否已归档';
COMMENT ON COLUMN member_card_transactions.archived_at IS '归档时间';
-- ============================================
-- 6. refund_application 表(退款申请表)
-- ============================================
CREATE TABLE IF NOT EXISTS refund_application (
id BIGSERIAL PRIMARY KEY,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
deleted_at TIMESTAMP,
record_id BIGINT NOT NULL,
member_id BIGINT NOT NULL,
status VARCHAR(20) NOT NULL DEFAULT 'PENDING',
CREATE TABLE IF NOT EXISTS refund_application (
id BIGSERIAL PRIMARY KEY,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
deleted_at TIMESTAMP,
record_id BIGINT NOT NULL,
member_id BIGINT NOT NULL,
status VARCHAR(20) NOT NULL DEFAULT 'PENDING',
reason VARCHAR(500),
apply_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
audit_time TIMESTAMP,
auditor_id BIGINT,
audit_remark VARCHAR(500),
refund_amount DECIMAL(10, 2)
);
);
CREATE INDEX IF NOT EXISTS idx_refund_application_record_id ON refund_application(record_id);
CREATE INDEX IF NOT EXISTS idx_refund_application_status ON refund_application(status);
@@ -1,5 +1,7 @@
-- ============================================
-- 团课相关表
-- 版本: V5
-- 描述: 创建团课课程表和团课预约记录表
-- ============================================
-- 团课课程表
@@ -76,4 +78,4 @@ COMMENT ON COLUMN group_course_booking.create_by IS '创建人';
COMMENT ON COLUMN group_course_booking.update_by IS '更新人';
COMMENT ON COLUMN group_course_booking.created_at IS '创建时间';
COMMENT ON COLUMN group_course_booking.updated_at IS '更新时间';
COMMENT ON COLUMN group_course_booking.deleted_at IS '删除时间(软删除)';
COMMENT ON COLUMN group_course_booking.deleted_at IS '删除时间(软删除)';
@@ -1,41 +0,0 @@
-- 创建操作日志表
CREATE TABLE IF NOT EXISTS sys_operation_log (
id BIGINT PRIMARY KEY,
username VARCHAR(50),
operation VARCHAR(100),
method VARCHAR(200),
params TEXT,
result TEXT,
ip VARCHAR(50),
duration BIGINT,
status VARCHAR(1) DEFAULT '0',
error_msg TEXT,
create_by VARCHAR(50),
update_by VARCHAR(50),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
deleted_at TIMESTAMP
);
-- 创建索引
CREATE INDEX IF NOT EXISTS idx_operation_log_username ON sys_operation_log(username);
CREATE INDEX IF NOT EXISTS idx_operation_log_created_at ON sys_operation_log(created_at);
CREATE INDEX IF NOT EXISTS idx_operation_log_status ON sys_operation_log(status);
-- 添加注释
COMMENT ON TABLE sys_operation_log IS '操作日志表';
COMMENT ON COLUMN sys_operation_log.id IS '主键ID';
COMMENT ON COLUMN sys_operation_log.username IS '操作用户';
COMMENT ON COLUMN sys_operation_log.operation IS '操作描述';
COMMENT ON COLUMN sys_operation_log.method IS '请求方法';
COMMENT ON COLUMN sys_operation_log.params IS '请求参数';
COMMENT ON COLUMN sys_operation_log.result IS '操作结果';
COMMENT ON COLUMN sys_operation_log.ip IS 'IP地址';
COMMENT ON COLUMN sys_operation_log.duration IS '执行时长(毫秒)';
COMMENT ON COLUMN sys_operation_log.status IS '操作状态(0成功 1失败)';
COMMENT ON COLUMN sys_operation_log.error_msg IS '错误消息';
COMMENT ON COLUMN sys_operation_log.create_by IS '创建人';
COMMENT ON COLUMN sys_operation_log.update_by IS '更新人';
COMMENT ON COLUMN sys_operation_log.created_at IS '创建时间';
COMMENT ON COLUMN sys_operation_log.updated_at IS '更新时间';
COMMENT ON COLUMN sys_operation_log.deleted_at IS '删除时间';
@@ -1,6 +1,7 @@
-- ============================================
-- 为团课预约记录表添加课程冗余字段
-- 用于保存预约时的课程快照信息
-- 版本: V6
-- 描述: 保存预约时的课程快照信息
-- ============================================
ALTER TABLE group_course_booking
@@ -12,4 +13,4 @@ ALTER TABLE group_course_booking
COMMENT ON COLUMN group_course_booking.course_name IS '课程名称(冗余字段,保存预约时的课程快照)';
COMMENT ON COLUMN group_course_booking.course_start_time IS '课程开始时间(冗余字段,保存预约时的课程快照)';
COMMENT ON COLUMN group_course_booking.course_end_time IS '课程结束时间(冗余字段,保存预约时的课程快照)';
COMMENT ON COLUMN group_course_booking.location IS '上课地点(冗余字段,保存预约时的课程快照)';
COMMENT ON COLUMN group_course_booking.location IS '上课地点(冗余字段,保存预约时的课程快照)';
@@ -1,61 +1,39 @@
-- ============================================
-- 会员到店签到记录表
-- 版本: V13
-- 版本: V7
-- 描述: 创建sign_in_record表,用于记录会员签到信息
-- ============================================
-- 创建签到记录表
CREATE TABLE IF NOT EXISTS sign_in_record (
id BIGSERIAL PRIMARY KEY, -- 自增主键
member_id BIGINT NOT NULL, -- 会员ID,关联member表
member_card_id BIGINT, -- 签到时使用的会员卡ID
sign_in_time TIMESTAMP NOT NULL, -- 签到入场时间
sign_in_type VARCHAR(20) NOT NULL, -- 签到方式:QR_CODE-扫码签到,MANUAL-手动签到,FACE-人脸识别
sign_in_status VARCHAR(20) NOT NULL DEFAULT 'SUCCESS', -- 签到状态:SUCCESS-成功,FAILED-失败
verification_details TEXT, -- JSON格式,存储会员卡验证时的快照数据
fail_reason VARCHAR(500), -- 失败时的具体原因文案
operator_id BIGINT, -- 操作人ID(前台人员),自助签到时为NULL
operator_name VARCHAR(100), -- 操作人姓名冗余
device_info VARCHAR(200), -- 签到设备标识或型号
ip_address VARCHAR(50), -- 客户端IP地址
source VARCHAR(20) NOT NULL, -- 签到来源:MINI_PROGRAM-小程序扫码,PC_BACKEND-后台管理端
is_delete BOOLEAN DEFAULT FALSE, -- 软删除标识:false-未删除,true-已删除
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, -- 记录创建时间
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP -- 记录更新时间
id BIGSERIAL PRIMARY KEY,
member_id BIGINT NOT NULL,
member_card_id BIGINT,
sign_in_time TIMESTAMP NOT NULL,
sign_in_type VARCHAR(20) NOT NULL,
sign_in_status VARCHAR(20) NOT NULL DEFAULT 'SUCCESS',
verification_details TEXT,
fail_reason VARCHAR(500),
operator_id BIGINT,
operator_name VARCHAR(100),
device_info VARCHAR(200),
ip_address VARCHAR(50),
source VARCHAR(20) NOT NULL,
is_delete BOOLEAN DEFAULT FALSE,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
-- 创建索引
-- 会员ID索引(加速按会员查询签到记录)
CREATE INDEX IF NOT EXISTS idx_sign_in_record_member_id ON sign_in_record(member_id);
-- 签到时间索引(加速按时间范围查询)
CREATE INDEX IF NOT EXISTS idx_sign_in_record_sign_in_time ON sign_in_record(sign_in_time);
-- 签到状态索引(加速按状态筛选)
CREATE INDEX IF NOT EXISTS idx_sign_in_record_sign_in_status ON sign_in_record(sign_in_status);
-- 会员卡ID索引(加速按会员卡查询)
CREATE INDEX IF NOT EXISTS idx_sign_in_record_member_card_id ON sign_in_record(member_card_id);
-- 操作人ID索引(加速按操作人查询)
CREATE INDEX IF NOT EXISTS idx_sign_in_record_operator_id ON sign_in_record(operator_id);
-- 签到来源索引(加速按来源统计)
CREATE INDEX IF NOT EXISTS idx_sign_in_record_source ON sign_in_record(source);
-- 软删除索引(加速查询未删除的记录)
CREATE INDEX IF NOT EXISTS idx_sign_in_record_is_delete ON sign_in_record(is_delete);
-- 复合索引:会员ID + 签到时间(加速会员签到历史查询)
CREATE INDEX IF NOT EXISTS idx_sign_in_record_member_time ON sign_in_record(member_id, sign_in_time);
-- 复合索引:签到状态 + 签到时间(加速统计数据查询)
CREATE INDEX IF NOT EXISTS idx_sign_in_record_status_time ON sign_in_record(sign_in_status, sign_in_time);
-- 添加表注释
COMMENT ON TABLE sign_in_record IS '会员到店签到记录表';
-- 添加字段注释
COMMENT ON COLUMN sign_in_record.id IS '自增主键';
COMMENT ON COLUMN sign_in_record.member_id IS '会员ID,关联member表';
COMMENT ON COLUMN sign_in_record.member_card_id IS '签到时使用的会员卡ID';
@@ -0,0 +1,33 @@
-- ============================================
-- 团课类型表
-- 版本: V8
-- 描述: 创建团课类型表,用于分类管理团课
-- ============================================
CREATE TABLE IF NOT EXISTS group_course_type (
id BIGSERIAL PRIMARY KEY,
type_name VARCHAR(100) NOT NULL,
base_difficulty INTEGER DEFAULT 1,
description TEXT,
category VARCHAR(50),
create_by VARCHAR(50),
update_by VARCHAR(50),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
deleted_at TIMESTAMP
);
CREATE INDEX IF NOT EXISTS idx_group_course_type_type_name ON group_course_type(type_name);
CREATE INDEX IF NOT EXISTS idx_group_course_type_category ON group_course_type(category);
COMMENT ON TABLE group_course_type IS '团课类型表';
COMMENT ON COLUMN group_course_type.id IS '主键ID';
COMMENT ON COLUMN group_course_type.type_name IS '类型名称';
COMMENT ON COLUMN group_course_type.base_difficulty IS '基础难度(1-10';
COMMENT ON COLUMN group_course_type.description IS '类型描述';
COMMENT ON COLUMN group_course_type.category IS '分类(如:有氧、力量、柔韧等)';
COMMENT ON COLUMN group_course_type.create_by IS '创建人';
COMMENT ON COLUMN group_course_type.update_by IS '更新人';
COMMENT ON COLUMN group_course_type.created_at IS '创建时间';
COMMENT ON COLUMN group_course_type.updated_at IS '更新时间';
COMMENT ON COLUMN group_course_type.deleted_at IS '删除时间(软删除)';
@@ -1,5 +1,7 @@
-- ============================================
-- 团课标签相关表
-- 版本: V9
-- 描述: 创建团课标签表和类型-标签关联表
-- ============================================
-- 团课标签表
@@ -28,6 +30,10 @@ CREATE TABLE IF NOT EXISTS course_type_label (
UNIQUE (type_id, label_id)
);
CREATE INDEX IF NOT EXISTS idx_course_label_label_name ON course_label(label_name);
CREATE INDEX IF NOT EXISTS idx_course_type_label_type_id ON course_type_label(type_id);
CREATE INDEX IF NOT EXISTS idx_course_type_label_label_id ON course_type_label(label_id);
COMMENT ON TABLE course_label IS '团课标签表';
COMMENT ON COLUMN course_label.id IS '主键ID';
COMMENT ON COLUMN course_label.label_name IS '标签名称';
@@ -48,26 +54,3 @@ COMMENT ON COLUMN course_type_label.update_by IS '更新人';
COMMENT ON COLUMN course_type_label.created_at IS '创建时间';
COMMENT ON COLUMN course_type_label.updated_at IS '更新时间';
COMMENT ON COLUMN course_type_label.deleted_at IS '删除时间(软删除)';
-- 创建索引
CREATE INDEX idx_course_label_label_name ON course_label(label_name);
CREATE INDEX idx_course_type_label_type_id ON course_type_label(type_id);
CREATE INDEX idx_course_type_label_label_id ON course_type_label(label_id);
-- 插入初始标签数据
INSERT INTO course_label (label_name, color, description) VALUES
('适合新手', '#52c41a', '适合健身初学者'),
('中级过渡', '#faad14', '适合有一定基础的学员'),
('高级进阶', '#f5222d', '适合高级学员'),
('减脂塑形', '#722ed1', '有助于减脂塑形'),
('增肌强化', '#13c2c2', '有助于增肌强化'),
('柔韧性训练', '#eb2f96', '注重柔韧性提升'),
('核心训练', '#1890ff', '注重核心力量'),
('心肺训练', '#fa8c16', '提升心肺功能'),
('低冲击', '#52c41a', '低冲击运动,适合关节保护'),
('高强度', '#f5222d', '高强度间歇训练'),
('团体互动', '#722ed1', '注重团队协作'),
('私教推荐', '#13c2c2', '私教推荐课程'),
('热门课程', '#ff1493', '人气较高的课程'),
('新课上线', '#00ced1', '新上线的课程')
ON CONFLICT DO NOTHING;