|
|
|
<template>
|
|
|
|
<view class="action-container" @click="closeDifficulty">
|
|
|
|
<view class="action-list" v-if="deleteActionShow === false">
|
|
|
|
<view class="card">
|
|
|
|
<view class="card-top" @click.stop="isExpanded = !isExpanded">
|
|
|
|
<view v-if="type === 1">
|
|
|
|
<image class="action-image" :src="actionDetail?.urlImage || lostImage" mode="aspectFill"></image>
|
|
|
|
</view>
|
|
|
|
<view v-if="type === 2">
|
|
|
|
<image class="action-image"
|
|
|
|
src="https://fitness-hcxtec-bucket.oss-cn-shenzhen.aliyuncs.com/20260507/超级组_1778117889451.png"
|
|
|
|
mode="aspectFill"></image>
|
|
|
|
</view>
|
|
|
|
<view class="action-info">
|
|
|
|
<!-- 动作的 -->
|
|
|
|
<text class="name">{{ actionDetail?.name }}</text>
|
|
|
|
<text class="tags" v-if="type === 1">{{ actionDetail?.categoryDescription }} {{
|
|
|
|
actionDetail?.equipmentDescription }}</text>
|
|
|
|
<!-- 这里还缺kg/要搞个计算属性 -->
|
|
|
|
<text class="tags" v-if="type === 2">超级组</text>
|
|
|
|
<view class="dot-list" v-if="!isExpanded">
|
|
|
|
<view class="dot" v-for="(item, index) in recordList" :key="'dot-' + index"></view>
|
|
|
|
</view>
|
|
|
|
</view>
|
|
|
|
<view class="more-circle" @click.stop="toggleTips">
|
|
|
|
<up-icon name="more-dot-fill" color="#fff" size="15" class="icon"></up-icon>
|
|
|
|
<view class="tips" v-if="showTips">
|
|
|
|
<view class="tip" @click="openBeizhu">文字备注</view>
|
|
|
|
<view class="tip" @click="openAllQuickTimer">组间休息</view>
|
|
|
|
<view class="tip" @click="handleReplaceAction">动作替换</view>
|
|
|
|
<view class="tip" @click="deleteAction">删除动作</view>
|
|
|
|
</view>
|
|
|
|
</view>
|
|
|
|
</view>
|
|
|
|
|
|
|
|
<view class="main" v-if="isExpanded">
|
|
|
|
<!-- 当类型为4,5时,显示体重输入框 -->
|
|
|
|
<!--动作的 recordList 的输入控制 -->
|
|
|
|
<template v-if="type === 1">
|
|
|
|
<view class="userWeight" v-if="[4, 5].includes(actionDetail.exerciseType)">
|
|
|
|
<view class="row" hover-class="none" hover-stop-propagation="false">
|
|
|
|
<text class="label">体重</text>
|
|
|
|
<view class="userWeight-values" @click="openWeightPicker">
|
|
|
|
<text class="weight-text" style="color: #fbdc00; font-size: 20rpx;">
|
|
|
|
{{ displayWeight }}
|
|
|
|
</text>
|
|
|
|
<up-icon name="edit-pen" color="#8e8e93" size="20"></up-icon>
|
|
|
|
</view>
|
|
|
|
</view>
|
|
|
|
<view class="explain" v-if="actionDetail?.exerciseType === 4">
|
|
|
|
该动作为自重加重,根据你的体重加上辅助器械重量计算容量,下方的填写重量为辅助器械重量。
|
|
|
|
</view>
|
|
|
|
<view class="explain" v-if="actionDetail?.exerciseType === 5">
|
|
|
|
该动作为自重减重,根据你的体重减去辅助器械重量计算容量,下方的填写重量为辅助器械重量。
|
|
|
|
</view>
|
|
|
|
</view>
|
|
|
|
<!-- 导入子组件 -->
|
|
|
|
<action-set-input v-for="(item, index) in recordList" :key="index"
|
|
|
|
:exercise-type="actionDetail.exerciseType" :record="item" :index="index" :is-editing="isEditing"
|
|
|
|
@openPicker="openPicker" @openQuickTimer="openQuickTimer" @toggleActive="toggleActive" @addRow="addRow"
|
|
|
|
@deleteRow="deleteRow" :user-weight="userWeight" @change-weight="userWeight = $event" />
|
|
|
|
</template>
|
|
|
|
<!-- 超级组的训练数据控制 -->
|
|
|
|
<template v-else-if="type === 2">
|
|
|
|
<view class="super-group">
|
|
|
|
<view class="img-list" v-if="type === 2">
|
|
|
|
<image v-for="item in (actionDetail?.exercises || [])" :key="item.id" :src="item?.urlImage || lostImage"
|
|
|
|
class="img"></image>
|
|
|
|
</view>
|
|
|
|
<!-- 超级组:如果内部包含自重加重/减重,显示体重输入v-if="hasWeightExercise" -->
|
|
|
|
<view class="userWeight" v-if="hasWeightExercise">
|
|
|
|
<view class="row">
|
|
|
|
<text class="label">体重</text>
|
|
|
|
<view class="userWeight-values" @click="openWeightPicker">
|
|
|
|
<text class="weight-text" style="color: #fbdc00; font-size: 20rpx;">
|
|
|
|
{{ displayWeight }}
|
|
|
|
</text>
|
|
|
|
<up-icon name="edit-pen" color="#8e8e93" size="20"></up-icon>
|
|
|
|
</view>
|
|
|
|
</view>
|
|
|
|
<!-- <view class="explain" v-if="actionDetail?.exerciseType === 4">
|
|
|
|
该动作为自重加重,根据你的体重加上辅助器械重量计算容量,下方的填写重量为辅助器械重量。
|
|
|
|
</view>
|
|
|
|
<view class="explain" v-if="actionDetail?.exerciseType === 5">
|
|
|
|
该动作为自重减重,根据你的体重减去辅助器械重量计算容量,下方的填写重量为辅助器械重量。
|
|
|
|
</view> -->
|
|
|
|
</view>
|
|
|
|
<!-- 外层:循环【每一组】 -->
|
|
|
|
<view class="set-group" v-for="(setItem, setIndex) in superTotalSets" :key="setIndex">
|
|
|
|
<view class="set-header">
|
|
|
|
<view class="index-box">{{ setIndex + 1 }}</view>
|
|
|
|
<view class="set-action-names">
|
|
|
|
<text v-for="(sub, idx) in actionDetail.exercises" :key="sub.id">
|
|
|
|
{{ String.fromCharCode(65 + idx) }} {{ sub.name }}
|
|
|
|
</text>
|
|
|
|
</view>
|
|
|
|
<!-- 休息时间选择 -->
|
|
|
|
<view class="timer-selector" @click.stop="openSuperQuickTimer(setIndex)" v-if="!isEditing">
|
|
|
|
<text class="text">{{ superGroupSetData(setIndex).quickTimeDisplay || '60s' }}</text>
|
|
|
|
<up-icon name="arrow-down" color="#8e8e93" size="10"></up-icon>
|
|
|
|
</view>
|
|
|
|
<!-- 勾选框 -->
|
|
|
|
<view class="icon" @click.stop="toggleSuperSetActive(setIndex)"
|
|
|
|
:class="{ active: superGroupSetData(setIndex).isActive }" v-if="!isEditing">
|
|
|
|
<up-icon name="checkmark" :color="superGroupSetData(setIndex).isActive ? '#000' : '#919191'"
|
|
|
|
size="20" bold></up-icon>
|
|
|
|
</view>
|
|
|
|
<!-- 新增和删除按钮 -->
|
|
|
|
<view class="icons" v-if="isEditing">
|
|
|
|
<view class="icon" @click.stop="addSuperSet">
|
|
|
|
<up-icon name="plus-circle" color="#fff" size="20" bold></up-icon>
|
|
|
|
</view>
|
|
|
|
<view class="icon del" @click.stop="deleteSuperSet(setIndex)">
|
|
|
|
<up-icon name="trash" color="#e63e1e" size="20" bold></up-icon>
|
|
|
|
</view>
|
|
|
|
</view>
|
|
|
|
</view>
|
|
|
|
|
|
|
|
<!-- 内层:循环【组内的每个子动作A/B】 -->
|
|
|
|
<super-set-input v-for="(sub, idx) in actionDetail.exercises" :key="sub.id"
|
|
|
|
:sub-exercise-type="sub.exerciseType" :set-index="setIndex" :sub-index="idx" :user-weight="userWeight"
|
|
|
|
:data="getSubActionData(setIndex, sub.id)" @open-time-picker="openSuperPicker(setIndex, sub.id)" />
|
|
|
|
</view>
|
|
|
|
</view>
|
|
|
|
</template>
|
|
|
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
<view class="button-group" v-if="isExpanded">
|
|
|
|
<view class="btn-item" @click.stop="addGroup">加一组</view>
|
|
|
|
<view class="btn-item" @click="openHistory(props?.id)">历史</view>
|
|
|
|
<!-- 历史弹窗 -->
|
|
|
|
<actionHistory ref="historyPopupRef" :actionName="actionDetail.name" :historyType="props.type" />
|
|
|
|
<!-- 动作难度选择弹窗 -->
|
|
|
|
<view class="btn-item" @click.stop="showDifficulty = !showDifficulty">
|
|
|
|
<text :style="{ color: currentDifficulty.color }">{{ currentDifficulty.label }}</text>
|
|
|
|
<up-icon name="arrow-down" size="8" color="#fff"></up-icon>
|
|
|
|
|
|
|
|
<view class="difficulty-pop" v-if="showDifficulty">
|
|
|
|
<view class="difficulty-item" @click.stop="selectDifficulty('轻松', '#b2f055')">
|
|
|
|
<text :style="{ color: '#b2f055' }">轻松</text>
|
|
|
|
<up-icon v-if="currentDifficulty.label === '轻松'" name="checkmark" color="#b2f055" size="16"
|
|
|
|
bold></up-icon>
|
|
|
|
</view>
|
|
|
|
<view class="difficulty-item" @click.stop="selectDifficulty('正常', '#ffffff')">
|
|
|
|
<text :style="{ color: '#ffffff' }">正常</text>
|
|
|
|
<up-icon v-if="currentDifficulty.label === '正常'" name="checkmark" color="#ffffff" size="16"
|
|
|
|
bold></up-icon>
|
|
|
|
</view>
|
|
|
|
<view class="difficulty-item" @click.stop="selectDifficulty('困难', '#e26c2a')">
|
|
|
|
<text :style="{ color: '#e26c2a' }">困难</text>
|
|
|
|
<up-icon v-if="currentDifficulty.label === '困难'" name="checkmark" color="#e26c2a" size="16"
|
|
|
|
bold></up-icon>
|
|
|
|
</view>
|
|
|
|
</view>
|
|
|
|
</view>
|
|
|
|
|
|
|
|
<view class="btn-item" @click.stop="isEditing = !isEditing">
|
|
|
|
{{ isEditing ? '完成' : '编辑' }}
|
|
|
|
</view>
|
|
|
|
</view>
|
|
|
|
</view>
|
|
|
|
</view>
|
|
|
|
|
|
|
|
<up-picker :show="showPicker" :columns="timeColumns" :defaultIndex="defaultTimeIndex" title="请选择运动时长"
|
|
|
|
@confirm="onTimeConfirm" @cancel="showPicker = false" closeOnClickOverlay popupClass="custom-picker"></up-picker>
|
|
|
|
|
|
|
|
<up-picker :show="showQuickPicker" :columns="quickColumns" title="设置休息时长" @confirm="onQuickConfirm"
|
|
|
|
@cancel="showQuickPicker = false" closeOnClickOverlay popupClass="custom-picker"></up-picker>
|
|
|
|
|
|
|
|
<!-- 备注弹窗组件(可创建备注成功,但无法显示到动作详情弹窗组件) -->
|
|
|
|
<beizhu ref="showBeizhuRef" @saveSuccess="handleNoteSave" />
|
|
|
|
<!-- 动作替换弹窗 -->
|
|
|
|
<replaceActionPopup :show="replacePopupShow" :unitIndex="unitIndex" @close="replacePopupShow = false" />
|
|
|
|
|
|
|
|
<!-- 体重选择器 -->
|
|
|
|
<up-picker :show="showWeightPicker" :columns="weightColumns" :defaultIndex="defaultWeightIndex" title="设置体重"
|
|
|
|
@confirm="onWeightConfirm" @cancel="showWeightPicker = false" closeOnClickOverlay
|
|
|
|
popupClass="custom-picker"></up-picker>
|
|
|
|
|
|
|
|
</view>
|
|
|
|
</template>
|
|
|
|
|
|
|
|
<script setup>
|
|
|
|
import { ref, reactive, watch, computed, nextTick, onMounted } from 'vue';
|
|
|
|
import beizhu from '@/pages/xunji/components/beizhu.vue';
|
|
|
|
// import actionHistory from '../components/dongzuo-lianxi-history.vue'
|
|
|
|
import actionHistory from '@/pages/xunji/components/dongzuo-lianxi/dongzuo-lianxi-history.vue'
|
|
|
|
import SupersetsApi from '@/sheep/api/motion/supersets';
|
|
|
|
import ExercisesApi from '@/sheep/api/motion/exercises';
|
|
|
|
import { getCurrentInstance } from 'vue';
|
|
|
|
import { useTrainingStore } from '@/sheep/store/trainingStore'
|
|
|
|
// import replaceActionPopup from '../components/replace-action-popup.vue'
|
|
|
|
import replaceActionPopup from '@/pages/xunji/components/dongzuo-lianxi/replace-action-popup.vue'
|
|
|
|
// import actionSetInput from '@/pages4/components/action-set-input.vue'
|
|
|
|
import actionSetInput from '@/pages/xunji/components/dongzuo-lianxi/action-set-input.vue'
|
|
|
|
// import superSetInput from '../components/super-set-input.vue'
|
|
|
|
import superSetInput from '@/pages/xunji/components/dongzuo-lianxi/super-set-input.vue'
|
|
|
|
|
|
|
|
|
|
|
|
const trainingStore = useTrainingStore()
|
|
|
|
const deleteActionShow = ref(false)
|
|
|
|
const showTips = ref(false);
|
|
|
|
const isExpanded = ref(false);
|
|
|
|
const isEditing = ref(false);
|
|
|
|
const showPicker = ref(false);
|
|
|
|
const showQuickPicker = ref(false);
|
|
|
|
const activeIndex = ref(0);
|
|
|
|
const activeActionId = ref('');
|
|
|
|
const emit = defineEmits(['register', 'update:groupCount', 'replace-action', 'deleteAction', 'replaceActionForSave'])
|
|
|
|
const lostImage = "https://fitness-hcxtec-bucket.oss-cn-shenzhen.aliyuncs.com/20260316/order-empty_1773628059920.png"
|
|
|
|
|
|
|
|
const historyPopupRef = ref(null)
|
|
|
|
const showBeizhuRef = ref(null);
|
|
|
|
const userWeight = ref(70)
|
|
|
|
// 休息时间设置模式:single=单行,all=全部组
|
|
|
|
const restEditMode = ref('single');
|
|
|
|
const replacePopupShow = ref(false)
|
|
|
|
|
|
|
|
// 接收父组件的数据
|
|
|
|
const props = defineProps({
|
|
|
|
id: [Number, String],
|
|
|
|
type: [Number, String],
|
|
|
|
index: Number, // 新增
|
|
|
|
unitIndex: Number,
|
|
|
|
actionDetail: {
|
|
|
|
type: Object,
|
|
|
|
default: () => ({})
|
|
|
|
},
|
|
|
|
isDailyTemplates: {
|
|
|
|
type: Boolean,
|
|
|
|
default: false
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
watch(() => props.id, () => {
|
|
|
|
console.log('dongzuo组件 id/type:', props.id, props.type)
|
|
|
|
console.log('打印props.actionDetail', props.actionDetail)
|
|
|
|
console.log('dongzuo组件 unitIndex:', props.unitIndex)
|
|
|
|
if (props.type === 2)
|
|
|
|
console.log('打印父组件传过来超级组动作列表的props.actionDetail.exercises', props.actionDetail.exercises);
|
|
|
|
|
|
|
|
}, { immediate: true })
|
|
|
|
|
|
|
|
emit('register', props.index, getCurrentInstance()?.proxy)
|
|
|
|
|
|
|
|
// 体重选择器
|
|
|
|
const displayWeight = computed(() => {
|
|
|
|
return `${userWeight.value}kg`
|
|
|
|
})
|
|
|
|
|
|
|
|
// 2. 体重选择器状态
|
|
|
|
const showWeightPicker = ref(false)
|
|
|
|
const weightColumns = reactive([
|
|
|
|
// 整数部分:10 ~ 250
|
|
|
|
Array.from({ length: 241 }, (_, i) => (i + 10).toString()),
|
|
|
|
// 小数部分:0 ~ 9
|
|
|
|
Array.from({ length: 10 }, (_, i) => i.toString()),
|
|
|
|
['千克(kg)'] // 第三列固定文字
|
|
|
|
])
|
|
|
|
const defaultWeightIndex = ref([60, 0, 0]) // 默认 70.0kg(10+60=70)
|
|
|
|
|
|
|
|
// 3. 打开体重选择器
|
|
|
|
const openWeightPicker = () => {
|
|
|
|
// 直接用数字处理,避免转字符串
|
|
|
|
const num = userWeight.value
|
|
|
|
const intPart = Math.floor(num)
|
|
|
|
const decPart = Math.round((num - intPart) * 10) // 取小数第一位
|
|
|
|
|
|
|
|
// 计算索引(整数部分:intPart - 10,小数部分:decPart)
|
|
|
|
const intIndex = Math.max(0, Math.min(intPart - 10, 240))
|
|
|
|
defaultWeightIndex.value = [intIndex, decPart, 0]
|
|
|
|
showWeightPicker.value = true
|
|
|
|
}
|
|
|
|
|
|
|
|
// 4. 体重选择器确认事件
|
|
|
|
const onWeightConfirm = (e) => {
|
|
|
|
const intPart = e.value[0] // 整数部分
|
|
|
|
const decPart = e.value[1] // 小数部分
|
|
|
|
// 拼接成完整体重
|
|
|
|
userWeight.value = parseFloat(`${intPart}.${decPart}`)
|
|
|
|
showWeightPicker.value = false
|
|
|
|
}
|
|
|
|
|
|
|
|
// 文字备注
|
|
|
|
// 打开备注弹窗
|
|
|
|
const openBeizhu = () => {
|
|
|
|
nextTick(() => {
|
|
|
|
if (showBeizhuRef.value) {
|
|
|
|
showBeizhuRef.value.open(props.actionDetail.id);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
// 接收子组件传过来的备注内容
|
|
|
|
const handleNoteSave = async (content) => {
|
|
|
|
try {
|
|
|
|
if (props.type == 2) {
|
|
|
|
await SupersetsApi.addNotes({
|
|
|
|
supersetsId: props.id,
|
|
|
|
content: content,
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
await ExercisesApi.addNotes({
|
|
|
|
exerciseId: props.id,
|
|
|
|
content: content,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
props.actionDetail.userNote = content;
|
|
|
|
} catch (e) {
|
|
|
|
console.log(e);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
const toggleTips = () => {
|
|
|
|
showTips.value = !showTips.value
|
|
|
|
}
|
|
|
|
|
|
|
|
// 超级组是否包含间歇类型动作(用来控制组头休息时间选择器的显示)
|
|
|
|
const hasIntervalExercise = computed(() => {
|
|
|
|
if (props.type !== 2) return false
|
|
|
|
const exercises = props.actionDetail?.exercises || []
|
|
|
|
// 只要有一个子动作是间歇类型(6),就不显示组头的休息时间
|
|
|
|
return exercises.some(sub => sub.exerciseType === 6)
|
|
|
|
})
|
|
|
|
// 替换动作
|
|
|
|
const handleReplaceAction = () => {
|
|
|
|
showTips.value = false
|
|
|
|
replacePopupShow.value = true // 打开弹窗
|
|
|
|
console.log("✅ 弹窗打开:", replacePopupShow.value)
|
|
|
|
}
|
|
|
|
|
|
|
|
// 超级组是否包含 4(自重加重) / 5(自重减重)
|
|
|
|
const hasWeightExercise = computed(() => {
|
|
|
|
if (props.type !== 2) return false
|
|
|
|
const exercises = props.actionDetail?.exercises || []
|
|
|
|
return exercises.some(sub => [4, 5].includes(sub.exerciseType))
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
// 删除动作
|
|
|
|
const deleteAction = () => {
|
|
|
|
|
|
|
|
if (props.isDailyTemplates) {
|
|
|
|
showTips.value = false;
|
|
|
|
emit('deleteAction');
|
|
|
|
// trainingStore.actionDetail.units.splice(props.unitIndex, 1)
|
|
|
|
// trainingStore.clearTrainingStore()
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
trainingStore.deleteUnitRecord(props.unitIndex);
|
|
|
|
console.log('训练类型 type =', trainingStore.type)
|
|
|
|
console.log('组件类型 props.type =', props.type)
|
|
|
|
console.log('unitIndex =', props.unitIndex)
|
|
|
|
deleteActionShow.value = true
|
|
|
|
|
|
|
|
// 1. 如果是【模板训练】,删除对应项
|
|
|
|
if (trainingStore.type === 3) {
|
|
|
|
console.log('模板训练:删除第', props.unitIndex, '个单元')
|
|
|
|
trainingStore.actionDetail.units.splice(props.unitIndex, 1)
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
console.log('单个动作/超级组:清空')
|
|
|
|
trainingStore.clearTrainingStore()
|
|
|
|
}
|
|
|
|
// 关闭菜单
|
|
|
|
showTips.value = false
|
|
|
|
console.log('删除完成 ✅')
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// 难度控制逻辑
|
|
|
|
const showDifficulty = ref(false);
|
|
|
|
const initialDifficulty = { label: '难度', color: '#ffffff' };
|
|
|
|
const currentDifficulty = ref({ ...initialDifficulty });
|
|
|
|
|
|
|
|
const selectDifficulty = (label, color) => {
|
|
|
|
if (currentDifficulty.value.label === label) {
|
|
|
|
currentDifficulty.value = { ...initialDifficulty };
|
|
|
|
} else {
|
|
|
|
currentDifficulty.value = { label, color };
|
|
|
|
}
|
|
|
|
showDifficulty.value = false;
|
|
|
|
};
|
|
|
|
|
|
|
|
// 点击背景关闭所有弹窗
|
|
|
|
const closeDifficulty = () => {
|
|
|
|
showDifficulty.value = false;
|
|
|
|
showTips.value = false;
|
|
|
|
};
|
|
|
|
|
|
|
|
// 超级组数据控制
|
|
|
|
const superRecordMap = ref({})
|
|
|
|
// 超级组:总组数(计算第一个动作的组数即可)
|
|
|
|
const superTotalSets = computed(() => {
|
|
|
|
if (props.type !== 2) return 0
|
|
|
|
const exercises = props.actionDetail?.exercises || []
|
|
|
|
if (exercises.length === 0) return 0
|
|
|
|
const firstId = exercises[0].id
|
|
|
|
console.log('打印超级组的组数:', superRecordMap.value[firstId]?.length);
|
|
|
|
return superRecordMap.value[firstId]?.length || 0
|
|
|
|
})
|
|
|
|
|
|
|
|
onMounted(() => {
|
|
|
|
// 从 Pinia 加载当前 unit 的训练数据
|
|
|
|
const savedData = trainingStore.getUnitRecord(props.unitIndex);
|
|
|
|
// 恢复体重
|
|
|
|
userWeight.value = savedData.userWeight || 70;
|
|
|
|
console.log('从pinia加载的数据:', savedData);
|
|
|
|
|
|
|
|
// 1. 先从 Pinia 恢复已有数据
|
|
|
|
if (props.type === 1) {
|
|
|
|
// 关键:只有当前是初始默认1条,才赋值,不再覆盖watch结果
|
|
|
|
if (savedData.records?.[props.actionDetail.id]) {
|
|
|
|
recordList.value = [...savedData.records[props.actionDetail.id]]
|
|
|
|
console.log('onMounted兜底赋值', recordList.value)
|
|
|
|
}
|
|
|
|
} else if (props.type === 2) {
|
|
|
|
if (savedData.records && Object.keys(savedData.records).length > 0) {
|
|
|
|
superRecordMap.value = { ...savedData.records };
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// 2. 超级组兜底初始化:只要有子动作,且 superRecordMap 为空就初始化
|
|
|
|
if (props.type === 2 && props.actionDetail?.exercises?.length) {
|
|
|
|
const exercises = props.actionDetail.exercises;
|
|
|
|
// 判断:当前超级组还没任何结构 才初始化
|
|
|
|
const firstId = exercises[0].id;
|
|
|
|
if (!superRecordMap.value[firstId]) {
|
|
|
|
const map = {};
|
|
|
|
exercises.forEach(item => {
|
|
|
|
map[item.id] = [{
|
|
|
|
h: '00', m: '00', s: '00', quickTimeDisplay: '60s',
|
|
|
|
distance: '', weight: '', reps: '', duration: '', restTime: '', isActive: false
|
|
|
|
}];
|
|
|
|
});
|
|
|
|
superRecordMap.value = map;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
nextTick(() => {
|
|
|
|
emit('register', props.index, {
|
|
|
|
recordList: recordList.value,
|
|
|
|
superRecordMap: superRecordMap.value
|
|
|
|
})
|
|
|
|
})
|
|
|
|
});
|
|
|
|
// 动作组数据记录
|
|
|
|
const recordList = ref([
|
|
|
|
{ h: '00', m: '00', s: '00', quickTimeDisplay: '60s', distance: '', weight: '', reps: '', duration: '', restTime: '', isActive: false },
|
|
|
|
]);
|
|
|
|
|
|
|
|
watch(recordList, () => {
|
|
|
|
// console.log('recordList变化,发送长度:', recordList.value.length)
|
|
|
|
emit('update:groupCount', recordList.value.length)
|
|
|
|
}, { deep: true, immediate: true })
|
|
|
|
|
|
|
|
const saveToStore = () => {
|
|
|
|
let records = {};
|
|
|
|
|
|
|
|
if (props.type === 1) {
|
|
|
|
// 普通动作
|
|
|
|
records[props.actionDetail.id] = recordList.value;
|
|
|
|
|
|
|
|
} else if (props.type === 2) {
|
|
|
|
// 超级组
|
|
|
|
records = superRecordMap.value;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 调用 Pinia 保存
|
|
|
|
trainingStore.saveUnitRecord(props.unitIndex, {
|
|
|
|
records: records,
|
|
|
|
userWeight: userWeight.value
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
watch([recordList, superRecordMap, userWeight], () => {
|
|
|
|
saveToStore();
|
|
|
|
console.log('+++++++++打印全局训练数据 trainingStore.unitRecords++++++++', trainingStore.unitRecords);
|
|
|
|
}, { deep: true, immediate: false });
|
|
|
|
|
|
|
|
const toggleActive = (index) => {
|
|
|
|
recordList.value[index].isActive = !recordList.value[index].isActive;
|
|
|
|
};
|
|
|
|
|
|
|
|
// 超级组工具方法
|
|
|
|
const superGroupSetData = (setIndex) => {
|
|
|
|
const firstSub = props.actionDetail?.exercises?.[0]
|
|
|
|
if (!firstSub) return {}
|
|
|
|
return superRecordMap.value[firstSub.id]?.[setIndex] || {}
|
|
|
|
}
|
|
|
|
const getSubActionData = (setIndex, actionId) => {
|
|
|
|
return superRecordMap.value[actionId]?.[setIndex] || {
|
|
|
|
h: '00', m: '00', s: '00',
|
|
|
|
quickTimeDisplay: '60s',
|
|
|
|
distance: '',
|
|
|
|
weight: '',
|
|
|
|
reps: '',
|
|
|
|
duration: '',
|
|
|
|
restTime: '',
|
|
|
|
isActive: false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const openSuperPicker = (setIndex, actionId) => {
|
|
|
|
activeIndex.value = setIndex
|
|
|
|
activeActionId.value = actionId; // 保存当前动作ID
|
|
|
|
showPicker.value = true
|
|
|
|
}
|
|
|
|
const openSuperQuickTimer = (setIndex) => {
|
|
|
|
activeIndex.value = setIndex
|
|
|
|
showQuickPicker.value = true
|
|
|
|
}
|
|
|
|
const toggleSuperSetActive = (setIndex) => {
|
|
|
|
props.actionDetail.exercises.forEach(sub => {
|
|
|
|
const list = superRecordMap.value[sub.id]
|
|
|
|
if (list?.[setIndex]) {
|
|
|
|
list[setIndex].isActive = !list[setIndex].isActive
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
// 增加超级组的set组数
|
|
|
|
const addSuperSet = () => {
|
|
|
|
const exercises = props.actionDetail?.exercises || []
|
|
|
|
exercises.forEach(sub => {
|
|
|
|
if (superRecordMap.value[sub.id]) {
|
|
|
|
superRecordMap.value[sub.id].push({
|
|
|
|
h: '00', m: '00', s: '00',
|
|
|
|
quickTimeDisplay: '60s',
|
|
|
|
distance: '',
|
|
|
|
weight: '',
|
|
|
|
reps: '',
|
|
|
|
duration: '',
|
|
|
|
restTime: '',
|
|
|
|
isActive: false
|
|
|
|
})
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
// 删除超级组的组数
|
|
|
|
const deleteSuperSet = (setIndex) => {
|
|
|
|
const exercises = props.actionDetail?.exercises || []
|
|
|
|
exercises.forEach(sub => {
|
|
|
|
const list = superRecordMap.value[sub.id]
|
|
|
|
if (list && list.length > 1) {
|
|
|
|
list.splice(setIndex, 1)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
// 合并后的 Picker 逻辑
|
|
|
|
const timeColumns = reactive([
|
|
|
|
Array.from({ length: 24 }, (_, i) => String(i).padStart(2, '0') + '时'),
|
|
|
|
Array.from({ length: 60 }, (_, i) => String(i).padStart(2, '0') + '分'),
|
|
|
|
Array.from({ length: 60 }, (_, i) => String(i).padStart(2, '0') + '秒'),
|
|
|
|
]);
|
|
|
|
const defaultTimeIndex = ref([0, 0, 0]);
|
|
|
|
const quickColumns = reactive([
|
|
|
|
Array.from({ length: 60 }, (_, i) => String(i).padStart(2, '0') + '分'),
|
|
|
|
Array.from({ length: 60 }, (_, i) => String(i).padStart(2, '0') + '秒'),
|
|
|
|
]);
|
|
|
|
|
|
|
|
const openPicker = (index) => {
|
|
|
|
activeIndex.value = index;
|
|
|
|
const item = recordList.value[index];
|
|
|
|
const hIdx = timeColumns[0].indexOf(item.h + '时');
|
|
|
|
const mIdx = timeColumns[1].indexOf(item.m + '分');
|
|
|
|
const sIdx = timeColumns[2].indexOf(item.s + '秒');
|
|
|
|
defaultTimeIndex.value = [hIdx, mIdx, sIdx];
|
|
|
|
showPicker.value = true;
|
|
|
|
};
|
|
|
|
//
|
|
|
|
const openQuickTimer = (index) => {
|
|
|
|
activeIndex.value = index;
|
|
|
|
showQuickPicker.value = true;
|
|
|
|
};
|
|
|
|
// 组间休息
|
|
|
|
const openAllQuickTimer = () => {
|
|
|
|
restEditMode.value = 'all'; // 重点:标记为全部修改
|
|
|
|
showQuickPicker.value = true;
|
|
|
|
};
|
|
|
|
|
|
|
|
const onTimeConfirm = (e) => {
|
|
|
|
const rawValues = e.value.map((val) => String(val).replace(/[时分秒]/g, ''))
|
|
|
|
const setIdx = activeIndex.value
|
|
|
|
|
|
|
|
if (props.type === 1) {
|
|
|
|
const item = recordList.value[setIdx]
|
|
|
|
item.h = rawValues[0]
|
|
|
|
item.m = rawValues[1]
|
|
|
|
item.s = rawValues[2]
|
|
|
|
} else if (props.type === 2) {
|
|
|
|
// 只修改当前点击的动作,不批量修改所有动作!
|
|
|
|
const actionId = activeActionId.value;
|
|
|
|
const list = superRecordMap.value[actionId];
|
|
|
|
if (list?.[setIdx]) {
|
|
|
|
list[setIdx].h = rawValues[0];
|
|
|
|
list[setIdx].m = rawValues[1];
|
|
|
|
list[setIdx].s = rawValues[2];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
showPicker.value = false
|
|
|
|
}
|
|
|
|
|
|
|
|
const onQuickConfirm = (e) => {
|
|
|
|
const min = parseInt(e.value[0]) || 0
|
|
|
|
const sec = parseInt(e.value[1]) || 0
|
|
|
|
const totalSeconds = min * 60 + sec
|
|
|
|
const setIdx = activeIndex.value
|
|
|
|
|
|
|
|
// ============== 统一设置所有组 ==============
|
|
|
|
if (restEditMode.value === 'all') {
|
|
|
|
// 普通动作
|
|
|
|
if (props.type === 1) {
|
|
|
|
recordList.value.forEach(item => {
|
|
|
|
item.quickTimeDisplay = totalSeconds + 's'
|
|
|
|
})
|
|
|
|
}
|
|
|
|
// 超级组
|
|
|
|
else if (props.type === 2) {
|
|
|
|
const firstSub = props.actionDetail?.exercises?.[0]
|
|
|
|
if (!firstSub) return
|
|
|
|
const allSets = superRecordMap.value[firstSub.id]
|
|
|
|
if (!allSets) return
|
|
|
|
allSets.forEach(set => {
|
|
|
|
set.quickTimeDisplay = totalSeconds + 's'
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ============== 单行修改 ==============
|
|
|
|
else {
|
|
|
|
if (props.type === 1) {
|
|
|
|
recordList.value[setIdx].quickTimeDisplay = totalSeconds + 's'
|
|
|
|
} else if (props.type === 2) {
|
|
|
|
props.actionDetail.exercises.forEach(sub => {
|
|
|
|
const list = superRecordMap.value[sub.id]
|
|
|
|
if (list?.[setIdx]) {
|
|
|
|
list[setIdx].quickTimeDisplay = totalSeconds + 's'
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
restEditMode.value = 'single'
|
|
|
|
showQuickPicker.value = false
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 单动作的增加/删除
|
|
|
|
const addRow = () => {
|
|
|
|
recordList.value.push({
|
|
|
|
h: '00', m: '00', s: '00',
|
|
|
|
quickTimeDisplay: '60s',
|
|
|
|
distance: '', weight: '', reps: '', isActive: false,
|
|
|
|
});
|
|
|
|
};
|
|
|
|
const deleteRow = (index) => {
|
|
|
|
if (recordList.value.length > 1) {
|
|
|
|
recordList.value.splice(index, 1);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
const addGroup = () => {
|
|
|
|
if (props.type === 1) {
|
|
|
|
addRow()
|
|
|
|
} else if (props.type === 2) {
|
|
|
|
addSuperSet()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 历史
|
|
|
|
const openHistory = (id) => {
|
|
|
|
if (historyPopupRef.value && historyPopupRef.value.openHistoryPopup) {
|
|
|
|
historyPopupRef.value.openHistoryPopup(id);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 动作名称渲染
|
|
|
|
const exerciseNamesWithLabel = computed(() => {
|
|
|
|
const exercises = props.actionDetail?.exercises || []
|
|
|
|
return exercises.map((item, index) => {
|
|
|
|
const label = String.fromCharCode(65 + index)
|
|
|
|
return `${label} ${item?.name || '未知动作'}`
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
// 获得真正的重量(支持普通动作 + 超级组)
|
|
|
|
const getRealWeight = (item, subExerciseType = null) => {
|
|
|
|
const userW = Number(userWeight.value) || 0
|
|
|
|
const inputW = Number(item.weight) || 0
|
|
|
|
// 重要:超级组子动作会传入自己的 exerciseType
|
|
|
|
let type = subExerciseType ?? props.actionDetail?.exerciseType
|
|
|
|
|
|
|
|
// console.log('【重量计算】', {
|
|
|
|
// 动作类型: type,
|
|
|
|
// 体重: userW,
|
|
|
|
// 输入重量: inputW,
|
|
|
|
// 最终重量:
|
|
|
|
// type === 0 ? inputW :
|
|
|
|
// type === 4 ? userW + inputW :
|
|
|
|
// type === 5 ? userW - inputW : 0
|
|
|
|
// })
|
|
|
|
let realWeight = 0;
|
|
|
|
if (type === 0) {
|
|
|
|
realWeight = inputW;
|
|
|
|
} else if (type === 4) {
|
|
|
|
realWeight = userW + inputW;
|
|
|
|
} else if (type === 5) {
|
|
|
|
realWeight = userW - inputW;
|
|
|
|
// 只做数据兜底修正,不在这里弹提示
|
|
|
|
if (realWeight < 0) {
|
|
|
|
realWeight = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return realWeight;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 只暴露 isActive = true 的数据
|
|
|
|
const exposeRecordList = computed(() => {
|
|
|
|
return recordList.value.filter(item => item.isActive).map(item => {
|
|
|
|
return {
|
|
|
|
...item,
|
|
|
|
weight: getRealWeight(item) // 👈 自动计算真实重量
|
|
|
|
}
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
const exposeSuperRecordMap = computed(() => {
|
|
|
|
const map = {}
|
|
|
|
for (const key in superRecordMap.value) {
|
|
|
|
// 找到当前子动作的类型
|
|
|
|
const subExercise = props.actionDetail?.exercises?.find(s => s.id == key)
|
|
|
|
const subType = subExercise?.exerciseType
|
|
|
|
map[key] = superRecordMap.value[key]
|
|
|
|
.filter(item => item.isActive)
|
|
|
|
.map(item => {
|
|
|
|
return {
|
|
|
|
...item,
|
|
|
|
weight: getRealWeight(item, subType) // ✅ 传入子动作类型
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
return map
|
|
|
|
})
|
|
|
|
// 总组数
|
|
|
|
const totalSetCount = computed(() => {
|
|
|
|
// 1. 普通动作 type === 1
|
|
|
|
if (props.type === 1) {
|
|
|
|
return recordList.value.length
|
|
|
|
}
|
|
|
|
// 2. 超级组 type === 2
|
|
|
|
if (props.type === 2) {
|
|
|
|
const exercises = props.actionDetail?.exercises || []
|
|
|
|
if (exercises.length === 0) return 0
|
|
|
|
const firstId = exercises[0].id
|
|
|
|
return superRecordMap.value[firstId]?.length || 0
|
|
|
|
}
|
|
|
|
return 0
|
|
|
|
})
|
|
|
|
|
|
|
|
// 重量
|
|
|
|
// 1. 已勾选的重量总和(黄色框框)→ 现在 = 真实重量 × 次数
|
|
|
|
const checkedWeight = computed(() => {
|
|
|
|
let sum = 0
|
|
|
|
// 普通动作
|
|
|
|
if (props.type === 1 && recordList.value) {
|
|
|
|
recordList.value.forEach(item => {
|
|
|
|
if (item.isActive) {
|
|
|
|
const realWeight = getRealWeight(item) // 👈 真实重量(自重/加重/减重)
|
|
|
|
const reps = Number(item.reps) || 0 // 👈 次数
|
|
|
|
sum += realWeight * reps // 👈 重量 × 次数
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
// 超级组
|
|
|
|
if (props.type === 2 && superRecordMap.value) {
|
|
|
|
for (const actionId in superRecordMap.value) {
|
|
|
|
// 拿到子动作类型
|
|
|
|
const subExercise = props.actionDetail?.exercises?.find(s => s.id == actionId)
|
|
|
|
const subType = subExercise?.exerciseType
|
|
|
|
|
|
|
|
superRecordMap.value[actionId].forEach(item => {
|
|
|
|
if (item.isActive) {
|
|
|
|
const realWeight = getRealWeight(item, subType)
|
|
|
|
const reps = Number(item.reps) || 0
|
|
|
|
sum += realWeight * reps
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return sum
|
|
|
|
})
|
|
|
|
|
|
|
|
// 2. 所有组的重量总和(不管勾没勾)→ 现在 = 真实重量 × 次数
|
|
|
|
const totalWeight = computed(() => {
|
|
|
|
let sum = 0
|
|
|
|
if (props.type === 1 && recordList.value) {
|
|
|
|
recordList.value.forEach(item => {
|
|
|
|
const realWeight = getRealWeight(item)
|
|
|
|
const reps = Number(item.reps) || 0
|
|
|
|
sum += realWeight * reps
|
|
|
|
})
|
|
|
|
}
|
|
|
|
if (props.type === 2 && superRecordMap.value) {
|
|
|
|
for (const actionId in superRecordMap.value) {
|
|
|
|
const subExercise = props.actionDetail?.exercises?.find(s => s.id == actionId)
|
|
|
|
const subType = subExercise?.exerciseType
|
|
|
|
|
|
|
|
superRecordMap.value[actionId].forEach(item => {
|
|
|
|
const realWeight = getRealWeight(item, subType)
|
|
|
|
const reps = Number(item.reps) || 0
|
|
|
|
sum += realWeight * reps
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return sum
|
|
|
|
})
|
|
|
|
|
|
|
|
// ==============================================
|
|
|
|
// 统一监听:普通动作 + 超级组 的自重减重(type=5)
|
|
|
|
// ==============================================
|
|
|
|
watch(
|
|
|
|
() => [recordList.value, superRecordMap.value],
|
|
|
|
() => {
|
|
|
|
const userW = userWeight.value || 0;
|
|
|
|
|
|
|
|
// --------------------------
|
|
|
|
// 1. 监听【普通动作】
|
|
|
|
// --------------------------
|
|
|
|
if (props.type === 1 && props.actionDetail?.exerciseType === 5) {
|
|
|
|
recordList.value.forEach((item) => {
|
|
|
|
const inputW = Number(item.weight) || 0;
|
|
|
|
if (inputW > userW) {
|
|
|
|
item.weight = "";
|
|
|
|
uni.showToast({
|
|
|
|
title: "辅助重量不能超过体重",
|
|
|
|
icon: "none",
|
|
|
|
duration: 2000,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
// --------------------------
|
|
|
|
// 2. 监听【超级组】(包含多个子动作)
|
|
|
|
// --------------------------
|
|
|
|
if (props.type === 2) {
|
|
|
|
// 遍历超级组里的所有子动作
|
|
|
|
props.actionDetail?.exercises?.forEach((sub) => {
|
|
|
|
// 只校验 自重减重 type=5
|
|
|
|
if (sub.exerciseType === 5) {
|
|
|
|
const sets = superRecordMap.value[sub.id] || [];
|
|
|
|
sets.forEach((item) => {
|
|
|
|
const inputW = Number(item.weight) || 0;
|
|
|
|
if (inputW > userW) {
|
|
|
|
item.weight = "";
|
|
|
|
uni.showToast({
|
|
|
|
title: "辅助重量不能超过体重",
|
|
|
|
icon: "none",
|
|
|
|
duration: 2000,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
},
|
|
|
|
{ deep: true }
|
|
|
|
);
|
|
|
|
|
|
|
|
defineExpose({
|
|
|
|
recordList: exposeRecordList, // 过滤后
|
|
|
|
superRecordMap: exposeSuperRecordMap, // 过滤后
|
|
|
|
totalSetCount, //全部的组数
|
|
|
|
checkedWeight, // 已勾选重量
|
|
|
|
totalWeight // 全部重量
|
|
|
|
})
|
|
|
|
|
|
|
|
// 打开备注弹窗
|
|
|
|
// const openBeizhu = () => {
|
|
|
|
// console.log('传递到备注组件的id', actionId.value)
|
|
|
|
// showBeizhuRef.value.open(actionId.value)
|
|
|
|
// }
|
|
|
|
|
|
|
|
watch(() => props.actionDetail, () => {
|
|
|
|
console.log('actionDetail.exercises:', props.actionDetail?.exercises)
|
|
|
|
}, { immediate: true })
|
|
|
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
|
|
$bg-black: #303030;
|
|
|
|
$card-bg: #1c1c1e;
|
|
|
|
$item-bg: #2c2c2e;
|
|
|
|
$text-main: #ffffff;
|
|
|
|
$text-gray: #8e8e93;
|
|
|
|
$theme-yellow: #f8d714;
|
|
|
|
|
|
|
|
.action-container {
|
|
|
|
width: 100%;
|
|
|
|
/* 确保容器足够高以接收点击事件 */
|
|
|
|
background-color: $bg-black;
|
|
|
|
|
|
|
|
.action-list {
|
|
|
|
width: 100%;
|
|
|
|
|
|
|
|
.card {
|
|
|
|
border-radius: 24rpx;
|
|
|
|
margin-bottom: 20rpx;
|
|
|
|
padding-bottom: 20rpx;
|
|
|
|
|
|
|
|
.card-top {
|
|
|
|
display: flex;
|
|
|
|
align-items: center;
|
|
|
|
padding: 20rpx 30rpx 0;
|
|
|
|
box-sizing: border-box;
|
|
|
|
|
|
|
|
.action-image {
|
|
|
|
width: 110rpx;
|
|
|
|
height: 110rpx;
|
|
|
|
border-radius: 16rpx;
|
|
|
|
background-color: #3a3a3c;
|
|
|
|
}
|
|
|
|
|
|
|
|
.action-info {
|
|
|
|
flex: 1;
|
|
|
|
margin-left: 24rpx;
|
|
|
|
|
|
|
|
.name {
|
|
|
|
font-size: 34rpx;
|
|
|
|
font-weight: 600;
|
|
|
|
color: $text-main;
|
|
|
|
}
|
|
|
|
|
|
|
|
.tags {
|
|
|
|
font-size: 24rpx;
|
|
|
|
color: $text-gray;
|
|
|
|
margin-top: 6rpx;
|
|
|
|
margin-left: 6rpx;
|
|
|
|
}
|
|
|
|
|
|
|
|
.dot-list {
|
|
|
|
display: flex;
|
|
|
|
gap: 10rpx;
|
|
|
|
margin-top: 8rpx;
|
|
|
|
|
|
|
|
.dot {
|
|
|
|
width: 10rpx;
|
|
|
|
height: 10rpx;
|
|
|
|
border-radius: 50%;
|
|
|
|
background-color: $text-main;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
.more-circle {
|
|
|
|
width: 60rpx;
|
|
|
|
height: 60rpx;
|
|
|
|
background: $item-bg;
|
|
|
|
border-radius: 50%;
|
|
|
|
display: flex;
|
|
|
|
align-items: center;
|
|
|
|
justify-content: center;
|
|
|
|
border: 1rpx solid #a4a4a4;
|
|
|
|
position: relative;
|
|
|
|
|
|
|
|
.icon {
|
|
|
|
transform: rotate(90deg);
|
|
|
|
}
|
|
|
|
|
|
|
|
.tips {
|
|
|
|
position: absolute;
|
|
|
|
color: #fff;
|
|
|
|
background-color: #3e3e3e;
|
|
|
|
z-index: 6;
|
|
|
|
right: 10rpx;
|
|
|
|
top: 20rpx;
|
|
|
|
border-radius: 10rpx;
|
|
|
|
|
|
|
|
.tip {
|
|
|
|
width: 120rpx;
|
|
|
|
height: 40rpx;
|
|
|
|
padding: 20rpx 30rpx;
|
|
|
|
text-align: center;
|
|
|
|
font-size: 24rpx;
|
|
|
|
line-height: 40rpx;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
.main {
|
|
|
|
width: 100%;
|
|
|
|
margin-top: 20rpx;
|
|
|
|
|
|
|
|
.img-list {
|
|
|
|
display: flex;
|
|
|
|
align-items: center;
|
|
|
|
flex-wrap: wrap;
|
|
|
|
gap: 20rpx;
|
|
|
|
padding: 20rpx;
|
|
|
|
box-sizing: border-box;
|
|
|
|
|
|
|
|
.img {
|
|
|
|
width: 120rpx;
|
|
|
|
height: 120rpx;
|
|
|
|
border-radius: 10rpx;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// .userWeight-values {
|
|
|
|
// display: flex;
|
|
|
|
// align-items: center;
|
|
|
|
// gap: 8rpx; // 控制“体重文本”和“编辑图标”的间距
|
|
|
|
// padding: 8rpx;
|
|
|
|
|
|
|
|
// .weight-text {
|
|
|
|
// color: #fadc00;
|
|
|
|
// font-size: 20rpx;
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
|
|
|
|
.userWeight {
|
|
|
|
padding: 16rpx 32rpx;
|
|
|
|
gap: 16rpx;
|
|
|
|
|
|
|
|
.row {
|
|
|
|
display: flex;
|
|
|
|
align-items: center;
|
|
|
|
gap: 16rpx;
|
|
|
|
|
|
|
|
.label {
|
|
|
|
font-size: 20rpx;
|
|
|
|
color: $text-main;
|
|
|
|
font-weight: 500;
|
|
|
|
}
|
|
|
|
|
|
|
|
.userWeight-values {
|
|
|
|
display: flex;
|
|
|
|
align-items: center;
|
|
|
|
gap: 8rpx; // 控制“体重文本”和“编辑图标”的间距
|
|
|
|
padding: 8rpx;
|
|
|
|
|
|
|
|
.weight-text {
|
|
|
|
color: #fadc00;
|
|
|
|
font-size: 20rpx;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
.explain {
|
|
|
|
font-size: 20rpx;
|
|
|
|
color: #fff;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
.record-row {
|
|
|
|
display: flex;
|
|
|
|
align-items: flex-start;
|
|
|
|
justify-content: space-between;
|
|
|
|
padding: 10rpx 30rpx;
|
|
|
|
box-sizing: border-box;
|
|
|
|
|
|
|
|
&.active {
|
|
|
|
background-color: #4c4d3b;
|
|
|
|
}
|
|
|
|
|
|
|
|
.left {
|
|
|
|
display: flex;
|
|
|
|
flex-direction: column;
|
|
|
|
gap: 10rpx;
|
|
|
|
|
|
|
|
.left-header {
|
|
|
|
display: flex;
|
|
|
|
align-items: center;
|
|
|
|
gap: 20rpx;
|
|
|
|
|
|
|
|
.index-box {
|
|
|
|
width: 50rpx;
|
|
|
|
height: 70rpx;
|
|
|
|
background: #1f1f1f;
|
|
|
|
border-radius: 10rpx;
|
|
|
|
display: flex;
|
|
|
|
align-items: center;
|
|
|
|
justify-content: center;
|
|
|
|
font-size: 30rpx;
|
|
|
|
color: $text-main;
|
|
|
|
}
|
|
|
|
|
|
|
|
.input-col,
|
|
|
|
.distance {
|
|
|
|
height: 70rpx;
|
|
|
|
background: #1f1f1f;
|
|
|
|
border-radius: 10rpx;
|
|
|
|
padding: 5rpx 10rpx;
|
|
|
|
display: flex;
|
|
|
|
flex-direction: column;
|
|
|
|
justify-content: center;
|
|
|
|
|
|
|
|
.label {
|
|
|
|
font-size: 15rpx;
|
|
|
|
color: $text-gray;
|
|
|
|
margin-bottom: 2rpx;
|
|
|
|
}
|
|
|
|
|
|
|
|
.values {
|
|
|
|
display: flex;
|
|
|
|
align-items: baseline;
|
|
|
|
|
|
|
|
.num {
|
|
|
|
font-size: 32rpx;
|
|
|
|
color: $text-main;
|
|
|
|
}
|
|
|
|
|
|
|
|
.unit {
|
|
|
|
font-size: 15rpx;
|
|
|
|
color: $text-gray;
|
|
|
|
margin: 0 5rpx;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
.distance {
|
|
|
|
min-width: 100rpx;
|
|
|
|
|
|
|
|
:deep(.u-input) {
|
|
|
|
padding: 0 !important;
|
|
|
|
}
|
|
|
|
|
|
|
|
.u-input__content__field {
|
|
|
|
font-size: 32rpx !important;
|
|
|
|
color: $text-main !important;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
.timer-selector {
|
|
|
|
width: 75rpx;
|
|
|
|
height: 75rpx;
|
|
|
|
display: flex;
|
|
|
|
flex-direction: column;
|
|
|
|
align-items: center;
|
|
|
|
justify-content: center;
|
|
|
|
border-radius: 50%;
|
|
|
|
border: 1rpx solid #a4a4a4;
|
|
|
|
|
|
|
|
.text {
|
|
|
|
font-size: 20rpx;
|
|
|
|
color: $text-gray;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
.exercise-name-list {
|
|
|
|
display: flex;
|
|
|
|
flex-direction: column;
|
|
|
|
gap: 8rpx;
|
|
|
|
flex: 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
.exercise-name {
|
|
|
|
font-size: 26rpx;
|
|
|
|
color: $text-main;
|
|
|
|
line-height: 1.2;
|
|
|
|
}
|
|
|
|
|
|
|
|
.goal-list {
|
|
|
|
width: 100%;
|
|
|
|
margin-top: 10rpx;
|
|
|
|
|
|
|
|
.goal-item {
|
|
|
|
display: flex;
|
|
|
|
align-items: center;
|
|
|
|
gap: 20rpx;
|
|
|
|
|
|
|
|
border-radius: 10rpx;
|
|
|
|
|
|
|
|
.serial {
|
|
|
|
width: 50rpx;
|
|
|
|
height: 70rpx;
|
|
|
|
display: flex;
|
|
|
|
align-items: center;
|
|
|
|
justify-content: center;
|
|
|
|
font-size: 30rpx;
|
|
|
|
color: #929292;
|
|
|
|
font-weight: bold;
|
|
|
|
}
|
|
|
|
|
|
|
|
.goal-input-box {
|
|
|
|
display: flex;
|
|
|
|
flex-direction: column;
|
|
|
|
justify-content: center;
|
|
|
|
background-color: #1f1f1f;
|
|
|
|
width: 100rpx;
|
|
|
|
height: 70rpx;
|
|
|
|
border-radius: 10rpx;
|
|
|
|
|
|
|
|
.values {
|
|
|
|
display: flex;
|
|
|
|
align-items: flex-end;
|
|
|
|
padding-left: 10rpx;
|
|
|
|
box-sizing: border-box;
|
|
|
|
|
|
|
|
:deep(.uni-input-input[type='number']) {
|
|
|
|
text-align: center;
|
|
|
|
}
|
|
|
|
|
|
|
|
.num {
|
|
|
|
font-size: 32rpx;
|
|
|
|
color: $text-main;
|
|
|
|
}
|
|
|
|
|
|
|
|
.unit {
|
|
|
|
font-size: 15rpx;
|
|
|
|
color: $text-gray;
|
|
|
|
margin: 0 5rpx;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 确保 up-input 内部文字样式一致
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// 新增的间歇运动样式
|
|
|
|
.interval {
|
|
|
|
display: flex;
|
|
|
|
gap: 20rpx;
|
|
|
|
margin-top: 10rpx;
|
|
|
|
|
|
|
|
.goal-input-box {
|
|
|
|
flex: none;
|
|
|
|
width: 120rpx;
|
|
|
|
|
|
|
|
.label {
|
|
|
|
font-size: 15rpx;
|
|
|
|
color: $text-gray;
|
|
|
|
margin-bottom: 2rpx;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
.icons {
|
|
|
|
display: flex;
|
|
|
|
gap: 20rpx;
|
|
|
|
|
|
|
|
.icon {
|
|
|
|
width: 70rpx;
|
|
|
|
height: 70rpx;
|
|
|
|
background-color: #1f1f1f;
|
|
|
|
border-radius: 12rpx;
|
|
|
|
display: flex;
|
|
|
|
align-items: center;
|
|
|
|
justify-content: center;
|
|
|
|
|
|
|
|
&.active {
|
|
|
|
background-color: $theme-yellow;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
.del {
|
|
|
|
background-color: #58372d;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 新增超级组样式
|
|
|
|
.super-group {
|
|
|
|
width: 100%;
|
|
|
|
}
|
|
|
|
|
|
|
|
.super-record-row {
|
|
|
|
align-items: center;
|
|
|
|
background-color: red;
|
|
|
|
min-height: 100rpx;
|
|
|
|
}
|
|
|
|
|
|
|
|
.super-left {
|
|
|
|
flex-direction: row !important;
|
|
|
|
align-items: center;
|
|
|
|
gap: 20rpx;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.set-group {
|
|
|
|
margin-bottom: 30rpx;
|
|
|
|
}
|
|
|
|
|
|
|
|
.set-header {
|
|
|
|
display: flex;
|
|
|
|
align-items: center;
|
|
|
|
padding: 10rpx 30rpx;
|
|
|
|
gap: 20rpx;
|
|
|
|
|
|
|
|
.icons {
|
|
|
|
display: flex;
|
|
|
|
gap: 20rpx;
|
|
|
|
|
|
|
|
.icon {
|
|
|
|
width: 70rpx;
|
|
|
|
height: 70rpx;
|
|
|
|
background-color: #1f1f1f;
|
|
|
|
border-radius: 12rpx;
|
|
|
|
display: flex;
|
|
|
|
align-items: center;
|
|
|
|
justify-content: center;
|
|
|
|
}
|
|
|
|
|
|
|
|
.del {
|
|
|
|
background-color: #58372d;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
.index-box {
|
|
|
|
width: 50rpx;
|
|
|
|
height: 70rpx;
|
|
|
|
background: #1f1f1f;
|
|
|
|
border-radius: 10rpx;
|
|
|
|
display: flex;
|
|
|
|
align-items: center;
|
|
|
|
justify-content: center;
|
|
|
|
font-size: 30rpx;
|
|
|
|
color: #fff;
|
|
|
|
}
|
|
|
|
|
|
|
|
.set-action-names {
|
|
|
|
flex: 1;
|
|
|
|
display: flex;
|
|
|
|
flex-direction: column;
|
|
|
|
gap: 4rpx;
|
|
|
|
|
|
|
|
text {
|
|
|
|
font-size: 26rpx;
|
|
|
|
color: #fff;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
.timer-selector {
|
|
|
|
width: 75rpx;
|
|
|
|
height: 75rpx;
|
|
|
|
display: flex;
|
|
|
|
flex-direction: column;
|
|
|
|
align-items: center;
|
|
|
|
justify-content: center;
|
|
|
|
border-radius: 50%;
|
|
|
|
border: 1rpx solid #a4a4a4;
|
|
|
|
|
|
|
|
.text {
|
|
|
|
font-size: 20rpx;
|
|
|
|
color: #8e8e93;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
.icon {
|
|
|
|
width: 70rpx;
|
|
|
|
height: 70rpx;
|
|
|
|
background-color: #1f1f1f;
|
|
|
|
border-radius: 12rpx;
|
|
|
|
display: flex;
|
|
|
|
align-items: center;
|
|
|
|
justify-content: center;
|
|
|
|
|
|
|
|
&.active {
|
|
|
|
background-color: $theme-yellow;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
.serial {
|
|
|
|
width: 50rpx;
|
|
|
|
height: 70rpx;
|
|
|
|
display: flex;
|
|
|
|
align-items: center;
|
|
|
|
justify-content: center;
|
|
|
|
font-size: 30rpx;
|
|
|
|
color: #929292;
|
|
|
|
font-weight: bold;
|
|
|
|
}
|
|
|
|
|
|
|
|
.super-action-item {
|
|
|
|
margin-bottom: 30rpx;
|
|
|
|
}
|
|
|
|
|
|
|
|
.super-action-title {
|
|
|
|
font-size: 28rpx;
|
|
|
|
color: #fff;
|
|
|
|
padding: 10rpx 30rpx;
|
|
|
|
font-weight: bold;
|
|
|
|
}
|
|
|
|
|
|
|
|
.button-group {
|
|
|
|
display: flex;
|
|
|
|
justify-content: space-between;
|
|
|
|
padding: 30rpx;
|
|
|
|
box-sizing: border-box;
|
|
|
|
|
|
|
|
.btn-item {
|
|
|
|
background-color: #1f1f1f;
|
|
|
|
font-size: 26rpx;
|
|
|
|
color: #fff;
|
|
|
|
padding: 15rpx 35rpx;
|
|
|
|
border-radius: 50rpx;
|
|
|
|
display: flex;
|
|
|
|
align-items: center;
|
|
|
|
gap: 10rpx;
|
|
|
|
position: relative;
|
|
|
|
|
|
|
|
.difficulty-pop {
|
|
|
|
position: absolute;
|
|
|
|
bottom: 80rpx;
|
|
|
|
left: 50%;
|
|
|
|
transform: translateX(-50%);
|
|
|
|
background-color: #3e3e3e;
|
|
|
|
border-radius: 16rpx;
|
|
|
|
overflow: hidden;
|
|
|
|
z-index: 99;
|
|
|
|
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.5);
|
|
|
|
|
|
|
|
.difficulty-item {
|
|
|
|
width: 180rpx;
|
|
|
|
height: 80rpx;
|
|
|
|
padding: 0 25rpx;
|
|
|
|
box-sizing: border-box;
|
|
|
|
display: flex;
|
|
|
|
align-items: center;
|
|
|
|
justify-content: space-between;
|
|
|
|
font-size: 26rpx;
|
|
|
|
border-bottom: 1rpx solid #4e4e4e;
|
|
|
|
|
|
|
|
&:last-child {
|
|
|
|
border-bottom: none;
|
|
|
|
}
|
|
|
|
|
|
|
|
&:active {
|
|
|
|
background-color: #4e4e4e;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
</style> |
...
|
...
|
|