Browse Source

fix: 导航栏适配/时间格式/单列卡片/未读徽章/拒单显示/已完成计数

dev
mac 1 day ago
parent
commit
50d886d1fb
5 changed files with 62 additions and 29 deletions
  1. +12
    -11
      components/ProductCard.vue
  2. +1
    -1
      pages/menu/menu.vue
  3. +17
    -6
      pages/orders/orders.vue
  4. +24
    -9
      pages/staff/board.vue
  5. +8
    -2
      uni.scss

+ 12
- 11
components/ProductCard.vue View File

@ -1,15 +1,15 @@
<template>
<view class="product-card" @tap="$emit('tap', product)">
<view class="card-img">
<text>{{ product.emoji }}</text>
<view class="card-left">
<text class="card-emoji">{{ product.emoji }}</text>
<text v-if="product.alc > 0" class="alc-tag">{{ product.alc }}%</text>
</view>
<view class="card-body">
<text class="card-name">{{ product.name }}</text>
<text class="card-en">{{ product.en }}</text>
<text class="card-desc">{{ product.desc }}</text>
<view class="card-add" @tap.stop="$emit('add', product)">+</view>
</view>
<view class="card-add" @tap.stop="$emit('add', product)">+</view>
</view>
</template>
@ -22,12 +22,13 @@ export default {
</script>
<style scoped>
.product-card{width:calc(50% - 12rpx);background:var(--bg-card);border-radius:var(--radius);overflow:hidden;margin-bottom:20rpx;border:1px solid var(--border);position:relative;min-height:420rpx}
.card-img{width:100%;height:220rpx;display:flex;align-items:center;justify-content:center;font-size:88rpx;position:relative;background:rgba(245,166,35,.04)}
.alc-tag{position:absolute;top:16rpx;right:16rpx;background:rgba(0,0,0,.6);color:var(--gold-light);font-size:20rpx;padding:6rpx 16rpx;border-radius:20rpx;font-weight:700}
.card-body{padding:16rpx 20rpx 24rpx;position:relative}
.card-name{font-size:28rpx;font-weight:700;color:var(--text);display:block;margin-bottom:4rpx;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.card-en{font-size:20rpx;color:var(--text-muted);display:block;margin-bottom:6rpx;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.card-desc{font-size:22rpx;color:var(--text-dim);line-height:1.3;display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.card-add{position:absolute;bottom:16rpx;right:16rpx;width:56rpx;height:56rpx;border-radius:50%;background:var(--orange);color:#fff;font-size:32rpx;display:flex;align-items:center;justify-content:center;box-shadow:0 4rpx 20rpx rgba(255,107,53,.4)}
.product-card{width:100%;background:var(--bg-card);border-radius:var(--radius);margin-bottom:20rpx;border:1px solid var(--border);display:flex;align-items:center;padding:20rpx;gap:20rpx;min-height:140rpx}
.card-left{position:relative;flex-shrink:0;width:120rpx;height:120rpx;display:flex;align-items:center;justify-content:center;background:rgba(245,166,35,.06);border-radius:20rpx}
.card-emoji{font-size:64rpx}
.alc-tag{position:absolute;top:4rpx;right:4rpx;background:rgba(0,0,0,.6);color:var(--gold-light);font-size:18rpx;padding:2rpx 10rpx;border-radius:12rpx;font-weight:700}
.card-body{flex:1;min-width:0;display:flex;flex-direction:column;justify-content:center}
.card-name{font-size:30rpx;font-weight:700;color:var(--text);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.card-en{font-size:22rpx;color:var(--text-muted);margin:4rpx 0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.card-desc{font-size:24rpx;color:var(--text-dim);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.card-add{flex-shrink:0;width:56rpx;height:56rpx;border-radius:50%;background:var(--orange);color:#fff;font-size:32rpx;display:flex;align-items:center;justify-content:center;box-shadow:0 4rpx 20rpx rgba(255,107,53,.4)}
</style>

+ 1
- 1
pages/menu/menu.vue View File

@ -146,7 +146,7 @@ export default {
.card-badge{background:linear-gradient(135deg,var(--gold-dark),var(--gold));color:#1A1A1A;padding:10rpx 24rpx;border-radius:28rpx;font-weight:800;font-size:26rpx;letter-spacing:6rpx;animation:card-appear-top .5s ease}
.my-btn{font-size:26rpx;color:var(--gold);font-weight:600}
.menu-scroll{flex:1}
.product-grid{display:flex;flex-wrap:wrap;justify-content:space-between;padding:16rpx 20rpx}
.product-grid{padding:16rpx 20rpx}
.empty-state{display:flex;flex-direction:column;align-items:center;padding:120rpx 0}
.empty-icon{font-size:112rpx;opacity:.3}
.empty-text{font-size:28rpx;color:var(--text-muted);margin-top:16rpx}


+ 17
- 6
pages/orders/orders.vue View File

@ -11,7 +11,10 @@
<template #actions>
<view class="card-actions">
<button v-if="o.status===0" class="action-btn action-remind" @tap="onRemind(o.id)">🔔 催单</button>
<button class="action-btn action-chat" @tap="onChat">💬 联系调酒师</button>
<button class="action-btn action-chat" @tap="onChat">
💬 联系调酒师
<text v-if="card.unread > 0" class="unread-dot">{{ card.unread }}</text>
</button>
</view>
</template>
</OrderCard>
@ -45,7 +48,14 @@ export default {
if (Array.isArray(res)) orders.value = res
} catch (e) {}
}
async function checkUnread() {
try {
const res = await get(API.MESSAGE_LIST, { card_no: card.cardNo, since: 0 })
if (Array.isArray(res)) {
card.incrementUnread(res.filter(m => m.senderType === 'staff').length)
}
} catch (e) {}
}
async function onRemind(id) {
try {
await post(API.ORDER_REMIND, { id, card_no: card.cardNo })
@ -58,10 +68,10 @@ export default {
function goBack() { uni.navigateBack() }
function goMenu() { uni.navigateBack() }
onMounted(() => { loadOrders(); startPoll('orders', loadOrders, 15000) })
onUnmounted(() => stopPoll('orders'))
onMounted(() => { loadOrders(); checkUnread(); startPoll('orders', loadOrders, 15000); startPoll('ordersUnread', checkUnread, 10000) })
onUnmounted(() => { stopPoll('orders'); stopPoll('ordersUnread') })
return { orders, onRemind, onChat, goBack, goMenu }
return { card, orders, onRemind, onChat, goBack, goMenu }
}
}
</script>
@ -73,9 +83,10 @@ export default {
.nav-title{font-size:32rpx;font-weight:800;color:var(--gold)}
.orders-body{flex:1;padding:20rpx}
.card-actions{display:flex;gap:16rpx;padding-top:16rpx}
.action-btn{padding:12rpx 28rpx;border-radius:24rpx;font-size:24rpx;font-weight:600;border:none}
.action-btn{padding:12rpx 28rpx;border-radius:24rpx;font-size:24rpx;font-weight:600;border:none;position:relative}
.action-remind{background:rgba(255,59,59,.15);color:var(--red)}
.action-chat{background:rgba(74,144,217,.15);color:var(--blue)}
.unread-dot{margin-left:6rpx;background:var(--red);color:#fff;font-size:18rpx;min-width:32rpx;height:32rpx;border-radius:16rpx;display:inline-flex;align-items:center;justify-content:center;padding:0 8rpx;vertical-align:middle}
.empty-state{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center}
.empty-icon{font-size:112rpx;opacity:.3}
.empty-text{font-size:28rpx;color:var(--text-muted);margin:16rpx 0}


+ 24
- 9
pages/staff/board.vue View File

@ -10,12 +10,15 @@
</view>
</view>
<view class="staff-info">🧑🍳 {{ staff.nickname }} 别摸鱼了</view>
<view class="staff-info">
🧑🍳 {{ staff.nickname }} 别摸鱼了
<text v-if="staff.unread > 0" class="staff-unread">💬 {{ staff.unread }}条新消息</text>
</view>
<view class="board-tabs">
<view v-for="t in tabs" :key="t.status" class="board-tab" :class="{ active: activeTab === t.status }" @tap="switchTab(t.status)">
{{ t.label }}
<text v-if="t.status !== 2" class="tab-count">{{ counts[t.status] }}</text>
<text class="tab-count">{{ counts[t.status] }}</text>
</view>
</view>
@ -58,16 +61,27 @@ export default {
const tabs = [{ status: 0, label: '🔔 新订单' },{ status: 1, label: '⚡ 进行中' },{ status: 2, label: '✅ 已完成' }]
const activeTab = ref(0)
const orders = ref([])
const counts = ref({ 0: 0, 1: 0 })
const recipeVisible = ref(false)
const recipeCardNo = ref('')
const recipeItems = ref([])
const counts = ref({ 0: 0, 1: 0, 2: 0 })
async function loadOrders() {
try { const res = await get(API.STAFF_ORDERS, { status: activeTab.value }); if (Array.isArray(res)) orders.value = res } catch (e) {}
try {
const params = { status: activeTab.value }
if (activeTab.value === 2) params.include_cancel = 1
const res = await get(API.STAFF_ORDERS, params)
if (Array.isArray(res)) orders.value = res
} catch (e) {}
}
async function loadCounts() {
try { const r0 = await get(API.STAFF_ORDERS, { status: 0 }); const r1 = await get(API.STAFF_ORDERS, { status: 1 }); counts.value = { 0: Array.isArray(r0) ? r0.length : 0, 1: Array.isArray(r1) ? r1.length : 0 } } catch (e) {}
try {
const r0 = await get(API.STAFF_ORDERS, { status: 0 })
const r1 = await get(API.STAFF_ORDERS, { status: 1 })
const r2 = await get(API.STAFF_ORDERS, { status: 2, include_cancel: 1 })
counts.value = {
0: Array.isArray(r0) ? r0.length : 0,
1: Array.isArray(r1) ? r1.length : 0,
2: Array.isArray(r2) ? r2.length : 0
}
} catch (e) {}
}
function switchTab(s) { activeTab.value = s; loadOrders() }
async function onConfirm(id) { try { await post(API.STAFF_CONFIRM, { id }); uni.showToast({ title: '已接单 ✅', icon: 'none' }); loadOrders(); loadCounts() } catch (e) {} }
@ -93,7 +107,8 @@ export default {
.nav-logo{font-size:44rpx}
.nav-brand{font-size:32rpx;font-weight:900;color:var(--gold)}
.logout-btn{font-size:26rpx;color:var(--red)}
.staff-info{background:var(--bg-card);padding:16rpx 32rpx;font-size:24rpx;color:var(--text-dim);border-bottom:1px solid var(--border)}
.staff-info{background:var(--bg-card);padding:16rpx 32rpx;font-size:24rpx;color:var(--text-dim);border-bottom:1px solid var(--border);display:flex;align-items:center;justify-content:space-between}
.staff-unread{color:var(--red);font-weight:700;font-size:22rpx}
.board-tabs{display:flex;border-bottom:1px solid var(--border);position:sticky;top:0;z-index:50;background:var(--bg);flex-shrink:0}
.board-tab{flex:1;padding:24rpx;text-align:center;font-size:26rpx;font-weight:600;color:var(--text-dim);border-bottom:4rpx solid transparent}
.board-tab.active{color:var(--gold);border-bottom-color:var(--gold)}


+ 8
- 2
uni.scss View File

@ -1,4 +1,4 @@
// 纯瘾大 全局样式 (严格对齐 UI/css/miniapp.css)
// 纯瘾大 全局样式
view,text,button,input,scroll-view,image,navigator,swiper,swiper-item{box-sizing:border-box}
page {
@ -22,13 +22,19 @@ page {
--radius-xs: 12rpx;
--nav-h: 100rpx;
--safe-b: 68rpx;
--status-h: var(--status-bar-height);
background-color: var(--bg);
color: var(--text);
font-family: -apple-system, BlinkMacSystemFont, 'PingFang SC', 'Microsoft YaHei', sans-serif;
font-size: 28rpx;
min-height: 100vh;
width: 100%;
-webkit-font-smoothing: antialiased;
}
// 自定义导航栏基类所有页面 nav-bar 继承
page .nav-bar {
padding-top: var(--status-bar-height);
box-sizing: content-box;
}
// 动画


Loading…
Cancel
Save