diff --git a/pages/component/home.vue b/pages/component/home.vue index 25b7818..7fc684a 100644 --- a/pages/component/home.vue +++ b/pages/component/home.vue @@ -38,12 +38,12 @@ @pause="onVideoPause(index)" @ended="onVideoEnded(index)" > - - - - + + + + + + @@ -125,7 +125,10 @@ {{item.name}} - ¥ {{item.price}} + ¥ {{item.price}} + /{{item.unit}} + + ¥ {{item.price}}-{{item.maxPrice}} /{{item.unit}} @@ -383,6 +386,7 @@ icon: item.icon ? item.icon : '', name: item.title, price: item.priceNo ? item.priceNo : '', + maxPrice: item.maxPriceNo ? item.maxPriceNo : '', unit: item.unit ? item.unit : '' } }) @@ -688,7 +692,7 @@ left: 0; right: 0; bottom: 0; - background: rgba(0, 0, 0, 0.3); + background: rgba(0, 0, 0, 0.4); z-index: 10; cursor: pointer; display: flex; @@ -696,20 +700,41 @@ align-items: center; .play-button-large { - width: 100rpx; - height: 100rpx; - background: rgba(0, 0, 0, 0.7); + width: 120rpx; + height: 120rpx; + background: transparent; border-radius: 50%; display: flex; justify-content: center; align-items: center; backdrop-filter: blur(10rpx); transition: all 0.3s ease; - box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.3); + box-shadow: 0 8rpx 30rpx rgba(0, 0, 0, 0.3); + // border: 3rpx solid rgba(255, 255, 255, 0.9); &:active { transform: scale(0.9); - background: rgba(0, 0, 0, 0.8); + background: rgba(255, 255, 255, 0.1); + } + + .play-triangle { + width: 0; + height: 0; + border-left: 24rpx solid #fff; + border-top: 18rpx solid transparent; + border-bottom: 18rpx solid transparent; + margin-left: 8rpx; + transition: all 0.3s ease; + filter: drop-shadow(0 2rpx 4rpx rgba(0, 0, 0, 0.3)); + } + } + + &:hover .play-button-large { + transform: scale(1.1); + box-shadow: 0 12rpx 40rpx rgba(0, 0, 0, 0.4); + + .play-triangle { + border-left-color: #ff8917; } } } diff --git a/pages/component/recycle.vue b/pages/component/recycle.vue index bd2b7c3..42304c3 100644 --- a/pages/component/recycle.vue +++ b/pages/component/recycle.vue @@ -2,32 +2,61 @@ - --> + - + + @@ -70,11 +99,12 @@ - - ¥ - {{item.price}} - /{{ item.unit || '件' }} - + + ¥ + {{item.price}} + {{item.price}}-{{item.maxPrice}} + /{{ item.unit || '件' }} + {{getItemTotalQuantity(item)}} @@ -116,7 +146,8 @@ - ¥{{priceRange.min}}-{{priceRange.max}} + ¥{{priceRange.min}} + ¥{{priceRange.min}}-{{priceRange.max}} @@ -142,7 +173,8 @@ {{item.name}} 品牌:{{item.brandName}} {{item.service}} - ¥{{item.price}}/{{ item.unit || '件' }} + ¥{{item.price}}/{{ item.unit || '件' }} + ¥{{item.price}}-{{item.maxPrice}}/{{ item.unit || '件' }} @@ -159,7 +191,8 @@ - ¥{{priceRange.min}}-{{priceRange.max}} + ¥{{priceRange.min}} + ¥{{priceRange.min}}-{{priceRange.max}} @@ -330,6 +363,7 @@ export default { pageSize: 10, currentCategory: 0, tabbarHeight: 0, + videoPlayingStates: {}, // 记录每个视频的播放状态 showDetailPanel: false, showBrandPopup: false, showRulePopup: false, @@ -341,6 +375,7 @@ export default { name: '' }, brandList: [], + brandCache: {}, // 为每个商品缓存品牌信息 { productId: [brandList] } brandIndexList: ['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'], currentLetter: 'A', scrollToView: '', @@ -677,6 +712,14 @@ export default { }, // 获取品牌信息 getBrandInfo(brandId) { + // 从所有商品的品牌缓存中查找品牌信息 + for (const productId in this.brandCache) { + const brandInfo = this.brandCache[productId].find(brand => brand.id === brandId) + if (brandInfo) { + return brandInfo + } + } + // 如果缓存中没有找到,也从当前brandList中查找(兼容性) return this.brandList.find(brand => brand.id === brandId) }, // 获取商品的总数量(所有品牌) @@ -763,7 +806,7 @@ export default { icon: item.image, quantity: item.quantity, unitPrice: item.price, - maxPrice : item.maxPrice, + maxPrice: item.maxPrice, desc: item.brandName ? `品牌:${item.brandName}` : '允许脏破烂,160码以上' } @@ -824,6 +867,9 @@ export default { // 清空已查看规则的记录 this.viewedRuleItems.clear() + // 清空品牌缓存 + this.brandCache = {} + // 模拟网络请求延迟 await new Promise(resolve => setTimeout(resolve, 1000)) @@ -1017,7 +1063,7 @@ export default { this.$api('getGoodsBrandList', params, res => { // console.log(res,'res') if (res && res.success && res.result && res.result.records) { - this.brandList = res.result.records.map(item => { + const brandList = res.result.records.map(item => { // 获取品牌名称的拼音首字母 const firstChar = this.getPinyinFirstLetter(item.name) return { @@ -1027,6 +1073,13 @@ export default { letter: firstChar } }) + + // 缓存到对应商品的品牌列表中 + this.$set(this.brandCache, productId, brandList) + + // 同时更新当前显示的brandList(用于弹窗显示) + this.brandList = brandList + // console.log(this.brandList,'this.brandList') } }) @@ -1068,6 +1121,54 @@ export default { }, 500) }, + // 视频相关方法 + playVideoFullscreen(item, index) { + if (!this.videoPlayingStates[index]) { + // 第一次点击:显示视频并开始播放 + this.$set(this.videoPlayingStates, index, true); + + // 等待视频元素渲染后再进行操作 + this.$nextTick(() => { + setTimeout(() => { + const videoContext = uni.createVideoContext(`recycle-video-${index}`, this); + if (videoContext) { + // 直接进入全屏播放 + videoContext.requestFullScreen({ + direction: -1 // 自动选择方向 + }); + } + }, 200); + }); + } + }, + + onVideoPlay(index) { + this.$set(this.videoPlayingStates, index, true); + }, + + onVideoPause(index) { + this.$set(this.videoPlayingStates, index, false); + }, + + onVideoEnded(index) { + // 视频播放结束,回到预览状态 + this.$set(this.videoPlayingStates, index, false); + }, + + onFullscreenChange(e) { + console.log('全屏状态改变:', e.detail); + const videoIndex = e.target.id.replace('recycle-video-', ''); + + if (e.detail.fullScreen) { + // 进入全屏时,不做任何操作 + console.log('进入全屏模式,方向:', e.detail.direction); + } else { + // 退出全屏时,回到预览状态 + console.log('退出全屏模式,回到预览状态'); + this.$set(this.videoPlayingStates, videoIndex, false); + } + }, + // 初始化页面数据的方法 initializePageData() { const options = this.loadOptions || {} @@ -1102,6 +1203,7 @@ export default { // 清空已查看规则的记录 this.viewedRuleItems.clear() this.showDetailPanel = false + this.brandCache = {} // 清空品牌缓存 this.$forceUpdate() getApp().globalData.shouldClearRecycle = false } @@ -1197,6 +1299,7 @@ export default { // 清空已查看规则的记录 this.viewedRuleItems.clear() this.showDetailPanel = false + this.brandCache = {} // 清空品牌缓存 this.$forceUpdate() getApp().globalData.shouldClearRecycle = false } @@ -1213,6 +1316,8 @@ export default { }) // 清空已查看规则的记录 this.viewedRuleItems.clear() + // 清空品牌缓存 + this.brandCache = {} // 重置其他相关数据 this.showDetailPanel = false this.$forceUpdate() @@ -1256,13 +1361,80 @@ export default { width: 100%; height: 90%; } + + .video-container { + position: relative; + width: 100%; + height: 100%; + + .video-poster { + cursor: pointer; + transition: transform 0.2s ease; + + &:active { + transform: scale(0.98); + } + } + + .video-overlay { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: rgba(0, 0, 0, 0.4); + z-index: 10; + cursor: pointer; + display: flex; + justify-content: center; + align-items: center; + + .play-button-large { + width: 120rpx; + height: 120rpx; + background: transparent; + border-radius: 50%; + display: flex; + justify-content: center; + align-items: center; + backdrop-filter: blur(10rpx); + transition: all 0.3s ease; + box-shadow: 0 8rpx 30rpx rgba(0, 0, 0, 0.3); + + &:active { + transform: scale(0.9); + background: rgba(255, 255, 255, 0.1); + } + + .play-triangle { + width: 0; + height: 0; + border-left: 24rpx solid #fff; + border-top: 18rpx solid transparent; + border-bottom: 18rpx solid transparent; + margin-left: 8rpx; + transition: all 0.3s ease; + filter: drop-shadow(0 2rpx 4rpx rgba(0, 0, 0, 0.3)); + } + } + + &:hover .play-button-large { + transform: scale(1.1); + box-shadow: 0 12rpx 40rpx rgba(0, 0, 0, 0.4); + + .play-triangle { + border-left-color: #ff8917; + } + } + } + } } .goods-list { // flex: 1; display: flex; position: relative; - height: calc(100vh - 320rpx - 120rpx - env(safe-area-inset-bottom)); /* 减去banner和底部栏的高度 */ + height: calc(110vh - 320rpx - 160rpx - env(safe-area-inset-bottom)); /* 减去banner、底部栏和绿色提示条的高度 */ margin-top: -10rpx; z-index: 2; border-radius: 20rpx 20rpx 0 0; @@ -1336,13 +1508,14 @@ export default { .goods-content { flex: 1; height: 100%; - padding: 0 30rpx; + padding: 0 30rpx 180rpx 30rpx; /* 添加底部padding,为固定底部栏预留空间 */ background: #ffffff; width: 70%; margin: 1rpx; margin-left: 0; border-radius: 0 20rpx 0 0; overflow-y: auto; + box-sizing: border-box; scrollbar-width: none; /* Firefox */ -ms-overflow-style: none; /* IE and Edge */ &::-webkit-scrollbar { @@ -1432,11 +1605,15 @@ export default { display: flex; justify-content: space-between; align-items: center; + flex-wrap: nowrap; + gap: 10rpx; } .price-info { display: flex; align-items: baseline; + white-space: nowrap; + flex-shrink: 0; .price-symbol { font-size: 24rpx; @@ -1448,17 +1625,21 @@ export default { color: #ff7a0e; font-weight: bold; margin: 0 4rpx; + white-space: nowrap; } .price-unit { font-size: 24rpx; color: #999; + white-space: nowrap; } } .quantity-control { display: flex; align-items: center; + flex-shrink: 0; + white-space: nowrap; button { width: 60rpx; @@ -1484,7 +1665,7 @@ export default { } .quantity { - width: 80rpx; + width: 50rpx; text-align: center; font-size: 32rpx; color: #333; @@ -1531,15 +1712,16 @@ export default { flex-direction: column; justify-content: center; min-width: 0; + overflow: hidden; } .other-unrecycle-title { font-size: 30rpx; color: #222; font-weight: bold; margin-bottom: 8rpx; - word-break: break-all; - white-space: normal; - overflow: visible; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; } .other-unrecycle-desc { font-size: 24rpx; @@ -1552,11 +1734,13 @@ export default { .other-unrecycle-price-row { display: flex; align-items: center; + white-space: nowrap; } .other-unrecycle-price { font-size: 28rpx; color: #ff9c00; font-weight: bold; + white-space: nowrap; } .other-unrecycle-btn { width: 60rpx; @@ -1578,7 +1762,7 @@ export default { right: 0; bottom: calc(v-bind('tabbarHeight + "px"') + env(safe-area-inset-bottom)); width: 100vw; - z-index: 1001; + z-index: 100; background: transparent; box-sizing: border-box; pointer-events: auto; @@ -1597,13 +1781,14 @@ export default { background: #eaffea; color: #13ac47; font-size: 20rpx; - // padding: 16rpx 30rpx 0 30rpx; + padding: 8rpx 30rpx; box-sizing: border-box; - text-align: left; + text-align: center; display: flex; align-items: center; justify-content: center; - // flex-direction: r; + line-height: 1.4; + min-height: 40rpx; .tip-highlight { color: #ff9c00; font-weight: bold; @@ -1796,6 +1981,8 @@ export default { display: flex; align-items: center; margin-left: 20rpx; + margin-right: 30rpx; + flex-shrink: 0; } .panel-quantity-control button { width: 48rpx; @@ -1818,7 +2005,7 @@ export default { } } .panel-quantity-control .quantity { - width: 40rpx; + width: 30rpx; text-align: center; font-size: 28rpx; color: #333; diff --git a/pages/manager/inspect.vue b/pages/manager/inspect.vue index 2ed4c69..1de67b1 100644 --- a/pages/manager/inspect.vue +++ b/pages/manager/inspect.vue @@ -20,7 +20,7 @@ - + @@ -30,8 +30,6 @@ ¥ {{ item.price }} /件 {{ item.desc }} - 品牌:{{ item.brand }} - 总数量:{{ item.originalNum }}件 @@ -42,27 +40,59 @@ - - 不合格数量 - - - {{ item.unqualified }} - - - 总金额 - + 加载中... + 没有更多了 + + + + + + + 关闭 + 可回收的品牌 + + + + + + + {{letter}} + + + {{brand.name}} + + + + + + + + + + 品牌确认提示 + + + + {{ brandConfirmInfo.name }} + 请确认所选品牌是否与实物品牌信息一致,否则将无法进行回收。 + + + + + + @@ -76,121 +106,178 @@ export default { order: null, // 订单数据 currentGoods: [], // 当前显示的商品列表 inspectResult: {}, // 质检结果对象,按照新的数据格式 + allProducts: {}, // { [categoryId]: [商品数组] } + allProductsPage: {}, // { [categoryId]: 当前已加载页码 } + allProductsTotal: {}, // { [categoryId]: 总数 } + pageSize: 10, + loadingMore: false, + finished: false, + // 品牌选择相关 + showBrandPopup: false, + brandList: [], + brandSearch: '', + currentProductId: null, + pendingBrandIndex: null, + brandConfirmInfo: {}, + showBrandConfirm: false, + + searchTimer: null, + brandIndexList: ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'], + isPresetDataSync: false, // 标记是否为预置数据同步 } }, computed: { categories() { const list = getApp().globalData.pricePreviewList || [] - let filteredCategories = [] + console.log('categories计算 - pricePreviewList:', list.length) - // 如果有订单数据,根据订单商品过滤分类 - if (this.order && this.order.commonOrderList) { - // 获取订单中所有商品的分类ID(去重) - const orderCategoryIds = new Set() - this.order.commonOrderList.forEach(item => { - // 如果有shopClass字段直接使用 - if (item.shopClass) { - orderCategoryIds.add(item.shopClass) - } else { - // 如果没有shopClass,通过商品标题匹配分类 - const matchedCategory = list.find(cat => - cat.pid === '0' && item.title && item.title.includes(cat.title) - ) - if (matchedCategory) { - orderCategoryIds.add(matchedCategory.id) - } - } - }) - - // 过滤出订单中包含的分类 - filteredCategories = list.filter(item => - item.pid === '0' && orderCategoryIds.has(item.id) - ).sort((a, b) => a.sort - b.sort) - - // 如果没有匹配到任何分类,显示所有分类 - if (filteredCategories.length === 0) { - filteredCategories = list.filter(item => item.pid === '0').sort((a, b) => a.sort - b.sort) + // 显示所有分类,不再根据订单数据筛选 + const allCategories = list.filter(item => item.pid === '0').sort((a, b) => a.sort - b.sort) + console.log('categories计算 - allCategories:', allCategories.length) + + // 为每个分类计算数量 + const categoriesWithCount = allCategories.map(category => { + const count = this.getCategoryItemCountDirect(category.id) + return { + ...category, + badge: count > 0 ? count : null } - } else { - // 没有订单数据时显示所有分类 - filteredCategories = list.filter(item => item.pid === '0').sort((a, b) => a.sort - b.sort) - } + }) + + // 新增不可回收和质量问题分类 + const extra = [ + { id: 'unrecyclable', title: '不可回收', badge: this.getUnrecyclableCount() }, + { id: 'quality_issue', title: '质量问题', badge: this.getQualityIssueCount() } + ] - // 新增不可回收分类 - const extra = [{ id: 'unrecyclable', title: '不可回收' }] - return [...filteredCategories, ...extra] + const result = [...categoriesWithCount, ...extra] + console.log('categories计算 - 最终结果:', result.map(c => ({ id: c.id, title: c.title, badge: c.badge }))) + return result } }, methods: { initInspectResult() { - if (!this.order || !this.order.commonOrderList) return - + // 初始化一个空的质检结果结构 this.inspectResult = { - id: this.order.id, + id: this.order ? this.order.id : '', list: [] } - // 按照订单商品分组(按originalId分组) - const groupedGoods = {} - this.order.commonOrderList.forEach(item => { - if (!groupedGoods[item.id]) { - groupedGoods[item.id] = { - id: item.id, - price: '', // 初始为空字符串 - qualifiedNum: 0, - noQualifiedNum: 0, - unrecyclable: 0, - commonOrderList: [] + // 如果有订单数据,基于订单创建质检结果结构 + if (this.order && this.order.commonOrderList) { + const groupedGoods = {} + this.order.commonOrderList.forEach(item => { + if (!groupedGoods[item.id]) { + groupedGoods[item.id] = { + id: item.id, + price: '', + qualifiedNum: item.num || 0, // 初始化为订单中的数量 + noQualifiedNum: 0, + unrecyclable: 0, + commonOrderList: [] + } } - } - console.log('groupedGoods', groupedGoods) - // 为每个数量创建对应的质检项 - for (let i = 0; i < (item.num || 0); i++) { - // console.log('groupedGoods[item.id]', groupedGoods[item.id]) + + // 每个商品只需要一个质检项 groupedGoods[item.id].commonOrderList.push({ - id: `${item.commonOrderList[i].id}`, // 生成唯一ID + id: item.id, testingInstructions: '', testingImages: '', - testingStatus: '' // 默认为空 + testingStatus: 0 // 初始化为合格状态 }) + }) + + this.inspectResult.list = Object.values(groupedGoods) + console.log('初始化inspectResult:', JSON.stringify(this.inspectResult, null, 2)) + } + }, + + // 获取分类商品数量(直接方法,避免递归) + getCategoryItemCountDirect(categoryId) { + if (categoryId === 'unrecyclable') { + return this.getUnrecyclableCount() + } + + if (categoryId === 'quality_issue') { + return this.getQualityIssueCount() + } + + // 对于普通分类,从inspectResult中获取该分类下所有商品的合格数量总和 + let totalCount = 0 + + if (this.inspectResult.list && this.inspectResult.list.length > 0) { + // 遍历inspectResult中的所有商品 + this.inspectResult.list.forEach(inspectItem => { + // 跳过特殊分类 + if (inspectItem.id === 'unrecyclable' || inspectItem.id === 'quality_issue') { + return + } + + // 通过商品ID查找对应的订单项,获取分类信息 + const orderItem = this.order?.commonOrderList?.find(item => item.id == inspectItem.id) + if (orderItem && orderItem.shopClass === categoryId) { + // 累加该商品的合格数量 + totalCount += inspectItem.qualifiedNum || 0 + } + }) + } + + return totalCount + }, + + // 获取当前分类ID(避免递归) + getCurrentCategoryId() { + const list = getApp().globalData.pricePreviewList || [] + const allCategories = list.filter(item => item.pid === '0').sort((a, b) => a.sort - b.sort) + const extra = [ + { id: 'unrecyclable', title: '不可回收' }, + { id: 'quality_issue', title: '质量问题' } + ] + const allCategoriesWithExtra = [...allCategories, ...extra] + + return allCategoriesWithExtra[this.currentCategory]?.id + }, + + // 获取分类商品数量(保持原有方法名兼容性) + getCategoryItemCount(categoryId) { + return this.getCategoryItemCountDirect(categoryId) + }, + + // 获取不可回收数量 + getUnrecyclableCount() { + // 从inspectResult中获取不可回收的数量 + const unrecyclableItem = this.inspectResult.list?.find(item => item.id === 'unrecyclable') + return unrecyclableItem ? unrecyclableItem.unrecyclable : 0 + }, + + // 获取质量问题数量 + getQualityIssueCount() { + // 从inspectResult中获取质量问题的数量 + const qualityIssueItem = this.inspectResult.list?.find(item => item.id === 'quality_issue') + return qualityIssueItem ? qualityIssueItem.noQualifiedNum : 0 + }, + fetchGoodsList(categoryId, page = 1, callback) { + this.$api('getClassGoodsList', { + classId: categoryId, + pageNo: page, + pageSize: this.pageSize + }, res => { + if (res.code === 200 && res.result && Array.isArray(res.result.records)) { + const oldList = this.allProducts[categoryId] || [] + const newList = page === 1 ? res.result.records : oldList.concat(res.result.records) + this.$set(this.allProducts, categoryId, newList) + this.$set(this.allProductsPage, categoryId, page) + this.$set(this.allProductsTotal, categoryId, res.result.total) + this.updateCurrentGoods() } + if (callback) callback() }) - - // 添加不可回收分类 - 暂时注释掉 - // const totalOrderNum = this.order.commonOrderList.reduce((sum, item) => sum + (item.num || 0), 0) - // groupedGoods['unrecyclable'] = { - // id: 'unrecyclable', - // price: '', - // qualifiedNum: 0, - // noQualifiedNum: 0, - // unrecyclable: totalOrderNum, // 初始化时全部为不可回收状态 - // commonOrderList: [] - // } - - // // 为不可回收创建对应数量的质检项 - // for (let i = 0; i < totalOrderNum; i++) { - // groupedGoods['unrecyclable'].commonOrderList.push({ - // id: `unrecyclable-${i}`, - // testingInstructions: '', - // testingImages: '', - // testingStatus: 2 // 不可回收状态 - // }) - // } - - this.inspectResult.list = Object.values(groupedGoods) }, updateCurrentGoods() { const currentCategoryId = this.categories[this.currentCategory]?.id - const currentCategoryTitle = this.categories[this.currentCategory]?.title // 不可回收分类内容 if (currentCategoryId === 'unrecyclable') { - // 计算订单中所有商品的总数量作为不可回收的最大限制 - let totalOrderNum = 0 - if (this.order && this.order.commonOrderList) { - totalOrderNum = this.order.commonOrderList.reduce((sum, item) => sum + (item.num || 0), 0) - } - this.currentGoods = [{ id: 'unrecyclable-1', image: '/static/回收/衣物.png', @@ -198,47 +285,73 @@ export default { price: '—', desc: '允许脏破烂,160码以上', qualified: 0, - unqualified: 0, amount: '', - originalNum: totalOrderNum // 设置最大数量为订单总数 + originalNum: 0 // 不设置最大数量限制 }] return } - // 如果有订单数据,根据订单商品过滤当前分类的商品 - if (this.order && this.order.commonOrderList) { - const orderGoods = this.order.commonOrderList.filter(item => { - // 如果有shopClass字段,直接匹配 - if (item.shopClass) { - return item.shopClass === currentCategoryId - } - // 如果没有shopClass,通过商品标题匹配分类 - return item.title && currentCategoryTitle && item.title.includes(currentCategoryTitle) - }) - - // 根据pinName展示不同品牌的商品,不进行去重 - const goodsList = orderGoods.map((item, index) => ({ - id: `${item.id}`, - image: item.image || '/static/回收/衣物.png', - name: item.title, - brand: item.pinName || '未知品牌', - price: item.onePrice || 0, - desc: item.details || '', + // 质量问题分类内容 + if (currentCategoryId === 'quality_issue') { + this.currentGoods = [{ + id: 'quality-issue-1', + image: '/static/回收/衣物.png', + name: '质量问题品类', + price: '—', + desc: '存在质量问题,无法正常回收', qualified: 0, - unqualified: 0, amount: '', - originalNum: item.num || 0, - estimatedPrice: item.price || 0, - originalId: item.id // 保存原始ID - })) - - this.currentGoods = goodsList + originalNum: 0 // 不设置最大数量限制 + }] return } - // 没有订单数据时返回空数组 - this.currentGoods = [] + // 从API获取的商品数据 + const categoryGoods = this.allProducts[currentCategoryId] || [] + + // 将API商品数据转换为质检页面格式 + const goodsList = categoryGoods.map((item, index) => { + // 从订单数据中查找对应的商品,获取预置数量 + const orderItem = this.getOrderItemByProductId(item.id) + const presetQuantity = orderItem ? (orderItem.num || 0) : 0 + + return { + id: item.id, + image: item.image || '/static/回收/衣物.png', + name: item.name, + price: item.price || 0, + desc: item.service || '允许脏破烂,160码以上', + qualified: presetQuantity, // 使用订单中的预置数量 + amount: orderItem ? (orderItem.estimatedPrice || '') : '', + originalNum: presetQuantity, // 设置原始数量 + estimatedPrice: orderItem ? orderItem.estimatedPrice : 0, + originalId: item.id, + isPin: item.isPin || 'N', // 添加品牌标识 + orderItem: orderItem // 保存订单项引用,方便后续使用 + } + }) + + this.currentGoods = goodsList + }, + + // 根据商品ID从订单数据中查找对应商品 + getOrderItemByProductId(productId) { + if (!this.order || !this.order.commonOrderList) { + return null + } + + // 先通过商品ID直接匹配 + let orderItem = this.order.commonOrderList.find(item => item.id == productId) + + // 如果没找到,尝试通过shopId匹配 + if (!orderItem) { + orderItem = this.order.commonOrderList.find(item => item.shopId == productId) + } + + return orderItem }, + + goBack() { uni.navigateBack() @@ -275,8 +388,8 @@ export default { } for (const item of this.inspectResult.list) { - // 跳过不可回收分类的检查 - if (item.id === 'unrecyclable') { + // 跳过不可回收和质量问题分类的检查 + if (item.id === 'unrecyclable' || item.id === 'quality_issue') { continue } @@ -312,172 +425,303 @@ export default { }, switchCategory(idx) { this.currentCategory = idx - this.updateCurrentGoods() + this.loadingMore = false + this.finished = false + const categoryId = this.categories[idx]?.id + + if (categoryId === 'unrecyclable' || categoryId === 'quality_issue') { + // 不可回收和质量问题分类直接更新商品列表 + this.updateCurrentGoods() + return + } + + // 如果该分类的商品还没有加载,调用API获取 + if (!this.allProducts[categoryId]) { + this.fetchGoodsList(categoryId, 1) + } else { + // 已有数据,直接更新显示 + this.updateCurrentGoods() + } }, changeNum(item, key, delta) { - const currentQualified = item.qualified || 0 - const currentUnqualified = item.unqualified || 0 - const maxNum = item.originalNum || 0 - if (key === 'qualified') { - const newQualified = Math.max(0, currentQualified + delta) - const totalAfterChange = newQualified + currentUnqualified - - // 检查总数是否超过原始数量 - if (totalAfterChange <= maxNum) { - this.$set(item, 'qualified', newQualified) - // 更新inspectResult对象 - this.updateInspectResult(item, 'qualified', delta) - console.log('更新后的inspectResult:', JSON.stringify(this.inspectResult, null, 2)) - } else { - uni.showToast({ - title: `总数不能超过${maxNum}件`, - icon: 'none', - duration: 1500 - }) + // 如果是增加数量 + if (delta > 0) { + // 对于不可回收和质量问题分类,直接增加数量,不弹出品牌选择 + if (item.id === 'unrecyclable-1' || item.id === 'quality-issue-1') { + const newQualified = Math.max(0, (item.qualified || 0) + delta) + this.$set(item, 'qualified', newQualified) + this.updateInspectResult(item, 'qualified', delta) + this.$forceUpdate() + return + } + + // 其他商品弹出品牌选择弹窗 + this.pendingBrandIndex = this.currentGoods.findIndex(goods => goods.id === item.id) + this.getGoodsBrandList(item.id) + this.showBrandPopup = true + return } - } else if (key === 'unqualified') { - const newUnqualified = Math.max(0, currentUnqualified + delta) - const totalAfterChange = currentQualified + newUnqualified - // 检查总数是否超过原始数量 - if (totalAfterChange <= maxNum) { - this.$set(item, 'unqualified', newUnqualified) - // 更新inspectResult对象 - this.updateInspectResult(item, 'unqualified', delta) - } else { - uni.showToast({ - title: `总数不能超过${maxNum}件`, - icon: 'none', - duration: 1500 - }) - } + const newQualified = Math.max(0, (item.qualified || 0) + delta) + this.$set(item, 'qualified', newQualified) + // 更新inspectResult对象 + this.updateInspectResult(item, 'qualified', delta) + // 强制更新categories计算属性,使左侧分类数字变化 + this.$forceUpdate() + console.log('更新后的inspectResult:', JSON.stringify(this.inspectResult, null, 2)) } }, updateInspectResult(item, type, delta) { - // 处理不可回收分类 - 暂时注释掉 - // if (item.id === 'unrecyclable-1') { - // const unrecyclableItem = this.inspectResult.list.find(listItem => listItem.id === 'unrecyclable') - // if (!unrecyclableItem) return - - // if (type === 'qualified' && delta > 0) { - // // 增加合格数量:找到第一个不可回收状态的项改为合格 - // const targetItem = unrecyclableItem.commonOrderList.find(commonItem => commonItem.testingStatus === 2) - // if (targetItem) { - // targetItem.testingStatus = 0 - // unrecyclableItem.unrecyclable-- - // unrecyclableItem.qualifiedNum++ - // } - // } else if (type === 'qualified' && delta < 0) { - // // 减少合格数量:找到第一个合格状态的项改为不可回收 - // const targetItem = unrecyclableItem.commonOrderList.find(commonItem => commonItem.testingStatus === 0) - // if (targetItem) { - // targetItem.testingStatus = 2 - // unrecyclableItem.qualifiedNum-- - // unrecyclableItem.unrecyclable++ - // } - // } else if (type === 'unqualified' && delta > 0) { - // // 增加不合格数量:找到第一个不可回收状态的项改为质量问题 - // const targetItem = unrecyclableItem.commonOrderList.find(commonItem => commonItem.testingStatus === 2) - // if (targetItem) { - // targetItem.testingStatus = 1 - // unrecyclableItem.unrecyclable-- - // unrecyclableItem.noQualifiedNum++ - // } - // } else if (type === 'unqualified' && delta < 0) { - // // 减少不合格数量:找到第一个质量问题状态的项改为不可回收 - // const targetItem = unrecyclableItem.commonOrderList.find(commonItem => commonItem.testingStatus === 1) - // if (targetItem) { - // targetItem.testingStatus = 2 - // unrecyclableItem.noQualifiedNum-- - // unrecyclableItem.unrecyclable++ - // } - // } + // 处理不可回收分类 + if (item.id === 'unrecyclable-1') { + // 找到或创建不可回收的inspectResult项 + let inspectItem = this.inspectResult.list.find(listItem => listItem.id === 'unrecyclable') - // console.log('更新后的不可回收inspectResult:', JSON.stringify(unrecyclableItem, null, 2)) - // return - // } - - // 找到对应的inspectResult项 - const originalId = item.originalId || item.id.split('-')[0] - const inspectItem = this.inspectResult.list.find(listItem => listItem.id == originalId) - - if (!inspectItem) return - - if (type === 'qualified' && delta > 0) { - // 增加合格数量:优先找空状态的项,其次找非合格状态的项 - let targetItem = inspectItem.commonOrderList.find(commonItem => commonItem.testingStatus === '') - if (!targetItem) { - targetItem = inspectItem.commonOrderList.find(commonItem => - commonItem.testingStatus === 1 || commonItem.testingStatus === 2 - ) - } - if (targetItem) { - const oldStatus = targetItem.testingStatus - targetItem.testingStatus = 0 - inspectItem.qualifiedNum++ - if (oldStatus === 1) { - inspectItem.noQualifiedNum-- - } else if (oldStatus === 2) { - inspectItem.unrecyclable-- + if (!inspectItem) { + inspectItem = { + id: 'unrecyclable', + price: '', + qualifiedNum: 0, + noQualifiedNum: 0, + unrecyclable: 0, + commonOrderList: [] } + this.inspectResult.list.push(inspectItem) } - } else if (type === 'qualified' && delta < 0) { - // 减少合格数量:找到第一个合格状态的项改为空状态 - const targetItem = inspectItem.commonOrderList.find(commonItem => commonItem.testingStatus === 0) - if (targetItem) { - targetItem.testingStatus = '' - inspectItem.qualifiedNum-- + + if (type === 'qualified' && delta > 0) { + inspectItem.unrecyclable++ + } else if (type === 'qualified' && delta < 0) { + inspectItem.unrecyclable = Math.max(0, inspectItem.unrecyclable - 1) } - } else if (type === 'unqualified' && delta > 0) { - // 增加不合格数量:优先找空状态的项,其次找合格状态的项 - let targetItem = inspectItem.commonOrderList.find(commonItem => commonItem.testingStatus === '') - if (!targetItem) { - targetItem = inspectItem.commonOrderList.find(commonItem => commonItem.testingStatus === 0) + + console.log('不可回收数量更新:', inspectItem.unrecyclable) + return + } + + // 处理质量问题分类 + if (item.id === 'quality-issue-1') { + // 找到或创建质量问题的inspectResult项 + let inspectItem = this.inspectResult.list.find(listItem => listItem.id === 'quality_issue') + + if (!inspectItem) { + inspectItem = { + id: 'quality_issue', + price: '', + qualifiedNum: 0, + noQualifiedNum: 0, + unrecyclable: 0, + commonOrderList: [] + } + this.inspectResult.list.push(inspectItem) } - if (targetItem) { - const oldStatus = targetItem.testingStatus - targetItem.testingStatus = 1 + + if (type === 'qualified' && delta > 0) { inspectItem.noQualifiedNum++ - if (oldStatus === 0) { - inspectItem.qualifiedNum-- - } + } else if (type === 'qualified' && delta < 0) { + inspectItem.noQualifiedNum = Math.max(0, inspectItem.noQualifiedNum - 1) } - } else if (type === 'unqualified' && delta < 0) { - // 减少不合格数量:找到第一个质量问题状态的项改为空状态 - const targetItem = inspectItem.commonOrderList.find(commonItem => commonItem.testingStatus === 1) - if (targetItem) { - targetItem.testingStatus = '' - inspectItem.noQualifiedNum-- + + console.log('质量问题数量更新:', inspectItem.noQualifiedNum) + return + } + + // 找到或创建对应的inspectResult项 + const itemId = item.originalId || item.id + let inspectItem = this.inspectResult.list.find(listItem => listItem.id == itemId) + + // 如果不存在,动态创建 + if (!inspectItem) { + inspectItem = { + id: itemId, + price: '', + qualifiedNum: 0, + noQualifiedNum: 0, + unrecyclable: 0, + commonOrderList: [] } + this.inspectResult.list.push(inspectItem) + console.log('新增商品到inspectResult:', itemId) + } + + // 如果是预置数据同步,直接设置数量 + if (type === 'qualified' && delta > 0 && this.isPresetDataSync) { + inspectItem.qualifiedNum = delta + return + } + + if (type === 'qualified' && delta > 0) { + // 增加合格数量:直接更新数量 + inspectItem.qualifiedNum++ + console.log(`为商品 ${itemId} 增加数量,当前合格数量: ${inspectItem.qualifiedNum}`) + } else if (type === 'qualified' && delta < 0) { + // 减少合格数量:直接更新数量 + inspectItem.qualifiedNum = Math.max(0, inspectItem.qualifiedNum - 1) + console.log(`为商品 ${itemId} 减少数量,当前合格数量: ${inspectItem.qualifiedNum}`) } console.log('更新后的inspectResult:', JSON.stringify(this.inspectResult, null, 2)) }, getInspectPrice(item) { // 获取inspectResult中对应商品的price - if (item.id === 'unrecyclable-1') { + if (item.id === 'unrecyclable-1' || item.id === 'quality-issue-1') { return '' } - const originalId = item.originalId || item.id.split('-')[0] - const inspectItem = this.inspectResult.list?.find(listItem => listItem.id == originalId) + const itemId = item.originalId || item.id + const inspectItem = this.inspectResult.list?.find(listItem => listItem.id == itemId) return inspectItem ? inspectItem.price : '' }, updateInspectPrice(item, event) { // 更新inspectResult中对应商品的price - if (item.id === 'unrecyclable-1') { + if (item.id === 'unrecyclable-1' || item.id === 'quality-issue-1') { return } - const originalId = item.originalId || item.id.split('-')[0] - const inspectItem = this.inspectResult.list?.find(listItem => listItem.id == originalId) + const itemId = item.originalId || item.id + let inspectItem = this.inspectResult.list?.find(listItem => listItem.id == itemId) - if (inspectItem) { - const newPrice = parseFloat(event.detail.value) || 0 - inspectItem.price = newPrice - console.log('更新价格:', originalId, newPrice) + // 如果不存在,动态创建 + if (!inspectItem) { + inspectItem = { + id: itemId, + price: '', + qualifiedNum: 0, + noQualifiedNum: 0, + unrecyclable: 0, + commonOrderList: [] + } + this.inspectResult.list.push(inspectItem) + } + + const newPrice = parseFloat(event.detail.value) || 0 + inspectItem.price = newPrice + console.log('更新价格:', itemId, newPrice) + }, + + loadMoreGoods() { + const categoryId = this.categories[this.currentCategory]?.id + + // 不可回收和质量问题分类不支持加载更多 + if (categoryId === 'unrecyclable' || categoryId === 'quality_issue') { + return + } + + const page = (this.allProductsPage[categoryId] || 1) + 1 + const total = this.allProductsTotal[categoryId] || 0 + const loaded = (this.allProducts[categoryId] || []).length + + if (this.loadingMore || this.finished) return + + if (loaded < total) { + this.loadingMore = true + this.fetchGoodsList(categoryId, page, () => { + this.loadingMore = false + // 判断是否加载完 + const newLoaded = (this.allProducts[categoryId] || []).length + this.finished = newLoaded >= (this.allProductsTotal[categoryId] || 0) + }) + } else { + this.finished = true + } + }, + + + // 获取品牌列表 + getGoodsBrandList(productId, searchName = '') { + this.currentProductId = productId + const params = { productId } + if (searchName.trim()) { + params.name = searchName.trim() + } + + this.$api('getGoodsBrandList', params, res => { + if (res && res.success && res.result && res.result.records) { + this.brandList = res.result.records.map(item => { + // 获取品牌名称的拼音首字母 + const firstChar = this.getPinyinFirstLetter(item.name) + return { + id: item.id, + logo: item.image || '/static/brand/alexander.png', + name: item.name, + letter: firstChar + } + }) + } + }) + }, + + // 获取中文拼音首字母 + getPinyinFirstLetter(str) { + if (!str) return '#' + const firstChar = str.charAt(0) + + let index = this.brandIndexList.indexOf(firstChar.toUpperCase()) + if (index != -1) { + return this.brandIndexList[index] } + + return '#' + }, + + // 品牌搜索输入事件处理 + onBrandSearchInput(e) { + const searchValue = e.detail.value + + // 清除之前的定时器 + if (this.searchTimer) { + clearTimeout(this.searchTimer) + } + + // 设置防抖,500ms后执行搜索 + this.searchTimer = setTimeout(() => { + if (this.currentProductId) { + this.getGoodsBrandList(this.currentProductId, searchValue) + } + }, 500) + }, + + // 打开品牌确认弹窗 + openBrandConfirm(brand) { + this.brandConfirmInfo = { + id: brand.id, + logo: brand.logo, + name: brand.name + } + this.showBrandConfirm = true + }, + + // 关闭品牌确认弹窗 + closeBrandConfirm() { + this.showBrandConfirm = false + }, + + // 确认品牌选择 + confirmBrand() { + this.showBrandConfirm = false + this.showBrandPopup = false + + // 确认后增加商品数量 + if (this.pendingBrandIndex !== null) { + const item = this.currentGoods[this.pendingBrandIndex] + if (item) { + const newQualified = Math.max(0, (item.qualified || 0) + 1) + this.$set(item, 'qualified', newQualified) + this.updateInspectResult(item, 'qualified', 1) + // 强制更新categories计算属性,使左侧分类数字变化 + this.$forceUpdate() + } + this.pendingBrandIndex = null + } + }, + + // 关闭品牌弹窗 + closeBrandPopup() { + this.showBrandPopup = false + this.pendingBrandIndex = null + this.brandSearch = '' + this.currentProductId = null }, }, created() { @@ -490,10 +734,9 @@ export default { try { this.order = JSON.parse(decodeURIComponent(options.orderData)) console.log('接收到的订单数据:', this.order) - // 订单数据加载完成后更新商品列表和初始化质检结果 + // 订单数据加载完成后初始化质检结果 this.$nextTick(() => { this.initInspectResult() - this.updateCurrentGoods() }) } catch (error) { console.error('解析订单数据失败:', error) @@ -504,8 +747,49 @@ export default { this.orderId = options.orderId } + // 初始化加载第一个分类的商品 + this.$nextTick(() => { + // 确保categories已经计算完成 + if (this.categories.length > 0) { + const firstCategoryId = this.categories[0]?.id + console.log('第一个分类ID:', firstCategoryId, '所有分类:', this.categories.map(c => c.id)) + + if (firstCategoryId && firstCategoryId !== 'unrecyclable' && firstCategoryId !== 'quality_issue') { + this.fetchGoodsList(firstCategoryId, 1) + } else if (firstCategoryId === 'unrecyclable' || firstCategoryId === 'quality_issue') { + this.updateCurrentGoods() + } + } else { + console.log('categories为空,等待数据加载') + // 如果categories为空,等待一下再尝试 + setTimeout(() => { + if (this.categories.length > 0) { + const firstCategoryId = this.categories[0]?.id + if (firstCategoryId && firstCategoryId !== 'unrecyclable' && firstCategoryId !== 'quality_issue') { + this.fetchGoodsList(firstCategoryId, 1) + } else if (firstCategoryId === 'unrecyclable' || firstCategoryId === 'quality_issue') { + this.updateCurrentGoods() + } + } + }, 500) + } + }) + console.log(this.orderId, 'orderId') }, + + onShow() { + // 确保在页面显示时categories已经正确计算 + console.log('onShow - categories:', this.categories.map(c => ({ id: c.id, title: c.title, badge: c.badge }))) + + // 强制更新视图,确保所有分类都显示 + this.$nextTick(() => { + console.log('分类导航应该显示的分类数量:', this.categories.length) + this.categories.forEach((cat, index) => { + console.log(`分类 ${index}: ${cat.title} (${cat.id})`) + }) + }) + }, } @@ -557,21 +841,45 @@ export default { margin-top: calc(200rpx + var(--status-bar-height)); display: flex; background: none; + height: calc(100vh - 200rpx - var(--status-bar-height)); + min-height: calc(100vh - 200rpx - var(--status-bar-height)); } .category-nav { width: 80px; background: #fff; border-radius: 24px 0 0 24px; - padding: 24px 0; + // padding: 24px 0; display: flex; flex-direction: column; align-items: center; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.03); - height: 100%; - overflow-y: auto; + height: calc(100vh - 200rpx - var(--status-bar-height) - 80px); + max-height: calc(100vh - 200rpx - var(--status-bar-height) - 80px); + overflow-y: scroll; + overflow-x: hidden; position: relative; z-index: 2; + -webkit-overflow-scrolling: touch; + scrollbar-width: thin; + scrollbar-color: #ddd transparent; + + &::-webkit-scrollbar { + width: 4px; + } + + &::-webkit-scrollbar-track { + background: transparent; + } + + &::-webkit-scrollbar-thumb { + background: #ddd; + border-radius: 2px; + } + + &::-webkit-scrollbar-thumb:hover { + background: #ccc; + } .category-item { width: 64px; @@ -625,7 +933,7 @@ export default { .goods-list { flex: 1; - height: calc(100vh - 110rpx - var(--status-bar-height) - 80px); + height: calc(100vh - 200rpx - var(--status-bar-height) - 80px); padding: 0 0 0 16px; overflow-y: auto; background: none; @@ -793,20 +1101,222 @@ export default { -.goods-brand { - font-size: 12px; - color: #ffb400; - margin-top: 2px; - font-weight: 500; + + +.loading-more { + text-align: center; + color: #999; + padding: 20rpx 0; + font-size: 26rpx; } -.goods-limit { - font-size: 12px; - color: #ffb400; - margin-top: 2px; - font-weight: 500; +// 品牌选择弹窗样式 +.brand-popup-mask { + position: fixed; + left: 0; + right: 0; + top: 0; + bottom: 0; + background: rgba(0,0,0,0.35); + z-index: 3000; + display: flex; + align-items: flex-end; + justify-content: center; +} + +.brand-popup { + position: relative; + width: 100%; + max-width: 750px; + background: #fff; + border-radius: 32rpx 32rpx 0 0; + box-shadow: 0 -4rpx 24rpx rgba(0,0,0,0.08); + padding-bottom: 40rpx; + max-height: 90vh; + display: flex; + flex-direction: column; + overflow: hidden; +} + +.brand-popup-header { + display: flex; + align-items: center; + justify-content: center; + padding: 32rpx 24rpx 0 24rpx; + font-size: 32rpx; + font-weight: bold; + position: relative; +} + +.brand-popup-close { + position: absolute; + left: 24rpx; + font-size: 28rpx; + color: #888; +} + +.brand-popup-title { + font-size: 32rpx; + color: #222; + font-weight: bold; +} + +.brand-popup-search { + padding: 20rpx 24rpx 0 24rpx; +} + +.brand-search-input { + width: 100%; + height: 60rpx; + border-radius: 30rpx; + background: #f5f5f5; + border: none; + padding-left: 40rpx; + font-size: 28rpx; + color: #888; +} + +.brand-popup-list { + flex: 1; + overflow-y: auto; + max-height: 60vh; + padding: 0 24rpx; + scrollbar-width: none; /* Firefox */ + -ms-overflow-style: none; /* IE and Edge */ + &::-webkit-scrollbar { + width: 0 !important; + display: none; /* Chrome, Safari, Opera */ + } +} + +.brand-letter { + font-size: 28rpx; + color: #888; + margin: 24rpx 0 8rpx 0; + font-weight: bold; +} + +.brand-item { + display: flex; + align-items: center; + padding: 16rpx 0; + border-bottom: 1px solid #f0f0f0; +} + +.brand-logo { + width: 60rpx; + height: 60rpx; + margin-right: 20rpx; + border-radius: 8rpx; + background: #f8f8f8; +} + +.brand-name { + font-size: 28rpx; + color: #222; +} + +// 品牌确认弹窗样式 +.brand-confirm-mask { + position: fixed; + left: 0; + right: 0; + top: 0; + bottom: 0; + background: rgba(0,0,0,0.25); + z-index: 5001; + display: flex; + align-items: center; + justify-content: center; +} + +.brand-confirm-popup { + width: 70vw; + max-width: 270px; + background: #fff; + border-radius: 32rpx; + box-shadow: 0 8rpx 32rpx rgba(0,0,0,0.12); + display: flex; + flex-direction: column; + align-items: center; + padding: 48rpx 20rpx 36rpx 20rpx; + position: relative; +} + +.brand-confirm-title { + font-size: 36rpx; + color: #222; + font-weight: bold; + text-align: center; + margin-bottom: 24rpx; +} + +.brand-confirm-logo-wrap { + width: 120rpx; + height: 120rpx; + background: #f8f8f8; + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + margin-bottom: 18rpx; +} + +.brand-confirm-logo { + width: 80rpx; + height: 80rpx; + border-radius: 50%; +} + +.brand-confirm-name { + font-size: 28rpx; + color: #222; + font-weight: bold; + text-align: center; + margin-bottom: 16rpx; +} + +.brand-confirm-desc { + font-size: 24rpx; + color: #999; + text-align: center; + margin-bottom: 32rpx; + line-height: 1.6; +} + +.brand-confirm-btn-row { + width: 100%; + display: flex; + justify-content: space-between; + gap: 24rpx; +} + +.brand-confirm-btn { + flex: 1; + height: 72rpx; + border-radius: 36rpx; + font-size: 28rpx; + font-weight: bold; + display: flex; + align-items: center; + justify-content: center; + border: none; + margin: 0 0; +} + +.brand-confirm-btn.retry { + background: #fff; + color: #ff9c00; + border: 2rpx solid #ff9c00; +} + +.brand-confirm-btn.confirm { + background: linear-gradient(to right, #ffd01e, #ff8917); + color: #fff; + border: none; } + diff --git a/pages/manager/order-detail.vue b/pages/manager/order-detail.vue index 26f37b4..f415349 100644 --- a/pages/manager/order-detail.vue +++ b/pages/manager/order-detail.vue @@ -83,11 +83,13 @@ {{ item.pinName }} {{ item.details }} - ¥{{ item.onePrice }} /件 + ¥{{ item.onePrice }} /件 + ¥{{ getSinglePriceRange(item.estimatedPrice, item.num) }} /件 x{{ item.num }} - ¥{{ item.estimatedPrice }} + ¥{{ parseFloat(item.estimatedPrice.split('-')[0]).toFixed(2) }} + ¥{{ item.estimatedPrice.replace('-', '~') }} @@ -123,11 +125,13 @@ {{ item.pinName }} {{ item.details }} - ¥{{ item.onePrice }} /件 + ¥{{ item.onePrice }} /件 + ¥{{ getSinglePriceRange(item.estimatedPrice, item.num) }} /件 x{{ item.num }} - ¥{{ item.estimatedPrice }} + ¥{{ parseFloat(item.estimatedPrice.split('-')[0]).toFixed(2) }} + ¥{{ item.estimatedPrice.replace('-', '~') }} @@ -166,11 +170,13 @@ {{ item.pinName }} {{ item.details }} - ¥{{ item.onePrice }} /件 + ¥{{ item.onePrice }} /件 + ¥{{ getSinglePriceRange(item.estimatedPrice, item.num) }} /件 x{{ item.num }} - ¥{{ item.estimatedPrice }} + ¥{{ parseFloat(item.estimatedPrice.split('-')[0]).toFixed(2) }} + ¥{{ item.estimatedPrice.replace('-', '~') }} @@ -326,6 +332,34 @@ export default { url: `/pages/subcomponent/inspection-report?orderId=${this.order.orderId}` }) }, + // 判断是否显示单价格(根据estimatedPrice格式判断) + shouldShowSinglePrice(estimatedPrice) { + if (!estimatedPrice || typeof estimatedPrice !== 'string') return true; + + // 解析estimatedPrice,格式如"25-0"或"25-50" + const parts = estimatedPrice.split('-'); + if (parts.length !== 2) return true; + + const maxPrice = parseFloat(parts[1]); + return maxPrice === 0; + }, + // 从总价反推单件价格区间 + getSinglePriceRange(estimatedPrice, quantity) { + if (!estimatedPrice || typeof estimatedPrice !== 'string' || !quantity) return ''; + + // 解析estimatedPrice,格式如"25-50" + const parts = estimatedPrice.split('-'); + if (parts.length !== 2) return estimatedPrice; + + const minTotal = parseFloat(parts[0]); + const maxTotal = parseFloat(parts[1]); + + // 反推单件价格 + const minPrice = (minTotal / quantity).toFixed(2); + const maxPrice = (maxTotal / quantity).toFixed(2); + + return `${minPrice}~${maxPrice}`; + }, } } @@ -793,6 +827,8 @@ $order-card-padding: 40px 28px; box-shadow: 0 2px 8px rgba(255, 156, 0, 0.04); position: relative; margin-bottom: 18px; + min-width: 0; + flex-wrap: nowrap; } .custom-goods-img { width: 48px; @@ -806,27 +842,42 @@ $order-card-padding: 40px 28px; display: flex; flex-direction: column; justify-content: center; + min-width: 0; + margin-right: 10px; } .custom-goods-name { font-size: 15px; color: #222; font-weight: bold; margin-bottom: 2px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; } .custom-goods-desc { font-size: 13px; color: #bcbcbc; - margin-bottom: 10px; + margin-bottom: 8px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + &:last-child { + margin-bottom: 10px; + } } .custom-goods-meta { display: flex; align-items: center; gap: 10px; + flex-wrap: nowrap; + white-space: nowrap; } .custom-goods-price { color: #ffb400; font-size: 15px; font-weight: bold; + white-space: nowrap; + flex-shrink: 0; } .custom-goods-unit { color: #bcbcbc; @@ -837,6 +888,8 @@ $order-card-padding: 40px 28px; color: #bcbcbc; font-size: 13px; margin-left: 8px; + white-space: nowrap; + flex-shrink: 0; } .custom-goods-total { color: #222; @@ -844,6 +897,9 @@ $order-card-padding: 40px 28px; font-weight: bold; margin-left: 18px; flex-shrink: 0; + white-space: nowrap; + min-width: 80px; + text-align: right; } .user-stat-modal-mask { position: fixed; diff --git a/pages/subcomponent/detail.vue b/pages/subcomponent/detail.vue index 1361d54..57f392b 100644 --- a/pages/subcomponent/detail.vue +++ b/pages/subcomponent/detail.vue @@ -115,11 +115,13 @@ {{ item.pinName }} {{ item.details }} - ¥ {{ item.onePrice }} /件 + ¥ {{ item.onePrice }} /件 + ¥ {{ getSinglePriceRange(item.estimatedPrice, item.num) }} /件 x{{ item.num }} - ¥{{ item.estimatedPrice }} + ¥{{ parseFloat(item.estimatedPrice.split('-')[0]).toFixed(2) }} + ¥{{ item.estimatedPrice.replace('-', '~') }} @@ -347,6 +349,34 @@ export default { const min = now.getMinutes().toString().padStart(2, '0'); return `${y}-${m}-${d} ${h}:${min}`; }, + // 判断是否显示单价格(根据estimatedPrice格式判断) + shouldShowSinglePrice(estimatedPrice) { + if (!estimatedPrice || typeof estimatedPrice !== 'string') return true; + + // 解析estimatedPrice,格式如"5-0"或"5-10" + const parts = estimatedPrice.split('-'); + if (parts.length !== 2) return true; + + const maxPrice = parseFloat(parts[1]); + return maxPrice === 0; + }, + // 从总价反推单件价格区间 + getSinglePriceRange(estimatedPrice, quantity) { + if (!estimatedPrice || typeof estimatedPrice !== 'string' || !quantity) return ''; + + // 解析estimatedPrice,格式如"25-50"(总价区间) + const parts = estimatedPrice.split('-'); + if (parts.length !== 2) return estimatedPrice; + + const minTotal = parseFloat(parts[0]); + const maxTotal = parseFloat(parts[1]); + + // 计算单件价格区间 + const minPrice = (minTotal / quantity).toFixed(2); + const maxPrice = (maxTotal / quantity).toFixed(2); + + return `${parseFloat(minPrice)}~${parseFloat(maxPrice)}`; + }, contactCourier() { // 联系快递员逻辑 if (this.phone) { @@ -396,7 +426,7 @@ export default { this.currentStatus = { text: '【在线预约】', time: data.goTime || '', - icon: '/static/home/① 在线预约.png' + icon: '/static/my/【待取件】快递员正在赶来.png' } } else if (status == 1 && state == 0) { this.currentStep = 2 @@ -802,15 +832,15 @@ letter-spacing: 0%; position: fixed; left: 0; right: 0; - bottom: 30rpx; - z-index: 10; + bottom: 0; + z-index: 999; background: #fff; display: flex; justify-content: space-between; align-items: center; - padding: 24rpx 24rpx calc(env(safe-area-inset-bottom) + 12rpx) 24rpx; - box-shadow: 0 -2rpx 8rpx rgba(255, 156, 0, 0.04); - border-radius: 24rpx 24rpx 0 0; + padding: 24rpx 24rpx calc(env(safe-area-inset-bottom) + 24rpx) 24rpx; + box-shadow: 0 -4rpx 16rpx rgba(0, 0, 0, 0.1); + border-top: 1rpx solid #f0f0f0; gap: 24rpx; } .btn { @@ -954,5 +984,6 @@ letter-spacing: 0%; } .content { margin-top: calc(150rpx + var(--status-bar-height)); + padding-bottom: calc(140rpx + env(safe-area-inset-bottom)); } \ No newline at end of file diff --git a/pages/subcomponent/pickup.vue b/pages/subcomponent/pickup.vue index fe39e5e..bd65f56 100644 --- a/pages/subcomponent/pickup.vue +++ b/pages/subcomponent/pickup.vue @@ -66,9 +66,11 @@ - ¥{{ item.price || item.unitPrice }}~{{ item.maxPrice || item.unitPrice }}/件 + ¥{{ item.price || item.unitPrice }}/件 + ¥{{ item.price || item.unitPrice }}~{{ item.maxPrice }}/件 x{{ item.quantity }} - ¥{{ ((item.price || item.unitPrice) * item.quantity).toFixed(2) }}~{{ ((item.maxPrice || item.unitPrice) * item.quantity).toFixed(2) }} + ¥{{ ((item.price || item.unitPrice) * item.quantity).toFixed(2) }} + ¥{{ ((item.price || item.unitPrice) * item.quantity).toFixed(2) }}~{{ ((item.maxPrice) * item.quantity).toFixed(2) }} @@ -239,18 +241,23 @@ export default { return this.selectedItems.reduce((sum, item) => sum + item.quantity, 0) }, totalPriceRange() { - if (this.selectedItems.length === 0) return '0-0' + if (this.selectedItems.length === 0) return '0.0' let minTotal = 0 let maxTotal = 0 this.selectedItems.forEach(item => { const minPrice = item.price || item.unitPrice || 0 - const maxPrice = item.maxPrice || item.unitPrice || 0 + const maxPrice = item.maxPrice || minPrice || 0 minTotal += minPrice * item.quantity maxTotal += maxPrice * item.quantity }) + // 如果最小值和最大值相等,只显示一个值 + if (minTotal === maxTotal) { + return minTotal.toFixed(2) + } + return `${minTotal.toFixed(2)}~${maxTotal.toFixed(2)}` }, canSubmit() { diff --git a/pages/subcomponent/promotion.vue b/pages/subcomponent/promotion.vue index 22e98ed..0b00c08 100644 --- a/pages/subcomponent/promotion.vue +++ b/pages/subcomponent/promotion.vue @@ -88,6 +88,7 @@ 联系客服 + 添加客服可以获取更多推广福利 diff --git a/pages/subcomponent/select.vue b/pages/subcomponent/select.vue index cd3782e..19d60ff 100644 --- a/pages/subcomponent/select.vue +++ b/pages/subcomponent/select.vue @@ -64,7 +64,7 @@ 手机号 - + 所在地区 @@ -302,7 +302,7 @@ export default { this.regionIndex = [pIdx, cIdx, dIdx] }, // 选择地区 - selectAddress() { + selectRegion() { // 首先检查位置权限 uni.getSetting({ success: (res) => { diff --git a/pages/subcomponent/wallet.vue b/pages/subcomponent/wallet.vue index 9972010..a5153cd 100644 --- a/pages/subcomponent/wallet.vue +++ b/pages/subcomponent/wallet.vue @@ -16,9 +16,46 @@ - + + + + + + + + + + + + @@ -127,7 +164,8 @@ export default { noMore: false, refreshing: false, isInitialized: false, - bannerList: [] + bannerList: [], + videoPlayingStates: {} // 记录每个视频的播放状态 } }, computed: { @@ -357,6 +395,54 @@ export default { } finally { this.loadingMore = false } + }, + + // 视频相关方法 + playVideoFullscreen(item, index) { + if (!this.videoPlayingStates[index]) { + // 第一次点击:显示视频并开始播放 + this.$set(this.videoPlayingStates, index, true); + + // 等待视频元素渲染后再进行操作 + this.$nextTick(() => { + setTimeout(() => { + const videoContext = uni.createVideoContext(`wallet-video-${index}`, this); + if (videoContext) { + // 直接进入全屏播放 + videoContext.requestFullScreen({ + direction: -1 // 自动选择方向 + }); + } + }, 200); + }); + } + }, + + onVideoPlay(index) { + this.$set(this.videoPlayingStates, index, true); + }, + + onVideoPause(index) { + this.$set(this.videoPlayingStates, index, false); + }, + + onVideoEnded(index) { + // 视频播放结束,回到预览状态 + this.$set(this.videoPlayingStates, index, false); + }, + + onFullscreenChange(e) { + console.log('全屏状态改变:', e.detail); + const videoIndex = e.target.id.replace('wallet-video-', ''); + + if (e.detail.fullScreen) { + // 进入全屏时,不做任何操作 + console.log('进入全屏模式,方向:', e.detail.direction); + } else { + // 退出全屏时,回到预览状态 + console.log('退出全屏模式,回到预览状态'); + this.$set(this.videoPlayingStates, videoIndex, false); + } } } } @@ -408,23 +494,78 @@ export default { overflow: hidden; border-radius: 0 0 30rpx 30rpx; margin-top: 0; -} + .video-container { + position: relative; + width: 100%; + height: 100%; + + .video-poster { + cursor: pointer; + transition: transform 0.2s ease; + + &:active { + transform: scale(0.98); + } + } + + .video-overlay { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: rgba(0, 0, 0, 0.4); + z-index: 10; + cursor: pointer; + display: flex; + justify-content: center; + align-items: center; + + .play-button-large { + width: 120rpx; + height: 120rpx; + background: transparent; + border-radius: 50%; + display: flex; + justify-content: center; + align-items: center; + backdrop-filter: blur(10rpx); + transition: all 0.3s ease; + box-shadow: 0 8rpx 30rpx rgba(0, 0, 0, 0.3); + + &:active { + transform: scale(0.9); + background: rgba(255, 255, 255, 0.1); + } + + .play-triangle { + width: 0; + height: 0; + border-left: 24rpx solid #fff; + border-top: 18rpx solid transparent; + border-bottom: 18rpx solid transparent; + margin-left: 8rpx; + transition: all 0.3s ease; + filter: drop-shadow(0 2rpx 4rpx rgba(0, 0, 0, 0.3)); + } + } + + &:hover .play-button-large { + transform: scale(1.1); + box-shadow: 0 12rpx 40rpx rgba(0, 0, 0, 0.4); + + .play-triangle { + border-left-color: #ff8917; + } + } + } + } +} -.banner-content { - position: relative; - z-index: 1; - height: 100%; - display: flex; - justify-content: center; - align-items: center; - .wallet-icon { - width: 240rpx; - height: 240rpx; - } -} +/* .banner-content 样式已移除,现在使用轮播图 */ .balance-card { margin: -60rpx 30rpx 0;