dma-work-h5/src/components/menuSettingTop.vue
2026-04-08 09:51:49 +08:00

327 lines
10 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<script setup lang="ts">
import { ref, watch, computed } from 'vue';
const props = defineProps({
detail: {
type: Object,
default: () => {
return {
id: 0,
name: '',
mode: '',
date: '',
avatar: '',
};
},
},
});
const emit = defineEmits(['update:date', 'update:mode']);
const activeModal = ref(-1);
const initialDate = ref('--');
const date = ref('--');
const showDate = ref(false);
const dateValues = ref<any[]>([`${new Date().getFullYear()}`, `${new Date().getMonth() + 1 < 10 ? `0${new Date().getMonth() + 1}` : new Date().getMonth() + 1}`, `${new Date().getDate()}`]);
const minDate = new Date(new Date().getFullYear() - 120, 0, 1);
const maxDate = (() => {
const d = new Date();
d.setDate(1);
d.setMonth(d.getMonth() + 1);
d.setDate(Math.min(new Date().getDate(), new Date(d.getFullYear(), d.getMonth() + 1, 0).getDate()));
d.setHours(0, 0, 0, 0);
return d;
})();
// 模式文本映射
const getModalText = (mode: number) => {
if (mode === 1) return '减肥型';
if (mode === 2) return '其他型';
return '--';
};
const modalText = ref('未选择');
let hasUserChangedMode = false;
let hasUserChangedDate = false;
const showChange = ref(false);
const showModalText = ref('');
// 切换模式
const changeModal = (type) => {
activeModal.value = type;
modalText.value = getModalText(type);
hasUserChangedMode = true;
maybeEmitMode();
showModal.value = false;
};
let initialModeValue = '';
let initialDateValue = '';
// 监听详情赋值
watch(
() => props.detail,
(newDetail) => {
if (!newDetail) return;
// 优先级log.id 存在则用 log.model否则用外层 model
let realModel = 0;
if (newDetail.log && newDetail.log.id > 0) {
realModel = newDetail.log.model ?? 0;
} else {
realModel = newDetail.model ?? 0;
}
activeModal.value = realModel;
modalText.value = getModalText(realModel);
initialModeValue = modalText.value;
// 同步日期
const startDate = newDetail.log?.start_date_str || '--';
date.value = startDate;
initialDateValue = startDate;
if (startDate !== '--') {
const [year, month, day] = startDate.split('-').map(Number);
dateValues.value = [String(year), String(month).padStart(2, '0'), String(day).padStart(2, '0')];
}
},
{ immediate: true, deep: true },
);
// 条件 emit
const maybeEmitMode = () => {
if (modalText.value !== initialModeValue) {
emit('update:mode', modalText.value, date.value);
}
};
const maybeEmitDate = () => {
if (date.value !== initialDateValue) {
emit('update:date', date.value, modalText.value);
}
};
const toShowDate = () => {};
// 日期选择确认
const onConfirm = ({ selectedValues }) => {
date.value = `${selectedValues[0]}-${selectedValues[1]}-${selectedValues[2]}`;
showDate.value = false;
hasUserChangedDate = true;
maybeEmitDate();
};
const showModal = ref(false);
// 已执行天数
const executedDays = computed(() => {
const startDateStr = props.detail?.log?.start_date_str;
if (!startDateStr || startDateStr === '--') return 0;
const startDate = new Date(startDateStr);
const today = new Date();
startDate.setHours(0, 0, 0, 0);
today.setHours(0, 0, 0, 0);
const diffTime = today.getTime() - startDate.getTime();
const diffDays = Math.floor(diffTime / (1000 * 60 * 60 * 24));
return Math.max(0, diffDays);
});
</script>
<template>
<div class="menu-setting-top" @click="showModal = false">
<div class="menu-setting-card">
<img class="menu-setting-card-bg" src="https://images.health.ufutx.com/202511/18/fb38114f13f3065021c3bd6843d06989.png" alt="" />
<div class="menu-setting-message-box">
<img :src="detail.avatar || 'https://image.fulllinkai.com/202203/09/cc1c73eb1a4941fef25a15cd1ff2f9df.png'" alt="" class="menu-setting-message-avatar" />
<div class="menu-setting-message-name text-center">{{ detail.name || '未知用户' }}</div>
<div class="menu-setting-message-sub">ID· {{ 52330000 + detail.id }}</div>
</div>
<div class="menu-setting-message-list">
<div class="menu-setting-message-item" @click.stop="showModal = !showModal">
<div>当前模式</div>
<div class="menu-setting-message-item-right">
<div>{{ modalText }}</div>
<svg class="menu-setting-message-item-r-icon" xmlns="http://www.w3.org/2000/svg" width="14" height="9" viewBox="0 0 14 9" fill="none">
<path d="M12 2L7 7L2 2" stroke="#66676C" stroke-width="1.5" stroke-linecap="round" />
</svg>
</div>
<div v-if="showModal" class="menu-setting-message-modal" @click.stop>
<div class="menu-setting-message-m-item" :class="{ 'menu-setting-message-m-i-active': activeModal === 1 }" @click.stop="changeModal(1)">
<div class="menu-setting-message-m-i-title">
<div>减肥型</div>
<svg v-if="activeModal === 1" xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 22 22" fill="none">
<path d="M5.2998 12L9.16254 15.8627L16.5498 8.47547" stroke="#18CA6E" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" />
</svg>
</div>
<div class="menu-setting-message-m-i-sub">适用减脂需求,强化热量缺口与代谢调节</div>
<div v-if="activeModal === 1" class="menu-setting-message-m-i-default">当前选中</div>
</div>
<div class="menu-setting-message-m-item" :class="{ 'menu-setting-message-m-i-active': activeModal === 2 }" @click.stop="changeModal(2)">
<div class="menu-setting-message-m-i-title">
<div>其他型</div>
<svg v-if="activeModal === 2" xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 22 22" fill="none">
<path d="M5.2998 12L9.16254 15.8627L16.5498 8.47547" stroke="#18CA6E" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" />
</svg>
</div>
<div class="menu-setting-message-m-i-sub">按照特殊规则在一定范围内生成</div>
<div v-if="activeModal === 2" class="menu-setting-message-m-i-default">当前选中</div>
</div>
</div>
</div>
<div class="menu-setting-message-item">
<div>方案周期</div>
<div class="menu-setting-message-i-two">共49天 已执行{{ executedDays }}天</div>
</div>
<div class="menu-setting-message-item" @click="showDate = true">
<div>开始时间</div>
<div class="menu-setting-message-item-right" @click="toShowDate">
<div>{{ date }}</div>
<svg class="menu-setting-message-item-r-icon" xmlns="http://www.w3.org/2000/svg" width="14" height="9" viewBox="0 0 14 9" fill="none">
<path d="M12 2L7 7L2 2" stroke="#66676C" stroke-width="1.5" stroke-linecap="round" />
</svg>
</div>
</div>
</div>
</div>
<van-popup v-model:show="showDate" round position="bottom" :duration="0.5">
<van-date-picker v-model="dateValues" title="选择日期" :min-date="minDate" :max-date="maxDate" @cancel="showDate = false" @confirm="onConfirm" />
</van-popup>
</div>
</template>
<style scoped lang="scss">
.menu-setting-top {
border-radius: 0 0 16px 16px;
background: #fff;
}
.menu-setting-card {
position: relative;
margin: 51px 10px 0;
z-index: 10;
flex-shrink: 0;
.menu-setting-card-bg {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
z-index: -1;
}
}
.menu-setting-message-box {
padding: 40px 6px 0;
}
.menu-setting-message-avatar {
position: absolute;
left: 50%;
top: -30px;
transform: translateX(-50%);
width: 60px;
height: 60px;
border-radius: 30px;
border: 2px solid #fff;
}
.menu-setting-message-name {
margin-top: 10px;
margin-bottom: 3px;
color: #0e0e0e;
text-align: center;
font-size: 18px;
font-weight: 600;
}
.menu-setting-message-sub {
margin-bottom: 20px;
color: #66676c;
text-align: center;
font-size: 12px;
}
.menu-setting-message-list {
padding: 10px 16px 16px;
.menu-setting-message-item {
position: relative;
display: flex;
align-items: center;
justify-content: space-between;
padding: 16px 0;
color: #0e0e0e;
font-size: 14px;
border-bottom: 1px solid #f2f2f2;
.menu-setting-message-item-right {
display: flex;
align-items: center;
.menu-setting-message-item-r-icon {
margin-left: 10px;
}
}
.menu-setting-message-i-two {
color: #18ca6e;
font-weight: bold;
}
.menu-setting-message-modal {
position: absolute;
top: 30px;
left: 50%;
transform: translateX(-50%);
display: flex;
width: 311px;
padding: 16px;
flex-direction: column;
gap: 16px;
border-radius: 16px;
background: #fff;
box-shadow: 0 3px 20px 0 rgba(0, 0, 0, 0.25);
z-index: 1;
.menu-setting-message-m-item {
display: flex;
padding: 16px;
flex-direction: column;
gap: 6px;
border-radius: 10px;
background: #f8f8f8;
.menu-setting-message-m-i-title {
width: 100%;
display: flex;
justify-content: space-between;
align-items: center;
font-size: 16px;
font-weight: bold;
}
.menu-setting-message-m-i-sub {
color: #66676c;
font-size: 14px;
}
.menu-setting-message-m-i-default {
padding: 3px 6px;
color: #18ca6e;
font-size: 14px;
border-radius: 6px;
background: #e8faf1;
}
}
.menu-setting-message-m-i-active {
background: #fff;
border: 0.3px solid #18ca6e;
}
}
}
.menu-setting-message-item:nth-child(1) {
padding-top: 0;
}
.menu-setting-message-item:last-child {
padding-bottom: 0;
border-bottom: none;
}
}
</style>