|
...
|
...
|
@@ -4,12 +4,12 @@ |
|
|
|
<!-- 顶部日期栏 -->
|
|
|
|
<view class="header-bar">
|
|
|
|
<view class="close-btn" @click="closeCellPopup">
|
|
|
|
<uni-icons type="down" size="24" color="#333"></uni-icons>
|
|
|
|
<u-icon name="arrow-down" size="15" color="#333"></u-icon>
|
|
|
|
</view>
|
|
|
|
<view class="date-wrapper">
|
|
|
|
<text class="date-text">{{ displayDate }}</text>
|
|
|
|
</view>
|
|
|
|
<button class="date-note-btn" @click.stop="handleDateNote">日期备注</button>
|
|
|
|
<button class="date-note-btn" @click="handleDateNote">日期备注</button>
|
|
|
|
<button class="go-train-btn" @click.stop="startTraining">
|
|
|
|
<text class="go-train-text">去训练</text>
|
|
|
|
<text class="go-train-tag">GO</text>
|
|
...
|
...
|
@@ -21,10 +21,8 @@ |
|
|
|
<view class="noteContent" v-if="noteList.length > 0">
|
|
|
|
<text class="noteTitle">日程备注:</text>
|
|
|
|
<view class="noteTags">
|
|
|
|
<view class="noteTag" v-for="(item, idx) in noteList" :key="item.id"
|
|
|
|
:style="{ backgroundColor: item.backgroundColor }" @click="handleEditNote(item)">
|
|
|
|
{{ item.content }}
|
|
|
|
</view>
|
|
|
|
<u-tag class="noteTag" v-for="(item, idx) in noteList" :key="item.id" :text="item.content"
|
|
|
|
:bg-color="item.backgroundColor" color="#fff" shape="circle" @click="handleEditNote(item)" />
|
|
|
|
</view>
|
|
|
|
</view>
|
|
|
|
|
|
...
|
...
|
@@ -54,13 +52,10 @@ |
|
|
|
{{ currentPlan?.totalWeight }}kg</text>
|
|
|
|
</view>
|
|
|
|
<view class="plan-header-btns">
|
|
|
|
<button class="plan-btn more-btn" @click.stop="handlePlanMore">更多</button>
|
|
|
|
<button class="plan-btn copy-btn" @click.stop="openCopyCalendarPopup(currentPlan?.templateId)">
|
|
|
|
复制到
|
|
|
|
</button>
|
|
|
|
<button class="plan-btn go-train-btn-small" @click.stop="handleTrainAgain">
|
|
|
|
<button class="plan-btn more-btn" @click="handlePlanMore">更多</button>
|
|
|
|
<button class="plan-btn copy-btn" @click="openCopyCalendarPopup(currentPlan?.templateId)">复制到</button>
|
|
|
|
<button class="plan-btn go-train-btn-small" @click="handleTrainAgain">
|
|
|
|
<text class="go-train-text-sm">今日再练</text>
|
|
|
|
<!-- <text class="go-train-tag-sm">GO</text> -->
|
|
|
|
</button>
|
|
|
|
</view>
|
|
|
|
</view>
|
|
...
|
...
|
@@ -84,7 +79,7 @@ |
|
|
|
<view class="action-top">
|
|
|
|
<text class="action-name">{{ unit.exercises[0]?.exerciseName || '动作名称' }}</text>
|
|
|
|
<text class="action-totalWeight">{{ unit.totalWeight
|
|
|
|
}}kg</text>
|
|
|
|
}}kg</text>
|
|
|
|
</view>
|
|
|
|
|
|
|
|
<!-- 下半部分:组次行 → 向左对齐图片 ✅核心-->
|
|
...
|
...
|
@@ -93,25 +88,8 @@ |
|
|
|
<view class="set-item" v-for="(set, setIdx) in unit.exercises[0]?.sets || []" :key="setIdx">
|
|
|
|
<!-- 新增:把左边所有内容包起来 -->
|
|
|
|
<view class="set-left" :style="{ color: set.isCompleted === 1 ? '#333' : '#a2a2a2' }">
|
|
|
|
<!-- <text class="indexData">{{ setIdx + 1 }}</text> -->
|
|
|
|
<text class="set-content" v-if="unit.exercises[0].exerciseType === 0">
|
|
|
|
{{ set.weight }}kg x {{ set.reps }}次
|
|
|
|
</text>
|
|
|
|
<text class="set-content" v-if="unit.exercises[0].exerciseType === 1">
|
|
|
|
{{ formatSecondsToHms(set.duration) }} x {{ set.distance }}km
|
|
|
|
</text>
|
|
|
|
<text class="set-content" v-if="unit.exercises[0].exerciseType === 2">
|
|
|
|
{{ set.reps }}次
|
|
|
|
</text>
|
|
|
|
<text class="set-content" v-if="unit.exercises[0].exerciseType === 3">
|
|
|
|
{{ formatSecondsToHms(set.duration) }}
|
|
|
|
</text>
|
|
|
|
<text class="set-content" v-if="[4, 5].includes(unit.exercises[0].exerciseType)">
|
|
|
|
{{ set.weight }}kg x {{ set.duration }}s x {{ set.restTime }}
|
|
|
|
</text>
|
|
|
|
<text class="set-content" v-if="unit.exercises[0].exerciseType === 6">
|
|
|
|
{{ set.reps }}组 x {{ set.duration }}秒 x {{ set.restTime || 0 }}秒/组休息
|
|
|
|
</text>
|
|
|
|
<text class="set-content">{{ getSetDisplayText(set, unit.exercises[0].exerciseType)
|
|
|
|
}}</text>
|
|
|
|
</view>
|
|
|
|
<view class="set-right">
|
|
|
|
<text class="rest-time" v-if="set.restTime && unit.exercises[0].exerciseType != 6">
|
|
...
|
...
|
@@ -127,7 +105,6 @@ |
|
|
|
<!-- 右侧:修改按钮 + 完成对勾 -->
|
|
|
|
<view class="action-right" @click="openXiuGai(unit, unitIdx)">
|
|
|
|
<button class="modify-btn">修改</button>
|
|
|
|
<!-- <view class="check-icon">✓</view> -->
|
|
|
|
</view>
|
|
|
|
</view>
|
|
|
|
<!-- 情况2:超级组 unitType=2 -->
|
|
...
|
...
|
@@ -168,28 +145,8 @@ |
|
|
|
|
|
|
|
<view class="set-content"
|
|
|
|
:style="{ color: ex.sets[idx].isCompleted === 1 ? '#333' : '#a2a2a2' }">
|
|
|
|
<!-- 适配不同动作类型的显示文本 -->
|
|
|
|
<text v-if="ex.exerciseType === 0" class="detai-data">
|
|
|
|
{{ ex.sets[idx].weight }}kg x {{ ex.sets[idx].reps }}次
|
|
|
|
</text>
|
|
|
|
<text v-if="ex.exerciseType === 1" class="detai-data">
|
|
|
|
{{ formatSecondsToHms(ex.sets[idx].duration) }} x {{
|
|
|
|
ex.sets[idx].distance
|
|
|
|
}}km
|
|
|
|
</text>
|
|
|
|
<text v-if="ex.exerciseType === 2" class="detai-data">
|
|
|
|
{{ ex.sets[idx].reps }}次
|
|
|
|
</text>
|
|
|
|
<text v-if="ex.exerciseType === 3" class="detai-data">
|
|
|
|
{{ formatSecondsToHms(ex.sets[idx].duration) }}
|
|
|
|
</text>
|
|
|
|
<text v-if="[4, 5].includes(ex.exerciseType)" class="detai-data">
|
|
|
|
{{ ex.sets[idx].weight }}kg x {{ ex.sets[idx].reps }}次
|
|
|
|
</text>
|
|
|
|
<text v-if="ex.exerciseType === 6" class="detai-data">
|
|
|
|
{{ ex.sets[idx].reps }}次 x {{ ex.sets[idx].duration }}秒 x {{ ex.sets[idx].restTime
|
|
|
|
}}秒/组休息
|
|
|
|
</text>
|
|
|
|
<text class="detai-data">{{ getSuperSetDisplayText(ex.sets[idx], ex.exerciseType)
|
|
|
|
}}</text>
|
|
|
|
<view class="rest-time" v-if="ex.sets[idx]?.restTime && ex.exerciseType !== 6"
|
|
|
|
:style="{ color: ex.sets[idx].isCompleted === 1 ? '#999 !important' : '#a2a2a2 !important' }">
|
|
|
|
{{ ex.sets[idx].restTime }}s
|
|
...
|
...
|
@@ -212,21 +169,13 @@ |
|
|
|
<!-- 空状态区域 -->
|
|
|
|
<view v-else class="empty-section">
|
|
|
|
<image class="empty-img"
|
|
|
|
src="https://fitness-hcxtec-bucket.oss-cn-shenzhen.aliyuncs.com/20260316/order-empty_1773628059920.png"
|
|
|
|
src="https://fitness-hcxtec-bucket.oss-cn-shenzhen.aliyuncs.com/20260724/空状态自助_1784875704380.png"
|
|
|
|
mode="aspectFit">
|
|
|
|
</image>
|
|
|
|
<text class="empty-tip">今天没有安排</text>
|
|
|
|
<button class="add-train-btn" @click="openAddTrainPopup">+ 添加自助训练</button>
|
|
|
|
|
|
|
|
<!-- 底部课程类型卡片 -->
|
|
|
|
<!-- <view class="course-section">
|
|
|
|
<view class="course-item" v-for="(item, index) in courseList" :key="index"
|
|
|
|
@click="handleCourseClick(item.type)">
|
|
|
|
<image class="course-icon" :src="item.icon" mode="aspectFill"></image>
|
|
|
|
<text class="course-title">{{ item.title }}</text>
|
|
|
|
<text class="course-desc">{{ item.desc }}</text>
|
|
|
|
</view>
|
|
|
|
</view> -->
|
|
|
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
<AddTrainPopup v-model:visible="showAddTrainPopup" @successAddTrain="handleAddTrain" />
|
|
...
|
...
|
@@ -298,59 +247,44 @@ import CalendarColorPicker from '@/pages/xunji/components/rili-components/Calend |
|
|
|
import { useTrainingStore } from '@/sheep/store/trainingStore'
|
|
|
|
import MeiRiMoBanXiuGai from '../rili-components/meiri-moban-xiugai.vue'
|
|
|
|
|
|
|
|
// ===== Props & Emits =====
|
|
|
|
const props = defineProps({
|
|
|
|
date: { type: String, default: '' },
|
|
|
|
// noteList: {
|
|
|
|
// type: Array,
|
|
|
|
// default: () => []
|
|
|
|
// }
|
|
|
|
})
|
|
|
|
|
|
|
|
const show = ref(false);
|
|
|
|
const emit = defineEmits(['close', 'refreshCalendar']);
|
|
|
|
const noteList = ref([]);
|
|
|
|
|
|
|
|
// ===== 响应式状态 =====
|
|
|
|
const show = ref(false);
|
|
|
|
const showAddTrainPopup = ref(false);
|
|
|
|
const selectedDate = ref('');
|
|
|
|
const displayDate = ref('');
|
|
|
|
const resdailyData = ref([]);
|
|
|
|
// const noteList = ref([])
|
|
|
|
const currentPlanIndex = ref(0);
|
|
|
|
const noteList = ref([]);
|
|
|
|
const noteHistoryList = ref([]);
|
|
|
|
|
|
|
|
// 弹窗相关
|
|
|
|
const isMoveMode = ref(false);
|
|
|
|
const isCopyMode = ref(false);
|
|
|
|
const showRiqibeizhu = ref(false)
|
|
|
|
const moreShow = ref(false)
|
|
|
|
const showRiqibeizhu = ref(false);
|
|
|
|
const moreShow = ref(false);
|
|
|
|
const showColorPopup = ref(false);
|
|
|
|
const calendarPopupRef = ref(null);
|
|
|
|
const currentEditId = ref(null); // 新增这一行
|
|
|
|
const noteHistoryList = ref([]);
|
|
|
|
const currentEditId = ref(null);
|
|
|
|
const selectedPlanId = ref(null);
|
|
|
|
|
|
|
|
const showColorPopup = ref(false)
|
|
|
|
const selectedPlanId = ref(null)
|
|
|
|
// Store / 子组件引用
|
|
|
|
const trainingStore = useTrainingStore();
|
|
|
|
const meirimobanRef = ref(null);
|
|
|
|
|
|
|
|
const trainingStore = useTrainingStore()
|
|
|
|
// 修改单元缓存
|
|
|
|
const editUnitInfo = ref({
|
|
|
|
unit: null,
|
|
|
|
unitIndex: null,
|
|
|
|
dailyTemplate: null,
|
|
|
|
});
|
|
|
|
|
|
|
|
const meirimobanRef = ref(null)
|
|
|
|
// 没有训练模板时推荐课程
|
|
|
|
const courseList = ref([
|
|
|
|
{
|
|
|
|
type: 'group',
|
|
|
|
title: '团课',
|
|
|
|
desc: '大家一起练',
|
|
|
|
icon: 'https://fitness-hcxtec-bucket.oss-cn-shenzhen.aliyuncs.com/20260316/group-course.png'
|
|
|
|
},
|
|
|
|
{
|
|
|
|
type: 'private',
|
|
|
|
title: '私教',
|
|
|
|
desc: '1对1专人指导',
|
|
|
|
icon: 'https://fitness-hcxtec-bucket.oss-cn-shenzhen.aliyuncs.com/20260316/private-course.png'
|
|
|
|
},
|
|
|
|
{
|
|
|
|
type: 'smallClass',
|
|
|
|
title: '小班课',
|
|
|
|
desc: '28天极速瘦身',
|
|
|
|
icon: 'https://fitness-hcxtec-bucket.oss-cn-shenzhen.aliyuncs.com/20260316/small-class.png'
|
|
|
|
}
|
|
|
|
]);
|
|
|
|
|
|
|
|
// 打开弹窗
|
|
|
|
const openPopup = async () => {
|
|
...
|
...
|
@@ -370,14 +304,7 @@ defineExpose({ |
|
|
|
closeCellPopup
|
|
|
|
});
|
|
|
|
|
|
|
|
// 修改
|
|
|
|
// 定义缓存变量,传给弹窗
|
|
|
|
const editUnitInfo = ref({
|
|
|
|
unit: null,
|
|
|
|
unitIndex: null,
|
|
|
|
dailyTemplate: null // currentPlan(整个每日模板对象,含id、templateId)
|
|
|
|
})
|
|
|
|
// 打开弹窗修改单个unit
|
|
|
|
// ===== 弹窗:打开修改单个 unit =====
|
|
|
|
const openXiuGai = (unit, idx) => {
|
|
|
|
editUnitInfo.value = {
|
|
|
|
unit: JSON.parse(JSON.stringify(unit)), // 深拷贝防止原数据被实时篡改
|
|
...
|
...
|
@@ -410,12 +337,14 @@ const handleAddTrain = async () => { |
|
|
|
// 更新主页面
|
|
|
|
emit('refreshCalendar');
|
|
|
|
}
|
|
|
|
// ===== 计算属性 =====
|
|
|
|
// 当前正在显示的训记
|
|
|
|
const currentPlan = computed(() => {
|
|
|
|
if (!resdailyData.value.length) return null;
|
|
|
|
return resdailyData.value[currentPlanIndex.value] || null;
|
|
|
|
});
|
|
|
|
|
|
|
|
// ===== API:加载每日模板数据 =====
|
|
|
|
const loaddailytemplate = async () => {
|
|
|
|
if (!selectedDate.value) return;
|
|
|
|
console.log('【子组件】开始加载数据...');
|
|
...
|
...
|
@@ -458,7 +387,7 @@ const switchPlan = (index) => { |
|
|
|
console.log('【切换标签后 - currentPlan】', currentPlan.value);
|
|
|
|
};
|
|
|
|
|
|
|
|
// 更多弹窗控制
|
|
|
|
// ===== 更多弹窗:操作项 =====
|
|
|
|
const handlePlanMore = () => {
|
|
|
|
if (!currentPlan.value) { // 加这个
|
|
|
|
return
|
|
...
|
...
|
@@ -472,6 +401,13 @@ const closeMorePopup = () => { |
|
|
|
|
|
|
|
// 一键打勾(完成训练)
|
|
|
|
const handleCompleteCheck = async () => {
|
|
|
|
// 日期校验:只能对今天及以前的日期一键打勾
|
|
|
|
const today = dayjs().format('YYYY-MM-DD');
|
|
|
|
if (selectedDate.value > today) {
|
|
|
|
uni.showToast({ title: '一键打勾只能用于今天及以前的日期', icon: 'none' });
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!currentPlan.value?.id) {
|
|
|
|
uni.showToast({ title: '未找到训练ID', icon: 'none' })
|
|
|
|
return
|
|
...
|
...
|
@@ -494,13 +430,17 @@ const handleCompleteCheck = async () => { |
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 保存到我的模板
|
|
|
|
// const saveToMyTemplate = (dailyTemplate) => {
|
|
|
|
// console.log('dailyTemplate', dailyTemplate);
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
// ===== 保存训练为个人模板 =====
|
|
|
|
const openSaveTemplateDialog = async (item) => {
|
|
|
|
// 关闭所有可能遮挡的弹窗
|
|
|
|
moreShow.value = false;
|
|
|
|
showColorPopup.value = false;
|
|
|
|
showAddTrainPopup.value = false;
|
|
|
|
showRiqibeizhu.value = false;
|
|
|
|
show.value = false
|
|
|
|
// 等待 DOM 更新后再弹出模板名称输入框,确保弹窗完全关闭
|
|
|
|
await nextTick();
|
|
|
|
|
|
|
|
// uni弹窗输入框:只填模板名称
|
|
|
|
uni.showModal({
|
|
|
|
title: '确认保存为你的训练模板?',
|
|
...
|
...
|
@@ -520,7 +460,6 @@ const openSaveTemplateDialog = async (item) => { |
|
|
|
// 发起创建接口
|
|
|
|
console.log('reqData', reqData);
|
|
|
|
await submitCreateTemplate(reqData)
|
|
|
|
moreShow.value = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
...
|
...
|
@@ -580,25 +519,42 @@ const closeAddTrainPopup = () => { |
|
|
|
showAddTrainPopup.value = false;
|
|
|
|
};
|
|
|
|
|
|
|
|
// 弹窗选项点击事件
|
|
|
|
// const handleAddFromPlan = () => {
|
|
|
|
// uni.showToast({ title: '从训练计划添加', icon: 'none' });
|
|
|
|
// closeAddTrainPopup();
|
|
|
|
// };
|
|
|
|
// const handleAddFromTemplate = () => {
|
|
|
|
// uni.navigateTo({ url: '/pages4/pages/xunji/xunji-rili-tianjia-moban' });
|
|
|
|
// closeAddTrainPopup();
|
|
|
|
// };
|
|
|
|
// const handleFreeTraining = () => {
|
|
|
|
// uni.navigateTo({ url: '/pages4/pages/xunji/xunji-dongzuo-lianxi' });
|
|
|
|
// closeAddTrainPopup();
|
|
|
|
// };
|
|
|
|
|
|
|
|
// ===== 工具函数 =====
|
|
|
|
const formatSecondsToHms = (seconds) => {
|
|
|
|
if (!seconds || isNaN(seconds)) return '00:00:00';
|
|
|
|
return dayjs.duration(parseInt(seconds, 10), 'seconds').format('HH:mm:ss');
|
|
|
|
}
|
|
|
|
|
|
|
|
// ===== 工具函数:根据动作类型生成组次显示文本 =====
|
|
|
|
const getSetDisplayText = (set, exerciseType) => {
|
|
|
|
if (!set) return '';
|
|
|
|
switch (exerciseType) {
|
|
|
|
case 0: return `${set.weight || 0}kg x ${set.reps || 0}次`;
|
|
|
|
case 1: return `${formatSecondsToHms(set.duration)} x ${set.distance || 0}km`;
|
|
|
|
case 2: return `${set.reps || 0}次`;
|
|
|
|
case 3: return formatSecondsToHms(set.duration);
|
|
|
|
case 4:
|
|
|
|
case 5: return `${set.weight || 0}kg x ${set.duration || 0}s x ${set.restTime || 0}`;
|
|
|
|
case 6: return `${set.reps || 0}组 x ${set.duration || 0}秒 x ${set.restTime || 0}秒/组休息`;
|
|
|
|
default: return '';
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
// 超级组中的动作显示(与普通动作在 type 4/5 上的展示略有差异)
|
|
|
|
const getSuperSetDisplayText = (set, exerciseType) => {
|
|
|
|
if (!set) return '';
|
|
|
|
switch (exerciseType) {
|
|
|
|
case 0: return `${set.weight || 0}kg x ${set.reps || 0}次`;
|
|
|
|
case 1: return `${formatSecondsToHms(set.duration)} x ${set.distance || 0}km`;
|
|
|
|
case 2: return `${set.reps || 0}次`;
|
|
|
|
case 3: return formatSecondsToHms(set.duration);
|
|
|
|
case 4:
|
|
|
|
case 5: return `${set.weight || 0}kg x ${set.reps || 0}次`;
|
|
|
|
case 6: return `${set.reps || 0}次 x ${set.duration || 0}秒 x ${set.restTime || 0}秒/组休息`;
|
|
|
|
default: return '';
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
// 返回按钮逻辑
|
|
|
|
const goBack = () => {
|
|
|
|
uni.navigateBack({
|
|
...
|
...
|
@@ -609,19 +565,15 @@ const goBack = () => { |
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
// 日期格式化(兼容iOS)
|
|
|
|
// 日期格式化(使用 dayjs 处理,兼容性更好)
|
|
|
|
const formatDateWithWeek = (dateStr) => {
|
|
|
|
if (!dateStr) return '';
|
|
|
|
const d = dayjs(dateStr);
|
|
|
|
const weekMap = ['日', '一', '二', '三', '四', '五', '六'];
|
|
|
|
const iosSafeDate = new Date(dateStr.replace(/-/g, '/'));
|
|
|
|
const year = iosSafeDate.getFullYear();
|
|
|
|
const month = String(iosSafeDate.getMonth() + 1).padStart(2, '0');
|
|
|
|
const day = String(iosSafeDate.getDate()).padStart(2, '0');
|
|
|
|
const week = weekMap[iosSafeDate.getDay()];
|
|
|
|
return `${year}/${month}/${day} 周${week}`;
|
|
|
|
return `${d.format('YYYY/MM/DD')} 周${weekMap[d.day()]}`;
|
|
|
|
};
|
|
|
|
|
|
|
|
// 打开日期备注组件
|
|
|
|
// ===== 日期备注相关 =====
|
|
|
|
const handleDateNote = () => {
|
|
|
|
if (noteList.value.length >= 5) {
|
|
|
|
uni.showToast({
|
|
...
|
...
|
@@ -648,7 +600,7 @@ const handleCloseNotePopup = () => { |
|
|
|
currentEditId.value = null;
|
|
|
|
};
|
|
|
|
|
|
|
|
// 打开「添加到日历」弹窗
|
|
|
|
// ===== 复制到 / 移动到 =====
|
|
|
|
const openCalendarPopup = (templateId) => {
|
|
|
|
console.log('点击了添加到日历按钮', templateId); // 新增日志
|
|
|
|
console.log('子组件实例', calendarPopupRef.value); // 新增日志
|
|
...
|
...
|
@@ -695,6 +647,14 @@ const handleDeleteTemplate = async () => { |
|
|
|
uni.showToast({ title: '未找到模板ID', icon: 'none' });
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
// 关闭所有可能遮挡的弹窗
|
|
|
|
moreShow.value = false;
|
|
|
|
showColorPopup.value = false;
|
|
|
|
showAddTrainPopup.value = false;
|
|
|
|
showRiqibeizhu.value = false;
|
|
|
|
show.value = false
|
|
|
|
// 等待 DOM 更新后再弹出模板名称输入框,确保弹窗完全关闭
|
|
|
|
await nextTick();
|
|
|
|
// 弹出确认框
|
|
|
|
uni.showModal({
|
|
|
|
title: '确认删除',
|
|
...
|
...
|
@@ -820,7 +780,7 @@ const calendarColorPickerSuccess = () => { |
|
|
|
emit('refreshCalendar')
|
|
|
|
}
|
|
|
|
|
|
|
|
// 去训练
|
|
|
|
// ===== 去训练 / 每日模板编辑 =====
|
|
|
|
const startTraining = () => {
|
|
|
|
|
|
|
|
if (trainingStore.isTraining) {
|
|
...
|
...
|
@@ -861,6 +821,7 @@ const templateEdit = (plan) => { |
|
|
|
console.log('开始进入编辑模板页面,模板ID:', plan.templateId, '每日模板ID:', plan.id);
|
|
|
|
};
|
|
|
|
|
|
|
|
// ===== 监听 & 生命周期 =====
|
|
|
|
// 监听父组件传进来的 date 变化
|
|
|
|
watch(
|
|
|
|
() => props.date,
|
|
...
|
...
|
@@ -888,6 +849,19 @@ onMounted(() => { |
|
|
|
</script>
|
|
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
|
|
// ===== 公共变量 =====
|
|
|
|
$color-primary: #333;
|
|
|
|
$color-accent: #ffc107;
|
|
|
|
$color-bg: #f2f3f5;
|
|
|
|
$color-white: #fff;
|
|
|
|
$color-danger: #ff4d4f;
|
|
|
|
$color-muted: #a2a2a2;
|
|
|
|
$color-card-bg: #f9f9f9;
|
|
|
|
$radius-sm: 8rpx;
|
|
|
|
$radius-md: 12rpx;
|
|
|
|
$radius-lg: 16rpx;
|
|
|
|
$radius-round: 40rpx;
|
|
|
|
|
|
|
|
/* 全局容器 */
|
|
|
|
.container {
|
|
|
|
display: flex;
|
|
...
|
...
|
@@ -941,9 +915,14 @@ onMounted(() => { |
|
|
|
|
|
|
|
.date-text {
|
|
|
|
font-size: 28rpx;
|
|
|
|
white-space: nowrap;
|
|
|
|
overflow: hidden;
|
|
|
|
text-overflow: ellipsis;
|
|
|
|
}
|
|
|
|
|
|
|
|
.date-note-btn {
|
|
|
|
display: inline-flex;
|
|
|
|
align-items: center;
|
|
|
|
font-size: 28rpx;
|
|
|
|
color: #333;
|
|
|
|
background: #e7e7e9;
|
|
...
|
...
|
@@ -1066,11 +1045,11 @@ onMounted(() => { |
|
|
|
}
|
|
|
|
|
|
|
|
.go-train-btn-small {
|
|
|
|
// background: #ffc107;
|
|
|
|
color: #000;
|
|
|
|
display: flex;
|
|
|
|
align-items: center;
|
|
|
|
padding: 12rpx 20rpx;
|
|
|
|
background: inherit;
|
|
|
|
}
|
|
|
|
|
|
|
|
.go-train-text-sm {
|
|
...
|
...
|
@@ -1286,34 +1265,34 @@ onMounted(() => { |
|
|
|
flex-direction: column;
|
|
|
|
align-items: center;
|
|
|
|
justify-content: center;
|
|
|
|
// width: 500rpx;
|
|
|
|
height: 500rpx;
|
|
|
|
margin-top: 100rpx;
|
|
|
|
padding: 20rpx 20rpx 60rpx;
|
|
|
|
padding: 80rpx 40rpx 120rpx;
|
|
|
|
box-sizing: border-box;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
.empty-img {
|
|
|
|
width: 280rpx;
|
|
|
|
height: 280rpx;
|
|
|
|
margin-bottom: 30rpx;
|
|
|
|
width: 360rpx;
|
|
|
|
height: 360rpx;
|
|
|
|
margin-bottom: 40rpx;
|
|
|
|
transform: scale(3);
|
|
|
|
}
|
|
|
|
|
|
|
|
.empty-tip {
|
|
|
|
font-size: 32rpx;
|
|
|
|
color: #666;
|
|
|
|
margin-bottom: 60rpx;
|
|
|
|
font-weight: 500;
|
|
|
|
margin-bottom: 80rpx;
|
|
|
|
letter-spacing: 2rpx;
|
|
|
|
}
|
|
|
|
|
|
|
|
.add-train-btn {
|
|
|
|
font-size: 30rpx;
|
|
|
|
color: #000;
|
|
|
|
background: #ffc107;
|
|
|
|
border-radius: 40rpx;
|
|
|
|
padding: 20rpx 80rpx;
|
|
|
|
background: $color-accent;
|
|
|
|
border-radius: $radius-round;
|
|
|
|
padding: 24rpx 80rpx;
|
|
|
|
border: none;
|
|
|
|
margin-bottom: 60rpx;
|
|
|
|
font-weight: 500;
|
|
|
|
box-shadow: 0 4rpx 12rpx rgba(255, 193, 7, 0.3);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* 底部课程类型区域 */
|
|
...
|
...
|
@@ -1485,6 +1464,7 @@ button::after { |
|
|
|
border: none;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 训记切换标签 */
|
|
|
|
.plan-tabs {
|
|
|
|
white-space: nowrap;
|
|
...
|
...
|
@@ -1512,152 +1492,145 @@ button::after { |
|
|
|
color: #fff;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ========== 超级组样式(已修复 无重复 无嵌套错误)========== */
|
|
|
|
/* ========== 超级组样式 ========== */
|
|
|
|
.superset-wrapper {
|
|
|
|
margin-bottom: 20rpx;
|
|
|
|
background: #fff;
|
|
|
|
border-radius: 12rpx;
|
|
|
|
background: $color-white;
|
|
|
|
border-radius: $radius-md;
|
|
|
|
overflow: hidden;
|
|
|
|
}
|
|
|
|
|
|
|
|
.superset-wrapper .super-head {
|
|
|
|
display: flex;
|
|
|
|
align-items: center;
|
|
|
|
padding: 24rpx 20rpx;
|
|
|
|
position: relative;
|
|
|
|
gap: 16rpx;
|
|
|
|
}
|
|
|
|
|
|
|
|
.superset-wrapper .super-image {
|
|
|
|
width: 75rpx;
|
|
|
|
height: 75rpx;
|
|
|
|
flex-shrink: 0;
|
|
|
|
}
|
|
|
|
.super-head {
|
|
|
|
display: flex;
|
|
|
|
align-items: center;
|
|
|
|
padding: 24rpx 20rpx;
|
|
|
|
position: relative;
|
|
|
|
gap: 16rpx;
|
|
|
|
}
|
|
|
|
|
|
|
|
.superset-wrapper .super-title-wrap {
|
|
|
|
flex: 1;
|
|
|
|
display: flex;
|
|
|
|
flex-direction: column;
|
|
|
|
gap: 8rpx;
|
|
|
|
}
|
|
|
|
.super-image {
|
|
|
|
width: 75rpx;
|
|
|
|
height: 75rpx;
|
|
|
|
flex-shrink: 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
.superset-wrapper .super-title {
|
|
|
|
font-size: 32rpx;
|
|
|
|
color: #111;
|
|
|
|
font-weight: 500;
|
|
|
|
}
|
|
|
|
.super-title-wrap {
|
|
|
|
flex: 1;
|
|
|
|
display: flex;
|
|
|
|
flex-direction: column;
|
|
|
|
gap: 8rpx;
|
|
|
|
}
|
|
|
|
|
|
|
|
.superset-wrapper .super-totalWeight {
|
|
|
|
font-size: 24rpx;
|
|
|
|
color: #666;
|
|
|
|
}
|
|
|
|
.super-title {
|
|
|
|
font-size: 32rpx;
|
|
|
|
color: #111;
|
|
|
|
font-weight: 500;
|
|
|
|
}
|
|
|
|
|
|
|
|
.superset-wrapper .super-actionName {
|
|
|
|
padding: 0 20rpx 20rpx 70rpx;
|
|
|
|
display: flex;
|
|
|
|
flex-direction: column;
|
|
|
|
gap: 12rpx;
|
|
|
|
}
|
|
|
|
.super-totalWeight {
|
|
|
|
font-size: 24rpx;
|
|
|
|
color: #666;
|
|
|
|
}
|
|
|
|
|
|
|
|
.superset-wrapper .name-item {
|
|
|
|
display: flex;
|
|
|
|
align-items: center;
|
|
|
|
gap: 12rpx;
|
|
|
|
}
|
|
|
|
.super-actionName {
|
|
|
|
padding: 0 20rpx 20rpx 70rpx;
|
|
|
|
display: flex;
|
|
|
|
flex-direction: column;
|
|
|
|
gap: 12rpx;
|
|
|
|
|
|
|
|
.superset-wrapper .letter {
|
|
|
|
font-size: 28rpx;
|
|
|
|
font-weight: bold;
|
|
|
|
color: #333;
|
|
|
|
}
|
|
|
|
.action-name {
|
|
|
|
font-size: 28rpx;
|
|
|
|
color: $color-primary;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
.superset-wrapper .super-actionName .action-name {
|
|
|
|
font-size: 28rpx;
|
|
|
|
color: #333;
|
|
|
|
}
|
|
|
|
.name-item {
|
|
|
|
display: flex;
|
|
|
|
align-items: center;
|
|
|
|
gap: 12rpx;
|
|
|
|
}
|
|
|
|
|
|
|
|
.superset-wrapper .super-set-list {
|
|
|
|
padding: 0 20rpx 20rpx 20rpx;
|
|
|
|
display: flex;
|
|
|
|
flex-direction: column;
|
|
|
|
gap: 12rpx;
|
|
|
|
}
|
|
|
|
.letter {
|
|
|
|
font-size: 28rpx;
|
|
|
|
font-weight: bold;
|
|
|
|
color: $color-primary;
|
|
|
|
}
|
|
|
|
|
|
|
|
.superset-wrapper .super-set-item {
|
|
|
|
display: flex;
|
|
|
|
// flex-direction: column; // 新增:垂直排列
|
|
|
|
align-items: stretch; // 让每个动作占满宽度
|
|
|
|
gap: 12rpx; // 垂直间距(可根据需要微调)
|
|
|
|
padding: 16rpx;
|
|
|
|
background: #f9f9f9;
|
|
|
|
border-radius: 12rpx;
|
|
|
|
}
|
|
|
|
.super-set-list {
|
|
|
|
padding: 0 20rpx 20rpx 20rpx;
|
|
|
|
display: flex;
|
|
|
|
flex-direction: column;
|
|
|
|
gap: 12rpx;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 为了让序号独立占一行
|
|
|
|
.superset-wrapper .super-set-item {
|
|
|
|
margin-bottom: 8rpx;
|
|
|
|
}
|
|
|
|
.super-set-item {
|
|
|
|
display: flex;
|
|
|
|
align-items: stretch;
|
|
|
|
gap: 12rpx;
|
|
|
|
padding: 16rpx;
|
|
|
|
background: #f9f9f9;
|
|
|
|
border-radius: 12rpx;
|
|
|
|
margin-bottom: 8rpx;
|
|
|
|
}
|
|
|
|
|
|
|
|
.superset-wrapper .set-number {
|
|
|
|
font-size: 26rpx;
|
|
|
|
background: #e4e4e4;
|
|
|
|
color: #282828;
|
|
|
|
width: 37rpx;
|
|
|
|
height: 37rpx;
|
|
|
|
text-align: center;
|
|
|
|
flex-shrink: 0; // /* 不被父容器挤压变形,保持固定大小 */
|
|
|
|
border-radius: 50%;
|
|
|
|
// line-height: 60rpx;
|
|
|
|
}
|
|
|
|
.set-number {
|
|
|
|
font-size: 26rpx;
|
|
|
|
background: #e4e4e4;
|
|
|
|
color: #282828;
|
|
|
|
width: 37rpx;
|
|
|
|
height: 37rpx;
|
|
|
|
text-align: center;
|
|
|
|
flex-shrink: 0; // /* 不被父容器挤压变形,保持固定大小 */
|
|
|
|
border-radius: 50%;
|
|
|
|
// line-height: 60rpx;
|
|
|
|
}
|
|
|
|
|
|
|
|
.superset-wrapper .set-column {
|
|
|
|
display: flex;
|
|
|
|
flex-direction: column;
|
|
|
|
}
|
|
|
|
.set-column {
|
|
|
|
display: flex;
|
|
|
|
flex-direction: column;
|
|
|
|
}
|
|
|
|
|
|
|
|
.superset-wrapper .action-in-set {
|
|
|
|
// display: flex;
|
|
|
|
// flex-direction: column;
|
|
|
|
width: 100%;
|
|
|
|
display: flex;
|
|
|
|
align-items: center;
|
|
|
|
margin-bottom: 8rpx;
|
|
|
|
}
|
|
|
|
.action-in-set {
|
|
|
|
// display: flex;
|
|
|
|
// flex-direction: column;
|
|
|
|
width: 100%;
|
|
|
|
display: flex;
|
|
|
|
align-items: center;
|
|
|
|
margin-bottom: 8rpx;
|
|
|
|
}
|
|
|
|
|
|
|
|
.superset-wrapper .action-in-set:last-child {
|
|
|
|
margin-bottom: 0;
|
|
|
|
}
|
|
|
|
.action-in-set:last-child {
|
|
|
|
margin-bottom: 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
.superset-wrapper .action-letter {
|
|
|
|
display: inline-block;
|
|
|
|
font-size: 26rpx;
|
|
|
|
color: #666;
|
|
|
|
// width: 35rpx;
|
|
|
|
white-space: nowrap;
|
|
|
|
margin-right: 12rpx;
|
|
|
|
flex-shrink: 0;
|
|
|
|
}
|
|
|
|
.action-letter {
|
|
|
|
display: inline-block;
|
|
|
|
font-size: 26rpx;
|
|
|
|
color: #666;
|
|
|
|
// width: 35rpx;
|
|
|
|
white-space: nowrap;
|
|
|
|
margin-right: 12rpx;
|
|
|
|
flex-shrink: 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
.superset-wrapper .set-content {
|
|
|
|
font-size: 26rpx;
|
|
|
|
color: inherit;
|
|
|
|
flex: 1;
|
|
|
|
}
|
|
|
|
.set-content {
|
|
|
|
font-size: 26rpx;
|
|
|
|
color: inherit;
|
|
|
|
flex: 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
.superset-wrapper .rest-time {
|
|
|
|
font-size: 24rpx;
|
|
|
|
// color: inherit;
|
|
|
|
margin-left: 10rpx;
|
|
|
|
flex-shrink: 0;
|
|
|
|
}
|
|
|
|
.rest-time {
|
|
|
|
font-size: 24rpx;
|
|
|
|
// color: inherit;
|
|
|
|
margin-left: 10rpx;
|
|
|
|
flex-shrink: 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
.superset-wrapper .check {
|
|
|
|
font-size: 26rpx;
|
|
|
|
color: #333;
|
|
|
|
margin-left: 275rpx !important;
|
|
|
|
/* 这里控制和左边内容的距离,数值你可以自己调 */
|
|
|
|
flex-shrink: 0;
|
|
|
|
/* 防止被压缩 */
|
|
|
|
.check {
|
|
|
|
font-size: 26rpx;
|
|
|
|
color: #333;
|
|
|
|
margin-left: 275rpx !important;
|
|
|
|
flex-shrink: 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
.superset-title {
|
|
...
|
...
|
@@ -1673,16 +1646,14 @@ button::after { |
|
|
|
.noteContent {
|
|
|
|
display: flex;
|
|
|
|
align-items: flex-start;
|
|
|
|
/* 改成顶部对齐,而不是居中 */
|
|
|
|
gap: 12rpx;
|
|
|
|
padding: 20rpx;
|
|
|
|
background: #fff;
|
|
|
|
background: $color-white;
|
|
|
|
}
|
|
|
|
|
|
|
|
.noteTitle {
|
|
|
|
font-size: 26rpx;
|
|
|
|
color: #666;
|
|
|
|
/* 关键:固定宽度,保证标签容器的左边距稳定 */
|
|
|
|
flex-shrink: 0;
|
|
|
|
width: 150rpx;
|
|
|
|
}
|
|
...
|
...
|
@@ -1694,11 +1665,10 @@ button::after { |
|
|
|
gap: 12rpx;
|
|
|
|
}
|
|
|
|
|
|
|
|
.noteTag {
|
|
|
|
// u-tag 微调
|
|
|
|
:deep(.noteTag) {
|
|
|
|
width: auto !important;
|
|
|
|
font-size: 24rpx;
|
|
|
|
color: #fff;
|
|
|
|
padding: 6rpx 14rpx;
|
|
|
|
border-radius: 10rpx;
|
|
|
|
line-height: 1.2;
|
|
|
|
}
|
|
|
|
</style> |
|
|
\ No newline at end of file |
...
|
...
|
|