refactor: 训练模块整体迁入分包,减小主包体积
主包超出 2MB 上限无法上传发布版,把训练相关全部移到独立分包。
目录调整:
- pages/training/* → training/pages/*
- hooks/use{Metronome,VoiceCoach,TrainingSession,TrainingBgm}.ts
→ training/hooks/*
- static/training/* → training/static/*
- 主包 hooks/ 目录已清空,所有 use* 都被分包独占
引用路径更新:
- 分包内 hook import 用相对路径 ../hooks/xxx,不依赖 @/ alias
- 资源路径 /static/training/audio/click.mp3
→ /training/static/audio/click.mp3
- useMetronome 默认 clickSrc / useVoiceCoach VOICE_BASE
/ useTrainingBgm BGM_BASE 全部对齐新路径
pages.json:
- 主包 pages 移除 training/index 和 training/metronome
- subPackages 新增 root="training",含 pages/index 和 pages/metronome
- 跟现有 TUIKit / doctor 分包风格一致
调用方:
- components/dev-training-entry navigateTo URL 更新成
/training/pages/metronome (此组件留在主包,主包跳分包是合法操作)
文档/工具同步:
- training/static/README.md 路径示例改为 training/static/...
- scripts/generate-voice.mjs VOICE_DIR 与提示输出对齐新路径
Git mv 检测到的全是 rename(R),历史完整保留。
分包总体 80K(pages 44K + hooks 20K + static 16K),主包瘦身明显。
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
<!-- 展开后的菜单卡片(从下往上动画) -->
|
||||
<view v-if="expanded" class="menu-list" @click.stop>
|
||||
<!-- "练一练" 暂时隐藏,后续恢复时取消注释即可
|
||||
<view class="menu-item" @click="goto('/pages/training/index')">
|
||||
<view class="menu-item" @click="goto('/training/pages/index')">
|
||||
<view class="menu-icon menu-icon--train">
|
||||
<text class="menu-icon-text">💪</text>
|
||||
</view>
|
||||
@@ -14,7 +14,7 @@
|
||||
<view class="menu-arrow">›</view>
|
||||
</view>
|
||||
-->
|
||||
<view class="menu-item" @click="goto('/pages/training/metronome')">
|
||||
<view class="menu-item" @click="goto('/training/pages/metronome')">
|
||||
<view class="menu-icon menu-icon--metro">
|
||||
<view class="metro-bar metro-bar-1" />
|
||||
<view class="metro-bar metro-bar-2" />
|
||||
|
||||
+21
-16
@@ -69,22 +69,6 @@
|
||||
"style": {
|
||||
"navigationBarTitleText": "付款"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/training/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "练一练"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/training/metronome",
|
||||
"style": {
|
||||
"navigationBarTitleText": "节拍器",
|
||||
"navigationBarBackgroundColor": "#f8fafc",
|
||||
"navigationBarTextStyle": "black",
|
||||
"backgroundColor": "#f8fafc",
|
||||
"disableScroll": true
|
||||
}
|
||||
}
|
||||
],
|
||||
"subPackages": [
|
||||
@@ -121,6 +105,27 @@
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"root": "training",
|
||||
"pages": [
|
||||
{
|
||||
"path": "pages/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "练一练"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/metronome",
|
||||
"style": {
|
||||
"navigationBarTitleText": "节拍器",
|
||||
"navigationBarBackgroundColor": "#f8fafc",
|
||||
"navigationBarTextStyle": "black",
|
||||
"backgroundColor": "#f8fafc",
|
||||
"disableScroll": true
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"tabBar": {
|
||||
|
||||
@@ -16,9 +16,9 @@
|
||||
* node scripts/generate-voice.mjs --voice 茉莉
|
||||
* node scripts/generate-voice.mjs --force # 已存在的也重新生成
|
||||
*
|
||||
* 输出:
|
||||
* src/static/training/voice/numbers/{1..30}.mp3
|
||||
* src/static/training/voice/prompts/{key}.mp3
|
||||
* 输出(分包):
|
||||
* training/static/voice/numbers/{1..30}.mp3
|
||||
* training/static/voice/prompts/{key}.mp3
|
||||
*
|
||||
* 需要 Node 18+(用内置 fetch)
|
||||
*/
|
||||
@@ -32,7 +32,7 @@ const __filename = fileURLToPath(import.meta.url)
|
||||
const __dirname = dirname(__filename)
|
||||
|
||||
const ROOT = join(__dirname, '..')
|
||||
const VOICE_DIR = join(ROOT, 'src/static/training/voice')
|
||||
const VOICE_DIR = join(ROOT, 'training/static/voice')
|
||||
const NUMBERS_DIR = join(VOICE_DIR, 'numbers')
|
||||
const PROMPTS_DIR = join(VOICE_DIR, 'prompts')
|
||||
|
||||
@@ -202,9 +202,9 @@ async function main() {
|
||||
}
|
||||
|
||||
console.log('\n下一步:')
|
||||
console.log(' 1. 准备 click 音 → src/static/training/audio/click.mp3')
|
||||
console.log(' 2. 准备 BGM → src/static/training/bgm/{train-light,rest-meditation}.mp3')
|
||||
console.log(' 3. npm run dev:mp-weixin → 进入 /pages/training/index')
|
||||
console.log(' 1. 准备 click 音 → training/static/audio/click.mp3')
|
||||
console.log(' 2. 准备 BGM → training/static/bgm/{train-light,rest-meditation}.mp3')
|
||||
console.log(' 3. 编译运行 → 进入 /training/pages/index')
|
||||
}
|
||||
|
||||
main().catch((e) => {
|
||||
|
||||
+1
-1
@@ -93,7 +93,7 @@ export function useMetronome(options: MetronomeOptions = {}) {
|
||||
initialBpm = 80,
|
||||
bpmMin = 40,
|
||||
bpmMax = 240,
|
||||
clickSrc = '/static/training/audio/click.mp3',
|
||||
clickSrc = '/training/static/audio/click.mp3',
|
||||
accentSrc,
|
||||
poolSize = 4,
|
||||
onBeat,
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
import { ref, onUnmounted } from 'vue'
|
||||
|
||||
const BGM_BASE = '/static/training/bgm'
|
||||
const BGM_BASE = '/training/static/bgm'
|
||||
|
||||
export type BgmMode = 'none' | 'training' | 'resting'
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
import { onUnmounted } from 'vue'
|
||||
|
||||
const VOICE_BASE = '/static/training/voice'
|
||||
const VOICE_BASE = '/training/static/voice'
|
||||
|
||||
export type VoicePromptKey =
|
||||
| 'start'
|
||||
@@ -151,10 +151,10 @@ import { onShow, onHide } from '@dcloudio/uni-app'
|
||||
import ExerciseAnim from './components/exercise-anim.vue'
|
||||
import { EXERCISE_PRESETS, getPresetById } from './exercises'
|
||||
import type { ExercisePreset } from './exercises'
|
||||
import { useMetronome } from '@/hooks/useMetronome'
|
||||
import { useTrainingSession } from '@/hooks/useTrainingSession'
|
||||
import { useVoiceCoach } from '@/hooks/useVoiceCoach'
|
||||
import { useTrainingBgm } from '@/hooks/useTrainingBgm'
|
||||
import { useMetronome } from '../hooks/useMetronome'
|
||||
import { useTrainingSession } from '../hooks/useTrainingSession'
|
||||
import { useVoiceCoach } from '../hooks/useVoiceCoach'
|
||||
import { useTrainingBgm } from '../hooks/useTrainingBgm'
|
||||
|
||||
const equipmentList = ['哑铃', '握力环', '健身环', '徒手'] as const
|
||||
type Equipment = (typeof equipmentList)[number]
|
||||
@@ -286,7 +286,7 @@ const onSkipRest = () => {
|
||||
}
|
||||
|
||||
const goMetronome = () => {
|
||||
uni.navigateTo({ url: '/pages/training/metronome' })
|
||||
uni.navigateTo({ url: '/training/pages/metronome' })
|
||||
}
|
||||
|
||||
onHide(() => {
|
||||
+3
-3
@@ -89,7 +89,7 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, onMounted, onUnmounted, ref, watch } from 'vue'
|
||||
import { onShow, onHide } from '@dcloudio/uni-app'
|
||||
import { useMetronome } from '@/hooks/useMetronome'
|
||||
import { useMetronome } from '../hooks/useMetronome'
|
||||
|
||||
/**
|
||||
* 跑步动画视频(腾讯云 COS CDN)
|
||||
@@ -145,8 +145,8 @@ const METER_OPTIONS = [
|
||||
const metronome = useMetronome({
|
||||
initialBpm: 80,
|
||||
accentEvery: 4,
|
||||
clickSrc: '/static/training/audio/click.mp3',
|
||||
accentSrc: '/static/training/audio/click-wood.mp3',
|
||||
clickSrc: '/training/static/audio/click.mp3',
|
||||
accentSrc: '/training/static/audio/click-wood.mp3',
|
||||
})
|
||||
const {
|
||||
bpm,
|
||||
+4
-4
@@ -5,7 +5,7 @@
|
||||
## 目录结构
|
||||
|
||||
```
|
||||
src/static/training/
|
||||
training/static/
|
||||
├── audio/
|
||||
│ └── click.mp3 # 节拍器主音(短促金属敲击声,约 50ms)
|
||||
├── voice/
|
||||
@@ -92,9 +92,9 @@ node scripts/generate-voice.mjs --force
|
||||
|
||||
## 在代码里被引用的位置
|
||||
|
||||
- `src/hooks/useMetronome.ts` → `audio/click.mp3`
|
||||
- `src/hooks/useVoiceCoach.ts` → `voice/numbers/*.mp3`、`voice/prompts/*.mp3`
|
||||
- `src/hooks/useTrainingBgm.ts` → `bgm/*.mp3`
|
||||
- `training/hooks/useMetronome.ts` → `audio/click.mp3`
|
||||
- `training/hooks/useVoiceCoach.ts` → `voice/numbers/*.mp3`、`voice/prompts/*.mp3`
|
||||
- `training/hooks/useTrainingBgm.ts` → `bgm/*.mp3`
|
||||
|
||||
如需修改路径,修改对应 hook 文件里的常量即可。
|
||||
|
||||
|
Before Width: | Height: | Size: 730 B After Width: | Height: | Size: 730 B |
Reference in New Issue
Block a user