index.vue 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. <template>
  2. <view>
  3. <view class='searchGood'>
  4. <view class='search acea-row row-between-wrapper'>
  5. <view class='input acea-row row-between-wrapper'>
  6. <text class='iconfont icon-sousuo2'></text>
  7. <input type='text' :value='searchValue' :focus="focus" placeholder='点击搜索商品'
  8. placeholder-class='placeholder' @input="setValue" />
  9. </view>
  10. <view class='bnt' @tap='searchBut'>搜索</view>
  11. </view>
  12. <!-- 搜索词 -->
  13. <view class='title'>热门搜索</view>
  14. <view class='list acea-row'>
  15. <block v-for="(item,index) in hotSearchList" :key="index">
  16. <view class='item' @tap='setHotSearchValue(item.title)'>{{item.title}}</view>
  17. </block>
  18. </view>
  19. <view class='line'></view>
  20. <!-- 搜索结果 -->
  21. <goodList :bastList="bastList" v-if="bastList.length > 0" />
  22. <view class='loadingicon acea-row row-center-wrapper' v-if="bastList.length > 0">
  23. <text class='loading iconfont icon-jiazai' :hidden='!loading' /> {{loadTitle}}
  24. </view>
  25. </view>
  26. <!-- 商品推荐 -->
  27. <view class='noCommodity'>
  28. <view class='pictrue' v-if="bastList.length === 0 && isbastList">
  29. <image src='../../static/images/noSearch.png'></image>
  30. </view>
  31. <recommend :hostProduct='hostProduct' v-if="bastList.length === 0"></recommend>
  32. </view>
  33. </view>
  34. </template>
  35. <script>
  36. import { getSearchKeyword } from '@/api/store.js';
  37. import goodList from '@/components/goodList';
  38. import recommend from '@/components/recommend';
  39. import * as ProductSpuApi from '@/api/product/spu.js';
  40. import * as PromotionActivityApi from '@/api/promotion/activity.js';
  41. import * as ProductUtil from '@/utils/product.js';
  42. export default {
  43. components: {
  44. goodList,
  45. recommend
  46. },
  47. data() {
  48. return {
  49. // ========== 商品搜索 ==========
  50. hotSearchList: [], // 热门搜索词
  51. searchValue: '',
  52. focus: true,
  53. bastList: [], // 商品搜索结果
  54. limit: 8,
  55. page: 1,
  56. loading: false,
  57. loadend: false,
  58. loadTitle: '加载更多',
  59. isbastList: false,
  60. // ========== 商品推荐 ==========
  61. hostProduct: [],
  62. hotPage: 1,
  63. isScroll: true,
  64. };
  65. },
  66. onShow: function() {
  67. this.getRoutineHotSearch();
  68. this.getHostProduct();
  69. },
  70. onReachBottom: function() {
  71. if(this.bastList.length > 0){
  72. this.getProductList();
  73. } else {
  74. this.getHostProduct();
  75. }
  76. },
  77. methods: {
  78. /**
  79. * TODO 芋艿:待接入
  80. */
  81. getRoutineHotSearch: function() {
  82. getSearchKeyword().then(res => {
  83. this.$set(this, 'hotSearchList', res.data);
  84. });
  85. },
  86. /**
  87. * 输入搜索热词
  88. *
  89. * @param searchValue 搜索热词
  90. */
  91. setHotSearchValue: function(searchValue) {
  92. this.setValue(searchValue);
  93. this.page = 1;
  94. this.loadend = false;
  95. this.$set(this, 'bastList', []);
  96. this.getProductList();
  97. },
  98. /**
  99. * 输入搜索词
  100. *
  101. * @param searchValue 搜索词
  102. */
  103. setValue: function(searchValue) {
  104. this.$set(this, 'searchValue', searchValue.detail.value);
  105. },
  106. /**
  107. * 点击搜索
  108. */
  109. searchBut: function() {
  110. this.focus = false;
  111. if (this.searchValue.length > 0) {
  112. this.page = 1;
  113. this.loadend = false;
  114. this.$set(this, 'bastList', []);
  115. uni.showLoading({
  116. title: '正在搜索中'
  117. });
  118. this.getProductList();
  119. uni.hideLoading();
  120. } else {
  121. return this.$util.Tips({
  122. title: '请输入要搜索的商品',
  123. icon: 'none',
  124. duration: 1000,
  125. mask: true,
  126. });
  127. }
  128. },
  129. /**
  130. * 执行搜索商品
  131. */
  132. getProductList: function() {
  133. if (this.loadend || this.loading) {
  134. return;
  135. }
  136. this.loading = true;
  137. this.loadTitle = '';
  138. ProductSpuApi.getSpuPage({
  139. keyword: this.searchValue,
  140. pageNo: this.page,
  141. pageSize: this.limit
  142. }).then(res => {
  143. const good_list = res.data.list;
  144. const loadend = good_list.length < this.limit;
  145. this.loading = false;
  146. this.loadend = loadend;
  147. this.loadTitle = loadend ? "😕人家是有底线的~~" : "加载更多";
  148. this.page = this.page + 1;
  149. this.isbastList = true;
  150. // 设置营销活动
  151. const spuIds = good_list.map(item => item.id);
  152. if (spuIds.length > 0) {
  153. PromotionActivityApi.getActivityListBySpuIds(spuIds).then(res => {
  154. ProductUtil.setActivityList(good_list, res.data);
  155. this.bastList = this.$util.SplitArray(good_list, this.bastList); // 放在此处,避免 Vue 监控不到数组里的元素变化
  156. });
  157. }
  158. }).catch(err => {
  159. this.loading = false
  160. this.loadTitle = '加载更多'
  161. });
  162. },
  163. /**
  164. * 获得热门推荐
  165. */
  166. getHostProduct: function() {
  167. if (!this.isScroll) {
  168. return
  169. }
  170. ProductSpuApi.getSpuPage({
  171. recommendType: 'hot',
  172. pageNo: this.hotPage,
  173. pageSize: this.limit
  174. }).then(res => {
  175. const good_list = res.data.list;
  176. this.isScroll = good_list.length >= this.limit
  177. this.hotPage += 1;
  178. // 设置营销活动
  179. const spuIds = good_list.map(item => item.id);
  180. if (spuIds.length > 0) {
  181. PromotionActivityApi.getActivityListBySpuIds(spuIds).then(res => {
  182. ProductUtil.setActivityList(good_list, res.data);
  183. this.hostProduct = this.hostProduct.concat(good_list); // 放在此处,避免 Vue 监控不到数组里的元素变化
  184. });
  185. }
  186. });
  187. }
  188. }
  189. }
  190. </script>
  191. <style lang="scss">
  192. page {
  193. background-color: #fff !important;
  194. }
  195. .searchGood .search {
  196. padding-left: 30rpx;
  197. background-color: #fff !important;
  198. }
  199. .searchGood .search {
  200. padding-top: 20rpx;
  201. }
  202. .searchGood .search .input {
  203. width: 598rpx;
  204. background-color: #f7f7f7;
  205. border-radius: 33rpx;
  206. padding: 0 35rpx;
  207. box-sizing: border-box;
  208. height: 66rpx;
  209. }
  210. .searchGood .search .input input {
  211. width: 472rpx;
  212. font-size: 26rpx;
  213. }
  214. .searchGood .search .input .placeholder {
  215. color: #bbb;
  216. }
  217. .searchGood .search .input .iconfont {
  218. color: #000;
  219. font-size: 35rpx;
  220. }
  221. .searchGood .search .bnt {
  222. width: 120rpx;
  223. text-align: center;
  224. height: 66rpx;
  225. line-height: 66rpx;
  226. font-size: 30rpx;
  227. color: #282828;
  228. }
  229. .searchGood .title {
  230. font-size: 28rpx;
  231. color: #999;
  232. margin: 50rpx 30rpx 25rpx 30rpx;
  233. }
  234. .searchGood .list {
  235. padding-left: 10rpx;
  236. }
  237. .searchGood .list .item {
  238. font-size: 26rpx;
  239. color: #454545;
  240. padding: 0 21rpx;
  241. height: 60rpx;
  242. border-radius: 30rpx;
  243. line-height: 60rpx;
  244. border: 1rpx solid #aaa;
  245. margin: 0 0 20rpx 20rpx;
  246. }
  247. .searchGood .line {
  248. border-bottom: 1rpx solid #eee;
  249. margin: 20rpx 30rpx 0 30rpx;
  250. }
  251. </style>