diff --git a/pages/cabinet/index.vue b/pages/cabinet/index.vue
index 5757d7c..1503d24 100644
--- a/pages/cabinet/index.vue
+++ b/pages/cabinet/index.vue
@@ -606,10 +606,10 @@ async function onShip() {
vibrateShort()
const user_id = uni.getStorageSync('user_id')
if (!user_id) return
-
+
const selectedItems = aggregatedList.value.filter(item => item.selected)
if (selectedItems.length === 0) return
-
+
// 收集所有需要发货的 inventory id
let allIds = []
selectedItems.forEach(item => {
@@ -618,13 +618,39 @@ async function onShip() {
allIds.push(...idsToShip)
}
})
-
+
if (allIds.length === 0) {
uni.showToast({ title: '选择无效', icon: 'none' })
return
}
- // 2. 确认发货
+ // 1. 先检查是否有默认地址
+ try {
+ const addresses = await listAddresses(user_id)
+ const addressList = addresses.list || addresses.data || addresses || []
+
+ if (!addressList || addressList.length === 0) {
+ // 没有默认地址,提示用户跳转到新建地址页面
+ uni.showModal({
+ title: '提示',
+ content: '申请发货需要设置默认地址,是否前往新建地址?',
+ confirmText: '前往',
+ cancelText: '取消',
+ success: (res) => {
+ if (res.confirm) {
+ uni.navigateTo({ url: '/pages-user/address/edit' })
+ }
+ }
+ })
+ return
+ }
+ } catch (e) {
+ console.error('获取地址列表失败:', e)
+ uni.showToast({ title: '获取地址失败', icon: 'none' })
+ return
+ }
+
+ // 2. 有默认地址,确认发货
uni.showModal({
title: '确认发货',
content: `共 ${allIds.length} 件物品,确认申请发货?`,
diff --git a/pages/shop/index.vue b/pages/shop/index.vue
index 0bdde1a..6495e29 100644
--- a/pages/shop/index.vue
+++ b/pages/shop/index.vue
@@ -11,12 +11,49 @@
+
+
+
+ 价格区间:
+
+
+ -
+
+
+ 筛选
+ 重置
+
+
+
+ {{ range.label }}
+
+
+
+
-
@@ -122,6 +159,19 @@ const page = ref(1)
const pageSize = 20
const hasMore = ref(true)
+// 价格筛选相关
+const priceMin = ref('')
+const priceMax = ref('')
+const priceRanges = [
+ { key: 'all', label: '全部', min: null, max: null },
+ { key: '0-100', label: '0-100', min: 0, max: 100 },
+ { key: '100-500', label: '100-500', min: 100, max: 500 },
+ { key: '500-1000', label: '500-1K', min: 500, max: 1000 },
+ { key: '1000-5000', label: '1K-5K', min: 1000, max: 5000 },
+ { key: '5000+', label: '5K+', min: 5000, max: null }
+]
+const activePriceRange = ref('all')
+
const tabs = [
{ id: 'product', name: '商品' },
{ id: 'coupon', name: '优惠券' },
@@ -163,25 +213,34 @@ function switchTab(id) {
}
async function loadItems(append = false) {
- if (loading.value && append) return
+ if (loading.value) return
loading.value = true
try {
const res = await getStoreItems(currentTab.value, page.value, pageSize)
const list = res.list || res || []
+ const total = res.total || 0
const newItems = normalizeItems(list, currentTab.value)
-
+
if (append) {
allItems.value = [...allItems.value, ...newItems]
} else {
allItems.value = newItems
}
-
- if (newItems.length < pageSize) {
- hasMore.value = false
- } else {
+
+ // 根据返回的total计算总页数
+ const totalPages = Math.ceil(total / pageSize)
+
+ // 如果当前页小于总页数,继续加载下一页
+ if (page.value < totalPages) {
page.value++
+ // 递归加载下一页
+ loading.value = false // 临时释放loading状态,允许递归调用
+ await loadItems(true)
+ } else {
+ // 所有数据加载完成
+ hasMore.value = false
}
-
+
applyFilters()
} catch (e) {
console.error(e)
@@ -193,12 +252,59 @@ async function loadItems(append = false) {
function applyFilters() {
const k = String(keyword.value || '').trim().toLowerCase()
+ const minPrice = priceMin.value !== '' ? parseFloat(priceMin.value) : null
+ const maxPrice = priceMax.value !== '' ? parseFloat(priceMax.value) : null
+
items.value = allItems.value.filter(item => {
+ // 关键词筛选
const title = String(item.title || '').toLowerCase()
- return !k || title.includes(k)
+ const matchKeyword = !k || title.includes(k)
+
+ // 价格筛选
+ const itemPrice = item.points || 0
+ let matchPrice = true
+ if (minPrice !== null) {
+ matchPrice = matchPrice && itemPrice >= minPrice
+ }
+ if (maxPrice !== null) {
+ matchPrice = matchPrice && itemPrice <= maxPrice
+ }
+
+ return matchKeyword && matchPrice
})
}
+function applyPriceFilter() {
+ activePriceRange.value = 'custom'
+ applyFilters()
+}
+
+function resetPriceFilter() {
+ priceMin.value = ''
+ priceMax.value = ''
+ activePriceRange.value = 'all'
+ applyFilters()
+}
+
+function selectQuickPrice(range) {
+ activePriceRange.value = range.key
+ if (range.min !== null) {
+ priceMin.value = range.min.toString()
+ } else {
+ priceMin.value = ''
+ }
+ if (range.max !== null) {
+ priceMax.value = range.max.toString()
+ } else {
+ priceMax.value = ''
+ }
+ applyFilters()
+}
+
+function isRangeActive(range) {
+ return activePriceRange.value === range.key
+}
+
function onSearchConfirm() { applyFilters() }
function onProductTap(p) {
@@ -269,9 +375,7 @@ onShow(() => {
})
onReachBottom(() => {
- if (!loading.value && hasMore.value) {
- loadItems(true)
- }
+ // 所有数据已在页面加载时一次性请求完成,无需触底加载
})
watch(keyword, () => applyFilters())
@@ -297,7 +401,7 @@ watch(keyword, () => applyFilters())
padding: 20rpx 24rpx 0;
box-shadow: 0 4rpx 20rpx rgba(0,0,0,0.05);
}
-.header-placeholder { height: 180rpx; }
+.header-placeholder { height: 340rpx; }
.search-box { margin-bottom: 20rpx; }
.search-input-wrap {
@@ -310,6 +414,78 @@ watch(keyword, () => applyFilters())
.search-input { flex: 1; font-size: 26rpx; color: $text-main; }
.placeholder-style { color: $text-tertiary; }
+/* 价格筛选 */
+.filter-section {
+ margin-bottom: 16rpx;
+ padding: 16rpx;
+ background: rgba(255, 255, 255, 0.6);
+ border-radius: $radius-md;
+}
+.filter-row {
+ display: flex;
+ align-items: center;
+ margin-bottom: 12rpx;
+}
+.filter-label {
+ font-size: 24rpx;
+ color: $text-secondary;
+ white-space: nowrap;
+ margin-right: 12rpx;
+}
+.price-inputs {
+ flex: 1;
+ display: flex;
+ align-items: center;
+ gap: 8rpx;
+}
+.price-input {
+ flex: 1;
+ height: 56rpx;
+ background: rgba(0, 0, 0, 0.04);
+ border-radius: $radius-sm;
+ padding: 0 16rpx;
+ font-size: 24rpx;
+ color: $text-main;
+ text-align: center;
+}
+.input-placeholder { color: $text-tertiary; }
+.price-separator {
+ font-size: 24rpx;
+ color: $text-tertiary;
+ padding: 0 4rpx;
+}
+.filter-btn {
+ padding: 12rpx 20rpx;
+ background: $gradient-brand;
+ color: #fff;
+ font-size: 24rpx;
+ border-radius: $radius-round;
+ margin-left: 12rpx;
+ white-space: nowrap;
+ &.reset {
+ background: rgba(0, 0, 0, 0.06);
+ color: $text-secondary;
+ }
+}
+.quick-prices {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 12rpx;
+}
+.quick-price-tag {
+ padding: 8rpx 20rpx;
+ background: rgba(0, 0, 0, 0.04);
+ border-radius: $radius-round;
+ font-size: 22rpx;
+ color: $text-secondary;
+ transition: all 0.2s;
+ &.active {
+ background: $gradient-brand;
+ color: #fff;
+ font-weight: 600;
+ }
+}
+
/* Tabs */
.tab-row {
display: flex;