fix: 修复 VoiceController Map.of 兼容性 + ExploreController 参数不匹配

- VoiceController: Map.of() -> Collections.singletonMap() 兼容 Java 8
- ExploreController: 补齐 takeoutService.roll() 缺失的 taste/priceRange/allergies 参数

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
王鹏
2026-05-08 20:02:27 +08:00
commit 802b4ba229
98 changed files with 5761 additions and 0 deletions

View File

@@ -0,0 +1,45 @@
const storage = require('../../utils/storage');
Page({
data: {
avatarUrl: '',
nickname: '',
prefs: { taste: '都可以', priceRange: 'all', allergies: '' },
shoppingList: []
},
onShow() {
const prefs = storage.get('user_prefs', { taste: '都可以', priceRange: 'all', allergies: '' });
const shoppingList = storage.get('shopping_list', []);
this.setData({ prefs, shoppingList });
},
setPref(e) {
const { key, val } = e.currentTarget.dataset;
const prefs = { ...this.data.prefs, [key]: val };
this.setData({ prefs });
storage.set('user_prefs', prefs);
},
setAllergies(e) {
const prefs = { ...this.data.prefs, allergies: e.detail.value };
this.setData({ prefs });
storage.set('user_prefs', prefs);
},
toggleItem(e) {
const idx = e.currentTarget.dataset.index;
const list = this.data.shoppingList;
list[idx].checked = !list[idx].checked;
this.setData({ shoppingList: list });
storage.set('shopping_list', list);
},
clearShopping() {
wx.showModal({
title: '清空清单',
content: '确定清空所有购物清单吗?',
success: (res) => {
if (res.confirm) {
this.setData({ shoppingList: [] });
storage.set('shopping_list', []);
}
}
});
}
});

View File

@@ -0,0 +1,3 @@
{
"navigationBarTitleText": "我的"
}

View File

@@ -0,0 +1,48 @@
<view class="mine-page">
<view class="profile">
<image class="avatar" src="{{avatarUrl}}" mode="aspectFill" wx:if="{{avatarUrl}}"></image>
<view class="avatar-placeholder" wx:else>👤</view>
<view class="nickname">{{nickname || '点击登录'}}</view>
</view>
<view class="card-section">
<view class="card-title">口味偏好</view>
<view class="tag-row">
<view class="pref-tag {{prefs.taste === '辣' ? 'active' : ''}}" data-key="taste" data-val="辣" bind:tap="setPref">🌶️ 辣</view>
<view class="pref-tag {{prefs.taste === '清淡' ? 'active' : ''}}" data-key="taste" data-val="清淡" bind:tap="setPref">🌱 清淡</view>
<view class="pref-tag {{prefs.taste === '酸甜' ? 'active' : ''}}" data-key="taste" data-val="酸甜" bind:tap="setPref">🍋 酸甜</view>
<view class="pref-tag {{prefs.taste === '都可以' ? 'active' : ''}}" data-key="taste" data-val="都可以" bind:tap="setPref">😋 都可以</view>
</view>
</view>
<view class="card-section">
<view class="card-title">价格区间(外卖)</view>
<view class="tag-row">
<view class="pref-tag {{prefs.priceRange === 'low' ? 'active' : ''}}" data-key="priceRange" data-val="low" bind:tap="setPref">¥ 人均&lt;30</view>
<view class="pref-tag {{prefs.priceRange === 'medium' ? 'active' : ''}}" data-key="priceRange" data-val="medium" bind:tap="setPref">¥ 人均30-80</view>
<view class="pref-tag {{prefs.priceRange === 'high' ? 'active' : ''}}" data-key="priceRange" data-val="high" bind:tap="setPref">¥¥ 人均&gt;80</view>
<view class="pref-tag {{prefs.priceRange === 'all' ? 'active' : ''}}" data-key="priceRange" data-val="all" bind:tap="setPref">都行</view>
</view>
</view>
<view class="card-section">
<view class="card-title">忌口/过敏</view>
<input class="allergy-input" placeholder="如:海鲜、花生、牛奶(逗号分隔)" value="{{prefs.allergies}}" bind:blur="setAllergies" />
</view>
<view class="card-section" wx:if="{{shoppingList.length}}">
<view class="card-title">
购物清单 ({{shoppingList.length}}项)
<text class="clear-btn" bind:tap="clearShopping">清空</text>
</view>
<view class="shop-item {{item.checked ? 'checked' : ''}}" wx:for="{{shoppingList}}" wx:key="name" bind:tap="toggleItem" data-index="{{index}}">
<view class="shop-check">{{item.checked ? '✅' : '⬜'}}</view>
<view class="shop-info">
<view class="shop-name">{{item.name}} <text class="shop-amount">{{item.amount}}</text></view>
<view class="shop-from">来自:{{item.from}}</view>
</view>
</view>
</view>
<view class="about">吃啥盲盒 ChowBox v1.0.0</view>
</view>

