国家标注,价格筛选
This commit is contained in:
@@ -31,9 +31,23 @@
|
||||
<view class="filter-group">
|
||||
<text class="filter-group-title">价格区间</text>
|
||||
<view class="filter-price-range">
|
||||
<input class="price-input" placeholder="最低价" type="number" />
|
||||
<input
|
||||
class="price-input"
|
||||
:class="{ 'input-error': minError }"
|
||||
placeholder="最低价"
|
||||
type="number"
|
||||
v-model="minPrice"
|
||||
@blur="onMinBlur"
|
||||
/>
|
||||
<text class="price-divider">-</text>
|
||||
<input class="price-input" placeholder="最高价" type="number" />
|
||||
<input
|
||||
class="price-input"
|
||||
:class="{ 'input-error': maxError }"
|
||||
placeholder="最高价"
|
||||
type="number"
|
||||
v-model="maxPrice"
|
||||
@blur="onMaxBlur"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
@@ -58,7 +72,83 @@ export default {
|
||||
default: () => []
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
minPrice: '',
|
||||
maxPrice: '',
|
||||
minError: false,
|
||||
maxError: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
* 清洗价格输入:只保留数字和小数点(仅一个)
|
||||
*/
|
||||
sanitizePrice(v) {
|
||||
if (v === '' || v === null || v === undefined) return ''
|
||||
var s = String(v).replace(/[^\d.]/g, '')
|
||||
var i = s.indexOf('.')
|
||||
if (i > -1) {
|
||||
s = s.slice(0, i + 1) + s.slice(i + 1).replace(/\./g, '')
|
||||
}
|
||||
return s
|
||||
},
|
||||
/**
|
||||
* 校验单个价格:非空时必须是 ≥0 的数字,否则提示并清空,返回 false
|
||||
*/
|
||||
validateSingle(key) {
|
||||
var raw = this.sanitizePrice(this[key])
|
||||
this[key] = raw
|
||||
if (raw === '') return true
|
||||
var num = parseFloat(raw)
|
||||
if (isNaN(num) || num < 0) {
|
||||
uni.showToast({ title: '价格不能小于0', icon: 'none' })
|
||||
this[key] = ''
|
||||
return false
|
||||
}
|
||||
return true
|
||||
},
|
||||
flashError(key) {
|
||||
this[key] = true
|
||||
setTimeout(() => { this[key] = false }, 1500)
|
||||
},
|
||||
onMinBlur() {
|
||||
if (!this.validateSingle('minPrice')) return
|
||||
// 最低价 > 已填的最高价 → 最低价钳制到最高价(反向同样不允许越界)
|
||||
var min = parseFloat(this.minPrice)
|
||||
var max = parseFloat(this.maxPrice)
|
||||
if (this.minPrice !== '' && this.maxPrice !== '' && min > max) {
|
||||
this.minPrice = this.maxPrice
|
||||
this.flashError('minError')
|
||||
uni.showToast({ title: '最低价不能大于最高价,已自动调整', icon: 'none' })
|
||||
}
|
||||
},
|
||||
onMaxBlur() {
|
||||
if (!this.validateSingle('maxPrice')) return
|
||||
// 最高价 < 已填的最低价 → 冒红并改成最低价
|
||||
var min = parseFloat(this.minPrice)
|
||||
var max = parseFloat(this.maxPrice)
|
||||
if (this.maxPrice !== '' && this.minPrice !== '' && max < min) {
|
||||
this.maxPrice = this.minPrice
|
||||
this.flashError('maxError')
|
||||
uni.showToast({ title: '最高价不能小于最低价,已自动调整', icon: 'none' })
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 点击确定前的价格校验,校验不过则阻止请求
|
||||
*/
|
||||
validatePrices() {
|
||||
if (!this.validateSingle('minPrice')) return false
|
||||
if (!this.validateSingle('maxPrice')) return false
|
||||
var min = parseFloat(this.minPrice)
|
||||
var max = parseFloat(this.maxPrice)
|
||||
if (this.minPrice !== '' && this.maxPrice !== '' && max < min) {
|
||||
this.flashError('maxError')
|
||||
uni.showToast({ title: '最高价不能小于最低价', icon: 'none' })
|
||||
return false
|
||||
}
|
||||
return true
|
||||
},
|
||||
isSelected(group, tagId) {
|
||||
return (group.selected || []).indexOf(tagId) > -1
|
||||
},
|
||||
@@ -66,10 +156,18 @@ export default {
|
||||
this.$emit('toggle-tag', { groupIndex: gIdx, tagId })
|
||||
},
|
||||
onReset() {
|
||||
this.minPrice = ''
|
||||
this.maxPrice = ''
|
||||
this.minError = false
|
||||
this.maxError = false
|
||||
this.$emit('reset')
|
||||
},
|
||||
onConfirm() {
|
||||
this.$emit('confirm')
|
||||
if (!this.validatePrices()) return
|
||||
this.$emit('confirm', {
|
||||
minPrice: this.minPrice,
|
||||
maxPrice: this.maxPrice
|
||||
})
|
||||
},
|
||||
onClose() {
|
||||
this.$emit('close')
|
||||
@@ -128,6 +226,10 @@ export default {
|
||||
}
|
||||
.filter-drawer-body {
|
||||
flex: 1;
|
||||
/* 框架默认 width:100% + padding 时 content-box 会超宽 64rpx,
|
||||
导致右侧"最高价"输入框被挤出屏幕,必须 border-box */
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
padding: 0 32rpx;
|
||||
}
|
||||
.filter-group {
|
||||
@@ -162,18 +264,26 @@ export default {
|
||||
.filter-price-range {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 20rpx;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.price-input {
|
||||
flex: 1;
|
||||
/* 固定宽度,不依赖 flex 收缩(uni-input 自定义元素收缩行为不可靠) */
|
||||
width: 230rpx;
|
||||
box-sizing: border-box;
|
||||
height: 72rpx;
|
||||
padding: 0 20rpx;
|
||||
background: #f5f5f5;
|
||||
border-radius: 12rpx;
|
||||
border: 2rpx solid transparent;
|
||||
font-size: 26rpx;
|
||||
color: #333333;
|
||||
text-align: center;
|
||||
}
|
||||
/* 校验失败冒红 */
|
||||
.price-input.input-error {
|
||||
border-color: #ff0000;
|
||||
background: #fff0f0;
|
||||
}
|
||||
.price-divider {
|
||||
font-size: 28rpx;
|
||||
color: #999999;
|
||||
|
||||
@@ -42,10 +42,19 @@
|
||||
<!-- 商品信息 -->
|
||||
<view class="product-info">
|
||||
<text class="product-name">{{ item.name }}</text>
|
||||
<!-- 价格 + "起"字 -->
|
||||
<!-- 价格 + "起"字 + 国家标签(未选国家时显示商品所属国家) -->
|
||||
<view class="price-row">
|
||||
<text class="product-price">¥{{ item.price }}</text>
|
||||
<text class="price-unit">起</text>
|
||||
<view class="country-tag" v-if="showCountryTag && item.countryName">
|
||||
<image
|
||||
class="country-tag-icon"
|
||||
:src="item.countryIcon"
|
||||
mode="aspectFill"
|
||||
v-if="item.countryIcon"
|
||||
></image>
|
||||
<text class="country-tag-name">{{ item.countryName }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@@ -75,6 +84,8 @@ export default {
|
||||
hasMore: { type: Boolean, default: true },
|
||||
loading: { type: Boolean, default: false },
|
||||
scrollTopVal: { type: Number, default: 0 },
|
||||
// 未选择国家时显示商品所属国家标签
|
||||
showCountryTag: { type: Boolean, default: false },
|
||||
// 商品滚动区固定高度(px),由父组件动态计算传入
|
||||
scrollHeight: { type: Number, default: 400 }
|
||||
},
|
||||
@@ -216,6 +227,34 @@ export default {
|
||||
line-height: 1.2;
|
||||
margin-left: 4rpx;
|
||||
}
|
||||
/* 国家标签 - 价格右侧,国旗图标 + 国家名 */
|
||||
.country-tag {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 6rpx;
|
||||
margin-left: 12rpx;
|
||||
padding: 4rpx 12rpx;
|
||||
background: #f7f7f7;
|
||||
border-radius: 20rpx;
|
||||
max-width: 50%;
|
||||
box-sizing: border-box;
|
||||
overflow: hidden;
|
||||
}
|
||||
.country-tag-icon {
|
||||
width: 28rpx;
|
||||
height: 20rpx;
|
||||
border-radius: 4rpx;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.country-tag-name {
|
||||
font-size: 20rpx;
|
||||
font-weight: 500;
|
||||
color: #666666;
|
||||
line-height: 1.2;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
/* 底部加载提示 */
|
||||
.load-tip {
|
||||
|
||||
Reference in New Issue
Block a user