Browse Source

feat(质检): 完善质检功能并优化UI

- 在订单详情页添加跳转质检功能
- 质检结果页支持多商品理由选择和图片上传
- 质检页增加价格范围显示和商品数量配置
- 调整UI样式使用rpx单位适配不同屏幕
- 修改图片上传限制为9张并优化布局
v1
前端-胡立永 2 months ago
parent
commit
e7eb8d64aa
4 changed files with 159 additions and 102 deletions
  1. +7
    -2
      pages/component/recycle.vue
  2. +32
    -26
      pages/manager/inspect-result.vue
  3. +118
    -73
      pages/manager/inspect.vue
  4. +2
    -1
      pages/manager/order-detail.vue

+ 7
- 2
pages/component/recycle.vue View File

@ -547,6 +547,11 @@ export default {
const item = config.find(i => i.keyName === 'min_money'); const item = config.find(i => i.keyName === 'min_money');
return item ? parseFloat(item.keyContent) : 0; return item ? parseFloat(item.keyContent) : 0;
}, },
minMumber() {
const config = getApp().globalData.configData || [];
const item = config.find(i => i.keyName === 'min_number');
return item ? parseFloat(item.keyContent) : 0;
},
// - ( * 0.066) // - ( * 0.066)
extraRecycleAmount() { extraRecycleAmount() {
const minPrice = parseFloat(this.priceRange.min) || 0; const minPrice = parseFloat(this.priceRange.min) || 0;
@ -822,9 +827,9 @@ export default {
return return
} }
if (this.totalCount < 3 || Number(this.totalPrice) < this.minMoney) {
if (this.totalCount < this.minMumber || Number(this.totalPrice) < this.minMoney) {
uni.showToast({ uni.showToast({
title: `各品类混合需要满3${this.totalUnitText}并且各品类混合需要满${this.minMoney}元才能回收哦`,
title: `各品类混合需要满${this.minMumber}${this.totalUnitText}并且各品类混合需要满${this.minMoney}元才能回收哦`,
icon: 'none' icon: 'none'
}) })
return return


+ 32
- 26
pages/manager/inspect-result.vue View File

@ -14,7 +14,7 @@
<!-- 合格产品卡片 --> <!-- 合格产品卡片 -->
<view v-if="hasQualifiedItems" class="result-card"> <view v-if="hasQualifiedItems" class="result-card">
<view class="card-title">合格产品</view> <view class="card-title">合格产品</view>
<view v-for="item in qualifiedList" :key="item.shopId" class="result-row">
<view v-for="item in qualifiedList" :key="item.shopId" class="result-group">
<view class="row-main"> <view class="row-main">
<view class="goods-name-section"> <view class="goods-name-section">
<text class="goods-name">{{ item.shopId ? getGoodsName(item.shopId) : (item.id === 'unrecyclable' ? '不可回收' <text class="goods-name">{{ item.shopId ? getGoodsName(item.shopId) : (item.id === 'unrecyclable' ? '不可回收'
@ -24,13 +24,16 @@
<text class="row-count">x{{ item.count }}</text> <text class="row-count">x{{ item.count }}</text>
<text class="row-total">¥{{ item.total }}</text> <text class="row-total">¥{{ item.total }}</text>
</view> </view>
<view class="row-reason">
<text class="reason-label">{{ getGoodsName(item.shopId) }}</text>
<view class="reason-select" @click="selectReasonForQualified(item)">
<text class="reason-placeholder" :class="{ 'selected': hasSelectedReason(item) }">
{{ hasSelectedReason(item) ? '已选择' : '请选择理由(选填)' }}
</text>
<uni-icons type="right" size="18" color="#bbb" />
<!-- 选择理由模块 -->
<view v-if="item.items && item.items.length > 0">
<view v-for="(commonItem, index) in item.items" :key="commonItem.id || index" class="row-reason">
<text class="reason-label">{{ getGoodsName(item.shopId) }}{{ index + 1 }}</text>
<view class="reason-select" @click="selectReasonForQualified(commonItem, item)">
<text class="reason-placeholder" :class="{ 'selected': hasSelectedReason(commonItem) }">
{{ hasSelectedReason(commonItem) ? '已选择' : '请选择理由(选填)' }}
</text>
<uni-icons type="right" size="18" color="#bbb" />
</view>
</view> </view>
</view> </view>
</view> </view>
@ -226,7 +229,8 @@ export default {
shopId: item.shopId, shopId: item.shopId,
count: item.qualifiedNum, count: item.qualifiedNum,
total: item.price, total: item.price,
classId: item.categoryId
classId: item.categoryId,
items: item.commonOrderList ? [...item.commonOrderList] : []
}) })
console.log('qualifiedList', this.qualifiedList) console.log('qualifiedList', this.qualifiedList)
} }
@ -248,7 +252,8 @@ export default {
this.unrecyclableList.push({ this.unrecyclableList.push({
id: item.id, id: item.id,
count: item.unrecyclable, count: item.unrecyclable,
total: item.price
total: item.price,
items: item.commonOrderList ? [...item.commonOrderList] : []
}) })
} }
}) })
@ -335,7 +340,7 @@ export default {
type = 1 // type = 1 //
} else if (item.testingStatus === 2) { } else if (item.testingStatus === 2) {
type = 2 // type = 2 //
}
}
this.currentReasonItem = popupItem this.currentReasonItem = popupItem
// //
@ -357,17 +362,17 @@ export default {
this.lockScroll() this.lockScroll()
this.$refs.reasonPopup.open() this.$refs.reasonPopup.open()
}, },
selectReasonForQualified(item) {
this.currentReasonItem = item
this.currentReasonTitle = this.getGoodsName(item.shopId || item.id)
selectReasonForQualified(commonItem, parentItem) {
this.currentReasonItem = commonItem
this.currentReasonTitle = this.getGoodsName(parentItem.shopId || parentItem.id)
// 使testingImages // 使testingImages
if (item.testingImages && item.testingImages.trim() !== '') {
this.reasonImages = item.testingImages.split(',').filter(img => img.trim() !== '')
if (commonItem.testingImages && commonItem.testingImages.trim() !== '') {
this.reasonImages = commonItem.testingImages.split(',').filter(img => img.trim() !== '')
} else { } else {
this.reasonImages = [] this.reasonImages = []
} }
// 使categoryId // 使categoryId
this.selectReasonForUnqualified(item, 0, item.classId)
this.selectReasonForUnqualified(commonItem, 0, parentItem.classId)
this.lockScroll() this.lockScroll()
this.$refs.reasonPopup.open() this.$refs.reasonPopup.open()
}, },
@ -427,9 +432,9 @@ export default {
}, },
addReasonImg() { addReasonImg() {
// //
if (this.reasonImages.length >= 3) {
if (this.reasonImages.length >= 9) {
uni.showToast({ uni.showToast({
title: '最多只能上传3张图片',
title: '最多只能上传9张图片',
icon: 'none' icon: 'none'
}) })
return return
@ -882,12 +887,13 @@ export default {
.img-list { .img-list {
display: flex; display: flex;
gap: 12px;
flex-wrap: wrap;
gap: 20rpx;
margin-bottom: 32px; margin-bottom: 32px;
.img-item { .img-item {
width: 80px;
height: 80px;
width: 150rpx;
height: 150rpx;
border-radius: 12px; border-radius: 12px;
background: #f8f8f8; background: #f8f8f8;
position: relative; position: relative;
@ -895,7 +901,7 @@ export default {
.img { .img {
width: 100%; width: 100%;
height: 100%; height: 100%;
border-radius: 12px;
border-radius: 24rpx;
object-fit: cover; object-fit: cover;
} }
@ -903,13 +909,13 @@ export default {
position: absolute; position: absolute;
top: -6px; top: -6px;
right: -6px; right: -6px;
width: 24px;
height: 24px;
width: 48rpx;
height: 48rpx;
background: rgba(0, 0, 0, 0.6); background: rgba(0, 0, 0, 0.6);
color: #fff; color: #fff;
border-radius: 50%; border-radius: 50%;
text-align: center; text-align: center;
line-height: 24px;
line-height: 48rpx;
font-size: 16px; font-size: 16px;
font-weight: bold; font-weight: bold;
} }


+ 118
- 73
pages/manager/inspect.vue View File

@ -27,7 +27,10 @@
<view class="goods-info"> <view class="goods-info">
<view class="goods-title-row"> <view class="goods-title-row">
<text class="goods-name">{{ item.name }}</text> <text class="goods-name">{{ item.name }}</text>
<text class="goods-price">¥ {{ item.price }} <text class="goods-unit">/{{item.unit}}</text></text>
<text class="goods-price">
{{ formatPrice(item) }}
<text class="goods-unit" v-if="item.unit">/{{item.unit}}</text>
</text>
</view> </view>
<text class="goods-desc">{{ item.desc }}</text> <text class="goods-desc">{{ item.desc }}</text>
</view> </view>
@ -309,6 +312,7 @@ export default {
image: item.image || '/static/回收/衣物.png', image: item.image || '/static/回收/衣物.png',
name: item.name, name: item.name,
price: item.price || 0, price: item.price || 0,
maxPrice: item.maxPrice || 0,
desc: item.service || '允许脏破烂,160码以上', desc: item.service || '允许脏破烂,160码以上',
qualified: inspectItem ? inspectItem.qualifiedNum : 0, qualified: inspectItem ? inspectItem.qualifiedNum : 0,
amount: inspectItem ? inspectItem.price : '', // inspectResult amount: inspectItem ? inspectItem.price : '', // inspectResult
@ -574,21 +578,25 @@ export default {
shopId: orderItem ? (orderItem.shopId || orderItem.id) : itemId, shopId: orderItem ? (orderItem.shopId || orderItem.id) : itemId,
pinId: '', pinId: '',
categoryId: currentCategoryId || '', // id categoryId: currentCategoryId || '', // id
commonOrderList: [
{
testingInstructions: '',
testingImages: '',
testingStatus: 0
}
]
commonOrderList: [] //
} }
this.inspectResult.list.push(inspectItem) this.inspectResult.list.push(inspectItem)
} }
if (!inspectItem) return if (!inspectItem) return
if (type === 'qualified' && delta > 0) { if (type === 'qualified' && delta > 0) {
inspectItem.qualifiedNum++ inspectItem.qualifiedNum++
// commonOrderList
inspectItem.commonOrderList.push({
testingInstructions: '',
testingImages: '',
testingStatus: 0
})
} else if (type === 'qualified' && delta < 0) { } else if (type === 'qualified' && delta < 0) {
inspectItem.qualifiedNum = Math.max(0, inspectItem.qualifiedNum - 1) inspectItem.qualifiedNum = Math.max(0, inspectItem.qualifiedNum - 1)
// commonOrderList
if (inspectItem.commonOrderList.length > 0) {
inspectItem.commonOrderList.pop()
}
// 0 // 0
if (inspectItem.qualifiedNum === 0) { if (inspectItem.qualifiedNum === 0) {
const idx = this.inspectResult.list.findIndex(listItem => listItem === inspectItem) const idx = this.inspectResult.list.findIndex(listItem => listItem === inspectItem)
@ -773,6 +781,36 @@ export default {
this.brandSearch = '' this.brandSearch = ''
this.currentProductId = null this.currentProductId = null
}, },
//
formatPrice(item) {
const price = item.price
const maxPrice = item.maxPrice
// 0
if ((!price || price === 0) && (!maxPrice || maxPrice === 0)) {
return '¥ —'
}
//
if (price && (!maxPrice || maxPrice === 0)) {
return `¥ ${price}`
}
if (maxPrice && (!price || price === 0)) {
return `¥ ${maxPrice}`
}
//
if (price && maxPrice && price !== maxPrice) {
const minPrice = Math.min(price, maxPrice)
const maxPriceValue = Math.max(price, maxPrice)
return `¥ ${minPrice} - ${maxPriceValue}`
}
//
return `¥ ${price || maxPrice}`
},
}, },
created() { created() {
this.currentCategory = 0 this.currentCategory = 0
@ -896,16 +934,16 @@ export default {
} }
.category-nav { .category-nav {
width: 80px;
width: 160rpx;
background: #fff; background: #fff;
border-radius: 24px 0 0 24px;
// padding: 24px 0;
border-radius: 48rpx 0 0 48rpx;
// padding: 48rpx 0;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.03);
height: calc(100vh - 200rpx - var(--status-bar-height) - 80px);
max-height: calc(100vh - 200rpx - var(--status-bar-height) - 80px);
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.03);
height: calc(100vh - 200rpx - var(--status-bar-height) - 160rpx);
max-height: calc(100vh - 200rpx - var(--status-bar-height) - 160rpx);
overflow-y: scroll; overflow-y: scroll;
overflow-x: hidden; overflow-x: hidden;
position: relative; position: relative;
@ -915,7 +953,7 @@ export default {
scrollbar-color: #ddd transparent; scrollbar-color: #ddd transparent;
&::-webkit-scrollbar { &::-webkit-scrollbar {
width: 4px;
width: 8rpx;
} }
&::-webkit-scrollbar-track { &::-webkit-scrollbar-track {
@ -924,7 +962,7 @@ export default {
&::-webkit-scrollbar-thumb { &::-webkit-scrollbar-thumb {
background: #ddd; background: #ddd;
border-radius: 2px;
border-radius: 4rpx;
} }
&::-webkit-scrollbar-thumb:hover { &::-webkit-scrollbar-thumb:hover {
@ -932,19 +970,19 @@ export default {
} }
.category-item { .category-item {
width: 64px;
height: 44px;
border-radius: 16px 0 0 16px;
width: 128rpx;
height: 88rpx;
border-radius: 32rpx 0 0 32rpx;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: flex-start; justify-content: flex-start;
font-size: 16px;
font-size: 32rpx;
color: #222; color: #222;
margin-bottom: 12px;
margin-bottom: 24rpx;
background: #fff; background: #fff;
position: relative; position: relative;
transition: background 0.2s, color 0.2s, font-weight 0.2s; transition: background 0.2s, color 0.2s, font-weight 0.2s;
padding-left: 12px;
padding-left: 24rpx;
&.active { &.active {
background: linear-gradient(90deg, #fff7e6 80%, #fff 100%); background: linear-gradient(90deg, #fff7e6 80%, #fff 100%);
@ -957,8 +995,8 @@ export default {
left: 0; left: 0;
top: 30%; top: 30%;
height: 40%; height: 40%;
width: 2px;
border-radius: 4px;
width: 4rpx;
border-radius: 8rpx;
background: #ffb400; background: #ffb400;
bottom: auto; bottom: auto;
} }
@ -966,14 +1004,14 @@ export default {
.category-badge { .category-badge {
position: absolute; position: absolute;
top: 6px;
right: 10px;
top: 12rpx;
right: 20rpx;
background: #ff4d4f; background: #ff4d4f;
color: #fff; color: #fff;
font-size: 12px;
font-size: 24rpx;
border-radius: 50%; border-radius: 50%;
width: 18px;
height: 18px;
width: 36rpx;
height: 36rpx;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
@ -983,18 +1021,18 @@ export default {
.goods-list { .goods-list {
flex: 1; flex: 1;
height: calc(100vh - 200rpx - var(--status-bar-height) - 80px);
padding: 0 0 0 16px;
height: calc(100vh - 200rpx - var(--status-bar-height) - 160rpx);
padding: 0 0 0 32rpx;
overflow-y: auto; overflow-y: auto;
background: none; background: none;
} }
.goods-card { .goods-card {
background: #fff; background: #fff;
border-radius: 24px;
box-shadow: 0 4px 24px rgba(0, 0, 0, 0.06);
margin-bottom: 18px;
padding: 18px 18px 9px 18px;
border-radius: 48rpx;
box-shadow: 0 8rpx 48rpx rgba(0, 0, 0, 0.06);
margin-bottom: 36rpx;
padding: 36rpx 36rpx 18rpx 36rpx;
} }
@ -1002,13 +1040,13 @@ export default {
.goods-header { .goods-header {
display: flex; display: flex;
align-items: center; align-items: center;
margin-bottom: 12px;
margin-bottom: 24rpx;
.goods-img { .goods-img {
width: 56px;
height: 56px;
border-radius: 16px;
margin-right: 12px;
width: 112rpx;
height: 112rpx;
border-radius: 32rpx;
margin-right: 24rpx;
background: #f8f8f8; background: #f8f8f8;
object-fit: contain; object-fit: contain;
} }
@ -1023,30 +1061,37 @@ export default {
.goods-title-row { .goods-title-row {
display: flex; display: flex;
align-items: baseline; align-items: baseline;
justify-content: space-between;
.goods-name { .goods-name {
font-size: 16px;
font-size: 28rpx;
font-weight: bold; font-weight: bold;
color: #222; color: #222;
margin-right: 8px;
margin-right: 16rpx;
flex: 1;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
} }
.goods-price { .goods-price {
font-size: 15px;
font-size: 30rpx;
color: #ffb400; color: #ffb400;
font-weight: bold; font-weight: bold;
white-space: nowrap;
flex-shrink: 0;
.goods-unit { .goods-unit {
font-size: 13px;
font-size: 26rpx;
color: #bbb; color: #bbb;
} }
} }
} }
.goods-desc { .goods-desc {
font-size: 13px;
font-size: 26rpx;
color: #999; color: #999;
margin-top: 4px;
margin-top: 8rpx;
} }
} }
} }
@ -1054,12 +1099,12 @@ export default {
.goods-row { .goods-row {
display: flex; display: flex;
align-items: center; align-items: center;
margin-bottom: 12px;
margin-bottom: 24rpx;
.row-label { .row-label {
font-size: 14px;
font-size: 28rpx;
color: #888; color: #888;
width: 80px;
width: 160rpx;
flex-shrink: 0; flex-shrink: 0;
} }
@ -1100,14 +1145,14 @@ export default {
.amount-input { .amount-input {
flex: 1; flex: 1;
height: 32px;
border-radius: 12px;
height: 64rpx;
border-radius: 24rpx;
background: #f6f6f6; background: #f6f6f6;
border: none; border: none;
font-size: 15px;
font-size: 30rpx;
color: #222; color: #222;
padding-left: 10px;
margin-left: 8px;
padding-left: 20rpx;
margin-left: 16rpx;
} }
} }
@ -1118,34 +1163,34 @@ export default {
bottom: 0; bottom: 0;
background: #fff; background: #fff;
display: flex; display: flex;
gap: 16px;
padding: 12px 16px 24px 16px;
gap: 32rpx;
padding: 24rpx 32rpx 48rpx 32rpx;
z-index: 101; z-index: 101;
.btn-outline { .btn-outline {
flex: 1; flex: 1;
height: 40px;
border-radius: 16px;
border: 1px solid #ffe09a;
height: 80rpx;
border-radius: 32rpx;
border: 2rpx solid #ffe09a;
color: #ffb400; color: #ffb400;
background: #fff0d2; background: #fff0d2;
font-size: 15px;
font-size: 30rpx;
font-weight: 500; font-weight: 500;
box-shadow: none; box-shadow: none;
padding: 0 18px;
padding: 0 36rpx;
} }
.btn-main { .btn-main {
flex: 1; flex: 1;
height: 40px;
border-radius: 16px;
height: 80rpx;
border-radius: 32rpx;
background: linear-gradient(90deg, #ffd01e 0%, #ffac04 100%); background: linear-gradient(90deg, #ffd01e 0%, #ffac04 100%);
color: #fff; color: #fff;
border: none; border: none;
font-size: 15px;
font-size: 30rpx;
font-weight: 500; font-weight: 500;
box-shadow: none; box-shadow: none;
padding: 0 18px;
padding: 0 36rpx;
} }
} }
@ -1177,11 +1222,11 @@ export default {
.brand-popup { .brand-popup {
position: relative; position: relative;
width: 100%; width: 100%;
max-width: 750px;
max-width: 1500rpx;
background: #fff; background: #fff;
border-radius: 32rpx 32rpx 0 0;
box-shadow: 0 -4rpx 24rpx rgba(0,0,0,0.08);
padding-bottom: 40rpx;
border-radius: 64rpx 64rpx 0 0;
box-shadow: 0 -8rpx 48rpx rgba(0,0,0,0.08);
padding-bottom: 80rpx;
max-height: 90vh; max-height: 90vh;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@ -1282,14 +1327,14 @@ export default {
.brand-confirm-popup { .brand-confirm-popup {
width: 70vw; width: 70vw;
max-width: 270px;
max-width: 540rpx;
background: #fff; background: #fff;
border-radius: 32rpx;
box-shadow: 0 8rpx 32rpx rgba(0,0,0,0.12);
border-radius: 64rpx;
box-shadow: 0 16rpx 64rpx rgba(0,0,0,0.12);
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
padding: 48rpx 20rpx 36rpx 20rpx;
padding: 96rpx 40rpx 72rpx 40rpx;
position: relative; position: relative;
} }


+ 2
- 1
pages/manager/order-detail.vue View File

@ -11,7 +11,8 @@
</view> </view>
</view> </view>
<view class="main-content" >
<view class="main-content" @click="goToInspect">
<!-- 回收信息卡片高保真参考流程卡片 --> <!-- 回收信息卡片高保真参考流程卡片 -->
<view class="info-card process-card"> <view class="info-card process-card">
<view v-if="order.cancelReason" class="cancel-reason">{{ order.cancelReason }}</view> <view v-if="order.cancelReason" class="cancel-reason">{{ order.cancelReason }}</view>


Loading…
Cancel
Save