feat: 新增饮食记录和分析功能

- 创建饮食记录相关的数据库模型、DTO和API接口,支持用户手动添加和AI视觉识别记录饮食。
- 实现饮食分析服务,提供营养分析和健康建议,优化AI教练服务以集成饮食分析功能。
- 更新用户控制器,添加饮食记录的增删查改接口,增强用户饮食管理体验。
- 提供详细的API使用指南和数据库创建脚本,确保功能的完整性和可用性。
This commit is contained in:
richarjiang
2025-08-18 16:27:01 +08:00
parent 3d36ee90f0
commit 485ba1f67c
19 changed files with 2031 additions and 52 deletions

View File

@@ -0,0 +1,45 @@
-- 创建用户饮食记录表
-- 该表用于存储用户通过AI视觉识别或手动输入的饮食记录
-- 包含详细的营养成分信息,支持营养分析和健康建议功能
CREATE TABLE IF NOT EXISTS `t_user_diet_history` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`user_id` varchar(255) NOT NULL COMMENT '用户ID',
`meal_type` enum('breakfast','lunch','dinner','snack','other') NOT NULL DEFAULT 'other' COMMENT '餐次类型',
`food_name` varchar(100) NOT NULL COMMENT '食物名称',
`food_description` varchar(500) DEFAULT NULL COMMENT '食物描述(详细信息)',
`weight_grams` float DEFAULT NULL COMMENT '食物重量(克)',
`portion_description` varchar(50) DEFAULT NULL COMMENT '份量描述1碗、2片、100g等',
`estimated_calories` float DEFAULT NULL COMMENT '估算总热量(卡路里)',
`protein_grams` float DEFAULT NULL COMMENT '蛋白质含量(克)',
`carbohydrate_grams` float DEFAULT NULL COMMENT '碳水化合物含量(克)',
`fat_grams` float DEFAULT NULL COMMENT '脂肪含量(克)',
`fiber_grams` float DEFAULT NULL COMMENT '膳食纤维含量(克)',
`sugar_grams` float DEFAULT NULL COMMENT '糖分含量(克)',
`sodium_mg` float DEFAULT NULL COMMENT '钠含量(毫克)',
`additional_nutrition` json DEFAULT NULL COMMENT '其他营养信息(维生素、矿物质等)',
`source` enum('manual','vision','other') NOT NULL DEFAULT 'manual' COMMENT '记录来源',
`meal_time` datetime DEFAULT NULL COMMENT '用餐时间',
`image_url` varchar(500) DEFAULT NULL COMMENT '食物图片URL',
`ai_analysis_result` json DEFAULT NULL COMMENT 'AI识别原始结果',
`notes` text DEFAULT NULL COMMENT '用户备注',
`deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否已删除',
`created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updated_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`),
KEY `idx_user_id` (`user_id`),
KEY `idx_meal_type` (`meal_type`),
KEY `idx_created_at` (`created_at`),
KEY `idx_user_created` (`user_id`, `created_at`),
KEY `idx_deleted` (`deleted`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户饮食记录表';
-- 创建索引以优化查询性能
CREATE INDEX `idx_user_meal_time` ON `t_user_diet_history` (`user_id`, `meal_time`);
CREATE INDEX `idx_source` ON `t_user_diet_history` (`source`);
-- 示例数据(可选)
-- INSERT INTO `t_user_diet_history` (`user_id`, `meal_type`, `food_name`, `food_description`, `portion_description`, `estimated_calories`, `protein_grams`, `carbohydrate_grams`, `fat_grams`, `fiber_grams`, `source`, `meal_time`, `notes`) VALUES
-- ('test_user_001', 'breakfast', '燕麦粥', '燕麦片加牛奶和香蕉', '1碗', 320, 12.5, 45.2, 8.3, 6.8, 'manual', '2024-01-15 08:00:00', '早餐很有营养'),
-- ('test_user_001', 'lunch', '鸡胸肉沙拉', '烤鸡胸肉配蔬菜沙拉', '1份', 280, 35.0, 15.5, 8.0, 5.2, 'vision', '2024-01-15 12:30:00', 'AI识别添加'),
-- ('test_user_001', 'dinner', '三文鱼配糙米', '煎三文鱼配蒸糙米和西兰花', '1份', 450, 28.5, 52.0, 18.2, 4.5, 'manual', '2024-01-15 19:00:00', '晚餐丰富');

View File

@@ -0,0 +1,67 @@
-- 一键导入普拉提动作分类与动作MySQL 8+
-- 说明:表由 Sequelize 同步创建t_exercise_categories / t_exercises
-- 若要幂等导入,使用 INSERT ... ON DUPLICATE KEY UPDATE
USE `db-plates`;
START TRANSACTION;
-- 分类
INSERT INTO `t_exercise_categories` (`key`, `name`, `sort_order`, `created_at`, `updated_at`) VALUES
('core', '核心与腹部', 0, NOW(), NOW()),
('spine_posterior_chain', '脊柱与后链', 1, NOW(), NOW()),
('lateral_hip', '侧链与髋', 2, NOW(), NOW()),
('balance_support', '平衡与支撑', 3, NOW(), NOW()),
('advanced_control', '进阶控制', 4, NOW(), NOW()),
('mobility_stretch', '柔韧与拉伸', 5, NOW(), NOW())
ON DUPLICATE KEY UPDATE `name` = VALUES(`name`), `sort_order` = VALUES(`sort_order`), `updated_at` = NOW();
-- 动作
INSERT INTO `t_exercises` (`key`, `name`, `description`, `category_key`, `category_name`, `sort_order`, `created_at`, `updated_at`) VALUES
('hundred', '百次拍击 (The Hundred)', '仰卧桌面位,小幅摆臂协同吸呼,核心激活。', 'core', '核心与腹部', 0, NOW(), NOW()),
('single_leg_stretch', '单腿伸展 (Single Leg Stretch)', '交替伸直一条腿,另一腿屈膝抱向胸口,稳定骨盆。', 'core', '核心与腹部', 1, NOW(), NOW()),
('double_leg_stretch', '双腿伸展 (Double Leg Stretch)', '双臂双腿同时伸直/收回,呼吸控制,核心稳定。', 'core', '核心与腹部', 2, NOW(), NOW()),
('criss_cross', '扭转卷腹 (Criss Cross)', '肘碰对侧膝,腹斜肌发力与呼吸配合。', 'core', '核心与腹部', 3, NOW(), NOW()),
('single_straight_leg', '单腿直剪 (Scissors)', '交替拉长上抬直腿,控制下放,避免耸肩。', 'core', '核心与腹部', 4, NOW(), NOW()),
('double_straight_leg', '双腿抬降 (Double Straight Leg Lower Lift)', '双腿并拢抬降,腹直肌抗伸展。', 'core', '核心与腹部', 5, NOW(), NOW()),
('spine_stretch_forward', '脊柱前伸 (Spine Stretch Forward)', '坐姿脊柱分节前伸,强调轴向延展与呼吸。', 'core', '核心与腹部', 6, NOW(), NOW()),
('roll_up', '卷起 (Roll Up)', '仰卧分节卷起到坐,前屈后还原,控制节律。', 'core', '核心与腹部', 7, NOW(), NOW()),
('rolling_like_a_ball', '小球滚动 (Rolling Like a Ball)', '抱膝蜷成球,控制滚动回正,核心稳定。', 'core', '核心与腹部', 8, NOW(), NOW()),
('teaser', '船式 (Teaser)', 'V字平衡腿躯干对抗重力与摆动。', 'core', '核心与腹部', 9, NOW(), NOW()),
('swan', '天鹅式 (Swan)', '俯卧伸展胸椎,后链发力,延展不挤压。', 'spine_posterior_chain', '脊柱与后链', 10, NOW(), NOW()),
('swan_dive', '天鹅下潜 (Swan Dive)', '在Swan基础上前后摆动弹性控制。', 'spine_posterior_chain', '脊柱与后链', 11, NOW(), NOW()),
('swimming', '游泳式 (Swimming)', '俯卧交替抬对侧上肢与下肢,脊柱中立。', 'spine_posterior_chain', '脊柱与后链', 12, NOW(), NOW()),
('shoulder_bridge', '肩桥 (Shoulder Bridge)', '仰卧卷尾抬盆,臀腿后侧力量与脊柱分节。', 'spine_posterior_chain', '脊柱与后链', 13, NOW(), NOW()),
('spine_twist', '脊柱扭转 (Spine Twist)', '坐姿轴向延展上的控制旋转。', 'spine_posterior_chain', '脊柱与后链', 14, NOW(), NOW()),
('saw', '锯式 (Saw)', '坐姿分腿,旋转前屈触对侧脚尖。', 'spine_posterior_chain', '脊柱与后链', 15, NOW(), NOW()),
('side_kick_front_back', '侧踢腿 前后摆 (Side Kick Front/Back)', '侧卧,髋稳定,腿前后摆动。', 'lateral_hip', '侧链与髋', 16, NOW(), NOW()),
('side_kick_up_down', '侧踢腿 上下 (Side Kick Up/Down)', '侧卧,上侧腿上抬下放,控制不耸肩。', 'lateral_hip', '侧链与髋', 17, NOW(), NOW()),
('side_leg_lift', '侧抬腿 (Side Leg Lift)', '侧卧抬腿,髋稳定,中臀肌激活。', 'lateral_hip', '侧链与髋', 18, NOW(), NOW()),
('clam', '蛤蜊式 (Clam)', '侧卧屈髋屈膝,抬起上侧膝,臀中刺激。', 'lateral_hip', '侧链与髋', 19, NOW(), NOW()),
('mermaid', '美人鱼 (Mermaid)', '坐姿侧屈拉伸,改善侧链柔韧。', 'lateral_hip', '侧链与髋', 20, NOW(), NOW()),
('plank', '平板支撑 (Plank)', '掌/前臂支撑,身体成一直线,核心稳定。', 'balance_support', '平衡与支撑', 21, NOW(), NOW()),
('side_plank', '侧板支撑 (Side Plank)', '单侧支撑,侧链与肩带稳定。', 'balance_support', '平衡与支撑', 22, NOW(), NOW()),
('push_up', '俯卧撑 (Push Up)', '胸肩臂与核心协同的推举支撑。', 'balance_support', '平衡与支撑', 23, NOW(), NOW()),
('leg_pull_front', '前拉腿 (Leg Pull Front)', '俯撑抬腿,后链与肩带控制。', 'balance_support', '平衡与支撑', 24, NOW(), NOW()),
('leg_pull_back', '后拉腿 (Leg Pull Back)', '仰撑抬腿,后链与肩带控制。', 'balance_support', '平衡与支撑', 25, NOW(), NOW()),
('jackknife', '折刀 (Jackknife)', '仰卧抬腿过头后折刀上推,核心与控制。', 'advanced_control', '进阶控制', 26, NOW(), NOW()),
('open_leg_rocker', '开腿摇滚 (Open Leg Rocker)', '开腿V坐平衡来回滚动。', 'advanced_control', '进阶控制', 27, NOW(), NOW()),
('corkscrew', '开瓶器 (Corkscrew)', '躯干稳定下的双腿画圈,控制髋与核心。', 'advanced_control', '进阶控制', 28, NOW(), NOW()),
('boomerang', '回旋镖 (Boomerang)', '融合Roll Over/Teaser的串联流畅控制。', 'advanced_control', '进阶控制', 29, NOW(), NOW()),
('control_balance', '控制平衡 (Control Balance)', '过头位下的单腿抬降与控制。', 'advanced_control', '进阶控制', 30, NOW(), NOW()),
('neck_pull', '抱颈卷起 (Neck Pull)', '更具挑战的卷起,背侧链参与更高。', 'advanced_control', '进阶控制', 31, NOW(), NOW()),
('roll_over', '翻滚过头 (Roll Over)', '仰卧双腿过头落地,脊柱分节控制。', 'advanced_control', '进阶控制', 32, NOW(), NOW()),
('cat_cow', '猫牛 (Cat-Cow)', '四点支撑的屈伸热身/整理放松。', 'mobility_stretch', '柔韧与拉伸', 33, NOW(), NOW()),
('hamstring_stretch', '腘绳肌拉伸', '仰卧或坐姿,拉伸大腿后侧。', 'mobility_stretch', '柔韧与拉伸', 34, NOW(), NOW()),
('hip_flexor_stretch', '髋屈肌拉伸', '弓步位,前髋前侧拉伸。', 'mobility_stretch', '柔韧与拉伸', 35, NOW(), NOW()),
('thoracic_extension', '胸椎伸展', '泡沫轴/垫上胸椎延展放松。', 'mobility_stretch', '柔韧与拉伸', 36, NOW(), NOW())
ON DUPLICATE KEY UPDATE `name` = VALUES(`name`), `description` = VALUES(`description`), `category_key` = VALUES(`category_key`), `category_name` = VALUES(`category_name`), `sort_order` = VALUES(`sort_order`), `updated_at` = NOW();
COMMIT;

View File

@@ -0,0 +1,121 @@
-- 普拉提分类和动作数据导入 SQL
-- 执行前请确保数据库表结构已更新
-- 清空现有数据(可选,根据实际情况决定是否执行)
-- DELETE FROM t_exercises;
-- DELETE FROM t_exercise_categories;
-- 插入普拉提分类数据
INSERT INTO t_exercise_categories (key, name, pilates_type, equipment_name, sort_order, created_at, updated_at) VALUES
-- 垫上普拉提
('mat_pilates', '垫上普拉提', 'mat_pilates', NULL, 1, NOW(), NOW()),
-- 器械普拉提
('reformer', '核心床', 'equipment_pilates', '核心床', 2, NOW(), NOW()),
('cadillac', '凯迪拉克', 'equipment_pilates', '凯迪拉克', 3, NOW(), NOW()),
('chair', '普拉提椅', 'equipment_pilates', '普拉提椅', 4, NOW(), NOW()),
('barrel', '普拉提桶', 'equipment_pilates', '普拉提桶', 5, NOW(), NOW());
-- 插入垫上普拉提动作数据
INSERT INTO t_exercises (
key, name, category_name, description, target_muscle_groups, equipment_name,
beginner_reps, beginner_sets, breathing_cycles, hold_duration, special_instructions,
category_key, sort_order, created_at, updated_at
) VALUES
('mat_hundred', '百次拍打', '垫上普拉提', '经典的普拉提动作,通过有节奏的手臂拍打配合呼吸来激活核心', '核心肌群、呼吸肌群、肩部稳定性', NULL, NULL, NULL, 10, NULL, '10个呼吸循环', 'mat_pilates', 1, NOW(), NOW()),
('mat_roll_up', '卷起', '垫上普拉提', '从仰卧位缓慢卷起至坐姿,锻炼脊柱逐节控制能力', '核心肌群、脊柱灵活性、腘绳肌柔韧性', NULL, 6, NULL, NULL, NULL, NULL, 'mat_pilates', 2, NOW(), NOW()),
('mat_single_leg_circle', '单腿画圈', '垫上普拉提', '单腿做圆周运动,保持骨盆稳定', '核心稳定性、髋关节灵活性、股四头肌、腘绳肌、臀肌', NULL, 5, NULL, NULL, NULL, '每条腿每个方向5次', 'mat_pilates', 3, NOW(), NOW()),
('mat_rolling_like_ball', '滚球', '垫上普拉提', '保持紧凑姿势前后滚动,挑战平衡和控制', '核心肌群、脊柱柔韧性、平衡感', NULL, 8, NULL, NULL, NULL, '6-8次', 'mat_pilates', 4, NOW(), NOW()),
('mat_single_leg_stretch', '单腿伸展', '垫上普拉提', '交替单腿伸展,保持上身抬起', '核心肌群、髋屈肌、股四头肌', NULL, 10, NULL, NULL, NULL, '每侧8-10次', 'mat_pilates', 5, NOW(), NOW()),
('mat_double_leg_stretch', '双腿伸展', '垫上普拉提', '双腿和手臂同时伸展,回到起始位置', '核心肌群、髋屈肌、股四头肌、肩部稳定性', NULL, 10, NULL, NULL, NULL, '6-10次', 'mat_pilates', 6, NOW(), NOW()),
('mat_spine_stretch', '脊柱伸展', '垫上普拉提', '坐姿前屈,逐节伸展脊柱', '脊柱柔韧性、腘绳肌伸展、核心控制', NULL, 6, NULL, NULL, NULL, NULL, 'mat_pilates', 7, NOW(), NOW()),
('mat_saw', '锯式', '垫上普拉提', '坐姿扭转配合前屈,增强脊柱旋转能力', '腹斜肌、背部伸肌、脊柱旋转灵活性', NULL, 6, NULL, NULL, NULL, '每侧6次', 'mat_pilates', 8, NOW(), NOW()),
('mat_swan', '天鹅式', '垫上普拉提', '俯卧位脊柱后伸,强化背部肌群', '背部伸肌、臀肌、腘绳肌', NULL, 6, NULL, NULL, NULL, NULL, 'mat_pilates', 9, NOW(), NOW()),
('mat_shoulder_bridge', '肩桥', '垫上普拉提', '仰卧抬臀,激活后链肌群', '臀肌、腘绳肌、下背部、脊柱灵活性', NULL, 6, NULL, NULL, NULL, NULL, 'mat_pilates', 10, NOW(), NOW());
-- 插入核心床(Reformer)动作数据
INSERT INTO t_exercises (
key, name, category_name, description, target_muscle_groups, equipment_name,
beginner_reps, beginner_sets, breathing_cycles, hold_duration, special_instructions,
category_key, sort_order, created_at, updated_at
) VALUES
('reformer_footwork', '脚部练习系列', '核心床', '在核心床上进行各种脚部位置的推蹬练习', '腿部、足部、核心稳定性', '核心床', 10, NULL, NULL, NULL, NULL, 'reformer', 1, NOW(), NOW()),
('reformer_hundred', '百次拍打', '核心床', '在核心床上进行百次拍打,增加阻力挑战', '核心肌群、呼吸肌群、上身耐力', '核心床', NULL, NULL, 10, NULL, '10个呼吸循环', 'reformer', 2, NOW(), NOW()),
('reformer_bridge', '桥式', '核心床', '在核心床上进行桥式动作,利用弹簧阻力', '臀肌、腘绳肌、脊柱关节', '核心床', 10, NULL, NULL, NULL, '6-10次', 'reformer', 3, NOW(), NOW()),
('reformer_straps', '脚套带练习', '核心床', '使用脚套带进行各种腿部和髋部练习', '髋部灵活性、骨盆稳定性、身体控制、内收肌', '核心床', 10, NULL, NULL, NULL, '8-10次', 'reformer', 4, NOW(), NOW()),
('reformer_elephant', '象式', '核心床', '四点跪撑位置进行推拉练习', '核心肌群、腘绳肌、背部伸肌、肩部稳定性', '核心床', 10, NULL, NULL, NULL, '8-10次', 'reformer', 5, NOW(), NOW()),
('reformer_knee_stretch', '跪姿伸展系列', '核心床', '跪姿位置进行多种伸展动作', '核心肌群、髋部灵活性、肩部控制', '核心床', 10, NULL, NULL, NULL, NULL, 'reformer', 6, NOW(), NOW());
-- 插入凯迪拉克(Cadillac)动作数据
INSERT INTO t_exercises (
key, name, category_name, description, target_muscle_groups, equipment_name,
beginner_reps, beginner_sets, breathing_cycles, hold_duration, special_instructions,
category_key, sort_order, created_at, updated_at
) VALUES
('cadillac_leg_springs', '腿部弹簧系列', '凯迪拉克', '使用腿部弹簧进行各种腿部强化练习', '腘绳肌、股四头肌、臀肌、髋屈肌、内收肌', '凯迪拉克', 20, NULL, NULL, NULL, '10-20次', 'cadillac', 1, NOW(), NOW()),
('cadillac_arm_springs', '手臂弹簧系列', '凯迪拉克', '使用手臂弹簧进行上身力量训练', '胸部、肩部、上背部、手臂', '凯迪拉克', 15, NULL, NULL, NULL, '10-15次', 'cadillac', 2, NOW(), NOW()),
('cadillac_roll_down_bar', '滚背杆卷下', '凯迪拉克', '使用滚背杆进行脊柱逐节控制练习', '腹部肌肉、脊柱灵活性', '凯迪拉克', 12, NULL, NULL, NULL, '8-12次', 'cadillac', 3, NOW(), NOW()),
('cadillac_push_through_bar', '推杆', '凯迪拉克', '推拉横杆进行全身协调练习', '肩部、核心、背部', '凯迪拉克', 12, NULL, NULL, NULL, '8-12次', 'cadillac', 4, NOW(), NOW());
-- 插入普拉提椅(Chair)动作数据
INSERT INTO t_exercises (
key, name, category_name, description, target_muscle_groups, equipment_name,
beginner_reps, beginner_sets, breathing_cycles, hold_duration, special_instructions,
category_key, sort_order, created_at, updated_at
) VALUES
('chair_seated_march', '坐姿行进', '普拉提椅', '坐在椅子上进行交替抬腿练习', '核心肌群、髋屈肌', '普拉提椅', 12, NULL, NULL, NULL, '每侧10-12次', 'chair', 1, NOW(), NOW()),
('chair_seated_leg_lift', '坐姿抬腿', '普拉提椅', '坐姿单腿伸展练习', '股四头肌、核心肌群', '普拉提椅', 12, NULL, NULL, NULL, '每侧10-12次', 'chair', 2, NOW(), NOW()),
('chair_seated_arm_circles', '坐姿手臂画圈', '普拉提椅', '坐姿手臂做圆周运动', '肩部、上背部、手臂', '普拉提椅', 12, NULL, NULL, NULL, '前后各10-12次', 'chair', 3, NOW(), NOW()),
('chair_spine_twist', '脊柱扭转', '普拉提椅', '坐姿脊柱旋转练习', '腹斜肌、脊柱旋转肌', '普拉提椅', 10, NULL, NULL, NULL, '每侧8-10次', 'chair', 4, NOW(), NOW()),
('chair_squat', '椅子深蹲', '普拉提椅', '使用椅子进行深蹲练习', '臀肌、股四头肌、腘绳肌、核心', '普拉提椅', 12, NULL, NULL, NULL, '10-12次', 'chair', 5, NOW(), NOW());
-- 插入普拉提桶(Barrel)动作数据
INSERT INTO t_exercises (
key, name, category_name, description, target_muscle_groups, equipment_name,
beginner_reps, beginner_sets, breathing_cycles, hold_duration, special_instructions,
category_key, sort_order, created_at, updated_at
) VALUES
('barrel_spine_stretch', '脊柱伸展', '普拉提桶', '在桶上进行脊柱后伸练习', '核心肌群、脊柱伸肌、背部肌肉', '普拉提桶', 12, 3, NULL, NULL, '10-12次2-3组', 'barrel', 1, NOW(), NOW()),
('barrel_mermaid', '美人鱼伸展', '普拉提桶', '侧坐在桶上进行侧向伸展', '核心肌群、腹斜肌、侧向柔韧性', '普拉提桶', 10, 3, NULL, NULL, '每侧8-10次2-3组', 'barrel', 2, NOW(), NOW()),
('barrel_side_bend', '侧弯', '普拉提桶', '侧卧在桶上进行侧向弯曲练习', '腹斜肌、腰部塑形、平衡感、核心稳定性', '普拉提桶', 10, 3, NULL, NULL, '每侧8-10次2-3组', 'barrel', 3, NOW(), NOW()),
('barrel_teaser_prep', '预备式Teaser', '普拉提桶', '在桶上进行Teaser动作的预备练习', '核心肌群、平衡感、本体感受', '普拉提桶', 5, 2, NULL, 3, '5次2组保持3秒', 'barrel', 4, NOW(), NOW()),
('barrel_swan_dive_prep', '预备式Swan Dive', '普拉提桶', '在桶上进行Swan Dive的预备练习', '背部伸肌、脊柱伸展、平衡感', '普拉提桶', 5, 2, NULL, 3, '5次2组保持3秒', 'barrel', 5, NOW(), NOW());
-- 提交事务
COMMIT;
-- 验证数据插入
SELECT
ec.name as category_name,
ec.pilates_type,
ec.equipment_name,
COUNT(e.key) as exercise_count
FROM t_exercise_categories ec
LEFT JOIN t_exercises e ON ec.key = e.category_key
GROUP BY ec.key, ec.name, ec.pilates_type, ec.equipment_name
ORDER BY ec.sort_order;

View File

@@ -0,0 +1,64 @@
-- 普拉提数据库结构迁移脚本
-- 此脚本用于将现有的数据库结构升级以支持新的普拉提分类和动作系统
-- 开始事务
BEGIN;
-- 1. 为分类表添加新字段
ALTER TABLE t_exercise_categories
ADD COLUMN pilates_type ENUM('mat_pilates', 'equipment_pilates') NOT NULL DEFAULT 'mat_pilates' COMMENT '普拉提类型:垫上普拉提或器械普拉提';
ALTER TABLE t_exercise_categories
ADD COLUMN equipment_name VARCHAR(255) NULL COMMENT '器械名称(仅器械普拉提需要)';
-- 2. 为动作表添加新字段
ALTER TABLE t_exercises
ADD COLUMN target_muscle_groups TEXT NOT NULL DEFAULT '' COMMENT '主要锻炼肌肉群';
ALTER TABLE t_exercises
ADD COLUMN equipment_name VARCHAR(255) NULL COMMENT '器械名称(器械普拉提专用)';
ALTER TABLE t_exercises
ADD COLUMN beginner_reps INTEGER NULL COMMENT '入门级别建议练习次数';
ALTER TABLE t_exercises
ADD COLUMN beginner_sets INTEGER NULL COMMENT '入门级别建议组数';
ALTER TABLE t_exercises
ADD COLUMN breathing_cycles INTEGER NULL COMMENT '呼吸循环次数(替代普通次数)';
ALTER TABLE t_exercises
ADD COLUMN hold_duration INTEGER NULL COMMENT '保持时间(秒)';
ALTER TABLE t_exercises
ADD COLUMN special_instructions VARCHAR(255) NULL COMMENT '特殊说明(如每侧、前后各等)';
-- 3. 修改现有字段属性
ALTER TABLE t_exercises
MODIFY COLUMN description TEXT NULL COMMENT '动作描述';
-- 提交事务
COMMIT;
-- 验证表结构
SELECT
COLUMN_NAME,
COLUMN_TYPE,
IS_NULLABLE,
COLUMN_DEFAULT,
COLUMN_COMMENT
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 't_exercise_categories'
AND TABLE_SCHEMA = DATABASE()
ORDER BY ORDINAL_POSITION;
SELECT
COLUMN_NAME,
COLUMN_TYPE,
IS_NULLABLE,
COLUMN_DEFAULT,
COLUMN_COMMENT
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 't_exercises'
AND TABLE_SCHEMA = DATABASE()
ORDER BY ORDINAL_POSITION;

View File

@@ -0,0 +1,247 @@
-- 普拉提训练系统完整表结构创建脚本
-- 执行前请确保删除旧表(注意删除顺序,避免外键约束错误)
-- 禁用外键检查(创建时)
SET FOREIGN_KEY_CHECKS = 0;
-- 删除现有表(如果存在)
DROP TABLE IF EXISTS `t_schedule_exercises`;
DROP TABLE IF EXISTS `t_training_plans`;
DROP TABLE IF EXISTS `t_exercises`;
DROP TABLE IF EXISTS `t_exercise_categories`;
-- 重新启用外键检查
SET FOREIGN_KEY_CHECKS = 1;
-- 创建分类表
CREATE TABLE `t_exercise_categories` (
`key` varchar(255) NOT NULL COMMENT '分类唯一键(英文/下划线)',
`name` varchar(255) NOT NULL COMMENT '分类中文名称',
`type` enum('mat_pilates','equipment_pilates') NOT NULL DEFAULT 'mat_pilates' COMMENT '普拉提类型:垫上普拉提或器械普拉提',
`equipment_name` varchar(255) DEFAULT NULL COMMENT '器械名称(仅器械普拉提需要)',
`sort_order` int NOT NULL DEFAULT '0' COMMENT '排序(升序)',
`created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updated_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`key`),
KEY `idx_sort_order` (`sort_order`),
KEY `idx_type` (`type`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='普拉提训练分类表';
-- 创建动作表
CREATE TABLE `t_exercises` (
`key` varchar(255) NOT NULL COMMENT '动作唯一键(英文/下划线)',
`name` varchar(255) NOT NULL COMMENT '动作名称',
`category_name` varchar(255) NOT NULL COMMENT '中文分类名(冗余,便于展示)',
`description` text DEFAULT NULL COMMENT '动作描述',
`target_muscle_groups` text NOT NULL COMMENT '主要锻炼肌肉群',
`equipment_name` varchar(255) DEFAULT NULL COMMENT '器械名称(器械普拉提专用)',
`beginner_reps` int DEFAULT NULL COMMENT '入门级别建议练习次数',
`beginner_sets` int DEFAULT NULL COMMENT '入门级别建议组数',
`breathing_cycles` int DEFAULT NULL COMMENT '呼吸循环次数(替代普通次数)',
`hold_duration` int DEFAULT NULL COMMENT '保持时间(秒)',
`special_instructions` varchar(255) DEFAULT NULL COMMENT '特殊说明(如每侧、前后各等)',
`category_key` varchar(255) NOT NULL COMMENT '分类键',
`sort_order` int NOT NULL DEFAULT '0' COMMENT '排序(分类内)',
`created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updated_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`key`),
KEY `idx_category_key` (`category_key`),
KEY `idx_sort_order` (`sort_order`),
KEY `idx_category_sort` (`category_key`, `sort_order`),
KEY `idx_equipment_name` (`equipment_name`),
CONSTRAINT `fk_exercises_category` FOREIGN KEY (`category_key`) REFERENCES `t_exercise_categories` (`key`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='普拉提训练动作表';
-- 创建训练计划表
CREATE TABLE `t_training_plans` (
`id` char(36) NOT NULL COMMENT '训练计划唯一ID',
`is_active` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否激活',
`user_id` varchar(255) NOT NULL COMMENT '用户ID',
`name` varchar(255) DEFAULT NULL COMMENT '计划名称',
`created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`start_date` datetime NOT NULL COMMENT '开始日期',
`mode` enum('daysOfWeek','sessionsPerWeek') NOT NULL COMMENT '计划模式',
`days_of_week` json NOT NULL COMMENT '周几训练0-6',
`sessions_per_week` int NOT NULL COMMENT '每周训练次数',
`goal` enum('postpartum_recovery','fat_loss','posture_correction','core_strength','flexibility','rehab','stress_relief','') NOT NULL COMMENT '训练目标',
`start_weight_kg` float DEFAULT NULL COMMENT '起始体重(公斤)',
`preferred_time_of_day` enum('morning','noon','evening','') NOT NULL DEFAULT '' COMMENT '偏好训练时间',
`updated_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否已删除',
PRIMARY KEY (`id`),
KEY `idx_user_id` (`user_id`),
KEY `idx_is_active` (`is_active`),
KEY `idx_deleted` (`deleted`),
KEY `idx_user_active` (`user_id`, `is_active`, `deleted`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='训练计划表';
-- 创建训练计划动作表
CREATE TABLE `t_schedule_exercises` (
`id` char(36) NOT NULL COMMENT '计划动作唯一ID',
`training_plan_id` char(36) NOT NULL COMMENT '训练计划ID',
`user_id` varchar(255) NOT NULL COMMENT '用户ID',
`exercise_key` varchar(255) DEFAULT NULL COMMENT '关联的动作key仅exercise类型',
`name` varchar(255) NOT NULL COMMENT '项目名称',
`sets` int DEFAULT NULL COMMENT '组数',
`reps` int DEFAULT NULL COMMENT '重复次数',
`duration_sec` int DEFAULT NULL COMMENT '持续时长(秒)',
`rest_sec` int DEFAULT NULL COMMENT '休息时长(秒)',
`note` text DEFAULT NULL COMMENT '备注',
`item_type` enum('exercise','rest','note') NOT NULL DEFAULT 'exercise' COMMENT '项目类型',
`completed` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否已完成',
`sort_order` int NOT NULL COMMENT '排序顺序',
`created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updated_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否已删除',
PRIMARY KEY (`id`),
KEY `idx_training_plan_id` (`training_plan_id`),
KEY `idx_exercise_key` (`exercise_key`),
KEY `idx_user_id` (`user_id`),
KEY `idx_sort_order` (`sort_order`),
KEY `idx_item_type` (`item_type`),
KEY `idx_plan_sort` (`training_plan_id`, `sort_order`),
CONSTRAINT `fk_schedule_exercises_training_plan` FOREIGN KEY (`training_plan_id`) REFERENCES `t_training_plans` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT `fk_schedule_exercises_exercise` FOREIGN KEY (`exercise_key`) REFERENCES `t_exercises` (`key`) ON DELETE SET NULL ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='训练计划动作表';
-- 创建索引以优化查询性能
-- 分类表索引已在建表时创建
-- 动作表额外索引
CREATE INDEX `idx_target_muscle_groups` ON `t_exercises` (`target_muscle_groups`(100));
-- 插入初始数据
-- 插入普拉提分类数据
INSERT INTO `t_exercise_categories` (`key`, `name`, `type`, `equipment_name`, `sort_order`, `created_at`, `updated_at`) VALUES
-- 垫上普拉提
('mat_pilates', '垫上普拉提', 'mat_pilates', NULL, 1, NOW(), NOW()),
-- 器械普拉提
('reformer', '核心床', 'equipment_pilates', '核心床', 2, NOW(), NOW()),
('cadillac', '凯迪拉克', 'equipment_pilates', '凯迪拉克', 3, NOW(), NOW()),
('chair', '普拉提椅', 'equipment_pilates', '普拉提椅', 4, NOW(), NOW()),
('barrel', '普拉提桶', 'equipment_pilates', '普拉提桶', 5, NOW(), NOW());
-- 插入垫上普拉提动作数据
INSERT INTO `t_exercises` (
`key`, `name`, `category_name`, `description`, `target_muscle_groups`, `equipment_name`,
`beginner_reps`, `beginner_sets`, `breathing_cycles`, `hold_duration`, `special_instructions`,
`category_key`, `sort_order`, `created_at`, `updated_at`
) VALUES
('mat_hundred', '百次拍打', '垫上普拉提', '经典的普拉提动作,通过有节奏的手臂拍打配合呼吸来激活核心', '核心肌群、呼吸肌群、肩部稳定性', NULL, NULL, NULL, 10, NULL, '10个呼吸循环', 'mat_pilates', 1, NOW(), NOW()),
('mat_roll_up', '卷起', '垫上普拉提', '从仰卧位缓慢卷起至坐姿,锻炼脊柱逐节控制能力', '核心肌群、脊柱灵活性、腘绳肌柔韧性', NULL, 6, NULL, NULL, NULL, NULL, 'mat_pilates', 2, NOW(), NOW()),
('mat_single_leg_circle', '单腿画圈', '垫上普拉提', '单腿做圆周运动,保持骨盆稳定', '核心稳定性、髋关节灵活性、股四头肌、腘绳肌、臀肌', NULL, 5, NULL, NULL, NULL, '每条腿每个方向5次', 'mat_pilates', 3, NOW(), NOW()),
('mat_rolling_like_ball', '滚球', '垫上普拉提', '保持紧凑姿势前后滚动,挑战平衡和控制', '核心肌群、脊柱柔韧性、平衡感', NULL, 8, NULL, NULL, NULL, '6-8次', 'mat_pilates', 4, NOW(), NOW()),
('mat_single_leg_stretch', '单腿伸展', '垫上普拉提', '交替单腿伸展,保持上身抬起', '核心肌群、髋屈肌、股四头肌', NULL, 10, NULL, NULL, NULL, '每侧8-10次', 'mat_pilates', 5, NOW(), NOW()),
('mat_double_leg_stretch', '双腿伸展', '垫上普拉提', '双腿和手臂同时伸展,回到起始位置', '核心肌群、髋屈肌、股四头肌、肩部稳定性', NULL, 10, NULL, NULL, NULL, '6-10次', 'mat_pilates', 6, NOW(), NOW()),
('mat_spine_stretch', '脊柱伸展', '垫上普拉提', '坐姿前屈,逐节伸展脊柱', '脊柱柔韧性、腘绳肌伸展、核心控制', NULL, 6, NULL, NULL, NULL, NULL, 'mat_pilates', 7, NOW(), NOW()),
('mat_saw', '锯式', '垫上普拉提', '坐姿扭转配合前屈,增强脊柱旋转能力', '腹斜肌、背部伸肌、脊柱旋转灵活性', NULL, 6, NULL, NULL, NULL, '每侧6次', 'mat_pilates', 8, NOW(), NOW()),
('mat_swan', '天鹅式', '垫上普拉提', '俯卧位脊柱后伸,强化背部肌群', '背部伸肌、臀肌、腘绳肌', NULL, 6, NULL, NULL, NULL, NULL, 'mat_pilates', 9, NOW(), NOW()),
('mat_shoulder_bridge', '肩桥', '垫上普拉提', '仰卧抬臀,激活后链肌群', '臀肌、腘绳肌、下背部、脊柱灵活性', NULL, 6, NULL, NULL, NULL, NULL, 'mat_pilates', 10, NOW(), NOW());
-- 插入核心床(Reformer)动作数据
INSERT INTO `t_exercises` (
`key`, `name`, `category_name`, `description`, `target_muscle_groups`, `equipment_name`,
`beginner_reps`, `beginner_sets`, `breathing_cycles`, `hold_duration`, `special_instructions`,
`category_key`, `sort_order`, `created_at`, `updated_at`
) VALUES
('reformer_footwork', '脚部练习系列', '核心床', '在核心床上进行各种脚部位置的推蹬练习', '腿部、足部、核心稳定性', '核心床', 10, NULL, NULL, NULL, NULL, 'reformer', 1, NOW(), NOW()),
('reformer_hundred', '百次拍打', '核心床', '在核心床上进行百次拍打,增加阻力挑战', '核心肌群、呼吸肌群、上身耐力', '核心床', NULL, NULL, 10, NULL, '10个呼吸循环', 'reformer', 2, NOW(), NOW()),
('reformer_bridge', '桥式', '核心床', '在核心床上进行桥式动作,利用弹簧阻力', '臀肌、腘绳肌、脊柱关节', '核心床', 10, NULL, NULL, NULL, '6-10次', 'reformer', 3, NOW(), NOW()),
('reformer_straps', '脚套带练习', '核心床', '使用脚套带进行各种腿部和髋部练习', '髋部灵活性、骨盆稳定性、身体控制、内收肌', '核心床', 10, NULL, NULL, NULL, '8-10次', 'reformer', 4, NOW(), NOW()),
('reformer_elephant', '象式', '核心床', '四点跪撑位置进行推拉练习', '核心肌群、腘绳肌、背部伸肌、肩部稳定性', '核心床', 10, NULL, NULL, NULL, '8-10次', 'reformer', 5, NOW(), NOW()),
('reformer_knee_stretch', '跪姿伸展系列', '核心床', '跪姿位置进行多种伸展动作', '核心肌群、髋部灵活性、肩部控制', '核心床', 10, NULL, NULL, NULL, NULL, 'reformer', 6, NOW(), NOW());
-- 插入凯迪拉克(Cadillac)动作数据
INSERT INTO `t_exercises` (
`key`, `name`, `category_name`, `description`, `target_muscle_groups`, `equipment_name`,
`beginner_reps`, `beginner_sets`, `breathing_cycles`, `hold_duration`, `special_instructions`,
`category_key`, `sort_order`, `created_at`, `updated_at`
) VALUES
('cadillac_leg_springs', '腿部弹簧系列', '凯迪拉克', '使用腿部弹簧进行各种腿部强化练习', '腘绳肌、股四头肌、臀肌、髋屈肌、内收肌', '凯迪拉克', 20, NULL, NULL, NULL, '10-20次', 'cadillac', 1, NOW(), NOW()),
('cadillac_arm_springs', '手臂弹簧系列', '凯迪拉克', '使用手臂弹簧进行上身力量训练', '胸部、肩部、上背部、手臂', '凯迪拉克', 15, NULL, NULL, NULL, '10-15次', 'cadillac', 2, NOW(), NOW()),
('cadillac_roll_down_bar', '滚背杆卷下', '凯迪拉克', '使用滚背杆进行脊柱逐节控制练习', '腹部肌肉、脊柱灵活性', '凯迪拉克', 12, NULL, NULL, NULL, '8-12次', 'cadillac', 3, NOW(), NOW()),
('cadillac_push_through_bar', '推杆', '凯迪拉克', '推拉横杆进行全身协调练习', '肩部、核心、背部', '凯迪拉克', 12, NULL, NULL, NULL, '8-12次', 'cadillac', 4, NOW(), NOW());
-- 插入普拉提椅(Chair)动作数据
INSERT INTO `t_exercises` (
`key`, `name`, `category_name`, `description`, `target_muscle_groups`, `equipment_name`,
`beginner_reps`, `beginner_sets`, `breathing_cycles`, `hold_duration`, `special_instructions`,
`category_key`, `sort_order`, `created_at`, `updated_at`
) VALUES
('chair_seated_march', '坐姿行进', '普拉提椅', '坐在椅子上进行交替抬腿练习', '核心肌群、髋屈肌', '普拉提椅', 12, NULL, NULL, NULL, '每侧10-12次', 'chair', 1, NOW(), NOW()),
('chair_seated_leg_lift', '坐姿抬腿', '普拉提椅', '坐姿单腿伸展练习', '股四头肌、核心肌群', '普拉提椅', 12, NULL, NULL, NULL, '每侧10-12次', 'chair', 2, NOW(), NOW()),
('chair_seated_arm_circles', '坐姿手臂画圈', '普拉提椅', '坐姿手臂做圆周运动', '肩部、上背部、手臂', '普拉提椅', 12, NULL, NULL, NULL, '前后各10-12次', 'chair', 3, NOW(), NOW()),
('chair_spine_twist', '脊柱扭转', '普拉提椅', '坐姿脊柱旋转练习', '腹斜肌、脊柱旋转肌', '普拉提椅', 10, NULL, NULL, NULL, '每侧8-10次', 'chair', 4, NOW(), NOW()),
('chair_squat', '椅子深蹲', '普拉提椅', '使用椅子进行深蹲练习', '臀肌、股四头肌、腘绳肌、核心', '普拉提椅', 12, NULL, NULL, NULL, '10-12次', 'chair', 5, NOW(), NOW());
-- 插入普拉提桶(Barrel)动作数据
INSERT INTO `t_exercises` (
`key`, `name`, `category_name`, `description`, `target_muscle_groups`, `equipment_name`,
`beginner_reps`, `beginner_sets`, `breathing_cycles`, `hold_duration`, `special_instructions`,
`category_key`, `sort_order`, `created_at`, `updated_at`
) VALUES
('barrel_spine_stretch', '脊柱伸展', '普拉提桶', '在桶上进行脊柱后伸练习', '核心肌群、脊柱伸肌、背部肌肉', '普拉提桶', 12, 3, NULL, NULL, '10-12次2-3组', 'barrel', 1, NOW(), NOW()),
('barrel_mermaid', '美人鱼伸展', '普拉提桶', '侧坐在桶上进行侧向伸展', '核心肌群、腹斜肌、侧向柔韧性', '普拉提桶', 10, 3, NULL, NULL, '每侧8-10次2-3组', 'barrel', 2, NOW(), NOW()),
('barrel_side_bend', '侧弯', '普拉提桶', '侧卧在桶上进行侧向弯曲练习', '腹斜肌、腰部塑形、平衡感、核心稳定性', '普拉提桶', 10, 3, NULL, NULL, '每侧8-10次2-3组', 'barrel', 3, NOW(), NOW()),
('barrel_teaser_prep', '预备式Teaser', '普拉提桶', '在桶上进行Teaser动作的预备练习', '核心肌群、平衡感、本体感受', '普拉提桶', 5, 2, NULL, 3, '5次2组保持3秒', 'barrel', 4, NOW(), NOW()),
('barrel_swan_dive_prep', '预备式Swan Dive', '普拉提桶', '在桶上进行Swan Dive的预备练习', '背部伸肌、脊柱伸展、平衡感', '普拉提桶', 5, 2, NULL, 3, '5次2组保持3秒', 'barrel', 5, NOW(), NOW());
-- 验证数据插入结果
SELECT
ec.name as category_name,
ec.type,
ec.equipment_name,
COUNT(e.key) as exercise_count
FROM t_exercise_categories ec
LEFT JOIN t_exercises e ON ec.key = e.category_key
GROUP BY ec.key, ec.name, ec.type, ec.equipment_name
ORDER BY ec.sort_order;
-- 验证表结构
SELECT
TABLE_NAME,
TABLE_COMMENT,
TABLE_ROWS
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME IN ('t_exercise_categories', 't_exercises', 't_training_plans', 't_schedule_exercises')
ORDER BY TABLE_NAME;
-- 验证外键约束
SELECT
CONSTRAINT_NAME,
TABLE_NAME,
COLUMN_NAME,
REFERENCED_TABLE_NAME,
REFERENCED_COLUMN_NAME
FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE
WHERE TABLE_SCHEMA = DATABASE()
AND REFERENCED_TABLE_NAME IS NOT NULL
AND TABLE_NAME IN ('t_exercises', 't_schedule_exercises')
ORDER BY TABLE_NAME, CONSTRAINT_NAME;

View File

@@ -0,0 +1,138 @@
-- 训练计划相关表单独创建脚本
-- 此脚本仅创建训练计划相关的表,前提是动作表已经存在
-- 禁用外键检查
SET FOREIGN_KEY_CHECKS = 0;
-- 删除训练计划相关表(如果存在)
DROP TABLE IF EXISTS `t_schedule_exercises`;
DROP TABLE IF EXISTS `t_training_plans`;
-- 重新启用外键检查
SET FOREIGN_KEY_CHECKS = 1;
-- 创建训练计划表
CREATE TABLE `t_training_plans` (
`id` char(36) NOT NULL COMMENT '训练计划唯一ID',
`is_active` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否激活',
`user_id` varchar(255) NOT NULL COMMENT '用户ID',
`name` varchar(255) DEFAULT NULL COMMENT '计划名称',
`created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`start_date` datetime NOT NULL COMMENT '开始日期',
`mode` enum('daysOfWeek','sessionsPerWeek') NOT NULL COMMENT '计划模式',
`days_of_week` json NOT NULL COMMENT '周几训练0-6',
`sessions_per_week` int NOT NULL COMMENT '每周训练次数',
`goal` enum('postpartum_recovery','fat_loss','posture_correction','core_strength','flexibility','rehab','stress_relief','') NOT NULL COMMENT '训练目标',
`start_weight_kg` float DEFAULT NULL COMMENT '起始体重(公斤)',
`preferred_time_of_day` enum('morning','noon','evening','') NOT NULL DEFAULT '' COMMENT '偏好训练时间',
`updated_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否已删除',
PRIMARY KEY (`id`),
KEY `idx_user_id` (`user_id`),
KEY `idx_is_active` (`is_active`),
KEY `idx_deleted` (`deleted`),
KEY `idx_user_active` (`user_id`, `is_active`, `deleted`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='训练计划表';
-- 创建训练计划动作表
CREATE TABLE `t_schedule_exercises` (
`id` char(36) NOT NULL COMMENT '计划动作唯一ID',
`training_plan_id` char(36) NOT NULL COMMENT '训练计划ID',
`user_id` varchar(255) NOT NULL COMMENT '用户ID',
`exercise_key` varchar(255) DEFAULT NULL COMMENT '关联的动作key仅exercise类型',
`name` varchar(255) NOT NULL COMMENT '项目名称',
`sets` int DEFAULT NULL COMMENT '组数',
`reps` int DEFAULT NULL COMMENT '重复次数',
`duration_sec` int DEFAULT NULL COMMENT '持续时长(秒)',
`rest_sec` int DEFAULT NULL COMMENT '休息时长(秒)',
`note` text DEFAULT NULL COMMENT '备注',
`item_type` enum('exercise','rest','note') NOT NULL DEFAULT 'exercise' COMMENT '项目类型',
`completed` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否已完成',
`sort_order` int NOT NULL COMMENT '排序顺序',
`created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updated_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否已删除',
PRIMARY KEY (`id`),
KEY `idx_training_plan_id` (`training_plan_id`),
KEY `idx_exercise_key` (`exercise_key`),
KEY `idx_user_id` (`user_id`),
KEY `idx_sort_order` (`sort_order`),
KEY `idx_item_type` (`item_type`),
KEY `idx_plan_sort` (`training_plan_id`, `sort_order`),
CONSTRAINT `fk_schedule_exercises_training_plan` FOREIGN KEY (`training_plan_id`) REFERENCES `t_training_plans` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT `fk_schedule_exercises_exercise` FOREIGN KEY (`exercise_key`) REFERENCES `t_exercises` (`key`) ON DELETE SET NULL ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='训练计划动作表';
-- 验证表创建
SELECT
TABLE_NAME,
TABLE_COMMENT,
ENGINE
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME IN ('t_training_plans', 't_schedule_exercises')
ORDER BY TABLE_NAME;
-- 验证外键约束
SELECT
CONSTRAINT_NAME,
TABLE_NAME,
COLUMN_NAME,
REFERENCED_TABLE_NAME,
REFERENCED_COLUMN_NAME
FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE
WHERE TABLE_SCHEMA = DATABASE()
AND REFERENCED_TABLE_NAME IS NOT NULL
AND TABLE_NAME = 't_schedule_exercises'
ORDER BY CONSTRAINT_NAME;
-- 测试外键约束(插入测试数据)
-- 注意:这需要先有有效的 exercise_key 数据
/*
示例测试(请根据实际数据调整):
-- 插入测试训练计划
INSERT INTO t_training_plans (
id, user_id, name, start_date, mode, days_of_week, sessions_per_week, goal
) VALUES (
'550e8400-e29b-41d4-a716-446655440000',
'test_user_123',
'测试训练计划',
NOW(),
'daysOfWeek',
'[1,3,5]',
3,
'core_strength'
);
-- 插入测试动作
INSERT INTO t_schedule_exercises (
id, training_plan_id, user_id, exercise_key, name, sets, reps, item_type, sort_order
) VALUES (
'550e8400-e29b-41d4-a716-446655440001',
'550e8400-e29b-41d4-a716-446655440000',
'test_user_123',
'mat_hundred',
'百次拍打',
3,
10,
'exercise',
1
);
-- 验证数据
SELECT
tp.name as plan_name,
se.name as exercise_name,
se.exercise_key,
e.target_muscle_groups
FROM t_training_plans tp
JOIN t_schedule_exercises se ON tp.id = se.training_plan_id
LEFT JOIN t_exercises e ON se.exercise_key = e.key
WHERE tp.user_id = 'test_user_123';
-- 清理测试数据
DELETE FROM t_schedule_exercises WHERE user_id = 'test_user_123';
DELETE FROM t_training_plans WHERE user_id = 'test_user_123';
*/

View File

@@ -0,0 +1,31 @@
-- 创建训练会话表
CREATE TABLE t_workout_sessions (
id VARCHAR(36) PRIMARY KEY DEFAULT (UUID()),
user_id VARCHAR(255) NOT NULL COMMENT '用户ID',
training_plan_id VARCHAR(36) NOT NULL COMMENT '关联的训练计划模板',
name VARCHAR(255) NOT NULL COMMENT '训练会话名称',
scheduled_date DATETIME NOT NULL COMMENT '计划训练日期',
started_at DATETIME NULL COMMENT '实际开始时间',
completed_at DATETIME NULL COMMENT '实际结束时间',
status ENUM('planned', 'in_progress', 'completed', 'skipped') NOT NULL DEFAULT 'planned' COMMENT '训练状态',
total_duration_sec INT NULL COMMENT '总时长(秒)',
summary TEXT NULL COMMENT '训练总结/备注',
calories_burned INT NULL COMMENT '消耗卡路里(估算)',
stats JSON NULL COMMENT '训练统计数据',
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
deleted BOOLEAN DEFAULT FALSE COMMENT '是否已删除',
-- 外键约束
FOREIGN KEY (training_plan_id) REFERENCES t_training_plans(id),
-- 索引
INDEX idx_user_id (user_id),
INDEX idx_training_plan_id (training_plan_id),
INDEX idx_scheduled_date (scheduled_date),
INDEX idx_status (status),
INDEX idx_deleted (deleted)
);
-- 添加表注释
ALTER TABLE t_workout_sessions COMMENT = '训练会话表';

View File

@@ -0,0 +1,85 @@
-- 训练会话相关表创建脚本
-- 用于支持每日训练实例功能
-- 禁用外键检查
SET FOREIGN_KEY_CHECKS = 0;
-- 删除训练会话相关表(如果存在)
DROP TABLE IF EXISTS `t_workout_exercises`;
DROP TABLE IF EXISTS `t_workout_sessions`;
-- 重新启用外键检查
SET FOREIGN_KEY_CHECKS = 1;
-- 创建训练会话表
CREATE TABLE `t_workout_sessions` (
`id` char(36) NOT NULL COMMENT '训练会话唯一ID',
`user_id` varchar(255) NOT NULL COMMENT '用户ID',
`training_plan_id` char(36) NOT NULL COMMENT '关联的训练计划模板',
`name` varchar(255) NOT NULL COMMENT '训练会话名称',
`scheduled_date` datetime NOT NULL COMMENT '计划训练日期',
`started_at` datetime DEFAULT NULL COMMENT '实际开始时间',
`completed_at` datetime DEFAULT NULL COMMENT '实际结束时间',
`status` enum('planned','in_progress','completed','skipped') NOT NULL DEFAULT 'planned' COMMENT '训练状态',
`total_duration_sec` int DEFAULT NULL COMMENT '总时长(秒)',
`summary` text COMMENT '训练总结/备注',
`calories_burned` int DEFAULT NULL COMMENT '消耗卡路里(估算)',
`stats` json DEFAULT NULL COMMENT '训练统计数据',
`created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updated_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否已删除',
PRIMARY KEY (`id`),
KEY `idx_user_id` (`user_id`),
KEY `idx_training_plan_id` (`training_plan_id`),
KEY `idx_scheduled_date` (`scheduled_date`),
KEY `idx_status` (`status`),
KEY `idx_deleted` (`deleted`),
KEY `idx_user_date` (`user_id`, `scheduled_date`, `deleted`),
CONSTRAINT `fk_workout_sessions_training_plan` FOREIGN KEY (`training_plan_id`) REFERENCES `t_training_plans` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='训练会话表(每日训练实例)';
-- 创建训练会话动作表
CREATE TABLE `t_workout_exercises` (
`id` char(36) NOT NULL COMMENT '训练动作唯一ID',
`workout_session_id` char(36) NOT NULL COMMENT '所属训练会话ID',
`user_id` varchar(255) NOT NULL COMMENT '用户ID',
`exercise_key` varchar(255) DEFAULT NULL COMMENT '关联的动作key仅exercise类型',
`name` varchar(255) NOT NULL COMMENT '项目名称',
`planned_sets` int DEFAULT NULL COMMENT '计划组数',
`completed_sets` int DEFAULT NULL COMMENT '实际完成组数',
`planned_reps` int DEFAULT NULL COMMENT '计划重复次数',
`completed_reps` int DEFAULT NULL COMMENT '实际完成重复次数',
`planned_duration_sec` int DEFAULT NULL COMMENT '计划持续时长(秒)',
`actual_duration_sec` int DEFAULT NULL COMMENT '实际持续时长(秒)',
`rest_sec` int DEFAULT NULL COMMENT '休息时长(秒)',
`note` text COMMENT '备注',
`item_type` enum('exercise','rest','note') NOT NULL DEFAULT 'exercise' COMMENT '项目类型',
`status` enum('pending','in_progress','completed','skipped') NOT NULL DEFAULT 'pending' COMMENT '动作状态',
`sort_order` int NOT NULL COMMENT '排序顺序',
`started_at` datetime DEFAULT NULL COMMENT '开始时间',
`completed_at` datetime DEFAULT NULL COMMENT '完成时间',
`performance_data` json DEFAULT NULL COMMENT '详细执行数据',
`created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updated_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否已删除',
PRIMARY KEY (`id`),
KEY `idx_workout_session_id` (`workout_session_id`),
KEY `idx_user_id` (`user_id`),
KEY `idx_exercise_key` (`exercise_key`),
KEY `idx_sort_order` (`sort_order`),
KEY `idx_status` (`status`),
KEY `idx_deleted` (`deleted`),
KEY `idx_session_order` (`workout_session_id`, `sort_order`, `deleted`),
CONSTRAINT `fk_workout_exercises_session` FOREIGN KEY (`workout_session_id`) REFERENCES `t_workout_sessions` (`id`) ON DELETE CASCADE,
CONSTRAINT `fk_workout_exercises_exercise` FOREIGN KEY (`exercise_key`) REFERENCES `t_exercises` (`key`) ON DELETE SET NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='训练会话动作表(每日训练实例动作)';
-- 为 t_schedule_exercises 表添加注释,澄清其用途
ALTER TABLE `t_schedule_exercises` COMMENT = '训练计划动作表(训练计划模板的动作配置)';
-- 创建一些有用的索引
CREATE INDEX `idx_workout_sessions_user_status` ON `t_workout_sessions` (`user_id`, `status`, `deleted`);
CREATE INDEX `idx_workout_exercises_session_type` ON `t_workout_exercises` (`workout_session_id`, `item_type`, `deleted`);
-- 插入一些示例数据来测试
-- 注意实际使用时应该通过API来创建数据