327 lines
10 KiB
Vue
327 lines
10 KiB
Vue
<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>
|