View File

@@ -0,0 +1,158 @@
/*
* 我的
*/
.mine-page {
padding: var(--space-xl) var(--space-lg);
min-height: 100vh;
}
/* ── 个人资料 ── */
.profile {
display: flex;
flex-direction: column;
align-items: center;
margin-bottom: var(--space-xl);
}
.avatar {
width: 120rpx;
height: 120rpx;
border-radius: 50%;
background: #F0EDE8;
}
.avatar-placeholder {
width: 120rpx;
height: 120rpx;
border-radius: 50%;
background: #F5F2EE;
display: flex;
align-items: center;
justify-content: center;
font-size: 56rpx;
}
.nickname {
font-size: var(--text-subtitle);
font-weight: 600;
color: var(--color-text);
margin-top: var(--space-sm);
}
/* ── 卡片 ── */
.card-section {
padding: var(--space-md);
margin-bottom: var(--space-sm);
background: var(--color-surface);
border-radius: var(--radius-md);
box-shadow: var(--shadow-sm);
}
.card-title {
font-size: var(--text-body);
font-weight: 600;
color: var(--color-text);
margin-bottom: var(--space-sm);
}
/* ── 偏好标签 ── */
.tag-row {
display: flex;
flex-wrap: wrap;
}
.pref-tag {
padding: 8rpx var(--space-md);
border-radius: var(--radius-full);
background: #F5F2EE;
font-size: var(--text-body-sm);
color: var(--color-text-secondary);
margin-right: 12rpx;
margin-bottom: 12rpx;
transition: all 0.2s var(--ease-out);
}
.pref-tag:active {
transform: scale(0.95);
}
.pref-tag.active {
background: var(--color-primary-pale);
color: var(--color-primary);
font-weight: 600;
}
/* ── 过敏原输入 ── */
.allergy-input {
width: 100%;
font-size: var(--text-body-sm);
padding: 12rpx 0;
color: var(--color-text);
border-bottom: 1rpx solid var(--color-hairline);
}
/* ── 清空按钮 ── */
.clear-btn {
font-size: var(--text-body-sm);
color: var(--color-primary);
float: right;
font-weight: 500;
}
/* ── 购物清单 ── */
.shop-item {
display: flex;
align-items: center;
padding: 14rpx 0;
border-bottom: 1rpx solid var(--color-hairline);
}
.shop-item:last-child {
border-bottom: none;
}
.shop-item:active {
opacity: 0.6;
}
.shop-item.checked .shop-name {
text-decoration: line-through;
color: var(--color-text-muted);
}
.shop-check {
font-size: 32rpx;
margin-right: var(--space-sm);
}
.shop-info {
flex: 1;
min-width: 0;
}
.shop-name {
font-size: var(--text-body);
font-weight: 500;
color: var(--color-text);
}
.shop-amount {
font-size: var(--text-body-sm);
color: var(--color-text-muted);
}
.shop-from {
font-size: var(--text-caption);
color: var(--color-text-muted);
margin-top: 2rpx;
}
/* ── 版本 ── */
.about {
text-align: center;
font-size: var(--text-body-sm);
color: var(--color-text-muted);
margin-top: var(--space-2xl);
padding-bottom: var(--space-xl);
}