Authored by qxm

Merge branch 'master' into feature/qxm

@@ -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"  
7 - class="media-content" mode="aspectFill" />  
8 - <view class="video" v-else @click="playVideo(actionDetail.urlTutorial)"> 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"
  13 + class="media-content" mode="aspectFill" />
  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">
@@ -150,7 +167,7 @@ @@ -150,7 +167,7 @@
150 <!-- <view class="difficulty">困难</view> --> 167 <!-- <view class="difficulty">困难</view> -->
151 <view class="difficulty">{{ 168 <view class="difficulty">{{
152 item.weight ? item.weight + 'kg' : '无负重' 169 item.weight ? item.weight + 'kg' : '无负重'
153 - }}</view> 170 + }}</view>
154 </view> 171 </view>
155 <view class="group-chips"> 172 <view class="group-chips">
156 <view class="chip" v-for="(set, index) in item.setConfigList" :key="index"> 173 <view class="chip" v-for="(set, index) in item.setConfigList" :key="index">
@@ -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 // 格式化时间
@@ -242,6 +242,7 @@ const loadsupersetsinfo = async () => { @@ -242,6 +242,7 @@ const loadsupersetsinfo = async () => {
242 242
243 // 页面跳转 243 // 页面跳转
244 const goToDetail = (id, type) => { 244 const goToDetail = (id, type) => {
  245 + console.log('type=', type);
245 nextTick(() => { 246 nextTick(() => {
246 actionDetailRef.value.open(id, type); 247 actionDetailRef.value.open(id, type);
247 }); 248 });
1 import request from '@/sheep/request'; 1 import request from '@/sheep/request';
2 2
3 const TrainingApi = { 3 const TrainingApi = {
4 -  
5 - //创建训练历史  
6 - creatTrainHistory:(data)=>{  
7 - return request({  
8 - url:'/app/training/history',  
9 - method:'POST',  
10 - data:data  
11 - });  
12 - },  
13 - // 获得训练历史  
14 - getTrainHistoryList: (id)=>{  
15 - return request({  
16 - url:'/app/training/history',  
17 - method:'GET',  
18 - params:{id}  
19 - });  
20 - }  
21 -} 4 + //创建训练历史
  5 + creatTrainHistory: (data) => {
  6 + return request({
  7 + url: '/app/training/history',
  8 + method: 'POST',
  9 + data: data,
  10 + });
  11 + },
  12 + // 获得训练历史
  13 + getTrainHistoryList: (id, unitType) => {
  14 + return request({
  15 + url: '/app/training/history',
  16 + method: 'GET',
  17 + params: { id, unitType },
  18 + });
  19 + },
  20 +};
22 21
23 -export default TrainingApi;  
  22 +export default TrainingApi;