| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242 |
- <template>
- <view class="preference-page">
- <!-- 月食品预算 -->
- <view class="form-section">
- <text class="label">月食品预算(元)</text>
- <slider :value="budget" :min="500" :max="10000" :step="100" show-value @change="onBudgetChange" />
- <text class="hint">当前: {{ budget }}元/月</text>
- </view>
- <!-- 口味偏好 -->
- <view class="form-section">
- <text class="label">口味偏好</text>
- <checkbox-group @change="onTasteChange">
- <view class="checkbox-row">
- <label class="checkbox-label" v-for="item in tasteOptions" :key="item">
- <checkbox :value="item" :checked="tastePreferences.indexOf(item) >= 0" />
- <text class="checkbox-text">{{ item }}</text>
- </label>
- </view>
- </checkbox-group>
- </view>
- <!-- 菜系偏好 -->
- <view class="form-section">
- <text class="label">偏好菜系</text>
- <picker :value="cuisineIndex" :range="cuisineList" @change="onCuisineChange">
- <view class="picker-value">{{ cuisineList[cuisineIndex] || '请选择' }}</view>
- </picker>
- </view>
- <!-- 每日餐数 -->
- <view class="form-section">
- <text class="label">每日餐数</text>
- <picker :value="mealIndex" :range="mealList" @change="onMealCountChange">
- <view class="picker-value">{{ mealList[mealIndex] || '请选择' }}</view>
- </picker>
- </view>
- <!-- 烹饪能力 -->
- <view class="form-section">
- <text class="label">烹饪能力</text>
- <radio-group @change="onCookingChange">
- <view class="radio-row">
- <label class="radio-label" v-for="item in cookingOptions" :key="item.value">
- <radio :value="item.value" :checked="cookingAbility === item.value" />
- <text class="radio-text">{{ item.label }}</text>
- </label>
- </view>
- </radio-group>
- </view>
- <button class="save-btn" type="primary" :loading="saving" @click="save" :disabled="saving">
- {{ saving ? '保存中...' : '保存设置' }}
- </button>
- </view>
- </template>
- <script>
- import { getNutritionProfile, saveNutritionProfile } from '@/utils/api'
- export default {
- name: 'MealPreference',
- data() {
- return {
- budget: 2000,
- tastePreferences: [],
- tasteOptions: ['清淡', '微辣', '甜', '酸', '咸', '鲜'],
- cuisineIndex: 0,
- cuisineList: ['中式', '粤菜', '川菜', '西式', '日式', '其他'],
- mealIndex: 1,
- mealList: ['2餐', '3餐', '4餐', '5餐'],
- cookingAbility: 'simple',
- cookingOptions: [
- { value: 'simple', label: '简单(只会基础)' },
- { value: 'medium', label: '一般(能炒家常菜)' },
- { value: 'advanced', label: '较强(能做大菜)' }
- ],
- saving: false
- }
- },
- onLoad() {
- this.loadCurrentPreferences()
- },
- methods: {
- async loadCurrentPreferences() {
- try {
- var res = await getNutritionProfile({})
- if (res.code === 0 && res.data) {
- var profile = res.data
- if (profile.budgetMonthly) {
- this.budget = profile.budgetMonthly
- }
- if (profile.familyTastePreferences) {
- try {
- var parsed = JSON.parse(profile.familyTastePreferences)
- if (Array.isArray(parsed)) {
- this.tastePreferences = parsed
- } else {
- this.tastePreferences = [String(parsed)]
- }
- } catch (e) {
- this.tastePreferences = profile.familyTastePreferences.split(',')
- }
- }
- if (profile.cuisineStyle) {
- var idx = this.cuisineList.indexOf(profile.cuisineStyle)
- if (idx >= 0) {
- this.cuisineIndex = idx
- }
- }
- if (profile.mealCount) {
- var mealIdx = profile.mealCount - 2
- if (mealIdx >= 0 && mealIdx < this.mealList.length) {
- this.mealIndex = mealIdx
- }
- }
- if (profile.cookingAbility) {
- this.cookingAbility = profile.cookingAbility
- }
- }
- } catch (e) {
- // 首次加载无偏好,使用默认值
- }
- },
- onBudgetChange(e) {
- this.budget = e.detail.value
- },
- onTasteChange(e) {
- this.tastePreferences = e.detail.value
- },
- onCuisineChange(e) {
- this.cuisineIndex = e.detail.value
- },
- onMealCountChange(e) {
- this.mealIndex = e.detail.value
- },
- onCookingChange(e) {
- this.cookingAbility = e.detail.value
- },
- async save() {
- this.saving = true
- try {
- var params = {
- budgetMonthly: this.budget,
- familyTastePreferences: JSON.stringify(this.tastePreferences),
- cuisineStyle: this.cuisineList[this.cuisineIndex],
- mealCount: this.mealIndex + 2,
- cookingAbility: this.cookingAbility
- }
- var res = await saveNutritionProfile(params)
- if (res.code === 0) {
- uni.showToast({ title: '保存成功', icon: 'success' })
- } else {
- uni.showToast({ title: res.message || '保存失败', icon: 'none' })
- }
- } catch (e) {
- uni.showToast({ title: '网络错误', icon: 'none' })
- } finally {
- this.saving = false
- }
- }
- }
- }
- </script>
- <style scoped>
- .preference-page {
- min-height: 100vh;
- background: var(--bg, #FFF7ED);
- padding: 20rpx 30rpx;
- }
- .form-section {
- background: #fff;
- border-radius: 16rpx;
- padding: 30rpx;
- box-shadow: var(--shadow-md, 0 2rpx 12rpx rgba(0,0,0,0.06));
- margin-bottom: 20rpx;
- }
- .label {
- font-size: 28rpx;
- color: #333;
- margin-bottom: 16rpx;
- display: block;
- font-weight: 500;
- }
- .hint {
- font-size: 24rpx;
- color: var(--color-primary, #F97316);
- margin-top: 10rpx;
- display: block;
- }
- .picker-value {
- font-size: 28rpx;
- color: var(--color-primary, #F97316);
- padding: 16rpx 20rpx;
- background: #FFF0E0;
- border-radius: 8rpx;
- }
- .checkbox-row {
- display: flex;
- flex-direction: row;
- flex-wrap: wrap;
- gap: 16rpx;
- }
- .checkbox-label {
- display: flex;
- flex-direction: row;
- align-items: center;
- margin-right: 16rpx;
- margin-bottom: 10rpx;
- }
- .checkbox-text {
- font-size: 28rpx;
- color: #333;
- margin-left: 8rpx;
- }
- .radio-row {
- display: flex;
- flex-direction: column;
- gap: 16rpx;
- }
- .radio-label {
- display: flex;
- flex-direction: row;
- align-items: center;
- margin-bottom: 10rpx;
- }
- .radio-text {
- font-size: 28rpx;
- color: #333;
- margin-left: 8rpx;
- }
- .save-btn {
- margin: 30rpx 0;
- background: var(--color-primary, #F97316);
- border: none;
- border-radius: 12rpx;
- font-size: 32rpx;
- height: 88rpx;
- line-height: 88rpx;
- }
- </style>
|