wip: frontend refactor

This commit is contained in:
Kroytz committed 2026-07-10 18:06:02 +08:00
1 parent aef417409a
commit c61283f466
2 files changed
+131 -262

No files matched your search

+56 -77
View File
@@ -14,16 +14,16 @@
<view class="notice-bar" v-if="store.notice">
<uv-notice-bar :text="store.notice"></uv-notice-bar>
</view>
<view class="main">
<view class="main menu-page">
<view class="nav">
<view class="header">
<view class="mr-1"><image :src="store.image" class="store-header-img"></image></view>
<image v-if="store.image" :src="store.image" mode="aspectFill" class="store-header-img"></image>
<view class="left" v-if="orderType == 'takein'">
<view class="store-name" @click="selectShop()">
<text>{{ store.name }}</text>
<view class="iconfont iconarrow-right"></view>
</view>
<view class="store-location">
<view class="store-location" v-if="store.dis">
<text>距离您 {{kmUnit(store.dis)}}</text>
</view>
</view>
@@ -39,14 +39,18 @@
</view>
<view class="right">
<view class="dinein" :class="{active: orderType == 'takein'}" @tap="takein">
<text>自取</text>
<text class="iconfont-yshop icon-takein"></text><text>堂食</text>
</view>
<view class="takeout" :class="{active: orderType == 'takeout'}" @tap="takout">
<text>外卖</text>
<text class="iconfont-yshop icon-takeout"></text><text>外卖</text>
</view>
</view>
</view>
</view>
<view class="menu-search">
<text class="iconsearch">⌕</text>
<input v-model="keyword" placeholder="搜索菜品、饮品" confirm-type="search" />
</view>
<!-- #ifdef H5 -->
<view class="content"
@@ -78,20 +82,20 @@
</view>
<view class="items">
<!-- 商品 begin -->
<view class="good" v-for="(good, key) in item.goodsList" :key="key"
<view class="good" v-for="(good, key) in item.goodsList" :key="key" v-show="isGoodVisible(good)"
:class="{'background-grey': good.stock <= 0}">
<image mode="aspectFill" :src="good.image" class="image"
@tap="showGoodDetailModal(item, good)"></image>
<view class="right">
<text class="name">{{ good.storeName }}</text>
<text class="tips">{{ good.storeInfo }}</text>
<text v-if="good.storeInfo" class="tips">{{ good.storeInfo }}</text>
<view class="price_and_action">
<text class="price">¥{{ good.price }}</text>
<view class="btn-group" v-if="good.stock > 0">
<button type="primary" class="btn property_btn"
hover-class="none" size="mini"
@tap="showGoodDetailModal(item, good)">
选规格
<text class="iconfont iconadd-select"></text><text> 选规格</text>
</button>
<view class="dot" v-show="goodCartNum(good.id)">
{{ goodCartNum(good.id) }}</view>
@@ -143,7 +147,7 @@
<view class="wrapper">
<view class="basic">
<view class="name">{{ good.storeName }}</view>
<view class="tips flex justify-between">{{ good.storeInfo }} <text style="color: red;">可获积分:10</text></view>
<view v-if="good.storeInfo" class="tips">{{ good.storeInfo }}</view>
</view>
<view class="properties">
<view class="property" v-for="(item, index) in good.productAttr" :key="index">
@@ -252,8 +256,9 @@ import {
} from '@/api/market'
const main = useMainStore()
const { orderType,address, store,location,isLogin } = storeToRefs(main)
const title = ref('点餐')
const title = ref('食刻点单')
const text = ref('滚动通知')
const keyword = ref('')
const goods = ref([])
const ads = ref([])
@@ -272,76 +277,9 @@ const shopAd = ref('')
const isCartShow = ref(true)
const popup = ref()
// #region agent log
// const debugLog = (hypothesisId, location, message, data = {}) => {
// fetch('http://127.0.0.1:7584/ingest/889fdfba-29d4-4509-84ce-3dfa9254da00', {
// method: 'POST',
// headers: { 'Content-Type': 'application/json', 'X-Debug-Session-Id': 'e0348b' },
// body: JSON.stringify({
// sessionId: 'e0348b',
// runId: 'pre-fix',
// hypothesisId,
// location,
// message,
// data,
// timestamp: Date.now()
// })
// }).catch(() => {})
// }
const measureMenuLayout = () => {
const sys = uni.getSystemInfoSync()
const notice = !!store.value?.notice
const inlineHeight = `calc(100vh - 500rpx + ${notice ? '0rpx' : '60rpx'})`
let platform = 'OTHER'
// #ifdef H5
platform = 'H5'
// #endif
// #ifdef MP-WEIXIN
platform = 'MP-WEIXIN'
// #endif
debugLog('H1', 'menu.vue:measureMenuLayout', 'layout context', {
platform,
windowHeight: sys.windowHeight,
screenHeight: sys.screenHeight,
statusBarHeight: sys.statusBarHeight,
hasNotice: notice,
inlineHeight,
cssExpectedH5: 'calc(100vh - 212rpx - 188rpx)',
cssExpectedDefault: 'calc(100vh - 212rpx)'
})
const q = uni.createSelectorQuery()
q.select('.container').boundingClientRect()
q.select('.main').boundingClientRect()
q.select('.content').boundingClientRect()
q.select('.menus').boundingClientRect()
q.select('.goods').boundingClientRect()
q.select('.nav').boundingClientRect()
q.exec((res) => {
const [container, main, content, menus, goods, nav] = res || []
debugLog('H3', 'menu.vue:measureMenuLayout', 'parent rects', {
containerH: container?.height,
mainH: main?.height,
navH: nav?.height
})
debugLog('H1', 'menu.vue:measureMenuLayout', 'content rect', {
contentH: content?.height,
contentTop: content?.top,
windowHeight: sys.windowHeight,
heightRatio: content?.height && sys.windowHeight ? (content.height / sys.windowHeight).toFixed(3) : null
})
debugLog('H5', 'menu.vue:measureMenuLayout', 'scroll columns', {
menusH: menus?.height,
goodsH: goods?.height,
menusGoodsDelta: menus?.height != null && goods?.height != null ? Math.abs(menus.height - goods.height) : null
})
})
}
// #endregion
const newkmUnit = computed(() => (param) =>{
console.log('param:',param)
return '10km'
})
const goodCartNum = computed(() => { //计算单个饮品添加到购物车的数量
return (id) => cart.value.reduce((acc, cur) => {
if (cur.id === id) {
@@ -373,6 +311,8 @@ const spread = computed(() => { //差多少元起送
if (orderType.value != 'takeout') return
return parseFloat((store.value.minPrice - getCartGoodsPrice).toFixed(2))
})
const isGoodVisible = (good) => !keyword.value || [good.storeName, good.storeInfo]
.filter(Boolean).join(' ').toLowerCase().includes(keyword.value.trim().toLowerCase())
// 监听自定义事件
uni.$on('refreshMenu', () => {
@@ -1508,4 +1448,43 @@ page {
padding: 15rpx !important;
background-color: $menu-sold-out-bg;
}
.menu-page {
padding: 0 24rpx;
box-sizing: border-box;
background: #fff;
.nav { height: auto; padding-top: 12rpx; }
.nav .header { height: 170rpx; padding: 24rpx; box-sizing: border-box; border-radius: 28rpx; background: linear-gradient(120deg, #fff3e5, #fffaf4); }
.nav .header .left { margin-left: 18rpx; }
.nav .header .left .store-name { font-size: 34rpx; font-weight: 700; }
.nav .header .right { padding: 4rpx; background: #fff; border: 2rpx solid #f5eee8; }
.nav .header .right .dinein, .nav .header .right .takeout { gap: 8rpx; margin: 0; padding: 16rpx 22rpx; }
.nav .header .right .active { margin: 0; background: linear-gradient(90deg, #ff9b20, #ff6f13); }
.menu-search { display: flex; align-items: center; height: 78rpx; margin: 22rpx 0; padding: 0 24rpx; border: 2rpx solid #eee9e5; border-radius: 42rpx; color: #9d9d9d; background: #fff; }
.menu-search input { flex: 1; margin-left: 14rpx; font-size: 28rpx; }
.menu-search .iconsearch { font-size: 40rpx; line-height: 1; }
.content { height: calc(100vh - 440rpx) !important; }
.menus { width: 156rpx; border-radius: 24rpx 0 0 24rpx; background: #fffaf5; }
.menus .wrapper .menu { justify-content: center; padding: 30rpx 10rpx; color: #7c756e; }
.menus .wrapper .menu.current { color: #ff7119; font-weight: 700; background: #fff; }
.menus .wrapper .menu.current::before { content: ''; position: absolute; left: 0; width: 8rpx; height: 42rpx; border-radius: 0 8rpx 8rpx 0; background: #ff781b; }
.goods { border-radius: 0 24rpx 24rpx 0; }
.goods .wrapper { padding: 0 20rpx; }
.goods .wrapper .list .category .title { padding: 24rpx 0 14rpx; font-size: 34rpx; font-weight: 700; }
.goods .wrapper .list .category .title::before { content: ''; width: 8rpx; height: 30rpx; margin-right: 12rpx; border-radius: 8rpx; background: #ff9b20; }
.goods .wrapper .list .category .items .good { padding: 20rpx 0; border-bottom: 1rpx solid #f4f0ec; }
.goods .wrapper .list .category .items .good .image { width: 178rpx; height: 178rpx; border-radius: 18rpx; }
.goods .wrapper .list .category .items .good .right { height: 178rpx; }
.goods .wrapper .list .category .items .good .right .name { font-size: 31rpx; font-weight: 700; }
.goods .wrapper .list .category .items .good .right .price_and_action .price { font-size: 36rpx; color: #ff6817; }
.goods .wrapper .list .category .items .good .right .price_and_action .btn-group .btn.property_btn { height: 56rpx; padding: 0 18rpx; line-height: 56rpx; border-radius: 28rpx; background: #ff7417; }
.cart-box { bottom: 28rpx; height: 116rpx; border-radius: 58rpx; box-shadow: 0 8rpx 28rpx rgba(91, 61, 32, .16); }
.cart-box .cart-img { width: 116rpx; height: 116rpx; }
.cart-box .pay-btn { padding: 0 46rpx; border-radius: 58rpx; background: linear-gradient(90deg, #ff9b20, #ff6817); }
}
.store-header-img { flex: 0 0 118rpx; width: 118rpx; height: 118rpx; border-radius: 16rpx; }
</style>