feat:app改造

This commit is contained in:
2026-08-17 09:27:07 +08:00
parent aa20d121f7
commit 97d3e1cd36
11 changed files with 1923 additions and 271 deletions
+2 -1
View File
@@ -8,7 +8,8 @@
"type" : "uni-app:app-android" "type" : "uni-app:app-android"
}, },
{ {
"playground" : "standard", "customPlaygroundType" : "device",
"playground" : "custom",
"type" : "uni-app:app-ios" "type" : "uni-app:app-ios"
}, },
{ {
+8 -2
View File
@@ -1,6 +1,6 @@
<template> <template>
<view class="choiceness_warp"> <view class="choiceness_warp">
<view class="choiceness_title"> <view class="choiceness_title" v-if="isTitle">
<up-image src="/static/common/jingxuan_left.png" width="24" height="8" bgColor="#f1f6ff00"></up-image> <up-image src="/static/common/jingxuan_left.png" width="24" height="8" bgColor="#f1f6ff00"></up-image>
<view class="choiceness_title_msg">为您精选</view> <view class="choiceness_title_msg">为您精选</view>
<up-image src="/static/common/jingxuan_right.png" width="24" height="8" bgColor="#f1f6ff00"></up-image> <up-image src="/static/common/jingxuan_right.png" width="24" height="8" bgColor="#f1f6ff00"></up-image>
@@ -28,6 +28,12 @@ import { searchList } from "@/api/product.js";
export default { export default {
name: "choiceness", name: "choiceness",
props: {
isTitle: {
type: Boolean,
default: true
},
},
data() { data() {
return { return {
productList: [], productList: [],
@@ -73,7 +79,7 @@ export default {
<style lang="scss" scoped> <style lang="scss" scoped>
.choiceness_warp { .choiceness_warp {
margin-top: 35rpx; margin-top: 30rpx;
} }
.choiceness_title { .choiceness_title {
+45 -4
View File
@@ -2,7 +2,7 @@
<view class="parity-product-item-wrap"> <view class="parity-product-item-wrap">
<!-- 样式 1 (图2样式) --> <!-- 样式 1 (图2样式) -->
<view class="parity-product-item type-1" @click.stop="onClick" v-if="type == 1 || type == '1'"> <view class="parity-product-item type-1" @click.stop="onClick" v-if="type == 1 || type == '1'">
<image class="top-img-1" :src="obj.url" mode="aspectFill" lazy-load /> <image class="top-img-1" :src="obj.bargainMainGraph || obj.url" mode="aspectFill" lazy-load />
<view class="shop-bottom-panel-1"> <view class="shop-bottom-panel-1">
<view class="title-box"> <view class="title-box">
<text class="tag-badge" :style="{ backgroundColor: effectiveTagColor }" v-if="tagName || obj.tagName"> <text class="tag-badge" :style="{ backgroundColor: effectiveTagColor }" v-if="tagName || obj.tagName">
@@ -11,6 +11,13 @@
<text class="title-text">{{ obj.title }}</text> <text class="title-text">{{ obj.title }}</text>
</view> </view>
<!-- 标签 sellingPoint -->
<view class="selling-point-box" v-if="sellingPointList && sellingPointList.length">
<text class="selling-point-item" v-for="(item, index) in sellingPointList" :key="index">
{{ item }}
</text>
</view>
<!-- 有优惠券/积分 --> <!-- 有优惠券/积分 -->
<view class="price-action-row" v-if="obj.buyDeductionValue"> <view class="price-action-row" v-if="obj.buyDeductionValue">
<view class="price-left"> <view class="price-left">
@@ -92,8 +99,8 @@ export default {
}, },
computed: { computed: {
getOrigPrice() { getOrigPrice() {
if (this.obj && this.obj.aa !== undefined && this.obj.aa !== null && this.obj.aa !== '') { if (this.obj && this.obj.adPrice !== undefined && this.obj.adPrice !== null && this.obj.adPrice !== '') {
return this.obj.aa; return this.obj.adPrice;
} }
return this.obj ? (this.obj.originalPrice || this.obj.marketPrice || this.obj.linePrice || this.obj.oldPrice || '') : ''; return this.obj ? (this.obj.originalPrice || this.obj.marketPrice || this.obj.linePrice || this.obj.oldPrice || '') : '';
}, },
@@ -111,6 +118,18 @@ export default {
if (tag.includes('低价') || tag.includes('好物')) return '#FF9800'; if (tag.includes('低价') || tag.includes('好物')) return '#FF9800';
if (tag.includes('品牌') || tag.includes('特卖')) return '#333333'; if (tag.includes('品牌') || tag.includes('特卖')) return '#333333';
return '#7A35F6'; return '#7A35F6';
},
sellingPointList() {
if (!this.obj) return [];
const sp = this.obj.sellingPoint || this.obj.selling_point || this.obj.sellingPoints;
if (!sp) return [];
if (Array.isArray(sp)) {
return sp.map(item => String(item).trim()).filter(Boolean);
}
if (typeof sp === 'string') {
return sp.split(/[,,]/).map(item => item.trim()).filter(Boolean);
}
return [];
} }
}, },
methods: { methods: {
@@ -150,7 +169,6 @@ export default {
.title-box { .title-box {
font-size: 28rpx; font-size: 28rpx;
color: #1a1a1a; color: #1a1a1a;
max-height: 80rpx;
font-weight: bold; font-weight: bold;
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
@@ -173,6 +191,29 @@ export default {
vertical-align: middle; vertical-align: middle;
} }
.selling-point-box {
display: flex;
flex-wrap: wrap;
align-items: center;
margin-top: 12rpx;
}
.selling-point-item {
display: inline-flex;
align-items: center;
justify-content: center;
font-size: 20rpx;
color: #34C79F;
background-color: #ECFAF7;
border: 1rpx solid #34C79F;
border-radius: 6rpx;
padding: 2rpx 10rpx;
margin-right: 10rpx;
margin-bottom: 6rpx;
white-space: nowrap;
box-sizing: border-box;
}
.price-action-row { .price-action-row {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
+6
View File
@@ -460,6 +460,12 @@
"navigationStyle": "custom" "navigationStyle": "custom"
} }
}, },
{
"path": "insights/search-result",
"style": {
"navigationStyle": "custom"
}
},
{ {
"path": "rwa_add/rwa_add", "path": "rwa_add/rwa_add",
"style": { "style": {
+10 -9
View File
@@ -56,7 +56,7 @@
<!-- #ifdef APP-PLUS --> <!-- #ifdef APP-PLUS -->
<view class="other_login">其他登录方式</view> <view class="other_login">其他登录方式</view>
<view class="login_other_icon"> <view class="login_other_icon">
<view class="login_other_item" @click="wechatOneLogin"> <view class="login_other_item" @click="wechatOneLogin(2)">
<up-image src="/pages/login_package/static/login/WXICON.png" width="44" height="44" <up-image src="/pages/login_package/static/login/WXICON.png" width="44" height="44"
bgColor="#f1f6ff00"></up-image> bgColor="#f1f6ff00"></up-image>
微信登录 微信登录
@@ -67,22 +67,22 @@
bgColor="#f1f6ff00"></up-image> bgColor="#f1f6ff00"></up-image>
支付宝登录 支付宝登录
</view> </view>
<!-- <view v-if="isIOS" class="login_other_item" @click="appleOneLogin"> <view v-if="isIOS" class="login_other_item" @click="appleOneLogin">
<up-icon name="apple-fill" size="44" color="#000000"></up-icon> <up-icon name="apple-fill" size="44" color="#000000"></up-icon>
Apple登录 Apple登录
</view> --> </view>
</view> </view>
<!-- #endif --> <!-- #endif -->
<!-- #ifdef MP-WEIXIN --> <!-- #ifdef MP-WEIXIN -->
<view class="other_login">其他登录方式</view> <view class="other_login">其他登录方式</view>
<!-- <view class="login_other_icon"> <view class="login_other_icon">
<view class="login_other_item" @click="wechatOneLogin"> <view class="login_other_item" @click="wechatOneLogin(1)">
<up-image src="/pages/login_package/static/login/WXICON.png" width="44" height="44" <up-image src="/pages/login_package/static/login/WXICON.png" width="44" height="44"
bgColor="#f1f6ff00"></up-image> bgColor="#f1f6ff00"></up-image>
微信登录 微信登录11
</view> </view>
</view> --> </view>
<view class="login_other_icon"> <view class="login_other_icon">
<view class="login_other_item_you" @click="jumpHome"> <view class="login_other_item_you" @click="jumpHome">
游客模式 游客模式
@@ -342,7 +342,7 @@ export default {
}, },
// 微信登录 // 微信登录
async wechatOneLogin() { async wechatOneLogin(type) {
const then = this; const then = this;
this.loading = true; this.loading = true;
@@ -356,7 +356,7 @@ export default {
success: (res) => { success: (res) => {
if (res.confirm) { if (res.confirm) {
this.isPolicy = true; this.isPolicy = true;
this.wechatOneLogin(); this.wechatOneLogin(type);
} else { } else {
this.loading = false; this.loading = false;
} }
@@ -381,6 +381,7 @@ export default {
const params = { const params = {
isValid: false, isValid: false,
token: loginRes.code, token: loginRes.code,
type
// 可以根据需要添加其他参数 // 可以根据需要添加其他参数
}; };
console.log("微信登录接口返回-1:", params); console.log("微信登录接口返回-1:", params);
+13 -8
View File
@@ -99,7 +99,7 @@
<view>共{{ item.buyNum }}件,合计¥{{ item.sumAmount }}</view> <view>共{{ item.buyNum }}件,合计¥{{ item.sumAmount }}</view>
</view> --> </view> -->
<view class="collect_msg" v-if="item.buyDeductionValue">共{{ item.buyNum }}件,合计数字积分{{ item.buyDeductionValue <view class="collect_msg" v-if="item.buyDeductionValue">共{{ item.buyNum }}件,合计数字积分{{ item.buyDeductionValue
}} }}
+¥{{ item.sumAmount }}</view> +¥{{ item.sumAmount }}</view>
<view class="collect_msg" v-if="!item.buyDeductionValue">运费:¥{{ item.postage }},商品总价:¥{{ item.sumAmount }} <view class="collect_msg" v-if="!item.buyDeductionValue">运费:¥{{ item.postage }},商品总价:¥{{ item.sumAmount }}
</view> </view>
@@ -143,14 +143,19 @@
<view :class="[ <view :class="[
'operate_comm', 'operate_comm',
form.type === MINE_ORDER_TYPE.UNPAID 'operate_but_3'
? 'operate_but_3' ]" v-if="!item.isAfter && form.type === MINE_ORDER_TYPE.UNPAID && item.status !== 5"
: 'operate_but_1',
]" v-if="!item.isAfter && form.type !== MINE_ORDER_TYPE.AFTER_SALE && item.status !== 5"
@click="onSaleAfter(item)"> @click="onSaleAfter(item)">
{{ 取消支付
form.type === MINE_ORDER_TYPE.UNPAID ? "取消支付" : "申请售后" </view>
}}
<view :class="[
'operate_comm',
'operate_but_1'
]"
v-if="(!item.isAfter && form.type !== MINE_ORDER_TYPE.UNPAID && form.type !== MINE_ORDER_TYPE.AFTER_SALE && item.status !== 5) || item.isAfterOpen"
@click="onSaleAfter(item)">
申请售后
</view> </view>
<view class="operate_comm operate_but_1" v-if="form.type === MINE_ORDER_TYPE.AFTER_SALE" <view class="operate_comm operate_but_1" v-if="form.type === MINE_ORDER_TYPE.AFTER_SALE"
@@ -298,10 +298,10 @@ export default {
formatDate, formatDate,
formatDate1, formatDate1,
jumpLeft() { jumpLeft() {
const type = this.orderInfo.status + 1;
uni.navigateTo({ uni.navigateTo({
url: url:
"/pages/mine_package/mine_order/mine_order?type=" + "/pages/mine_package/mine_order/mine_order?type=" + type
this.orderInfo.status,
}); });
}, },
wayShowFun(type) { wayShowFun(type) {
@@ -0,0 +1,529 @@
<template>
<view class="page-container">
<!-- 顶部状态栏安全高度 -->
<TopSafe bgColor="#ffffff"></TopSafe>
<!-- 1. 自定义导航栏:左侧返回箭头,中间“商品列表”标题 -->
<view class="custom-navbar">
<view class="nav-back flex-c" @click="onBack">
<u-icon name="arrow-left" size="36rpx" color="#333333"></u-icon>
</view>
<view class="nav-title">商品列表</view>
<view class="nav-right"></view>
</view>
<!-- 2. 搜索框区域 -->
<view class="search-bar-box">
<view class="search-inner">
<u-icon name="search" size="36rpx" color="#999999" class="search-icon"></u-icon>
<input class="search-input" v-model="searchInput" placeholder="请输入商品关键字"
placeholder-style="color: #999999; font-size: 28rpx;" confirm-type="search"
@confirm="onSearchBtnClick" />
<view class="search-btn flex-c" @click="onSearchBtnClick">
<text class="search-btn-text">搜索</text>
</view>
</view>
</view>
<!-- 3. 排序/筛选栏(右对齐:综合 / 价格) -->
<view class="filter-bar">
<view class="filter-item" :class="{ active: sortBy === 'relevance' }" @click="switchSort('relevance')">
<text class="filter-text">综合</text>
<view class="sort-icon-box">
<u-icon name="arrow-up-fill" size="12rpx"
:color="sortBy === 'relevance' && sortOrder === 'asc' ? '#7934f6' : '#cccccc'"
class="icon-up"></u-icon>
<u-icon name="arrow-down-fill" size="12rpx"
:color="sortBy === 'relevance' && sortOrder === 'desc' ? '#7934f6' : '#cccccc'"
class="icon-down"></u-icon>
</view>
</view>
<view class="filter-item" :class="{ active: sortBy === 'price' }" @click="switchSort('price')">
<text class="filter-text">价格</text>
<view class="sort-icon-box">
<u-icon name="arrow-up-fill" size="12rpx"
:color="sortBy === 'price' && sortOrder === 'asc' ? '#7934f6' : '#cccccc'"
class="icon-up"></u-icon>
<u-icon name="arrow-down-fill" size="12rpx"
:color="sortBy === 'price' && sortOrder === 'desc' ? '#7934f6' : '#cccccc'"
class="icon-down"></u-icon>
</view>
</view>
</view>
<!-- 4. 商品双列网格列表区域 -->
<scroll-view scroll-y class="product-scroll-view" @scrolltolower="loadMore" refresher-enabled
:refresher-triggered="isRefreshing" @refresherrefresh="onRefresh">
<view class="product-grid" v-if="dataList && dataList.length > 0">
<view class="product-card" v-for="(item, index) in dataList" :key="item.id || index"
@click="onJumpDetail(item)">
<!-- 商品大图 + 可选标签 -->
<view class="img-wrapper">
<image class="product-img"
:src="item.url || item.image || item.pic || '/static/common/default-goods.png'"
mode="aspectFill"></image>
<!-- <view class="image-tag" v-if="item.tagName || item.tag">
{{ item.tagName || item.tag }}
</view> -->
</view>
<!-- 商品信息 -->
<view class="card-info">
<view class="product-title">
{{ item.title || item.name || item.goodsName }}
</view>
<view class="price-sales-row">
<view class="price-box">
<text class="currency">¥</text>
<text class="price-val">{{ formatPrice(item.price || item.adPrice) }}</text>
</view>
<text class="sales-val"
v-if="item.sales !== undefined && item.sales !== null && item.sales !== ''">
全网销量{{ formatSales(item.sales) }}件
</text>
</view>
</view>
</view>
</view>
<!-- 加载状态 / 无数据提示 -->
<view class="empty-box" v-else-if="!loading">
<u-icon name="empty-data" size="140rpx" color="#cccccc"></u-icon>
<text class="empty-text">暂无相关商品</text>
</view>
<view class="loading-more-box" v-if="loading && dataList.length > 0">
<text class="loading-text">加载中...</text>
</view>
</scroll-view>
</view>
</template>
<script>
import TopSafe from '@/components/common/top-safe.nvue';
import { searchList } from '@/api/product.js';
export default {
components: {
TopSafe
},
data() {
return {
searchInput: '',
dataList: [],
loading: false,
isRefreshing: false,
sortBy: 'relevance', // 'relevance' | 'price'
sortOrder: 'asc', // 'asc' | 'desc'
page: 1,
pageSize: 20,
hasMore: true
};
},
onLoad(options) {
if (options && options.keyword) {
this.searchInput = decodeURIComponent(options.keyword);
}
this.fetchData();
},
methods: {
onBack() {
uni.navigateBack();
},
onSearchBtnClick() {
if (!this.searchInput || !this.searchInput.trim()) return;
this.saveSearchHistory(this.searchInput.trim());
this.page = 1;
this.hasMore = true;
this.fetchData();
},
saveSearchHistory(val) {
let historyStr = uni.getStorageSync('history') || '';
let historyList = historyStr ? historyStr.split(',').filter(item => item.trim() !== '') : [];
let idx = historyList.indexOf(val);
if (idx > -1) {
historyList.splice(idx, 1);
}
historyList.unshift(val);
if (historyList.length > 15) {
historyList.pop();
}
uni.setStorageSync('history', historyList.join(','));
},
async fetchData(isLoadMore = false) {
if (this.loading) return;
this.loading = true;
let params = {
keyword: this.searchInput.trim(),
page: this.page,
pageSize: this.pageSize,
sortBy: this.sortBy,
sortOrder: this.sortOrder
};
try {
const res = await searchList(params);
let list = [];
if (res && res.data) {
list = res.data;
} else if (Array.isArray(res)) {
list = res;
}
if (isLoadMore) {
this.dataList = [...this.dataList, ...list];
} else {
this.dataList = list;
}
if (list.length < this.pageSize) {
this.hasMore = false;
}
} catch (err) {
console.error('searchList error:', err);
} finally {
this.loading = false;
this.isRefreshing = false;
}
},
switchSort(type) {
if (type === 'relevance') {
if (this.sortBy === 'relevance') {
this.sortOrder = this.sortOrder === 'asc' ? 'desc' : 'asc';
} else {
this.sortBy = 'relevance';
this.sortOrder = 'asc';
}
} else if (type === 'price') {
if (this.sortBy === 'price') {
this.sortOrder = this.sortOrder === 'asc' ? 'desc' : 'asc';
} else {
this.sortBy = 'price';
this.sortOrder = 'asc';
}
}
this.page = 1;
this.hasMore = true;
this.fetchData();
},
onRefresh() {
this.isRefreshing = true;
this.page = 1;
this.hasMore = true;
this.fetchData();
},
loadMore() {
if (!this.hasMore || this.loading) return;
this.page++;
this.fetchData(true);
},
onJumpDetail(item) {
if (item && item.id) {
uni.navigateTo({
url: '/pages/other_package/productInfo/productInfo?id=' + item.id
});
}
},
formatPrice(val) {
if (val === undefined || val === null || val === '') return '0.00';
let num = parseFloat(val);
if (isNaN(num)) return val;
return num.toFixed(2);
},
formatSales(n) {
if (n === undefined || n === null || n === '') return '0';
let num = Number(n);
if (isNaN(num)) return n;
if (num >= 10000) {
return (num / 10000).toFixed(1).replace(/\.0$/, '') + '万+';
}
return String(num);
}
}
};
</script>
<style lang="scss" scoped>
.page-container {
width: 100%;
height: 100vh;
background-color: #f5f5f7;
display: flex;
flex-direction: column;
box-sizing: border-box;
}
/* 导航栏 */
.custom-navbar {
width: 100%;
height: 88rpx;
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
padding: 0 32rpx;
box-sizing: border-box;
background-color: #ffffff;
position: relative;
flex-shrink: 0;
.nav-back {
width: 60rpx;
height: 60rpx;
display: flex;
align-items: center;
justify-content: flex-start;
}
.nav-title {
font-size: 34rpx;
font-weight: bold;
color: #1a1a1a;
position: absolute;
left: 50%;
transform: translateX(-50%);
white-space: nowrap;
}
.nav-right {
width: 60rpx;
}
}
/* 搜索框区域 */
.search-bar-box {
width: 100%;
padding: 16rpx 32rpx;
box-sizing: border-box;
background-color: #ffffff;
flex-shrink: 0;
.search-inner {
width: 100%;
height: 80rpx;
background-color: #ffffff;
border-radius: 40rpx;
display: flex;
flex-direction: row;
align-items: center;
padding: 0 8rpx 0 28rpx;
box-sizing: border-box;
border: 2rpx solid #efefef;
.search-icon {
margin-right: 12rpx;
}
.search-input {
flex: 1;
height: 100%;
font-size: 28rpx;
color: #333333;
background: transparent;
border: none;
}
.search-btn {
height: 64rpx;
padding: 0 32rpx;
background: linear-gradient(270deg, #b164fb 0%, #7934f6 100%);
border-radius: 32rpx;
display: flex;
align-items: center;
justify-content: center;
.search-btn-text {
font-size: 28rpx;
color: #ffffff;
font-weight: 500;
}
}
}
}
/* 排序筛选栏 */
.filter-bar {
width: 100%;
padding: 20rpx 40rpx 16rpx;
box-sizing: border-box;
display: flex;
flex-direction: row;
align-items: center;
justify-content: flex-end;
gap: 48rpx;
background-color: #f5f5f7;
flex-shrink: 0;
.filter-item {
display: flex;
flex-direction: row;
align-items: center;
cursor: pointer;
.filter-text {
font-size: 28rpx;
color: #666666;
font-weight: 400;
margin-right: 8rpx;
}
&.active {
.filter-text {
color: #7934f6;
font-weight: bold;
}
}
.sort-icon-box {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
line-height: 1;
.icon-up {
margin-bottom: 2rpx;
}
}
}
}
/* 商品列表 Grid */
.product-scroll-view {
flex: 1;
height: 0;
width: 100%;
box-sizing: border-box;
}
.product-grid {
width: 100%;
padding: 0 24rpx 30rpx;
box-sizing: border-box;
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: space-between;
.product-card {
width: 342rpx;
margin-bottom: 20rpx;
background-color: #ffffff;
border-radius: 20rpx;
overflow: hidden;
display: flex;
flex-direction: column;
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.02);
.img-wrapper {
width: 100%;
height: 342rpx;
position: relative;
background-color: #f8f8f8;
.product-img {
width: 100%;
height: 100%;
border-radius: 20rpx 20rpx 0 0;
}
.image-tag {
position: absolute;
top: 12rpx;
right: 12rpx;
background: rgba(255, 192, 110, 0.9);
color: #8c4a00;
font-size: 20rpx;
padding: 4rpx 12rpx;
border-radius: 8rpx;
max-width: 80%;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
}
.card-info {
padding: 16rpx 20rpx 20rpx;
display: flex;
flex-direction: column;
justify-content: space-between;
flex: 1;
.product-title {
font-size: 28rpx;
color: #333333;
font-weight: bold;
line-height: 38rpx;
height: 76rpx;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
text-overflow: ellipsis;
word-break: break-all;
margin-bottom: 16rpx;
}
.price-sales-row {
display: flex;
flex-direction: row;
align-items: baseline;
justify-content: space-between;
width: 100%;
.price-box {
display: flex;
align-items: baseline;
color: #7934f6;
.currency {
font-size: 24rpx;
font-weight: bold;
margin-right: 2rpx;
}
.price-val {
font-size: 32rpx;
font-weight: bold;
}
}
.sales-val {
font-size: 22rpx;
color: #999999;
font-weight: normal;
}
}
}
}
}
.empty-box {
width: 100%;
padding: 120rpx 0;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
.empty-text {
font-size: 28rpx;
color: #999999;
margin-top: 20rpx;
}
}
.loading-more-box {
width: 100%;
padding: 20rpx 0 40rpx;
text-align: center;
.loading-text {
font-size: 24rpx;
color: #999999;
}
}
</style>
+31 -45
View File
@@ -16,14 +16,8 @@
<view class="search-bar-box"> <view class="search-bar-box">
<view class="search-inner"> <view class="search-inner">
<u-icon name="search" size="36rpx" color="#999999" class="search-icon"></u-icon> <u-icon name="search" size="36rpx" color="#999999" class="search-icon"></u-icon>
<input <input class="search-input" v-model="searchInput" placeholder="请输入商品关键字"
class="search-input" placeholder-style="color: #999999; font-size: 28rpx;" confirm-type="search" @confirm="onSearch" />
v-model="searchInput"
placeholder="请输入商品关键字"
placeholder-style="color: #999999; font-size: 28rpx;"
confirm-type="search"
@confirm="onSearch"
/>
<view class="search-btn flex-c" @click="onSearch"> <view class="search-btn flex-c" @click="onSearch">
<text class="search-btn-text">搜索</text> <text class="search-btn-text">搜索</text>
</view> </view>
@@ -34,26 +28,16 @@
<view class="history-container"> <view class="history-container">
<view class="history-header flex-r-lr"> <view class="history-header flex-r-lr">
<text class="section-title">历史搜索</text> <text class="section-title">历史搜索</text>
<u-icon name="trash" size="38rpx" color="#999999" @click="toggleDel"></u-icon> <u-icon name="trash" size="42rpx" color="#999999" @click="toggleDel"></u-icon>
</view> </view>
<!-- 历史记录标签列表 --> <!-- 历史记录标签列表 -->
<view class="history-tags flex-r" v-if="historyList.length"> <view class="history-tags flex-r" v-if="historyList.length">
<view <view class="history-tag-item flex-r" v-for="(item, index) in historyList" :key="index"
class="history-tag-item flex-r" @click="onText(item)">
v-for="(item, index) in historyList"
:key="index"
@click="onText(item)"
>
<text class="tag-text">{{ item }}</text> <text class="tag-text">{{ item }}</text>
<u-icon <u-icon name="close-circle-fill" size="28rpx" color="#999999" class="del-icon" v-if="isDel"
name="close-circle-fill" @click.stop="onDel(index)"></u-icon>
size="28rpx"
color="#999999"
class="del-icon"
v-if="isDel"
@click.stop="onDel(index)"
></u-icon>
</view> </view>
</view> </view>
@@ -68,19 +52,18 @@
<view class="recommend-header"> <view class="recommend-header">
<text class="section-title">猜你喜欢</text> <text class="section-title">猜你喜欢</text>
</view> </view>
<!-- 猜你喜欢下面的列表按要求空着 --> <view class="recommend-content">
<view class="recommend-list"> <choiceness :isTitle="false" />
<view class="product-grid" v-if="dataList && dataList.length">
<ShopItem
:obj="item"
class="product-item"
@click="onJump(item)"
v-for="item in dataList"
:key="item.id"
></ShopItem>
</view>
</view> </view>
<!-- <view class="recommend-list">
<view class="product-grid" v-if="dataList && dataList.length">
<ShopItem :obj="item" class="product-item" @click="onJump(item)" v-for="item in dataList"
:key="item.id"></ShopItem>
</view>
</view> -->
</view> </view>
<!-- 为您精选 -->
<DownPopup></DownPopup> <DownPopup></DownPopup>
</view> </view>
@@ -93,10 +76,10 @@ import TopSafe from '@/components/common/top-safe.nvue';
import DownPopup from '@/components/common/down-popup.vue'; import DownPopup from '@/components/common/down-popup.vue';
import { searchList } from '@/api/product.js'; import { searchList } from '@/api/product.js';
import ShopItem from './components/shop-item.vue'; import ShopItem from './components/shop-item.vue';
import func from '@/utils/func.js'; import choiceness from "@/components/choiceness/choiceness.vue";
export default { export default {
components: { Header, TopSafe, DownPopup, ShopItem }, components: { Header, TopSafe, DownPopup, ShopItem, choiceness },
data() { data() {
return { return {
searchInput: '', searchInput: '',
@@ -130,11 +113,8 @@ export default {
return; return;
} }
this.onAdd(); this.onAdd();
let params = { uni.navigateTo({
keyword: this.searchInput.trim() url: '/pages/rwa_package/insights/search-result?keyword=' + encodeURIComponent(this.searchInput.trim())
};
searchList(params).then((res) => {
this.dataList = res.data || [];
}); });
}, },
onDel(index) { onDel(index) {
@@ -305,9 +285,9 @@ export default {
width: 100%; width: 100%;
.history-tag-item { .history-tag-item {
padding: 10rpx 28rpx; padding: 6rpx 24rpx;
background-color: #f5f5f7; background-color: #f5f5f7;
border-radius: 30rpx; border-radius: 24rpx;
margin-right: 20rpx; margin-right: 20rpx;
margin-bottom: 20rpx; margin-bottom: 20rpx;
display: flex; display: flex;
@@ -339,7 +319,7 @@ export default {
/* 猜你喜欢 */ /* 猜你喜欢 */
.recommend-container { .recommend-container {
width: 100%; width: 100%;
padding: 32rpx 32rpx; padding: 20rpx 32rpx 0;
box-sizing: border-box; box-sizing: border-box;
.recommend-header { .recommend-header {
@@ -350,11 +330,17 @@ export default {
.section-title { .section-title {
font-size: 32rpx; font-size: 32rpx;
font-weight: bold;
color: #333333; color: #333333;
} }
} }
.recommend-content {
::v-deep(.choiceness_warp) {
margin-top: 15rpx;
}
}
.recommend-list { .recommend-list {
width: 100%; width: 100%;
margin-top: 24rpx; margin-top: 24rpx;
File diff suppressed because it is too large Load Diff
+265 -200
View File
@@ -1,7 +1,7 @@
<template> <template>
<view class="sort_warp" :class="platformType ? '' : 'iosplatformType'"> <view class="sort_warp" :class="platformType ? '' : 'iosplatformType'">
<!-- #ifndef MP-WEIXIN --> <!-- #ifndef MP-WEIXIN -->
<TopSafe></TopSafe> <TopSafe bgColor="#F2EBFF"></TopSafe>
<!-- #endif --> <!-- #endif -->
<!-- 顶部固定区域:搜索 + 分类区域 --> <!-- 顶部固定区域:搜索 + 分类区域 -->
@@ -67,8 +67,8 @@
<!-- 左侧分类侧边栏 --> <!-- 左侧分类侧边栏 -->
<scroll-view class="left_sidebar_scroll" scroll-y> <scroll-view class="left_sidebar_scroll" scroll-y>
<view class="sidebar_item" v-for="(item, index) in categoryList" :key="item.id || index" <view class="sidebar_item" v-for="(item, index) in subCategoryList" :key="item.id || index"
:class="{ active: currentCategoryIndex === index }" @click="selectCategory(index)"> :class="{ active: currentSubCategoryIndex === index }" @click="selectSubCategory(index)">
<text class="sidebar_name">{{ item.name }}</text> <text class="sidebar_name">{{ item.name }}</text>
</view> </view>
</scroll-view> </scroll-view>
@@ -77,28 +77,50 @@
<view class="right_content_area"> <view class="right_content_area">
<!-- 排序栏 --> <!-- 排序栏 -->
<view class="sort_option_bar"> <view class="sort_option_bar">
<view class="cat_title_text">{{ currentCategory ? currentCategory.name : '' }}</view> <view></view>
<!-- <view class="cat_title_text">{{ currentCategory ? currentCategory.name : '' }}</view> -->
<view class="sort_actions"> <view class="sort_actions">
<view class="sort_item" :class="{ active: sortType === 'default' }" @click="setSort('default')"> <view class="sort_item" :class="{ active: sortBy === 'relevance' }" @click="setSort('relevance')">
综合 <text class="sort_arrow">⇅</text> <text>综合</text>
<view class="sort_icon_box">
<u-icon name="arrow-up-fill" size="10rpx"
:color="sortBy === 'relevance' && sortOrder === 'asc' ? '#7a35f6' : '#cccccc'"
class="icon_up"></u-icon>
<u-icon name="arrow-down-fill" size="10rpx"
:color="sortBy === 'relevance' && sortOrder === 'desc' ? '#7a35f6' : '#cccccc'"
class="icon_down"></u-icon>
</view>
</view> </view>
<view class="sort_item" :class="{ active: sortType === 'sales' }" @click="setSort('sales')"> <view class="sort_item" :class="{ active: sortBy === 'sales' }" @click="setSort('sales')">
销量 <text class="sort_arrow">⇅</text> <text>销量</text>
<view class="sort_icon_box">
<u-icon name="arrow-up-fill" size="10rpx"
:color="sortBy === 'sales' && sortOrder === 'asc' ? '#7a35f6' : '#cccccc'" class="icon_up"></u-icon>
<u-icon name="arrow-down-fill" size="10rpx"
:color="sortBy === 'sales' && sortOrder === 'desc' ? '#7a35f6' : '#cccccc'"
class="icon_down"></u-icon>
</view>
</view> </view>
<view class="sort_item" :class="{ active: sortType === 'price' }" @click="setSort('price')"> <view class="sort_item" :class="{ active: sortBy === 'price' }" @click="setSort('price')">
价格 <text class="sort_arrow">⇅</text> <text>价格</text>
<view class="sort_icon_box">
<u-icon name="arrow-up-fill" size="10rpx"
:color="sortBy === 'price' && sortOrder === 'asc' ? '#7a35f6' : '#cccccc'" class="icon_up"></u-icon>
<u-icon name="arrow-down-fill" size="10rpx"
:color="sortBy === 'price' && sortOrder === 'desc' ? '#7a35f6' : '#cccccc'"
class="icon_down"></u-icon>
</view>
</view> </view>
</view> </view>
</view> </view>
<!-- 商品列表 --> <!-- 商品列表 -->
<scroll-view class="product_list_scroll" scroll-y> <scroll-view class="product_list_scroll" scroll-y @scrolltolower="onReachBottomGoods" :lower-threshold="50">
<view class="product_list_box" v-if="displayProducts && displayProducts.length > 0"> <view class="product_list_box" v-if="displayProducts && displayProducts.length > 0">
<view class="product_row_card" v-for="(item, index) in displayProducts" :key="item.id || index" <view class="product_row_card" v-for="(item, index) in displayProducts" :key="item.id || index"
@click="jumpInfo(item)"> @click="jumpInfo(item)">
<view class="product_img_box"> <view class="product_img_box">
<image class="product_img" :src="item.image || item.icon || defaultProductImg" mode="aspectFill" <image class="product_img" :src="item.url || defaultProductImg" mode="aspectFill" lazy-load />
lazy-load />
</view> </view>
<view class="product_info_box"> <view class="product_info_box">
<view class="product_title">{{ item.name || item.title }}</view> <view class="product_title">{{ item.name || item.title }}</view>
@@ -119,8 +141,12 @@
</view> </view>
</view> </view>
</view> </view>
<!-- 加载更多与无数据状态提示 -->
<view class="load_more_tips" v-if="loadingMore">加载中...</view>
<view class="load_more_tips" v-else-if="noMore && displayProducts.length > 0">没有更多了</view>
</view> </view>
<view class="empty_box" v-else> <view class="empty_box" v-else-if="!loading">
<image src="https://static.tbmall.xin/static/not_shopping.png" class="empty_img" /> <image src="https://static.tbmall.xin/static/not_shopping.png" class="empty_img" />
<text class="empty_text">暂无商品数据</text> <text class="empty_text">暂无商品数据</text>
</view> </view>
@@ -136,166 +162,32 @@
<script> <script>
import { getCascadeCategory } from "@/api/common.js"; import { getCascadeCategory } from "@/api/common.js";
import { searchList } from "@/api/product.js";
import CustomTabBar from "@/components/custom-tab-bar.vue"; import CustomTabBar from "@/components/custom-tab-bar.vue";
import TopSafe from "@/components/common/top-safe.nvue"; import TopSafe from "@/components/common/top-safe.nvue";
// 假数据列表:当后端接口未就绪时自动提供高保真模拟数据
const MOCK_CATEGORIES = [
{
id: 101,
name: '有机食品',
icon: 'https://static.tbmall.xin/static/new-home/xinren.png',
foods: [
{
id: 1001,
name: '鲜8有机贝贝南瓜2500g粉糯板栗味自然生长不催熟',
title: '鲜8有机贝贝南瓜2500g粉糯板栗味自然生长不催熟',
price: '39.00',
sales: 888,
tags: ['专业检测', '生态有机'],
image: 'https://static.tbmall.xin/static/new-home/nangua.png'
},
{
id: 1002,
name: '采缇国产车厘子5kg4j大连美早樱桃生鲜次日达樱桃',
title: '采缇国产车厘子5kg4j大连美早樱桃生鲜次日达樱桃',
price: '26.99',
sales: 888,
tags: ['专业检测', '生态有机'],
image: 'https://static.tbmall.xin/static/new-home/baokuan.png'
},
{
id: 1003,
name: '江苏白凤水蜜桃 应季水果 &新鲜礼盒装',
title: '江苏白凤水蜜桃 应季水果 &新鲜礼盒装',
price: '34.88',
sales: 888,
tags: ['专业检测', '生态有机'],
image: 'https://static.tbmall.xin/static/new-home/cart.png'
},
{
id: 1004,
name: '季新鲜 &进口山竹时令 &老树麻竹整箱送礼',
title: '季新鲜 &进口山竹时令 &老树麻竹整箱送礼',
price: '52.00',
sales: 888,
tags: ['专业检测', '生态有机'],
image: 'https://static.tbmall.xin/static/new-home/huiyuan.png'
}
]
},
{
id: 102,
name: '生鲜食材',
icon: 'https://static.tbmall.xin/static/new-home/baokuan.png',
foods: [
{
id: 1005,
name: '精选新鲜三文鱼中段切片 200g刺身级',
title: '精选新鲜三文鱼中段切片 200g刺身级',
price: '59.90',
sales: 1200,
tags: ['冷链速达', '产地直供'],
image: 'https://static.tbmall.xin/static/new-home/baokuan.png'
},
{
id: 1006,
name: '澳洲进口谷饲安格斯原切雪花牛肉卷 500g',
title: '澳洲进口谷饲安格斯原切雪花牛肉卷 500g',
price: '89.00',
sales: 650,
tags: ['原切牛肉', '品质严选'],
image: 'https://static.tbmall.xin/static/new-home/cart.png'
}
]
},
{
id: 103,
name: '米面粮油',
icon: 'https://static.tbmall.xin/static/new-home/cart.png',
foods: [
{
id: 1007,
name: '五常大米 优质长粒香米 5kg真空包装',
title: '五常大米 优质长粒香米 5kg真空包装',
price: '49.90',
sales: 3400,
tags: ['核心产区', '自然醇香'],
image: 'https://static.tbmall.xin/static/new-home/xinren.png'
}
]
},
{
id: 104,
name: '零食饮料',
icon: 'https://static.tbmall.xin/static/new-home/huiyuan.png',
foods: [
{
id: 1008,
name: '花生造黑松露黑麦苏打饼干 590g*2盒',
title: '花生造黑松露黑麦苏打饼干 590g*2盒',
price: '29.90',
sales: 2300,
tags: ['零反式脂肪酸', '拒绝油炸'],
image: 'https://static.tbmall.xin/static/new-home/huiyuan.png'
}
]
},
{
id: 105,
name: '滋补养生',
icon: 'https://static.tbmall.xin/static/new-home/xinren.png',
foods: [
{
id: 1009,
name: '青海野生黑枸杞干果 250g特级罐装',
title: '青海野生黑枸杞干果 250g特级罐装',
price: '78.00',
sales: 510,
tags: ['正宗原产', '花青素丰富'],
image: 'https://static.tbmall.xin/static/new-home/nangua.png'
}
]
},
{
id: 106,
name: '非遗传承',
icon: 'https://static.tbmall.xin/static/new-home/baokuan.png',
foods: []
},
{
id: 107,
name: '家居百货',
icon: 'https://static.tbmall.xin/static/new-home/cart.png',
foods: []
},
{
id: 108,
name: '美妆护肤',
icon: 'https://static.tbmall.xin/static/new-home/huiyuan.png',
foods: []
},
{
id: 109,
name: '其他特色',
icon: 'https://static.tbmall.xin/static/new-home/xinren.png',
foods: []
}
];
export default { export default {
components: { CustomTabBar, TopSafe }, components: { CustomTabBar, TopSafe },
data() { data() {
return { return {
platformType: true, platformType: true,
currentCategoryIndex: 0, categoryList: [], // 一级分类列表 (parentId = 0)
currentCategoryIndex: 0, // 当前选中的一级分类索引
subCategoryList: [], // 二级分类列表 (parentId = 一级ID)
currentSubCategoryIndex: 0, // 当前选中的二级分类索引
displayProducts: [], // 三级商品列表 (goods/searchList)
showAllCategories: false, showAllCategories: false,
sortType: 'default', // default | sales | price sortBy: 'relevance', // 'relevance' | 'sales' | 'price'
sortAsc: true, sortOrder: 'asc', // 'asc' | 'desc'
categoryList: [],
capsuleTop: 0, capsuleTop: 0,
defaultIcon: 'https://static.tbmall.xin/static/new-home/xinren.png', defaultIcon: 'https://static.tbmall.xin/static/new-home/xinren.png',
defaultProductImg: 'https://static.tbmall.xin/static/new-home/nangua.png' defaultProductImg: 'https://static.tbmall.xin/static/new-home/nangua.png',
isFromSortShop: false,
loading: false,
loadingMore: false,
noMore: false,
page: 1,
pageSize: 10
}; };
}, },
computed: { computed: {
@@ -311,22 +203,8 @@ export default {
currentCategory() { currentCategory() {
return this.categoryList[this.currentCategoryIndex] || null; return this.categoryList[this.currentCategoryIndex] || null;
}, },
displayProducts() { currentSubCategory() {
if (!this.currentCategory) return []; return this.subCategoryList[this.currentSubCategoryIndex] || null;
let list = this.currentCategory.foods || this.currentCategory.productList || [];
if (!list || list.length === 0) return [];
list = [...list];
if (this.sortType === 'sales') {
list.sort((a, b) => (Number(b.sales) || 0) - (Number(a.sales) || 0));
} else if (this.sortType === 'price') {
if (this.sortAsc) {
list.sort((a, b) => (Number(a.price) || 0) - (Number(b.price) || 0));
} else {
list.sort((a, b) => (Number(b.price) || 0) - (Number(a.price) || 0));
}
}
return list;
} }
}, },
onShow() { onShow() {
@@ -342,42 +220,207 @@ export default {
if (menu && menu.bottom) { if (menu && menu.bottom) {
this.capsuleTop = menu.bottom + 6; this.capsuleTop = menu.bottom + 6;
} }
} catch (e) {} } catch (e) { }
/*#endif*/ /*#endif*/
this.fetchCategories(); const isBackFromSortShop = this.isFromSortShop;
this.isFromSortShop = false;
this.fetchCategories(isBackFromSortShop);
}, },
methods: { methods: {
async fetchCategories() { // 异步查询级联分类接口 (common/getCascadeCategory)
async getCategoryApi(pId) {
try { try {
const resp = await getCascadeCategory({ parentId: 0 }); const resp = await getCascadeCategory({ parentId: pId });
if (resp && resp.bizcode === 100 && resp.data && resp.data.length > 0) { if (resp && resp.bizcode === 100 && Array.isArray(resp.data)) {
this.categoryList = resp.data; return resp.data;
} else {
this.categoryList = MOCK_CATEGORIES;
} }
} catch (e) { } catch (e) {
console.log("使用模拟分类数据", e); console.error("getCascadeCategory error:", e);
this.categoryList = MOCK_CATEGORIES;
} }
return [];
}, },
selectCategory(index, closePopup = false) {
// 1. 刚进来获取一级分类 (parentId = 0)
async fetchCategories(isBack = false) {
try {
const topList = await this.getCategoryApi(0);
this.categoryList = topList || [];
} catch (e) {
console.error("获取一级分类失败:", e);
this.categoryList = [];
}
if (this.categoryList.length === 0) {
this.subCategoryList = [];
this.displayProducts = [];
return;
}
let targetIndex = 0;
if (isBack) {
const sortId = uni.getStorageSync("sortId");
if (sortId) {
let idx = this.categoryList.findIndex(item => item.id === sortId);
if (idx !== -1) targetIndex = idx;
else if (this.currentCategoryIndex >= 0 && this.currentCategoryIndex < this.categoryList.length) {
targetIndex = this.currentCategoryIndex;
}
}
} else {
uni.removeStorageSync("sortId");
uni.removeStorageSync("subSortId");
targetIndex = 0;
}
this.selectCategory(targetIndex, false, isBack);
},
// 2. 选择一级分类,根据其 id 获取二级分类 (parentId = 该一级id)
async selectCategory(index, closePopup = false, isBack = false) {
this.currentCategoryIndex = index; this.currentCategoryIndex = index;
if (closePopup) { if (closePopup) {
this.showAllCategories = false; this.showAllCategories = false;
} }
const category = this.categoryList[index];
if (!category || !category.id) {
this.subCategoryList = [];
this.displayProducts = [];
return;
}
uni.setStorageSync("sortId", category.id);
this.loading = true;
try {
const subList = await this.getCategoryApi(category.id);
this.subCategoryList = subList || [];
if (this.subCategoryList.length === 0) {
this.displayProducts = [];
this.loading = false;
return;
}
let targetSubIndex = 0;
if (isBack) {
const subSortId = uni.getStorageSync("subSortId");
if (subSortId) {
let sIdx = this.subCategoryList.findIndex(item => item.id === subSortId);
if (sIdx !== -1) targetSubIndex = sIdx;
}
}
this.selectSubCategory(targetSubIndex);
} catch (e) {
console.error("获取二级分类失败:", e);
this.subCategoryList = [];
this.displayProducts = [];
this.loading = false;
}
}, },
// 3. 选择二级分类,更新当前二级分类并调用 goods/searchList 获取商品列表
selectSubCategory(subIndex) {
this.currentSubCategoryIndex = subIndex;
const subCat = this.subCategoryList[subIndex];
if (subCat && subCat.id) {
uni.setStorageSync("subSortId", subCat.id);
}
this.fetchGoodsList(false);
},
// 4. 调用 /goods/searchList 接口获取商品列表 (支持分页与排序)
async fetchGoodsList(isLoadMore = false) {
const currentSubCat = this.subCategoryList[this.currentSubCategoryIndex];
if (!currentSubCat || !currentSubCat.id) {
this.displayProducts = [];
this.loading = false;
this.loadingMore = false;
return;
}
if (isLoadMore) {
if (this.loadingMore || this.noMore) return;
this.loadingMore = true;
this.page++;
} else {
this.loading = true;
this.page = 1;
this.noMore = false;
}
const params = {
categoryId: currentSubCat.id,
page: this.page,
pageSize: this.pageSize,
sortBy: this.sortBy,
sortOrder: this.sortOrder
};
try {
const resp = await searchList(params);
if (resp && resp.bizcode === 100) {
let list = [];
if (Array.isArray(resp.data)) {
list = resp.data;
} else if (resp.data && Array.isArray(resp.data.entitys)) {
list = resp.data.entitys;
} else if (resp.data && Array.isArray(resp.data.list)) {
list = resp.data.list;
}
if (isLoadMore) {
this.displayProducts = [...this.displayProducts, ...list];
} else {
this.displayProducts = list;
}
if (list.length < this.pageSize) {
this.noMore = true;
}
} else {
if (!isLoadMore) {
this.displayProducts = [];
}
this.noMore = true;
}
} catch (e) {
console.error("searchList error:", e);
if (!isLoadMore) {
this.displayProducts = [];
}
} finally {
this.loading = false;
this.loadingMore = false;
}
},
// 5. 右侧商品列表触底触发分页加载
onReachBottomGoods() {
if (!this.noMore && !this.loadingMore && !this.loading) {
this.fetchGoodsList(true);
}
},
toggleAllCategories() { toggleAllCategories() {
this.showAllCategories = !this.showAllCategories; this.showAllCategories = !this.showAllCategories;
}, },
// 6. 排序作用于 goods/searchList 接口
setSort(type) { setSort(type) {
if (this.sortType === type && type === 'price') { if (this.sortBy === type) {
this.sortAsc = !this.sortAsc; this.sortOrder = this.sortOrder === 'asc' ? 'desc' : 'asc';
} else { } else {
this.sortType = type; this.sortBy = type;
this.sortAsc = true; this.sortOrder = 'asc';
} }
this.fetchGoodsList(false);
}, },
limit999(n) { limit999(n) {
const num = Number(n); const num = Number(n);
if (isNaN(num) || num < 10000) { if (isNaN(num) || num < 10000) {
@@ -385,12 +428,15 @@ export default {
} }
return `${Math.floor(num / 10000)}万+`; return `${Math.floor(num / 10000)}万+`;
}, },
jumpSearch() { jumpSearch() {
uni.navigateTo({ uni.navigateTo({
url: "/pages/rwa_package/insights/search", url: "/pages/rwa_package/insights/search",
}); });
}, },
jumpInfo(item) { jumpInfo(item) {
this.isFromSortShop = true;
uni.navigateTo({ uni.navigateTo({
url: `/pages/rwa_package/shop/sort-shop?id=${item.id}&name=${encodeURIComponent(item.name || item.title || '')}`, url: `/pages/rwa_package/shop/sort-shop?id=${item.id}&name=${encodeURIComponent(item.name || item.title || '')}`,
}); });
@@ -422,9 +468,12 @@ page {
.top_fixed_header { .top_fixed_header {
position: relative; position: relative;
z-index: 100; z-index: 100;
background: #ffffff; background: linear-gradient(180deg, #F2EBFF 0%, #FFFFFF 100%);
border-bottom-left-radius: 36rpx;
border-bottom-right-radius: 36rpx;
overflow: hidden;
flex-shrink: 0; flex-shrink: 0;
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.03); box-shadow: none;
transition: all 0.2s; transition: all 0.2s;
&.is_expanded { &.is_expanded {
@@ -693,7 +742,7 @@ page {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
border-bottom: 1rpx solid #f5f5f5; border-bottom: none;
flex-shrink: 0; flex-shrink: 0;
.cat_title_text { .cat_title_text {
@@ -712,15 +761,24 @@ page {
color: #999999; color: #999999;
display: flex; display: flex;
align-items: center; align-items: center;
cursor: pointer;
&.active { &.active {
color: #7a35f6; color: #7a35f6;
font-weight: bold; font-weight: bold;
} }
.sort_arrow { .sort_icon_box {
font-size: 20rpx; display: flex;
margin-left: 4rpx; flex-direction: column;
align-items: center;
justify-content: center;
margin-left: 6rpx;
line-height: 1;
.icon_up {
margin-bottom: 2rpx;
}
} }
} }
} }
@@ -853,5 +911,12 @@ page {
margin-top: 20rpx; margin-top: 20rpx;
} }
} }
.load_more_tips {
text-align: center;
font-size: 24rpx;
color: #999999;
padding: 24rpx 0;
}
} }
</style> </style>