new-goods.vue 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667
  1. <template>
  2. <view class="new-goods">
  3. <view class="status_bar">
  4. <!-- 这里是状态栏 -->
  5. </view>
  6. <!-- 标题栏 -->
  7. <view class="header">
  8. <u-icon @click="leftBackBtn" size="40" name="arrow-left"></u-icon>
  9. <view class="head-bar">
  10. <view @click="currentIndex=0" :class="{'bar-active':currentIndex==0}">新品</view>
  11. <view @click="currentIndex=1" :class="{'bar-active':currentIndex==1}">预告</view>
  12. </view>
  13. <view @click="goCart" class="alifont icon-gouwuche1" style="font-weight: bold;"></view>
  14. </view>
  15. <swiper :current="currentIndex" class="swiper-box" @change="ontabchange" :interval="3000" :duration="500">
  16. <swiper-item>
  17. <scroll-view class="scroll-v" lower-threshold="200" enableBackToTop="true" scroll-with-animation scroll-y @scrolltolower="loadMore">
  18. <!-- 推荐商品图 -->
  19. <image class="recommend-img" src="/pages/floor/imgs/recommend/head-sample.png"></image>
  20. <!-- 排序 start-->
  21. <view class="index-navs">
  22. <ms-dropdown-item class="index-nav" :class="{ 'index-nav-active': nav == 1 }" v-model="sortType" @click.native="handledropdown(1)"
  23. :hasSlot="true" :title="sortType || '综合排序'" :contentTopReduse="44" ref="dropdownItem1">
  24. <view class="dropdown-item-content">
  25. <view class="dropdown-list" :class="{ 'dropdown-list-active': sortType == '综合排序' }" @click="setSortType('综合排序')">综合排序</view>
  26. <view class="dropdown-list" :class="{ 'dropdown-list-active': sortType == '新品排序' }" @click="setSortType('新品排序')">新品排序</view>
  27. </view>
  28. </ms-dropdown-item>
  29. <view class="index-nav-divider"></view>
  30. <view class="index-nav" :class="{ 'index-nav-active': nav == 3 }" @click="setNav(3)">
  31. 销量
  32. <view class="index-nav-arrows">
  33. <view class="index-nav-arrow">
  34. <image class="img" src="/static/index/arrow-up-1.png" v-if="sale === 'asc'" mode="aspectFit"></image>
  35. <image class="img" src="/static/index/arrow-up.png" v-else mode="aspectFit"></image>
  36. </view>
  37. <view class="index-nav-arrow">
  38. <image class="img" src="/static/index/arrow-down.png" v-if="sale === 'dec'" mode="aspectFit"></image>
  39. <image class="img" src="/static/index/arrow-down-1.png" v-else mode="aspectFit"></image>
  40. </view>
  41. </view>
  42. </view>
  43. <view class="index-nav-divider"></view>
  44. <view class="index-nav" :class="{ 'index-nav-active': nav == 4 }" @click="setNav(4)">
  45. 价格
  46. <view class="index-nav-arrows">
  47. <view class="index-nav-arrow">
  48. <image class="img" src="/static/index/arrow-up-1.png" v-if="price === 'asc'" mode="aspectFit"></image>
  49. <image class="img" src="/static/index/arrow-up.png" v-else mode="aspectFit"></image>
  50. </view>
  51. <view class="index-nav-arrow">
  52. <image class="img" src="/static/index/arrow-down.png" v-if="price === 'dec'" mode="aspectFit"></image>
  53. <image class="img" src="/static/index/arrow-down-1.png" v-else mode="aspectFit"></image>
  54. </view>
  55. </view>
  56. </view>
  57. <view class="index-nav-divider"></view>
  58. <ms-dropdown-item class="index-nav" :class="{ 'index-nav-active': nav == 2 }" @click.native="handledropdown(2)"
  59. v-model="current_tag" :hasSlot="true" :title="current_tag || '分类'" :contentTopReduse="44" ref="dropdownItem2">
  60. <view class="dropdown-tags">
  61. <view class="dropdown-tag" :class="{ 'dropdown-tag-active': current_tag == item }" @click="setTags(item)" v-for="(item, index) in tags"
  62. :key="index">{{ item }}</view>
  63. <view class="dropdown-tag cancel-btn" @click="setTags('分类')">取消</view>
  64. </view>
  65. </ms-dropdown-item>
  66. </view>
  67. <!-- 排序 end-->
  68. <!-- 商品列表 -->
  69. <view class="index-items">
  70. <view class="index-item" v-for="(item, index) in goods" :key="index">
  71. <view class="index-item-tag">新品</view>
  72. <view class="index-item-img" @click="toProduct(item.goods_id)">
  73. <image :src="item.thumbnail" mode="aspectFill"></image>
  74. <view class="index-item-title">{{ item.goodsName }}</view>
  75. <view class="index-item-price">
  76. <!-- ¥{{ item.price | unitPrice }}{{ item.point ? '+' + item.point + '积分' : '' }} -->
  77. ¥{{ item.price | unitPrice }}
  78. <span class="tipsMkt">¥{{ item.mktprice }}</span>
  79. </view>
  80. <view class="index-item-title-desc">
  81. <view>已售 {{ item.buy_count }}</view>
  82. <view>好评率 {{ item.grade }}%</view>
  83. </view>
  84. </view>
  85. </view>
  86. </view>
  87. </scroll-view>
  88. </swiper-item>
  89. <swiper-item>
  90. <scroll-view class="scroll-v" lower-threshold="200" enableBackToTop="true" scroll-with-animation scroll-y @scrolltolower="loadMore">
  91. <!-- 推荐商品图 -->
  92. <image class="recommend-img" src="/pages/floor/imgs/recommend/head-sample.png"></image>
  93. <!-- 排序 start-->
  94. <view class="index-navs">
  95. <ms-dropdown-item class="index-nav" :class="{ 'index-nav-active': nav == 1 }" v-model="sortType" @click.native="handledropdown(1)"
  96. :hasSlot="true" :title="sortType || '综合排序'" :contentTopReduse="44" ref="dropdownItem11">
  97. <view class="dropdown-item-content">
  98. <view class="dropdown-list" :class="{ 'dropdown-list-active': sortType == '综合排序' }" @click="setSortType('综合排序')">综合排序</view>
  99. <view class="dropdown-list" :class="{ 'dropdown-list-active': sortType == '新品排序' }" @click="setSortType('新品排序')">新品排序</view>
  100. </view>
  101. </ms-dropdown-item>
  102. <view class="index-nav-divider"></view>
  103. <view class="index-nav" :class="{ 'index-nav-active': nav == 3 }" @click="setNav(3)">
  104. 销量
  105. <view class="index-nav-arrows">
  106. <view class="index-nav-arrow">
  107. <image class="img" src="/static/index/arrow-up-1.png" v-if="sale === 'asc'" mode="aspectFit"></image>
  108. <image class="img" src="/static/index/arrow-up.png" v-else mode="aspectFit"></image>
  109. </view>
  110. <view class="index-nav-arrow">
  111. <image class="img" src="/static/index/arrow-down.png" v-if="sale === 'dec'" mode="aspectFit"></image>
  112. <image class="img" src="/static/index/arrow-down-1.png" v-else mode="aspectFit"></image>
  113. </view>
  114. </view>
  115. </view>
  116. <view class="index-nav-divider"></view>
  117. <view class="index-nav" :class="{ 'index-nav-active': nav == 4 }" @click="setNav(4)">
  118. 价格
  119. <view class="index-nav-arrows">
  120. <view class="index-nav-arrow">
  121. <image class="img" src="/static/index/arrow-up-1.png" v-if="price === 'asc'" mode="aspectFit"></image>
  122. <image class="img" src="/static/index/arrow-up.png" v-else mode="aspectFit"></image>
  123. </view>
  124. <view class="index-nav-arrow">
  125. <image class="img" src="/static/index/arrow-down.png" v-if="price === 'dec'" mode="aspectFit"></image>
  126. <image class="img" src="/static/index/arrow-down-1.png" v-else mode="aspectFit"></image>
  127. </view>
  128. </view>
  129. </view>
  130. <view class="index-nav-divider"></view>
  131. <ms-dropdown-item class="index-nav" :class="{ 'index-nav-active': nav == 2 }" @click.native="handledropdown(2)"
  132. v-model="current_tag" :hasSlot="true" :title="current_tag || '分类'" :contentTopReduse="44" ref="dropdownItem22">
  133. <view class="dropdown-tags">
  134. <view class="dropdown-tag" :class="{ 'dropdown-tag-active': current_tag == item }" @click="setTags(item)" v-for="(item, index) in tags"
  135. :key="index">{{ item }}</view>
  136. <view class="dropdown-tag cancel-btn" @click="setTags('分类')">取消</view>
  137. </view>
  138. </ms-dropdown-item>
  139. </view>
  140. <!-- 排序 end-->
  141. <!-- 商品列表 -->
  142. <view class="index-items">
  143. <view class="index-item" v-for="(item, index) in goods" :key="index">
  144. <view class="index-item-tag">即将上架</view>
  145. <view class="index-item-img" @click="toProduct(item.goods_id)">
  146. <image :src="item.thumbnail" mode="aspectFill"></image>
  147. <view class="index-item-title">{{ item.goodsName }}</view>
  148. <view class="index-item-price">
  149. <!-- ¥{{ item.price | unitPrice }}{{ item.point ? '+' + item.point + '积分' : '' }} -->
  150. ¥{{ item.price | unitPrice }}
  151. <span class="tipsMkt">¥{{ item.mktprice }}</span>
  152. </view>
  153. <view class="index-item-title-desc">
  154. <view>已售 {{ item.buy_count }}</view>
  155. <view>好评率 {{ item.grade }}%</view>
  156. </view>
  157. </view>
  158. </view>
  159. </view>
  160. </scroll-view>
  161. </swiper-item>
  162. </swiper>
  163. </view>
  164. </template>
  165. <script>
  166. import msDropdownItem from '@/components/ms-dropdown/dropdown-item.vue';
  167. import {
  168. getCategory,
  169. getTagGoods
  170. } from '@/api/goods.js';
  171. import storage from '@/utils/storage.js';
  172. export default {
  173. components: {
  174. msDropdownItem
  175. },
  176. data() {
  177. return {
  178. currentIndex: 0,
  179. goods: [],
  180. originalGoods:[],
  181. nav: 1,
  182. sale: '',
  183. price: '',
  184. sortType: '',
  185. tags: [],
  186. current_tag: '',
  187. typeSort1: true,
  188. typeSort2: false
  189. };
  190. },
  191. watch:{
  192. currentIndex(val,oVal){
  193. this.nav = 1;
  194. this.originalGoods = []
  195. this.getData()
  196. }
  197. },
  198. onLoad(options) {
  199. this.getData()
  200. this.initCategory();
  201. },
  202. methods: {
  203. leftBackBtn() {
  204. uni.navigateBack()
  205. },
  206. toProduct(goods_id) {//跳转商品详情
  207. uni.navigateTo({
  208. url: '/pages/product/goods?id=' + goods_id
  209. });
  210. },
  211. goCart() { //跳转购物车
  212. let obj = {
  213. from: 'newGoods',
  214. id: ''
  215. };
  216. storage.setCartBackbtn(obj);
  217. uni.switchTab({
  218. url: '/pages/tabbar/cart/cartList'
  219. });
  220. },
  221. ontabchange(e){ //swiper切换
  222. this.currentIndex = e.detail.current
  223. },
  224. handledropdown(val) {
  225. // 如果没有值的话就是全部关闭
  226. if (!val) {
  227. this.$refs.dropdownItem2.closePopup()
  228. this.$refs.dropdownItem1.closePopup()
  229. this.$refs.dropdownItem22.closePopup()
  230. this.$refs.dropdownItem11.closePopup()
  231. }
  232. this.sale = '';
  233. this.price = '';
  234. // 如果等于1点击综合排序
  235. if (val == 1) {
  236. this.nav = 1
  237. this.$refs.dropdownItem2.closePopup()
  238. this.$refs.dropdownItem22.closePopup()
  239. } else {
  240. this.nav = 2
  241. this.$refs.dropdownItem1.closePopup()
  242. this.$refs.dropdownItem11.closePopup()
  243. }
  244. },
  245. async getData() { //获取数据
  246. let response = await getTagGoods(-1, this.mark, 9999);
  247. this.originalGoods.push(...response.data);
  248. this.reRank();
  249. },
  250. loadMore(){ //加载更多
  251. // this.getData()
  252. },
  253. cateSort(type) { //按照所选分类过滤,返回过滤后展示列表
  254. let sortData = [];
  255. for (let i = 0; i < this.originalGoods.length; i++) {
  256. if (this.originalGoods[i].category_name == type) {
  257. sortData.push(this.originalGoods[i]);
  258. }
  259. }
  260. this.goods = sortData;
  261. },
  262. // 降序
  263. sortDec(prop) {
  264. return function(obj1, obj2) {
  265. var val1 = obj1[prop];
  266. var val2 = obj2[prop];
  267. if (val1 < val2) {
  268. return 1;
  269. } else if (val1 > val2) {
  270. return -1;
  271. } else {
  272. return 0;
  273. }
  274. };
  275. },
  276. // 升序
  277. sortAsc(prop) {
  278. return function(obj1, obj2) {
  279. var val1 = obj1[prop];
  280. var val2 = obj2[prop];
  281. if (val1 < val2) {
  282. return -1;
  283. } else if (val1 > val2) {
  284. return 1;
  285. } else {
  286. return 0;
  287. }
  288. };
  289. },
  290. setNav(type) { //销量,价格的点击方法,升降序
  291. this.handledropdown();
  292. this.nav = type;
  293. if (type == 3) {
  294. // 销量 默认降序
  295. this.typeSort1 ? this.setSort('sale', 'dec') : this.setSort('sale', 'asc');
  296. this.typeSort1 = !this.typeSort1;
  297. } else if (type == 4) {
  298. // 价格 默认升序
  299. this.typeSort2 ? this.setSort('price', 'asc') : this.setSort('price', 'dec');
  300. this.typeSort2 = !this.typeSort2;
  301. }
  302. },
  303. setSort(key, type) {
  304. this.handledropdown();
  305. if (key === 'sale') {
  306. this.nav = 3;
  307. this.saleSort(type);
  308. this.$set(this, 'price', '');
  309. }
  310. if (key === 'price') {
  311. this.nav = 4;
  312. this.priceSort(type);
  313. this.$set(this, 'sale', '');
  314. }
  315. if (this[key] === type) {
  316. this.$set(this, key, '');
  317. } else {
  318. this.$set(this, key, type);
  319. }
  320. },
  321. // 销量排序
  322. saleSort(type) {
  323. type == 'asc' ? this.originalGoods.sort(this.sortAsc('buy_count')) : this.originalGoods.sort(this.sortDec(
  324. 'buy_count'));
  325. },
  326. // 价格排序
  327. priceSort(type) {
  328. type == 'asc' ? this.originalGoods.sort(this.sortAsc('price')) : this.originalGoods.sort(this.sortDec('price'));
  329. },
  330. //
  331. setSortType(value) {
  332. this.nav = 1;
  333. this.sortType = value;
  334. // 新品排序
  335. if (value == '新品排序') {
  336. this.originalGoods.sort(this.sortDec('goods_id'));
  337. } else {
  338. this.getData();
  339. }
  340. this.$refs.dropdownItem1.closePopup();
  341. this.$refs.dropdownItem11.closePopup()
  342. },
  343. setTags(value) {
  344. this.current_tag = value;
  345. this.$refs.dropdownItem2.closePopup();
  346. this.$refs.dropdownItem22.closePopup()
  347. if (value === '分类') {
  348. this.nav = 1;
  349. this.reRank();
  350. } else {
  351. this.nav = 2;
  352. this.cateSort(value);
  353. }
  354. },
  355. async initCategory() { //初始化分类列表项
  356. let res = await getCategory();
  357. if(res.statusCode != 200) return ;
  358. console.log(res)
  359. let tags = res.data;
  360. let result = [];
  361. for (let i = 0; i < tags.length; i++) {
  362. result.push(tags[i].name);
  363. }
  364. this.tags = this.unique(result);
  365. },
  366. unique(arr) { //去重
  367. for (var i = 0; i < arr.length; i++) {
  368. for (var j = i + 1; j < arr.length; j++) {
  369. if (arr[i] == arr[j]) {
  370. //第一个等同于第二个,splice方法删除第二个
  371. arr.splice(j, 1);
  372. j--;
  373. }
  374. }
  375. }
  376. return arr;
  377. },
  378. reRank() { //重置列表数据
  379. this.goods = this.originalGoods;
  380. }
  381. }
  382. }
  383. </script>
  384. <style>
  385. page{
  386. height: 100%;
  387. }
  388. </style>
  389. <style lang="scss" scoped>
  390. .status_bar {
  391. height: var(--status-bar-height);
  392. width: 100%;
  393. position: relative;
  394. background: #1abc9c;
  395. z-index: 100;
  396. }
  397. .new-goods {
  398. width: 100%;
  399. height: 100%;
  400. }
  401. .header {
  402. display: flex;
  403. height: 88rpx;
  404. width: 750rpx;
  405. justify-content: space-between;
  406. align-items: center;
  407. // padding-top: var(--status-bar-height);
  408. position: relative;
  409. .u-icon,
  410. .alifont {
  411. width: 40rpx;
  412. margin: 20rpx;
  413. color: #FFFFFF;
  414. }
  415. .head-bar {
  416. flex: 1;
  417. display: flex;
  418. justify-content: center;
  419. align-items: center;
  420. view {
  421. width: 150rpx;
  422. height: 50rpx;
  423. line-height: 50rpx;
  424. text-align: center;
  425. background-color: #8DDBCB;
  426. font-size: 28rpx;
  427. }
  428. view:nth-child(1) {
  429. border-radius: 24rpx 0 0 24rpx;
  430. }
  431. view:nth-child(2) {
  432. border-radius: 0 24rpx 24rpx 0;
  433. }
  434. .bar-active {
  435. background-color: #FFFFFF;
  436. }
  437. }
  438. }
  439. .swiper-box {
  440. height: calc(100% - 88rpx - var(--status-bar-height));
  441. .scroll-v {
  442. width: 750rpx;
  443. height: 100%;
  444. }
  445. }
  446. .recommend-img {
  447. width: 100%;
  448. height: 280rpx;
  449. }
  450. .index-navs {
  451. height: 80rpx;
  452. padding: 0 52rpx;
  453. background-color: #fff;
  454. display: flex;
  455. align-items: center;
  456. justify-content: space-between;
  457. }
  458. .index-nav {
  459. color: #999;
  460. font-size: 28rpx;
  461. display: flex;
  462. justify-content: center;
  463. align-items: center;
  464. &-active {
  465. color: #1abc9c;
  466. font-weight: 700;
  467. .index-nav-desc {
  468. color: #1abc9c;
  469. }
  470. }
  471. }
  472. .index-nav-desc {
  473. margin-top: 8rpx;
  474. font-size: 22rpx;
  475. color: #999;
  476. }
  477. .index-nav-divider {
  478. height: 64rpx;
  479. border-left: 1px solid #dddcdf;
  480. }
  481. .index-items {
  482. margin-top: 20rpx;
  483. padding-left: 20rpx;
  484. background-color: #f7f7f7;
  485. display: flex;
  486. align-items: center;
  487. flex-wrap: wrap;
  488. }
  489. .index-item {
  490. width: 346rpx;
  491. background-color: #fff;
  492. margin: 0 18rpx 20rpx 0;
  493. border-radius: 8rpx;
  494. box-sizing: border-box;
  495. // overflow: hidden;
  496. position: relative;
  497. &-tag{
  498. position: absolute;
  499. right: -8rpx;
  500. top: -7rpx;
  501. z-index: 1;
  502. width: 98rpx;
  503. height: 40rpx;
  504. color: #FFFFFF;
  505. text-align: center;
  506. font-size: 22rpx;
  507. line-height: 40rpx;
  508. background: linear-gradient(194deg,#ff9f0e 7%, #ffbb00 92%);
  509. border-radius: 0 0 0 20rpx;
  510. &::after{
  511. content: "";
  512. position: absolute;
  513. top: 40rpx;
  514. right: 0;
  515. z-index: 1;
  516. width: 0;
  517. height: 0;
  518. border-top: 8rpx solid #D95E00;
  519. border-right: 8rpx solid transparent;
  520. }
  521. }
  522. }
  523. .index-item-img {
  524. image {
  525. width: 346rpx;
  526. height: 320rpx;
  527. border-radius: 8rpx 8rpx 0 0 ;
  528. }
  529. }
  530. .index-item-title {
  531. font-size: 26rpx;
  532. color: #333333;
  533. padding: 20rpx 0 0 20rpx;
  534. box-sizing: border-box;
  535. overflow: hidden;
  536. text-overflow: ellipsis;
  537. white-space: nowrap;
  538. }
  539. .index-item-title-desc {
  540. font-size: 24rpx;
  541. color: #c0c4cc;
  542. margin: 10rpx 20rpx;
  543. display: flex;
  544. justify-content: space-between;
  545. }
  546. .index-item-price {
  547. overflow: hidden;
  548. font-size: 30rpx;
  549. color: #ff5a10;
  550. padding: 20rpx 0 0 20rpx;
  551. }
  552. .tipsMkt {
  553. float: right;
  554. color: #c0c4cc;
  555. text-decoration: line-through;
  556. margin-right: 20rpx;
  557. font-size:24rpx;
  558. line-height:40rpx;
  559. }
  560. .index-nav-arrows {
  561. margin-top: 4rpx;
  562. display: flex;
  563. justify-content: center;
  564. align-items: center;
  565. flex-direction: column;
  566. }
  567. .index-nav-arrow {
  568. image {
  569. width: 32rpx;
  570. height: 32rpx;
  571. }
  572. }
  573. .index-nav-arrow:last-child {
  574. margin-top: -14rpx;
  575. }
  576. .index-nav-arrow:first-child {
  577. margin-bottom: -14rpx;
  578. }
  579. .dropdown-list {
  580. width: 100%;
  581. height: 88rpx;
  582. padding-left: 40rpx;
  583. font-size: 30rpx;
  584. color: #999;
  585. font-weight: normal;
  586. display: flex;
  587. align-items: center;
  588. &-active {
  589. color: #1abc9c;
  590. }
  591. }
  592. .dropdown-tags {
  593. padding:30rpx;
  594. box-sizing: border-box;
  595. display: flex;
  596. align-items: center;
  597. flex-wrap: wrap;
  598. }
  599. .dropdown-tag {
  600. padding: 10rpx 20rpx;
  601. height: 60rpx;
  602. margin:0 22rpx 22rpx 0;
  603. border-radius: 60rpx;
  604. background-color: #f9f9f9;
  605. font-size: 30rpx;
  606. color: #999;
  607. display: flex;
  608. align-items: center;
  609. flex-wrap: wrap;
  610. &-active {
  611. background-color: #fff;
  612. border: 1px solid #ed4743;
  613. color: #ed4743;
  614. }
  615. }
  616. .cancel-btn {
  617. background-color: #e4e1e6;
  618. }
  619. </style>