search.vue 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. <route lang="json5">
  2. {
  3. layout: 'default',
  4. style: {
  5. navigationStyle: 'custom',
  6. },
  7. }
  8. </route>
  9. <script lang="ts" setup>
  10. // 必须导入需要用到的页面生命周期(即使在当前页面上没有直接使用到)
  11. // eslint-disable-next-line unused-imports/no-unused-imports
  12. import { onPageScroll, onReachBottom } from '@dcloudio/uni-app'
  13. import { useQueue } from 'wot-design-uni'
  14. import useZPaging from 'z-paging/components/z-paging/js/hooks/useZPaging.js'
  15. import { categoryList, getList } from '@/api/product'
  16. import { t } from '@/locale'
  17. import { goBack, toPage } from '@/utils/page'
  18. defineOptions({
  19. name: 'SearchPage', // 搜索
  20. })
  21. // 获取屏幕边界到安全区域距离
  22. const systemInfo = uni.getSystemInfoSync()
  23. const safeAreaInsets = systemInfo.safeAreaInsets
  24. // z-paging
  25. const paging = ref(null)
  26. // 类似mixins,如果是页面滚动务必要写这一行,并传入当前ref绑定的paging,注意此处是paging,而非paging.value
  27. useZPaging(paging)
  28. // 搜索关键词
  29. const formData = ref<any>({
  30. storeName: '',
  31. price: 0,
  32. cateId: 0,
  33. sort: 'SALES_DESC',
  34. })
  35. const { closeOutside } = useQueue()
  36. const option1 = ref<Record<string, any>[]>([
  37. { label: t('home.priceTab.allPrice'), value: 0 },
  38. {
  39. label: t('home.priceTab.300spot'),
  40. value: 300,
  41. minPrice: 0,
  42. maxPrice: 300,
  43. },
  44. {
  45. label: t('home.priceTab.500spot'),
  46. value: 500,
  47. minPrice: 300,
  48. maxPrice: 500,
  49. },
  50. {
  51. label: t('home.priceTab.1000spot'),
  52. value: 1000,
  53. minPrice: 500,
  54. maxPrice: 1000,
  55. },
  56. {
  57. label: t('home.priceTab.2000spot'),
  58. value: 2000,
  59. minPrice: 1000,
  60. maxPrice: 2000,
  61. },
  62. {
  63. label: t('home.priceTab.3000spot'),
  64. value: 3000,
  65. minPrice: 2000,
  66. maxPrice: 3000,
  67. },
  68. ])
  69. const option2 = ref<Record<string, any>[]>([
  70. { label: t('search.filterCategory'), value: 0 },
  71. ])
  72. const option3 = ref<Record<string, any>[]>([
  73. { label: t('search.filterSellers'), value: 'SALES_DESC' },
  74. { label: t('search.filterSellers1'), value: 'CREATE_DESC' },
  75. ])
  76. async function getCategoryList() {
  77. const res = await categoryList({ page: 1, size: 20 })
  78. console.log(res)
  79. option2.value = [...option2.value, ...res.data.list.map((i: any) => ({ label: i.name, value: i.id }))]
  80. }
  81. // 搜索结果
  82. const dataList = ref([])
  83. async function queryList(pageNo: number, pageSize: number) {
  84. try {
  85. // const currentTab = option1.value.find((i: any) => i.value === formData.value.price) || option1.value[0]
  86. // console.log(currentTab)
  87. // const minPrice = currentTab?.minPrice ?? undefined
  88. // const maxPrice = currentTab?.maxPrice ?? undefined
  89. const params = {
  90. page: pageNo,
  91. size: pageSize,
  92. price: formData.value.price || undefined,
  93. sort: formData.value.sort,
  94. storeName: formData.value.storeName,
  95. cateId: formData.value.cateId ? formData.value.cateId : undefined,
  96. // minPrice,
  97. // maxPrice,
  98. }
  99. const res = await getList(params)
  100. paging.value.complete(res.data.list)
  101. }
  102. catch (err) {
  103. console.log(err)
  104. paging.value.complete(false)
  105. }
  106. }
  107. onLoad(() => {
  108. getCategoryList()
  109. })
  110. </script>
  111. <template>
  112. <z-paging ref="paging" v-model="dataList" use-page-scroll @query="queryList" @click="closeOutside">
  113. <template #top>
  114. <view class="bg-white" :style="{ paddingTop: `${safeAreaInsets?.top}px` }">
  115. <wd-navbar :bordered="false">
  116. <template #title>
  117. <view class="content">
  118. <view class="back">
  119. <wd-icon name="thin-arrow-left" size="32rpx" @click="() => goBack()" />
  120. </view>
  121. <input v-model.trim="formData.storeName" class="search-input" type="text" :placeholder="$t('search.placeholder')" @confirm="queryList(1, 20)">
  122. <wd-icon name="search" custom-class="search-icon" color="#999" size="32rpx" />
  123. </view>
  124. </template>
  125. </wd-navbar>
  126. <view class="bg-white text-center">
  127. <wd-drop-menu>
  128. <wd-drop-menu-item v-model="formData.price" :options="option1" @change="queryList(1, 20)" />
  129. <wd-drop-menu-item v-model="formData.cateId" :options="option2" @change="queryList(1, 20)" />
  130. <wd-drop-menu-item v-model="formData.sort" :options="option3" @change="queryList(1, 20)" />
  131. </wd-drop-menu>
  132. </view>
  133. </view>
  134. </template>
  135. <view class="mt-24rpx px-24rpx pb-24rpx">
  136. <view class="grid grid-cols-2 gap-20rpx">
  137. <Product
  138. v-for="(item, index) in dataList"
  139. :key="index"
  140. width="100%"
  141. :height="340"
  142. :item="item"
  143. @item-click="toPage({ url: '/pages/productDetail/productDetail', params: { productId: item.productId } })"
  144. />
  145. </view>
  146. </view>
  147. </z-paging>
  148. </template>
  149. <style lang="scss" scoped>
  150. :deep() {
  151. .wd-navbar__title {
  152. margin: 0;
  153. max-width: 100%;
  154. .content {
  155. box-sizing: border-box;
  156. position: relative;
  157. height: 100%;
  158. display: flex;
  159. align-items: center;
  160. padding: 19rpx 25rpx 19rpx 0;
  161. .back {
  162. padding: 0 25rpx;
  163. }
  164. .search-input {
  165. flex: 1;
  166. height: 100%;
  167. text-align: left;
  168. background: rgba(245, 245, 245, 0.6);
  169. border-radius: 8rpx;
  170. border: 1px solid #efefef;
  171. font-size: 28rpx;
  172. padding: 16rpx 64rpx 16rpx 22rpx;
  173. font-weight: normal;
  174. &:active {
  175. border-color: rgba(230, 27, 40, 0.65);
  176. }
  177. &:focus-within {
  178. border-color: rgba(230, 27, 40, 0.65) !important;
  179. }
  180. &:focus-visible {
  181. border-color: rgba(230, 27, 40, 0.65) !important;
  182. }
  183. }
  184. .search-icon {
  185. position: absolute;
  186. right: 42rpx;
  187. top: 50%;
  188. transform: translateY(-50%);
  189. }
  190. }
  191. }
  192. .wd-drop-menu__list {
  193. background: none;
  194. .wd-drop-menu__item-title::after {
  195. width: 60% !important;
  196. }
  197. }
  198. .wd-sort-button--line {
  199. .wd-sort-button__left::after {
  200. width: 90% !important;
  201. }
  202. }
  203. }
  204. </style>