1523 lines
49 KiB
Vue
Raw Normal View History

2025-03-20 13:59:39 +08:00
<template>
<z-paging
ref="paging"
v-model="dataList"
:refresher-enabled="false"
:hide-no-more-inside="true"
:paging-style="{'top': '0','background': '#f2f3f7'}"
empty-view-text="没有找到对应商品,看看别的吧"
empty-view-img="/static/empty-img/order-empty.png"
@query="onGetDataList"
>
<view class="Mall4j page-search-list">
<!-- 搜索框 -->
<view
class="search-top"
:class="{'search-frame-fixed':searchType===2}"
>
<view
class="search-box"
@tap="onToSearchPage(1)"
>
<view class="icon">
<image src="/static/images/search.png" />
</view>
<div
v-if="showKeyword"
class="key-tag"
>
<span class="text">{{ showKeyword }}</span>
<span
class="close"
@tap.stop="onToSearchPage(0)"
>x</span>
</div>
<div
v-if="!showKeyword"
class="text"
>
输入关键字搜索
</div>
</view>
<view
v-if="searchType!==2"
class="list-style"
@tap="onChangeListStyle"
>
<image :src="isLineProds ? '/static/images/list-line.png' : '/static/images/list-row.png'" />
</view>
</view>
<!-- 商品头部店铺 -->
<view
v-if="(state!==3 && shopInfo && isFixedHead === false)"
class="head-shop-info"
>
<view class="shop-info-box">
<view class="con">
<view class="logo">
<image
:src="shopInfo.shopLogo ? util.addDomain(shopInfo.shopLogo) : defaultShopLogo"
@error="shopInfo.shopLogo=''"
/>
</view>
<view class="text">
<view
class="name"
style="padding-right:20rpx"
>
{{ shopInfo.shopName }}
</view>
<view class="focus-box">
<view
v-if="shopInfo.type===1"
class="self"
>
自营
</view>
<view class="focus">
关注人数{{ wxs.parseCollectionNumber(shopInfo.collectionNum) }}
</view>
</view>
</view>
<view
class="btn"
@tap="onToShopPage(shopInfo.shopId)"
>
进店
</view>
</view>
</view>
</view>
<!-- 排序栏 -->
<view
v-if="searchType!==2"
class="sortbar"
>
<view
class="item"
:class="{active:state===0}"
@tap="onSwitchSearchList(0)"
>
默认
</view>
<view
class="item"
:class="{active:state===1, 'arrow-up':sort===2, 'arrow-down':sort===3}"
@tap="onSwitchSearchList(1)"
>
销量
</view>
<view
class="item"
:class="{active:state===2, 'arrow-up':sort===4, 'arrow-down':sort===5}"
@tap="onSwitchSearchList(2)"
>
价格
</view>
</view>
<!-- 筛选栏 -->
<view
v-if="((brandList && brandList.length) || (categoryList && categoryList.length) || (attrList && attrList.length)) && state!==3"
class="screen-column"
>
<view class="sc-tab">
<scroll-view
scroll-x="true"
class="sc-wrap"
>
<!-- 品牌 -->
<view
class="item"
:class="{'active-item':(openWhichConditionItem.type === 0)}"
>
<view
v-if="brandList && brandList.length"
class="item-box"
:class="{'active-item-box': onShowBrandConditonText() && selectedBrandItem && openWhichConditionItem.type!==0}"
@tap="onOpenScreenCondition(0)"
>
<text class="text">
{{ onShowBrandConditonText() || '品牌' }}
</text>
</view>
</view>
<!-- 分类 -->
<view
class="item"
:class="{'active-item':(openWhichConditionItem.type === 1)}"
>
<view
v-if="categoryList && categoryList.length"
class="item-box"
:class="{'active-item-box':onShowCategoryConditionText() && selectedCategoryItem && openWhichConditionItem.type!==1}"
@tap="onOpenScreenCondition(1)"
>
<text class="text">
{{ onShowCategoryConditionText() || '类别' }}
</text>
</view>
</view>
<!-- 属性 -->
<view
v-for="(item, index) in attrList"
:key="index"
class="item"
:class="{'active-item':(openWhichConditionItem.type === 2 && openWhichConditionItem.attrIndex === index)}"
>
<view
class="item-box"
:class="{'active-item-box':item.isActive && openWhichConditionItem.attrIndex !== index}"
@tap="onOpenScreenCondition(2, index)"
>
<text class="text">
{{ onShowAttrConditionText(index) }}
</text>
</view>
</view>
</scroll-view>
<view
class="filter-btn"
@tap="onOpenAllScreenFrame"
>
筛选<image
class="screen-icon"
src="/static/images/screen.png"
/>
</view>
</view>
<!-- 筛选条件展开框 -->
<view
v-if="openWhichConditionItem.type !== ''"
class="sc-options"
>
<view class="opt-content">
<view
v-for="(item, index) in openConditionList"
:key="index"
class="o-item"
@tap="onSelectOrCancelCondition(index)"
>
<image
v-if="item.isSelected"
class="selected-item"
src="/static/images/seleced-item.png"
/>
<text>{{ item.brandName || item.name || item.attrValueName }}</text>
</view>
</view>
<view class="opt-btns">
<view class="btn-box">
<view
class="reset-btn btn"
@tap="onResetScreenCondition()"
>
重置
</view>
</view>
<view class="btn-box">
<view
class="confirm-btn btn"
@tap="onConfirmScreenCondition()"
>
确定
</view>
</view>
</view>
</view>
</view>
<!-- 遮蔽层 -->
<view
v-if="(openWhichConditionItem.type !== '') || (isOpenAllScreenFrame)"
class="filter-mask"
@tap="onCloseScreenCondition()"
/>
<!-- 所有筛选项的框 -->
<view
class="all-screen-frame"
:class="{'show':isOpenAllScreenFrame}"
>
<view class="condition-info">
<view class="first-part part">
<view class="server-or-discount">
<view class="title">
服务/折扣
</view>
<view class="content">
<view
class="c-item"
:class="{'active-c-item':isSelfShop}"
@tap="onSelectScreenCondition(3)"
>
商城自营
</view>
<view
class="c-item"
:class="{'active-c-item':isHasStock}"
@tap="onSelectScreenCondition(4)"
>
仅看有货
</view>
</view>
</view>
<view class="price-range">
<view class="title">
价格区间
</view>
<view class="price-box">
<view class="min-price price-frame">
<input
v-model="minPriceInp"
type="number"
placeholder="最低价"
@input="onLimitPriceRange('min')"
>
</view>
<view class="line">
-
</view>
<view class="max-price price-frame">
<input
v-model="maxPriceInp"
type="number"
placeholder="最高价"
@input="onLimitPriceRange('max')"
>
</view>
</view>
</view>
</view>
<view class="second-part part">
<view
v-if="otherBrandList && otherBrandList.length"
class="brand-item"
>
<view class="title">
品牌
</view>
<view class="content">
<view
v-for="(item, index) in otherBrandList"
:key="index"
class="c-item"
:class="{'active-c-item':item.isSelected}"
@tap="onSelectScreenCondition(0, index)"
>
{{ item.brandName }}
</view>
</view>
</view>
<view class="category-item">
<view class="title">
类别
</view>
<view class="content">
<view
v-for="(item, index) in otherCategoryList"
:key="index"
class="c-item"
:class="{'active-c-item':item.isSelected}"
@tap="onSelectScreenCondition(1, index)"
>
{{ item.name }}
</view>
</view>
</view>
</view>
<view class="third-part part">
<view
v-for="(attrItem, attrIndex) in otherAttrList"
:key="attrIndex"
class="attr-item"
>
<block>
<view class="title">
{{ attrItem.attrName }}
</view>
<view class="content">
<view
v-for="(attrValueItem, attrValueIndex) in attrItem.attrValues"
:key="attrValueIndex"
class="c-item"
:class="{'active-c-item':attrValueItem.isSelected}"
@tap="onSelectScreenCondition(2, attrIndex, attrValueIndex)"
>
{{ attrValueItem.attrValueName }}
</view>
</view>
</block>
</view>
</view>
</view>
<view class="asf-btns">
<view class="btn-box">
<view
class="reset-btn btn"
@tap="onResetAllScreenCondition"
>
重置
</view>
</view>
<view class="btn-box">
<view
class="confirm-btn btn"
@tap="onConfirmAllScreenCondition"
>
确定
</view>
</view>
</view>
</view>
<!-- 商品列表 -->
<view
v-if="searchType!==2 && dataList.length > 0"
:class="[isLineProds ? 'line-prods' : 'prods']"
:style="{'margin-top':((isFixedHead || openWhichConditionItem.type || openWhichConditionItem.type===0) ? '10px' : isLineProds ? '10px' : '0')}"
>
<block v-if="isLineProds">
<block
v-for="(prodItem, prodIndex) in dataList"
:key="prodIndex"
>
<view
class="item"
@tap="onToProdDetailPage(prodItem.spuId)"
>
<view class="img">
<img-show :src="prodItem.mainImgUrl" />
</view>
<view class="text-box">
<view class="name">
{{ prodItem.spuName }}
</view>
<view
v-if="prodItem.sellingPoint"
class="sku"
>
{{ prodItem.sellingPoint }}
</view>
<view class="discount-box">
<view v-if="prodItem.shopType===1">
<view class="discount">
自营
</view>
</view>
<view
v-if="prodItem.spuActivity"
style="display: inline-block;"
>
<view v-if="prodItem.spuActivity.groupActivity">
<view class="discount">
{{ prodItem.spuActivity.groupActivity.groupNumber }}人团
</view>
</view>
</view>
<view
v-if="prodItem.spuActivity"
style="display: inline-block;"
>
<view v-if="prodItem.spuActivity.sekillActivitySpuVO">
<view class="discount">
秒杀
</view>
</view>
</view>
<view
v-if="prodItem.spuActivity"
style="display: inline-block;"
>
<view v-if="prodItem.spuActivity.discountList">
<view
v-for="(item, index) in prodItem.spuActivity.discountList.slice(0, 1)"
:key="index"
class="discount"
>
{{ onDiscountTagText(prodItem.spuActivity.discountList) }}
</view>
</view>
</view>
<view
v-if="prodItem.spuActivity"
style="display: inline-block;"
>
<view v-if="prodItem.spuActivity.couponList">
<view
v-for="(item, index) in prodItem.spuActivity.couponList.slice(0, 1)"
:key="index"
class="coupons"
>
{{ onCouponTagText(prodItem.spuActivity.couponList[0]) }}
</view>
</view>
</view>
</view>
<view class="price-box">
<view class="price">
<view class="symbol">
</view>
<view class="big">
{{ wxs.parsePrice(prodItem.priceFee)[0] }}
</view>
<view class="symbol">
.{{ wxs.parsePrice(prodItem.priceFee)[1] }}
</view>
<view
v-if="prodItem.saleNum || prodItem.saleNum === 0"
class="symbol sold-num"
>
销量 {{ prodItem.saleNum }}
</view>
</view>
</view>
</view>
</view>
</block>
</block>
<block v-if="!isLineProds">
<view
v-for="(val,idx) in getColProdList"
:key="idx"
class="col"
>
<block
v-for="(prodItem, prodIndex) in val"
:key="prodIndex"
>
<view
class="item"
@tap="onToProdDetailPage(prodItem.spuId)"
>
<view class="img">
<img-show :src="prodItem.mainImgUrl" />
</view>
<view class="text-box">
<view class="name">
{{ prodItem.spuName }}
</view>
<view
v-if="prodItem.sellingPoint"
class="sku"
>
{{ prodItem.sellingPoint }}
</view>
<view class="discount-box">
<view v-if="prodItem.shopType===1">
<view class="discount">
自营
</view>
</view>
<view
v-if="prodItem.spuActivity"
style="display: inline-block;"
>
<view v-if="prodItem.spuActivity.groupActivity">
<view class="discount">
{{ prodItem.spuActivity.groupActivity.groupNumber }}人团
</view>
</view>
</view>
<view
v-if="prodItem.spuActivity"
style="display: inline-block;"
>
<view v-if="prodItem.spuActivity.sekillActivitySpuVO">
<view class="discount">
秒杀
</view>
</view>
</view>
<view
v-if="prodItem.spuActivity"
style="display: inline-block;"
>
<view v-if="prodItem.spuActivity.discountList">
<view
v-for="(item, index) in prodItem.spuActivity.discountList.slice(0, 1)"
:key="index"
class="discount"
>
{{ onDiscountTagText(prodItem.spuActivity.discountList) }}
</view>
</view>
</view>
<view
v-if="prodItem.spuActivity"
style="display: inline-block;"
>
<view v-if="prodItem.spuActivity.couponList">
<view
v-for="(item, index) in prodItem.spuActivity.couponList.slice(0, 1)"
:key="index"
class="coupons"
>
{{ onCouponTagText(prodItem.spuActivity.couponList[0]) }}
</view>
</view>
</view>
</view>
<view class="price-box">
<view class="price">
<view class="symbol">
</view>
<view class="big">
{{ wxs.parsePrice(prodItem.priceFee)[0] }}
</view>
<view class="symbol">
.{{ wxs.parsePrice(prodItem.priceFee)[1] }}
</view>
<view
v-if="prodItem.saleNum || prodItem.saleNum === 0"
class="symbol sold-num"
>
销量 {{ prodItem.saleNum }}
</view>
</view>
</view>
</view>
</view>
</block>
</view>
</block>
</view>
<!-- 店铺列表 -->
<view
v-if="searchType===2 && dataList.length > 0"
class="shop-list"
>
<block
v-for="(item, index) in dataList"
:key="index"
>
<view class="item">
<view :class="[!item.spuList?'no-prod':'','shop-info']">
<view class="logo">
<image
:src="item.shopLogo ? util.addDomain(item.shopLogo) : defaultShopLogo"
@error="dataList[index].shopLogo=''"
/>
</view>
<view class="text">
<view class="name">
{{ item.shopName }}
</view>
<view class="focus-box">
<view
v-if="item.type===1"
class="self"
>
自营
</view>
<view class="focus">
关注人数{{ wxs.parseCollectionNumber(item.collectionNum) }}
</view>
</view>
</view>
<view
class="btn"
@tap="onToShopPage(item.shopId)"
>
进店
</view>
</view>
<view class="shop-prods">
<block v-if="item.spuList">
<block
v-for="(prodItem, prodIndex) in item.spuList.slice(0, 3)"
:key="prodIndex"
>
<view
class="p-item"
@tap="onToProdDetailPage(prodItem.spuId)"
>
<view class="img">
<img-show :src="prodItem.mainImgUrl" />
</view>
<view class="name">
{{ prodItem.spuName }}
</view>
<view class="price">
{{ wxs.parsePrice(prodItem.priceFee)[0] + '.' + wxs.parsePrice(prodItem.priceFee)[1] }}
</view>
</view>
</block>
</block>
</view>
</view>
</block>
</view>
</view>
</z-paging>
</template>
<script setup>
import defaultShopLogo from '@/static/images/default-shop-logo.png'
import util from '@/utils/util'
const wxs = number()
const isFixedHead = ref(false) // 头部是固定
const dataList = ref([]) // 商品列表/店铺列表
// 请求参数
const selfShop = ref('') // 商城是否自营
const hasStock = ref('') // 仅看有货
const minPrice = ref('') // 最小价格
const maxPrice = ref('') // 最大价格
const secondaryCategoryId = ref('') // 第二级分类ID
const categoryId = ref('') // 第三级分类ID
const sort = ref('') // 商品排序
const brandIds = ref('') // 品牌
const attrIds = ref('') // 属性
// 搜索类型
const searchType = ref(1) // 1:商品 2:店铺
// 价格
const minPriceInp = ref('')
const initMinPriceInp = ref('')
const maxPriceInp = ref('')
const initMaxPriceInp = ref('')
// 是否自营
const isSelfShop = ref(false)
const initSelfShop = ref(false)
// 仅看有货
const isHasStock = ref(false)
const initHasStock = ref(false)
// 品牌
const brandList = ref([]) // 品牌列表
const selectedBrandList = ref([]) // 选中品牌的列表
const selectedBrandItem = ref('') // 选中品牌字符串(链接里的参数格式)
const otherBrandList = ref([])
// 分类
const categoryName = ref('') // 链接传过来的值
const categoryList = ref([])
const selectedCategoryId = ref('') // 选中的id
const selectedCategoryItem = ref('') // 选中分类项(用来传递)
const otherCategoryList = ref([])
// 属性
const attrList = ref([])
const selectedAttrId = ref('') // 选中的属性id
const selectedAttrValueIdList = ref([]) // 选中的属性值id
const selectedAttrItem = ref('') // 选中的属性项
const otherAttrList = ref([])
const shopInfo = ref('') // 关键词搜索中的店铺信息
/**
* 生命周期函数--监听页面加载
* @param {Object} options 上一个页面传递的参数
*/
onLoad((options) => {
// 处理传递过来的参数
onHandleLinkParams(options)
})
const getColProdList = computed(() => {
const prodListValue = dataList.value
if (prodListValue && prodListValue.length) return [prodListValue.filter((val, idx) => idx % 2 === 0), prodListValue.filter((val, idx) => idx % 2 === 1)] // eslint-disable-line
return []
})
/**
* 处理传来的参数
* @param {Object} options 传递的参数
*/
const showKeyword = ref('') // 用来展示的关键词
const state = ref(0) // 0:商品 1:商品销量排序 2:商品价格排序 3:店铺
const keyword = ref('') // 关键词
const onHandleLinkParams = (options) => {
// 搜索类型
searchType.value = options.type ? Number(options.type) : 1
// 商城自营和仅看有货
selfShop.value = options.shop ? options.shop : ''
hasStock.value = options.stock ? options.stock : ''
isSelfShop.value = initSelfShop.value = !!options.shop
isHasStock.value = initHasStock.value = !!options.stock
// 价格
minPriceInp.value = initMinPriceInp.value = options.minPrice ? options.minPrice : ''
maxPriceInp.value = initMaxPriceInp.value = options.maxPrice ? options.maxPrice : ''
minPrice.value = options.minPrice ? util.accuracyCount(options.minPrice, 100, 2) : ''
maxPrice.value = options.maxPrice ? util.accuracyCount(options.maxPrice, 100, 2) : ''
// 品牌部分
brandIds.value = options.bids ? (options.bids).replace(/\|\|/g, ',') : '' // 请求参数
selectedBrandItem.value = options.bids ? options.bids : '' // 链接参数
selectedBrandList.value = options.bids ? options.bids.split('||') : [] // 选中的列表
// 分类部分
categoryName.value = options.cName ? options.cName : ''
secondaryCategoryId.value = options.cid2
categoryId.value = options.cid
selectedCategoryItem.value = selectedCategoryId.value = options.cid ? options.cid : ''
// 属性参数
attrIds.value = options.aids ? (options.aids).replace(/\|\|/g, ',') : '' // 请求参数
selectedAttrItem.value = options.aids ? options.aids : ''
// 关键词
let keywordValue = ''
// #ifndef MP-WEIXIN
keywordValue = options.keyword ? options.keyword : ''
// #endif
// #ifdef MP-WEIXIN
keywordValue = options.keyword ? decodeURIComponent(decodeURIComponent(options.keyword)) : ''
// #endif
// #ifdef APP-PLUS
keywordValue = options.keyword ? decodeURIComponent(options.keyword) : ''
// #endif
showKeyword.value = keywordValue
keyword.value = keywordValue
// 排序
sort.value = !(options.sort) ? '' : Number(options.sort)
if (!(options.sort)) {
state.value = 0
} else if (Number(options.sort) === 2 || Number(options.sort) === 3) {
state.value = 1
} else if (Number(options.sort) === 4 || Number(options.sort) === 5) {
state.value = 2
}
}
/**
* 获取商品列表
*/
// 展开哪项筛选条件
const openWhichConditionItem = reactive({
type: '',
attrIndex: ''
})
const isOpenAllScreenFrame = ref(false)
const onGetDataList = (pageNum, pageSize) => {
if (searchType.value !== 2) {
// 价格筛选输入框低于0.01,都按0.01的价格处理
const minPriceValue = (minPrice.value && minPrice.value < 1) ? 1 : minPrice.value
const maxPriceValue = (maxPrice.value && maxPrice.value < 1) ? 1 : maxPrice.value
if (secondaryCategoryId.value === 'undefined') {
secondaryCategoryId.value = ''
}
const params = {
2025-03-25 23:27:44 +08:00
url: '/tmerclub_search/ua/search/search_page',
2025-03-20 13:59:39 +08:00
method: 'GET',
data: {
pageSize,
pageNum,
keyword: keyword.value,
needActivity: 1,
selfShop: selfShop.value,
hasStock: hasStock.value,
minPrice: minPriceValue,
maxPrice: maxPriceValue,
sort: sort.value,
secondaryCategoryId: secondaryCategoryId.value || '',
categoryId: categoryId.value || '',
brandIds: brandIds.value,
attrIds: attrIds.value
}
}
http.request(params).then((res) => {
if (res.list[0]?.categorys[0]?.categoryId || categoryId.value) {
onHandlePordReturnResult(res)
} else {
paging.value.complete(res.list[0].spus)
}
isOpenAllScreenFrame.value = false
openWhichConditionItem.type = ''
})
} else {
const params = {
2025-04-13 23:40:58 +08:00
url: '/tmerclub_admin/ua/shop_detail/page',
2025-03-20 13:59:39 +08:00
method: 'get',
data: {
pageNum,
pageSize,
shopName: keyword.value,
spuNum: 3
}
}
http.request(params).then(res => {
paging.value.complete(res.list)
})
}
}
/**
* 处理商品搜索接口返回的结果
* @param {Object} res 商品搜索接口返回结果
*/
const paging = ref(null)
const onHandlePordReturnResult = (res) => {
const params = {
2025-03-25 23:27:44 +08:00
url: '/tmerclub_product/ua/category/category_search_item',
2025-03-20 13:59:39 +08:00
method: 'get',
data: {
categoryId: res.list && (res.list[0]?.categorys[0]?.categoryId) ? res.list[0]?.categorys[0]?.categoryId : categoryId.value
}
}
http.request(params).then(({ categoryVO }) => {
// 品牌列表
if (res.list) {
res.list[0].brands.forEach((item) => {
item.isSelected = false
})
brandList.value = res.list[0].brands
// 找出数组相同项(需优化,如果几千个品牌和选中了多个品牌项,会占不少的速度)
if (selectedBrandItem.value) {
const selectedBrandItemList = selectedBrandItem.value.split('||')
// 使用该方式赋值,不是直接赋值对象的地址,而是赋值对象的值,从而不会出现新旧对象的值同时改变
brandList.value.forEach((brandItem) => {
selectedBrandItemList.forEach((idItem) => {
if (brandItem.brandId === Number(idItem)) {
brandItem.isSelected = true
}
})
})
}
// 属性列表
res.list[0].attrs.forEach((attrItem) => {
attrItem.isActive = false
attrItem.attrValues.forEach((attrValueItem) => {
attrValueItem.isSelected = false
})
})
attrList.value = res.list[0].attrs
// 处理链接里得属性参数, 用来回显 格式attrId1_attrValueId1||attrValueId2^attrId2_attrValueId1
if (selectedAttrItem.value) {
const attrItemArr = selectedAttrItem.value.split('^')
attrList.value.forEach(attrItem => {
attrItemArr.forEach((attrStrItem) => {
if (Number(attrItem.attrId) === Number(attrStrItem.split('_')[0])) {
const attrValueArr = attrStrItem.split('_')[1].split('||')
attrItem.isActive = true
attrItem.attrValues.forEach((attrValueItem) => {
attrValueArr.forEach((attrValueId) => {
if (Number(attrValueItem.attrValueId) === Number(attrValueId)) {
attrValueItem.isSelected = true
selectedAttrValueIdList.value.push(attrValueItem.attrValueId)
}
})
})
}
})
})
}
shopInfo.value = res.list[0].shopInfo
paging.value.complete(res.list[0].spus)
} else {
paging.value.complete([])
brandList.value = []
attrList.value = []
shopInfo.value = ''
}
// 分类列表
categoryVO.forEach((item) => {
item.isSelected = false
})
categoryList.value = categoryVO
// 回显
categoryList.value.forEach((item) => {
if (item.categoryId == selectedCategoryItem.value) {
item.isSelected = true
}
})
})
}
// 展示品牌筛选条件的文字
const onShowBrandConditonText = () => {
let result = ''
if (selectedBrandItem.value === '') {
result = '品牌'
} else {
// 这里有个问题,触发了两遍
const selectedBrandItemList = selectedBrandItem.value.split('||')
const brandListValue = brandList.value
// 筛选出两个数组相同的元素
const showBrandList = brandListValue.filter(function (n) {
return selectedBrandItemList.indexOf((n.brandId + '')) != -1
})
showBrandList.forEach((item, index, list) => {
if ((index + 1) < list.length) {
result += item.brandName + ','
} else {
result += item.brandName
}
})
}
return result
}
// 展示分类筛选条件的文字
const onShowCategoryConditionText = () => {
let result = ''
if (selectedCategoryItem.value === '') {
result = '类别'
} else {
const selectedCategoryItemValue = selectedCategoryItem.value
const categoryListValue = categoryList.value
for (let i = 0; i < categoryListValue.length; i++) {
if (Number(categoryListValue[i].categoryId) === Number(selectedCategoryItemValue)) {
result = categoryListValue[i].name
break
}
}
result = result || categoryName.value
}
return result
}
// 展示属性筛选条件的文字
const onShowAttrConditionText = (index) => {
let result = ''
const isActive = attrList.value[index].isActive
if (isActive) {
attrList.value[index].attrValues.forEach((item) => {
if (item.isSelected === true) {
result += item.attrValueName + ','
}
})
result = result.slice(0, result.length - 1)
} else {
result = attrList.value[index].attrName
}
return result
}
/**
* 满减折标签文字
* @param {Number} discountRule 0 满钱减钱 3满件打折
*/
const onDiscountTagText = (discountRule) => {
if (discountRule.length === 0) return
const dis = discountRule[0].discountRule
let result = ''
if (dis === 0) {
result = '满减钱'
} else if (dis === 3) {
result = '满件折'
}
return result
}
/**
* 优惠券标签文字
* @param {Object} couponInfo 优惠券信息
*/
const onCouponTagText = (couponInfo) => {
if (!couponInfo) return ''
let result = ''
// couponType 1:代金券 2:折扣券 3:兑换券(目前没有)
const couponType = couponInfo.couponType
const cashCondition = couponInfo.cashCondition
const reduceAmount = couponInfo.reduceAmount
const couponDiscount = couponInfo.couponDiscount
if (couponType === 1) {
result = '满' + ((cashCondition / 100).toFixed(2)) + '元减' + ((reduceAmount / 100).toFixed(2))
} else if (couponType === 2) {
result = '满' + ((cashCondition / 100).toFixed(2)) + '元打' + couponDiscount + '折'
}
return result
}
/**
* 展开搜索筛选条件
* @param {Number} index 0:品牌 1:分类 2:属性
* @param {Number} attrIndex 属性索引
*/
// 展开项的列表
const openConditionList = ref([])
const onOpenScreenCondition = (index, attrIndex) => {
if ((openWhichConditionItem.type === index && index !== 2) || (index === 2 && openWhichConditionItem.attrIndex === attrIndex)) {
// 收起
onCloseScreenCondition()
} else {
// 展开
onInitScreenConditionState()
openWhichConditionItem.type = index
if (index === 0) {
openWhichConditionItem.attrIndex = ''
openConditionList.value = JSON.parse(JSON.stringify(brandList.value))
selectedBrandList.value = selectedBrandItem.value ? selectedBrandItem.value.split('||') : []
} else if (index === 1) {
openWhichConditionItem.attrIndex = ''
openConditionList.value = JSON.parse(JSON.stringify(categoryList.value))
} else if (index === 2) {
openWhichConditionItem.attrIndex = attrIndex
openConditionList.value = JSON.parse(JSON.stringify(attrList.value[attrIndex].attrValues))
selectedAttrId.value = attrList.value[attrIndex].attrId
const tempSelectedAttrValueIdList = []
// 把回显的属性id加入selectAttrValueIdList
for (let i = 0; i < openConditionList.value.length; i++) {
if (openConditionList.value[i].isSelected === true) {
tempSelectedAttrValueIdList.push(openConditionList.value[i].attrValueId)
}
}
selectedAttrValueIdList.value = tempSelectedAttrValueIdList
}
}
}
// 选择/取消筛选条件
const onSelectOrCancelCondition = (index) => {
// type 0:品牌 1:分类 2:属性
const type = openWhichConditionItem.type
switch (type) {
case 0: {
const selectedBrandId = openConditionList.value[index].brandId
openConditionList.value[index].isSelected = !openConditionList.value[index].isSelected
if (openConditionList.value[index].isSelected === true) {
selectedBrandList.value.push(selectedBrandId)
} else {
for (let i = 0; i < selectedBrandList.value.length; i++) {
if (Number(selectedBrandList.value[i]) === Number(selectedBrandId)) {
selectedBrandList.value.splice(i, 1)
return
}
}
}
break
}
case 1:{
if (openConditionList.value[index].isSelected) {
openConditionList.value[index].isSelected = false
categoryList.value[index].isSelected = false
selectedCategoryId.value = ''
return
}
openConditionList.value.forEach((item) => {
item.isSelected = false
})
const selectedCategoryIdValue = openConditionList.value[index].categoryId
selectedCategoryId.value = selectedCategoryIdValue
openConditionList.value[index].isSelected = !openConditionList.value[index].isSelected
categoryList.value = openConditionList.value
break
}
case 2: {
const attrValueId = openConditionList.value[index].attrValueId
openConditionList.value[index].isSelected = !openConditionList.value[index].isSelected
// 选中或取消选中属性值
if (openConditionList.value[index].isSelected) {
selectedAttrValueIdList.value.push(attrValueId)
} else {
for (const i in selectedAttrValueIdList.value) {
if (selectedAttrValueIdList.value[i] === attrValueId) {
selectedAttrValueIdList.value.splice(i, 1)
break
}
}
}
break
}
}
}
// 重置筛选选中项
const onResetScreenCondition = () => {
// type 0:品牌 1:分类 2:属性
const type = openWhichConditionItem.type
openConditionList.value.forEach((item) => {
item.isSelected = false
})
switch (type) {
case 0:
selectedBrandList.value = []
break
case 1:
selectedCategoryId.value = ''
break
case 2:
selectedAttrValueIdList.value = []
break
}
}
// 确定筛选条件
const onConfirmScreenCondition = () => {
// type 0:品牌 1:分类 2:属性
const type = openWhichConditionItem.type
let selectedBrandItemValue = ''
let selectedCategoryItemValue = ''
let selectedAttrItemValue = ''
switch (type) {
case 0:{
let tempSeletedBrandItem = ''
for (let i = 0; i < selectedBrandList.value.length; i++) {
if ((i + 1) < selectedBrandList.value.length) {
tempSeletedBrandItem += selectedBrandList.value[i] + '||'
} else {
tempSeletedBrandItem += selectedBrandList.value[i]
}
}
selectedBrandItemValue = tempSeletedBrandItem
break
}
case 1: {
const index = openConditionList.value.findIndex(item => Number(selectedCategoryId.value) === item.categoryId)
if (index < 0) {
selectedCategoryId.value = ''
}
selectedCategoryItemValue = selectedCategoryId.value
categoryName.value = ''
break
}
case 2:{
// 处理属性的参数
const selectedAttrIdValue = selectedAttrId.value
const selectedAttrValueIdListValue = selectedAttrValueIdList.value
if (selectedAttrIdValue && selectedAttrValueIdListValue.length > 0) {
let selectedAttrValueIdStr = ''
for (let i = 0; i < selectedAttrValueIdList.value.length; i++) {
if ((i + 1) < selectedAttrValueIdList.value.length) {
selectedAttrValueIdStr += selectedAttrValueIdList.value[i] + '||'
} else {
selectedAttrValueIdStr += selectedAttrValueIdList.value[i]
}
}
if (selectedAttrItem.value) {
const attrItemArr = selectedAttrItem.value.split('^')
let isInSelectedAttrItem = false
let tempSelectedAttrItem = ''
for (let i = 0; i < attrItemArr.length; i++) {
const attrId = attrItemArr[i].split('_')[0]
if (Number(attrId) === Number(selectedAttrIdValue)) {
attrItemArr[i] = attrItemArr[i].split('_')[0] + '_' + selectedAttrValueIdStr
isInSelectedAttrItem = true
}
if ((i + 1) < attrItemArr.length) {
tempSelectedAttrItem += attrItemArr[i] + '^'
} else {
tempSelectedAttrItem += attrItemArr[i]
}
}
selectedAttrItemValue = isInSelectedAttrItem ? tempSelectedAttrItem : tempSelectedAttrItem + '^' + selectedAttrIdValue + '_' + selectedAttrValueIdStr
} else {
selectedAttrItemValue = selectedAttrIdValue + '_' + selectedAttrValueIdStr
}
} else {
if (selectedAttrItem.value) {
const selectedAttrIdValue = selectedAttrId.value
const attrItemArr = selectedAttrItem.value.split('^')
const selectedAttrArr = []
for (let i = 0; i < attrItemArr.length; i++) {
const attrId = attrItemArr[i].split('_')[0]
if (Number(attrId) !== Number(selectedAttrIdValue)) {
selectedAttrArr.push(attrItemArr[i])
}
}
for (let i = 0; i < selectedAttrArr.length; i++) {
if ((i + 1) < selectedAttrArr.length) {
selectedAttrItemValue += selectedAttrArr[i] + '^'
} else {
selectedAttrItemValue += selectedAttrArr[i]
}
}
} else {
selectedAttrItemValue = ''
}
}
break
}
}
// 处理原本已经有筛选条件情况下的判断
selectedBrandItem.value = type !== 0 ? selectedBrandItem.value : selectedBrandItemValue // 品牌
selectedCategoryItem.value = type !== 1 ? selectedCategoryItem.value : selectedCategoryItemValue // 分类
selectedAttrItem.value = type !== 2 ? selectedAttrItem.value : selectedAttrItemValue // 属性
// 防止未点击分类关键词时弹窗要点两次弹开 已经样式不变化
onCloseScreenCondition()
onToSearchList()
}
// 关掉浮起的内容
const onCloseScreenCondition = () => {
isOpenAllScreenFrame.value = false
openWhichConditionItem.type = ''
openWhichConditionItem.attrIndex = ''
onInitScreenConditionState()
}
// 初始化筛选条件的状态
const onInitScreenConditionState = () => {
openConditionList.value = [] // 展开筛选条件的列表
selectedBrandList.value = [] // 选中品牌列表
selectedAttrId.value = '' // 选中属性id
}
// 展开筛选框(所有项)
const onOpenAllScreenFrame = () => {
onCloseScreenCondition()
isOpenAllScreenFrame.value = true
// 初始化值
isSelfShop.value = initSelfShop.value
isHasStock.value = initHasStock.value
minPriceInp.value = initMinPriceInp.value
maxPriceInp.value = initMaxPriceInp.value
otherBrandList.value = JSON.parse(JSON.stringify(brandList.value))
otherCategoryList.value = JSON.parse(JSON.stringify(categoryList.value))
otherAttrList.value = JSON.parse(JSON.stringify(attrList.value))
}
/**
* 选中/取消筛选条件
* @param {Number} type 0:品牌 1:分类 2:属性 3:商城自营 4:仅看有货
*/
const onSelectScreenCondition = (type, index, attrValueIndex) => {
switch (type) {
case 0:
otherBrandList.value[index].isSelected = !otherBrandList.value[index].isSelected
break
case 1:
if (otherCategoryList.value[index].isSelected === true) {
otherCategoryList.value[index].isSelected = false
return
}
otherCategoryList.value.forEach((item) => {
item.isSelected = false
})
otherCategoryList.value[index].isSelected = !otherCategoryList.value[index].isSelected
break
case 2:
otherAttrList[index].attrValues[attrValueIndex].isSelected = !otherAttrList.value[index].attrValues[attrValueIndex].isSelected
break
case 3:
isSelfShop.value = !isSelfShop.value
break
case 4:
isHasStock.value = !isHasStock.value
break
}
}
// 重置所有筛选条件
const onResetAllScreenCondition = () => {
// 商城自营和仅看有货
isSelfShop.value = false
isHasStock.value = false
// 价格
minPriceInp.value = ''
maxPriceInp.value = ''
// 品牌
otherBrandList.value.forEach((item) => {
item.isSelected = false
})
// 分类
otherCategoryList.value.forEach((item) => {
item.isSelected = false
})
// 属性
otherAttrList.value.forEach((attrItem) => {
attrItem.attrValues.forEach((attrValueItem) => {
attrValueItem.isSelected = false
})
})
}
// 确定所有筛选条件
const onConfirmAllScreenCondition = () => {
// 商城自营和仅看有货
selfShop.value = isSelfShop.value ? 1 : ''
hasStock.value = isHasStock.value ? 1 : ''
// 品牌
let selectedBrandItemValue = ''
otherBrandList.value.forEach((item) => {
if (item.isSelected) {
selectedBrandItemValue += item.brandId + '||'
}
})
selectedBrandItemValue = selectedBrandItemValue ? selectedBrandItemValue.substring(0, selectedBrandItemValue.length - 2) : ''
selectedBrandItem.value = selectedBrandItemValue
// 分类
let selectedCategoryItemValue = ''
for (let i = 0; i < otherCategoryList.value.length; i++) {
if (otherCategoryList.value[i].isSelected) {
selectedCategoryItemValue = otherCategoryList.value[i].categoryId
break
}
}
selectedCategoryItem.value = selectedCategoryItemValue
// 属性
const attrList = otherAttrList.value
let selectedAttrItemValue = ''
attrList.forEach((attrItem) => {
let selectedAttrValueItem = ''
let isHaveSelectedItem = false
attrItem.attrValues.forEach((attrValueItem) => {
if (attrValueItem.isSelected) {
isHaveSelectedItem = true
selectedAttrValueItem += attrValueItem.attrValueId + '||'
}
})
selectedAttrValueItem = isHaveSelectedItem ? selectedAttrValueItem.substring(0, selectedAttrValueItem.length - 2) : ''
selectedAttrItemValue += isHaveSelectedItem ? attrItem.attrId + '_' + selectedAttrValueItem + '^' : ''
})
selectedAttrItemValue = selectedAttrItemValue.substring(0, selectedAttrItemValue.length - 1)
selectedAttrItem.value = selectedAttrItemValue
onToSearchList()
}
/**
* 切换搜索条件
* @param {Number} state 0:商品(默认) 1:商品销量排序 2:商品价格排序 3:店铺
*/
const onSwitchSearchList = (state) => {
switch (state) {
case 0:
sort.value = ''
break
case 1:
sort.value = sort.value === 2 ? 3 : 2
break
case 2:
sort.value = sort.value === 4 ? 5 : 4
break
case 3:
sort.value = 9
break
}
onToSearchList()
}
/**
* 限制价格筛选输入框的范围
* @param {String} mark min:最小价格输入框 max:最大价格输入框
*/
const onLimitPriceRange = (mark) => {
let limitPrice = ''
if (mark === 'min') {
limitPrice = minPriceInp.value
} else {
limitPrice = maxPriceInp.value
}
// 获取小数点后的数量
const count = onJudgeDecimalLength(limitPrice)
if (limitPrice > 0 && limitPrice < 0.01) {
limitPrice = 0.01
} else if (count > 2) {
limitPrice = Number(limitPrice).toFixed(2)
} else if (limitPrice > 100000000) {
limitPrice = 100000000
}
setTimeout(() => {
if (mark === 'min') {
minPriceInp.value = limitPrice
} else {
maxPriceInp.value = limitPrice
}
}, 0)
}
/**
* 判断一个数是多少位小数
* @param {Number} num 数字
* @returns {Number} count 小数点后的数字长度
*/
const onJudgeDecimalLength = (num) => {
const dotSite = String(num).indexOf('.') + 1
const count = dotSite > 0 ? String(num).length - dotSite : 0
return count
}
// 切换商品列表样式
const isLineProds = ref(true) // 列表格式,默认横排展示
const onChangeListStyle = () => {
isLineProds.value = !isLineProds.value
}
// 修改搜索参数
const onToSearchList = () => {
const options = {
keyword: keyword.value, // 关键字
minPrice: minPriceInp.value, // 最小价格
maxPrice: maxPriceInp.value, // 最大价格
shop: selfShop.value, // 是否是自营店
stock: hasStock.value, // 是否有库存
sort: sort.value, // 排序
bids: selectedBrandItem.value, // 品牌
cid: selectedCategoryItem.value, // 分类
cName: categoryName.value, // 分类名称
aids: selectedAttrItem.value, // 属性
cid2: secondaryCategoryId.value
}
onHandleLinkParams(options)
paging.value.reload()
}
/**
* 跳转到搜索页
* @param {Number} type 0:删除关键词跳转 1:直接跳转
*/
const onToSearchPage = (type) => {
const url = type === 0 ? `/pages/search-page/search-page?type=${searchType.value}` : `/pages/search-page/search-page?keyword=${encodeURIComponent(keyword.value)}&type=${searchType.value}`
uni.redirectTo({ url })
}
// 跳转到店铺页
const onToShopPage = (shopId) => {
onGetShopInfo(shopId)
}
/**
* 获取店铺信息
*/
const onGetShopInfo = (shopId) => {
const params = {
2025-04-13 23:40:58 +08:00
url: '/tmerclub_admin/ua/shop_detail/head_info',
2025-03-20 13:59:39 +08:00
method: 'GET',
data: {
shopId,
imgType: 0 // 图片类型0.app(h5) 1.pc
}
}
http.request(params).then((res) => {
uni.setStorageSync('cloudShopInfo', res)
uni.redirectTo({
url: res.renovationId ? '/package-shop/shop-page/feature-index/feature-index?shopId=' + res.shopId + '&renovationId=' + res.renovationId : '/package-shop/shop-page/shop-index/shop-index?shopId=' + shopId
})
})
}
// 跳转到商品详情页
const onToProdDetailPage = (spuId) => {
uni.navigateTo({
url: '/pages/detail/detail?spuId=' + spuId
})
}
</script>
<style lang="scss" scoped>
@use './search-list.scss';
</style>