SparkyFitness 自重训练完全指南:Bodyweight(+/− 体重)组类型详解

发布时间:2026/10/10 2:34:27
SparkyFitness 自重训练完全指南:Bodyweight(+/− 体重)组类型详解
后端前端移动开发【免费下载链接】SparkyFitnessSparkyFitness: Built for Families. Powered by AI. Track food, fitness, water, and health — together.项目地址https://gitcode.com/gh_mirrors/sp/SparkyFitness点击查看免费下载自重动作引体向上、双杠臂屈伸、俯卧撑等是力量训练中最基础也最容易被统计系统算错的一类。加片双杠臂屈伸20 kg 负重腰带和弹力带辅助引体−30 kg 助力之间真实移动的负荷相差几十公斤——如果只把数字当成普通杠铃片重量记录你的容量volume与预估 1RM 统计会严重失真。SparkyFitness 为此设计了专门的Bodyweight/− 体重组类型modalitybodyweight_reps以符号重量记录对自身体重的增减让加片、助力与纯自重训练都按真实负荷计入统计。本文基于 docs/src/features/exercises/bodyweight-exercises.md 官方文档结合 shared/src、SparkyFitnessServer、SparkyFitnessMobile 与 SparkyFitnessFrontend 仓库源码完整讲解从标记动作、录入数据到容量/1RM 计算原理的整条链路。一、什么是 Bodyweight/− 体重组类型SparkyFitness 的每次训练set都对应一种动作模态modality它决定了客户端渲染哪种编辑表单、服务端如何校验数据。模态定义集中在 shared/src/constants/exercise.tsexport const EXERCISE_MODALITIES [ weight_reps, // 重量 次数默认力量表 reps_only, // 仅次数无重量列 bodyweight_reps, // 次数 带符号重量本主题 weight_duration, // 重量 时长负重平板支撑等 weight_distance, // 重量 距离农夫行走、雪橇推等 duration, // 仅时长秒 duration_distance, // 有氧时长 距离公里 ] as const;bodyweight_reps的语义在源码注释中定义得非常清楚shared/src/constants/exercise.ts每组携带次数和一个带符号重量——正数表示额外负荷如 20 kg 的负重腰带负数表示助力如 −15 kg 的弹力带或助力器械。容量与预估 1RM 计算的是练习者体重加上该数值见effectiveLoadKg。也就是说这种组类型不再把重量理解为杠铃片重量而是理解为对自身体重的增减量。isBodyweightModality()shared/src/constants/exercise.ts用于判断某模态是否为自重模态它贯穿前后端与手表端的所有计算逻辑。二、将动作标记为自重训练2.1 手动选择在网页端或移动端创建/编辑动作时在组类型set type / modality下拉中选择Bodyweight/− 体重即可。移动端的选择器实现在 ExerciseFormScreen.tsx 的MODALITY_OPTIONS中其中就包含{ value: bodyweight_reps }。用户一旦手动选定模态该选择即被固定modalityManuallySet: true之后即使修改动作分类category模态也不会被静默重置ExerciseFormScreen.tsx。2.2 自动推导仅body only装备从动作库导入的动作若其唯一装备是body only徒手会自动预选该组类型。这一自动推导逻辑在 shared/src/constants/exercise.ts 的deriveExerciseModality()中category 为cardio→duration_distancecategory 为isometric/isometrics→duration装备列表只包含body only过滤掉被忽略的配件如 bench 等→bodyweight_reps其余情况 → 默认weight_reps注意两个细节shared/src/constants/exercise.ts空装备不算大量自定义动作与有氧动作的装备字段为空因此空装备不会被当作徒手处理未知装备名不算识别不了的装备名视为有装备不会把动作误判为自重——否则一个带自定义配件的动作会被错误标记为 bodyweight。在服务端resolveExerciseModality()shared/src/constants/exercise.ts作为显式模态优先、否则按分类推导的统一入口既用于服务端创建路径的清洗推导也作为客户端面对旧服务器的回退逻辑。2.3 随时可改自动预选只是默认值你可以在任何时候手动改回其他组类型。从架构上看这是刻意设计的数据库迁移 20260930190000_add_bodyweight_reps_modality.sql 只修改了exercises与exercise_entries两张表的modalityCHECK 约束加入bodyweight_reps不转换任何存量行——只有用户手动选择、或按上述装备规则新建/导入时才成为自重动作。三、录入组数据带符号重量每组数据包含次数reps与一个带符号重量signed weight你做的动作重量一栏怎么填普通引体向上留空或填 0负重腰带 20 kg 的双杠臂屈伸20或20弹力带/助力器械减 30 kg 的引体向上-30日志diary会把负重组显示为20读起来就是一个对体重的增量。在移动端这种动作的重量输入键盘会额外提供减号键iOS 的数字小键盘默认没有减号见 ActiveWorkoutSetRow.tsx。服务端对符号有严格校验assertSetWeightSign只允许bodyweight_reps模态出现负重量普通weight_reps模态的负重量会被直接拒绝详见测试 setWeightSign.test.ts。字符串形式的-10在自重模态下同样合法而在普通模态下抛错非数字字符串则原样放行交由后续数字解析处理。这从服务端堵死了给卧推填 −20 kg这类数据错误。四、容量Volume与预估 1RM 的计算原理4.1 真实负荷 体重 组重量自重组的真实移动负荷load是当前体重加上组重量。文档中的两个例子80 kg 练习者负重 20 kg 双杠臂屈伸移动100 kg助力 −30 kg 引体向上移动50 kg这一规则在 shared/src/utils/exerciseLoad.ts 的effectiveLoadKg()中精确实现export function effectiveLoadKg( weightKg: number | null | undefined, modality: ExerciseModality, bodyWeightKg: number | null | undefined, ): number { const weight Number(weightKg) || 0; if (!isBodyweightModality(modality)) return weight; const body Number(bodyWeightKg) || 0; return Math.max(0, body 0 ? body weight : weight); }关键点非自重模态直接返回组重量不受影响自重模态返回max(0, 体重 组重量)——地板为 0助力再大也不会算出负数负荷完全没有体重记录时只计算增加的重量负重组仍然计入统计20 就是 20 kg助力组则记为 0而不是负数。4.2 容量与 Epley 预估 1RM单组容量 真实负荷 × 次数即setVolumeKg()exerciseLoad.tseffectiveLoadKg × reps预估 1RM使用 Epley 公式epleyOneRepMaxKg()exerciseLoad.ts负荷 × (1 次数/30)负荷或次数非正数时返回 0重量 PR同样基于这个真实负荷。文档强调包括服务端 SQL 在内的所有容量/1RM 计算要么走effectiveLoadKg要么逐字复刻该规则exerciseLoad.ts。服务端的 SQL 镜像位于 SparkyFitnessServer/utils/exerciseLoadSql.ts其中setLoadSql()是同一规则的 SQL 版CASE WHEN ${entryAlias}.modality bodyweight_reps THEN GREATEST(0, COALESCE(bw.weight, 0) COALESCE(${setAlias}.weight, 0)) ELSE ${setAlias}.weight END容量统计在数据库端完成时使用这个setLoadSqlbodyWeightJoinSql则负责把体重读数 JOIN 进查询见下文。exerciseStatsService.ts 同时引用了这两个 SQL 工具。4.3 当天体重如何确定文档规定取训练日当天或之前最近一次的打卡体重若当天尚未称重则取之后最早的一次。完全没有记录时视为无体重。这个规则在 exerciseLoad.ts 的bodyWeightOnDay()中实现——先扫描≤ 训练日方向的最新一条再扫描 训练日方向的最早一条最终取before ?? after ?? null读数可按任意顺序传入日期为YYYY-MM-DD字符串。服务端 SQL 端用LEFT JOIN LATERAL复刻同一逻辑exerciseLoadSql.ts利用check_in_measurements表(user_id, entry_date)唯一索引分别取两个方向的最新/最早读数权重过滤条件为cim.weight 0。从源码结构看这套规则保证了即使训练当天没称重、几天后才补记历史训练的容量/1RM 也能用最接近的体重数据回填。4.4 移动端的实时 PR 比较移动端的实时 PRLive PR比较的是附加重量然后才是次数无负重组按 0 处理因此在普通引体向上上刷新最佳次数同样算 PR。这一语义来自文档定义自重组的统计口径是对体重的增量实时 PR 沿用同一口径避免用绝对负荷比较不同体重的训练者自己前后期的表现。五、自重组在其他统计中的表现重量 PR 排名在统计服务中负重引体等自重动作按其真实移动负荷排名exerciseStatsService.ts 注释明确a bodyweight exercise, so a weighted pull-up ranks on what it was分类统计exerciseStatsService的 SQL 查询会区分weight_reps/weight_duration/weight_distance与duration/duration_distance等模态exerciseStatsService.ts自重组归属力量类统计报表reportService.ts也引用了 bodyweight 相关逻辑自重动作的容量会进入各类训练报表。六、Apple Watch 上的自重动作在 Apple Watchtargets/watch 目录上自重动作的重量显示为BW 10——负重 10 kgBW −20——助力 20 kgBW——纯自重无增减显示格式化实现在 WorkoutView.swift 的bodyweightText()值为 0 时显示BW正数显示BW X负数显示BW −X使用真正的减号字符。重量小键盘带± 键用于输入助力组负数。判断某动作是否为自重动作的标志bodyweight由手机端通过ContextPayloadMapper.swifttargets/watch/Adapters/ContextPayloadMapper.swift随训练上下文下发给手表WorkoutSessionStore.swifttargets/watch/Application/WorkoutSessionStore.swift据此决定该组是否允许输入负数。因此文档特别提醒手表是在训练开始时学习动作是否为自重动作的请从包含该功能的手机端版本发起训练start the workout from a phone build that includes this确保训练计划中的自重标志能正确同步到手表。七、总结SparkyFitness 的 Bodyweight/− 体重组类型解决了自重训练统计中负重 ≠ 绝对负荷的核心痛点标记手动选择或按仅 body only 装备自动推导随时可改录入带符号重量 移动端减号键盘 服务端符号校验计算真实负荷 体重 组重量下限 0容量 负荷 × 次数预估 1RM 用 Epley 公式体重取训练日前后最近的打卡记录展示日志显示20增量、手表显示BW 10/BW −20/BW实时 PR 按附加重量与次数比较。从 shared/src 的纯 TS 核心计算到 exerciseLoadSql.ts 的 SQL 镜像、setWeightSign.test.ts 的符号校验测试再到 WorkoutView.swift 的BW渲染这套一处定义、多处镜像的规则让负重、助力和纯自重训练在容量、1RM 与 PR 统计中都能被准确衡量。赞分享后端前端移动开发【免费下载链接】SparkyFitnessSparkyFitness: Built for Families. Powered by AI. Track food, fitness, water, and health — together.项目地址https://gitcode.com/gh_mirrors/sp/SparkyFitness点击查看免费下载相关推荐lefthook 文件过滤器完全指南glob、exclude、file_types 与 root 的过滤管线解析lefthook 文件过滤器完全指南glob、exclude、file_types 与 root 的过滤管线解析 传给 Git 钩子的文件暂存文件、推送文件后端前端移动开发TorchVision ResNet 模型详解架构实现、预训练权重与实战训练指南TorchVision ResNet 模型详解架构实现、预训练权重与实战训练指南 本文以 TorchVision 仓库中 docs/source/models计算机视觉深度学习图像处理数据集告别重复劳动TensorFlow模型自动化再训练全流程详解告别重复劳动TensorFlow模型自动化再训练全流程详解 你是否还在手动处理模型再训练每次数据更新都要重新配置环境、调整参数、监控训练过程本文将带你掌握人工智能深度学习计算机视觉NLP语音上一篇Burp Suite汉化一条命令零配置启动让满屏英文界面变中文下一篇Loop完全免费的 macOS 窗口管理工具用径向菜单告别拖拽窗口创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考