|
@@ -3,9 +3,26 @@ |
|
@@ -3,9 +3,26 @@ |
|
3
|
<scroll-view class="action-container" scroll-y>
|
3
|
<scroll-view class="action-container" scroll-y>
|
|
4
|
<view class="header" v-if="type == 1">
|
4
|
<view class="header" v-if="type == 1">
|
|
5
|
<view class="explain">
|
5
|
<view class="explain">
|
|
6
|
- <image v-if="modeTab < 2" :src="modeTab == 0 ? actionDetail.url3dAnimation : actionDetail.urlRealPerson"
|
6
|
+ <!-- 3D 固定图片 -->
|
|
|
|
7
|
+ <image v-if="modeTab === 0" :src="actionDetail.url3dAnimation" class="media-content" mode="aspectFill" />
|
|
|
|
8
|
+
|
|
|
|
9
|
+ <!-- 真人模块:自动区分图片/视频 -->
|
|
|
|
10
|
+ <template v-else-if="modeTab === 1">
|
|
|
|
11
|
+ <!-- 是图片 -->
|
|
|
|
12
|
+ <image v-if="!isVideoUrl(actionDetail.urlRealPerson)" :src="actionDetail.urlRealPerson"
|
|
7
|
class="media-content" mode="aspectFill" />
|
13
|
class="media-content" mode="aspectFill" />
|
|
8
|
- <view class="video" v-else @click="playVideo(actionDetail.urlTutorial)">
|
14
|
+ <!-- 是视频 -->
|
|
|
|
15
|
+ <view v-else class="video" @click="playVideo(actionDetail.urlRealPerson)">
|
|
|
|
16
|
+ <video :src="actionDetail.urlRealPerson" class="media-content" :autoplay="false"
|
|
|
|
17
|
+ :show-center-play-btn="false" :controls="false" />
|
|
|
|
18
|
+ <view class="play-icon">
|
|
|
|
19
|
+ <up-icon name="play-right" size="28" class="icon" color="#fff"></up-icon>
|
|
|
|
20
|
+ </view>
|
|
|
|
21
|
+ </view>
|
|
|
|
22
|
+ </template>
|
|
|
|
23
|
+
|
|
|
|
24
|
+ <!-- 讲解 固定视频 -->
|
|
|
|
25
|
+ <view v-else class="video" @click="playVideo(actionDetail.urlTutorial)">
|
|
9
|
<video :src="actionDetail.urlTutorial" class="media-content" :autoplay="false" :show-center-play-btn="false"
|
26
|
<video :src="actionDetail.urlTutorial" class="media-content" :autoplay="false" :show-center-play-btn="false"
|
|
10
|
:controls="false" />
|
27
|
:controls="false" />
|
|
11
|
<view class="play-icon">
|
28
|
<view class="play-icon">
|
|
@@ -218,6 +235,7 @@ const actionId = ref(0); |
|
@@ -218,6 +235,7 @@ const actionId = ref(0); |
|
218
|
// 记录是超级组还是动作组 1=动作组,2=超级组
|
235
|
// 记录是超级组还是动作组 1=动作组,2=超级组
|
|
219
|
const type = ref(0);
|
236
|
const type = ref(0);
|
|
220
|
const showBeizhuRef = ref(null);
|
237
|
const showBeizhuRef = ref(null);
|
|
|
|
238
|
+
|
|
221
|
const historyList = ref([]); // 训练历史列表接口数据
|
239
|
const historyList = ref([]); // 训练历史列表接口数据
|
|
222
|
const lostImage =
|
240
|
const lostImage =
|
|
223
|
'https://fitness-hcxtec-bucket.oss-cn-shenzhen.aliyuncs.com/20260316/order-empty_1773628059920.png';
|
241
|
'https://fitness-hcxtec-bucket.oss-cn-shenzhen.aliyuncs.com/20260316/order-empty_1773628059920.png';
|
|
@@ -227,6 +245,14 @@ const switchModeTab = (index) => { |
|
@@ -227,6 +245,14 @@ const switchModeTab = (index) => { |
|
227
|
modeTab.value = index;
|
245
|
modeTab.value = index;
|
|
228
|
};
|
246
|
};
|
|
229
|
|
247
|
|
|
|
|
248
|
+// 判断链接是否为视频链接
|
|
|
|
249
|
+const isVideoUrl = (url) => {
|
|
|
|
250
|
+ if (!url) return false;
|
|
|
|
251
|
+ const videoExts = ['.mp4', '.mov', '.avi', '.mkv', '.webm'];
|
|
|
|
252
|
+ const lowerUrl = url.toLowerCase();
|
|
|
|
253
|
+ return videoExts.some(ext => lowerUrl.includes(ext));
|
|
|
|
254
|
+};
|
|
|
|
255
|
+
|
|
230
|
// 跳转到视频播放的页面
|
256
|
// 跳转到视频播放的页面
|
|
231
|
const playVideo = (url) => {
|
257
|
const playVideo = (url) => {
|
|
232
|
uni.navigateTo({
|
258
|
uni.navigateTo({
|
|
@@ -276,9 +302,9 @@ const startTraining = () => { |
|
@@ -276,9 +302,9 @@ const startTraining = () => { |
|
276
|
|
302
|
|
|
277
|
const open = (id, typeData) => {
|
303
|
const open = (id, typeData) => {
|
|
278
|
actionId.value = Number(id);
|
304
|
actionId.value = Number(id);
|
|
279
|
-
|
|
|
|
280
|
type.value = typeData;
|
305
|
type.value = typeData;
|
|
281
|
contentTab.value = 0;
|
306
|
contentTab.value = 0;
|
|
|
|
307
|
+ console.log('动作详情页面接收id和类型:', actionId.value, type.value);
|
|
282
|
// 如何判断是动作还是超级组
|
308
|
// 如何判断是动作还是超级组
|
|
283
|
if (typeData == 1) {
|
309
|
if (typeData == 1) {
|
|
284
|
loadexercisedetail(actionId.value);
|
310
|
loadexercisedetail(actionId.value);
|
|
@@ -289,6 +315,9 @@ const open = (id, typeData) => { |
|
@@ -289,6 +315,9 @@ const open = (id, typeData) => { |
|
289
|
checkSupersetFavorited();
|
315
|
checkSupersetFavorited();
|
|
290
|
}
|
316
|
}
|
|
291
|
|
317
|
|
|
|
|
318
|
+ console.log('请求参数actionId/typeData', actionId.value, type.value);
|
|
|
|
319
|
+
|
|
|
|
320
|
+
|
|
292
|
loadTrainHistoryDetail(actionId.value, type.value);
|
321
|
loadTrainHistoryDetail(actionId.value, type.value);
|
|
293
|
actionShow.value = true;
|
322
|
actionShow.value = true;
|
|
294
|
};
|
323
|
};
|
|
@@ -381,12 +410,21 @@ const loadAlternativeActions = async (id) => { |
|
@@ -381,12 +410,21 @@ const loadAlternativeActions = async (id) => { |
|
381
|
|
410
|
|
|
382
|
// 加载训练历史
|
411
|
// 加载训练历史
|
|
383
|
const loadTrainHistoryDetail = async (id, type) => {
|
412
|
const loadTrainHistoryDetail = async (id, type) => {
|
|
|
|
413
|
+ // 新增参数校验
|
|
|
|
414
|
+ if (!id || isNaN(Number(id)) || type === undefined || type === null) {
|
|
|
|
415
|
+ console.warn('训练历史参数非法,跳过请求', { id, type });
|
|
|
|
416
|
+ historyList.value = [];
|
|
|
|
417
|
+ return;
|
|
|
|
418
|
+ }
|
|
|
|
419
|
+ console.log('训练历史请求参数:', id, type);
|
|
|
|
420
|
+
|
|
384
|
try {
|
421
|
try {
|
|
385
|
- const res = await TrainingApi.getTrainHistoryList(id, type);
|
|
|
|
386
|
- historyList.value = res.data;
|
422
|
+ const res = await TrainingApi.getTrainHistoryList(Number(id), Number(type));
|
|
|
|
423
|
+ historyList.value = res.data || [];
|
|
387
|
console.log('训练历史列表接口返回结果historyList.value', historyList.value);
|
424
|
console.log('训练历史列表接口返回结果historyList.value', historyList.value);
|
|
388
|
} catch (error) {
|
425
|
} catch (error) {
|
|
389
|
console.error('加载训练历史失败:', error);
|
426
|
console.error('加载训练历史失败:', error);
|
|
|
|
427
|
+ historyList.value = [];
|
|
390
|
}
|
428
|
}
|
|
391
|
};
|
429
|
};
|
|
392
|
// 格式化时间
|
430
|
// 格式化时间
|