index.vue 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645
  1. <template>
  2. <view class="core">
  3. <!-- nav -->
  4. <u-navbar leftIconSize="0" :placeholder="true" bgColor="#ffffff">
  5. <view class="u-nav-slot" slot="left">
  6. <view class="u-nav-slot__input flex">
  7. <u--input v-model="goodsTitle" @confirm="toGoodsList()" confirmType="search" placeholder="搜索商品" border="none" prefixIcon="search" prefixIconStyle="font-size: 22px;color: #909399" />
  8. <!-- <view class="u-nav-slot__input__btn" @click="toGoodsList()">搜索</view> -->
  9. </view>
  10. </view>
  11. </u-navbar>
  12. <!-- 固定顶部搜索、分类 -->
  13. <view class="fixed-top">
  14. <view class="fixed-top-classify">
  15. <u-tabs @change="changeClassify" :scrollable="true" :list="classifyList" lineWidth="20" lineHeight="2"
  16. lineColor="#FF8D0B" :activeStyle="{
  17. color: '#333',
  18. transform: 'scale(1.1)'
  19. }" :inactiveStyle="{
  20. color: '#999',
  21. transform: 'scale(1.1)'
  22. }" itemStyle="padding-left: 15px; padding-right: 15px; height: 44px; text-align: center;">
  23. </u-tabs>
  24. </view>
  25. </view>
  26. <view class="core-none"></view>
  27. <!-- 轮播 -->
  28. <view class="core-swiper" v-if="swiperList.length">
  29. <swiper class="core-swiper-centent" circular :indicator-dots="true" :autoplay="true" :interval="3000" indicator-active-color="#fff">
  30. <swiper-item class="swiper-item" v-for="(item, index) in swiperList" :key="index" @click="toPage(item)">
  31. <image :src="item.picUrl" mode=""></image>
  32. </swiper-item>
  33. </swiper>
  34. </view>
  35. <!-- 二级分类 -->
  36. <view class="core-category">
  37. <swiper class="core-category-swiper" :autoplay="false">
  38. <swiper-item class="swiper-item" v-for="(item, index) in classifyIndex == 0 ? classifyListFilter : classifyList[classifyIndex].list" :key="index">
  39. <view class="swiper-item__content" v-for="(items, indexs) in item" :key="indexs">
  40. <image :src="items.picUrl" mode="aspectFit" @click="toCategoryGoods(index, indexs)"></image>
  41. <view class="name">{{ items.name }}</view>
  42. </view>
  43. </swiper-item>
  44. </swiper>
  45. </view>
  46. <!-- 标签商品 -->
  47. <view class="tag-goods" v-for="(item, index) in exclusiveSingle" :key="index">
  48. <image class="tag-goods-imgBg" src="../../static/core/core_bg.png" mode=""></image>
  49. <view class="tag-goods-content">
  50. <view class="tag-goods-content-nav flex">
  51. <view class="tag-goods-content-nav__left flex">
  52. <image src="../../static/core/core_tag.png" mode=""></image>
  53. <view class="title">{{ item.name }}</view>
  54. <image src="../../static/core/core_tag.png" mode=""></image>
  55. </view>
  56. <view class="tag-goods-content-nav__right flex" @click="toTagGoods(item)">
  57. <view class="title">更多</view>
  58. <image src="../../static/core/core_right.png" mode=""></image>
  59. </view>
  60. </view>
  61. <view class="tag-goods-content-list">
  62. <view class="tag-goods-content-list-item flex" v-for="(items, indexs) in item.data" :key="indexs" @click="toGoodsDetail(items)">
  63. <view class="image flex">
  64. <image :src="items.picUrl" mode="aspectFit"></image>
  65. </view>
  66. <view class="title">{{ items.exchangePrice }}盲豆</view>
  67. </view>
  68. </view>
  69. </view>
  70. </view>
  71. <!-- 商品列表 -->
  72. <view class="core-goods">
  73. <view class="core-goods-list flex">
  74. <view class="core-goods-list-item flex" v-for="(item, index) in list" :key="index" @click="toGoodsDetail(item)">
  75. <view class="image-wrap flex">
  76. <image :src="item.picUrl" mode="aspectFit"></image>
  77. </view>
  78. <view class="content">
  79. <view class="content-title ells-one">{{ item.title }}</view>
  80. <view class="content-coin flex">
  81. <view class="content-coin__left flex">
  82. <image src="../../static/public/goods_coin.png" mode=""></image>
  83. <view class="num"><text>×</text>{{ item.exchangePrice }}</view>
  84. </view>
  85. <view class="content-coin__right" v-if="item.originPrice">{{ item.originPrice }}</view>
  86. </view>
  87. <view class="content-price">¥{{ $numberFormat(item.value) }}</view>
  88. </view>
  89. </view>
  90. <view class="core-goods-list-item"></view>
  91. </view>
  92. </view>
  93. <custom-tab-bar :activeValue="'core'" />
  94. </view>
  95. </template>
  96. <script>
  97. import env from '../../config/env.js'
  98. import $http from '@/utils/request.js'
  99. import CustomTabBar from '../../components/custom-tab-bar/custom-tab-bar.vue'
  100. export default {
  101. components: {
  102. CustomTabBar,
  103. },
  104. data() {
  105. return {
  106. imgTop: [],
  107. goods: [],
  108. exclusive: [],
  109. exclusiveSingle: [],
  110. pageNum: 1,
  111. total: 0,
  112. list: [],
  113. /////////
  114. classifyList: [], // 分类列表
  115. classifyIndex: 0, // 分类选中下标
  116. classifyListFilter: [],
  117. swiperList: [], // 轮播图
  118. goodsTitle: '',
  119. };
  120. },
  121. onLoad() {
  122. this.pageList()
  123. this.getExclusive()
  124. this.getClassify()
  125. this.getSwiper()
  126. },
  127. methods: {
  128. pageList() {
  129. this.pageNum = 1
  130. this.total = 0
  131. this.list = []
  132. this.getList()
  133. },
  134. // 获取分类
  135. getClassify() {
  136. $http.post('/api/v1/mp/user/exchange/category/listTree', {}).then(res => {
  137. if(res.code == 0){
  138. let interval = 10
  139. this.classifyList = res && res.rows
  140. this.classifyList.forEach(item => {
  141. item.picUrl = env.filePublic + item.picUrl.split(',')[0] + '?imageView2/2/w/340'
  142. item.goodsCategoryList.forEach(ele => {
  143. ele.picUrl = env.filePublic + ele.picUrl.split(',')[0] + '?imageView2/2/w/340'
  144. })
  145. item.list = []
  146. if(item.goodsCategoryList.length > interval) {
  147. let num = Math.ceil(item.goodsCategoryList.length / interval)
  148. let arr = []
  149. let a = 0
  150. let stop = interval
  151. for(let i = 1; i <= num; i++) {
  152. arr = item.goodsCategoryList.slice(a, stop)
  153. a = i * interval
  154. stop = stop + interval
  155. }
  156. } else {
  157. item.list.push(item.goodsCategoryList)
  158. }
  159. })
  160. if(this.classifyList.length > interval) {
  161. let num = Math.ceil(this.classifyList.length / interval)
  162. let arr = []
  163. let a = 0
  164. let stop = interval
  165. for(let i = 1; i <= num; i++) {
  166. arr = this.classifyList.slice(a, stop)
  167. a = i * interval
  168. stop = stop + interval
  169. this.classifyListFilter.push(arr)
  170. }
  171. } else {
  172. this.classifyListFilter =[ [ ...this.classifyList ] ]
  173. }
  174. this.classifyList.unshift({ name: '全部' })
  175. }
  176. })
  177. },
  178. //轮播图
  179. getSwiper() {
  180. $http.post(`/api/v1/mp/user/exchange/banner/list`, {
  181. noToken: true,
  182. location: "top"
  183. }).then(res => {
  184. res.data.forEach(item => item.picUrl = env.filePublic + item.picUrl.split(',')[0])
  185. this.swiperList = res.data
  186. })
  187. },
  188. // 标签商品
  189. async getExclusive() {
  190. let resData = await $http.post(`/api/v1/mp/user/exchange/activity/list`, {
  191. noToken: true
  192. })
  193. let goodsList = []
  194. for (let item of resData.data) {
  195. let resDatas = await $http.post(`/api/v1/mp/user/exchange/goods/list?pageNum=1&pageSize=10`, {
  196. noToken: true,
  197. tagIds: item.tagId
  198. })
  199. goodsList.push({
  200. data: resDatas.rows,
  201. name: item.name,
  202. tagId: item.tagId
  203. })
  204. }
  205. goodsList.forEach(item => {
  206. item.data.forEach(items => {
  207. items.picUrl = env.filePublic + items.picUrl.split(',')[0] + '?imageView2/2/w/340'
  208. })
  209. })
  210. this.exclusiveSingle = goodsList
  211. },
  212. // 商品列表
  213. getList() {
  214. uni.showLoading({
  215. title: '加载中'
  216. });
  217. let data = {
  218. categoryId: this.categoryId,
  219. tagIds: this.tagIds,
  220. ...this.coinNum,
  221. noToken: true
  222. }
  223. $http.post(`/api/v1/mp/user/exchange/goods/list?pageNum=${this.pageNum}&pageSize=20`,data).then(
  224. res => {
  225. uni.hideLoading();
  226. if (res.code == 0) {
  227. res.rows.forEach(item => {
  228. let picUrlArr = item.picUrl.split(',')
  229. item.picUrl = env.filePublic + picUrlArr[0] + '?imageView2/2/w/340'
  230. })
  231. this.total = res.total
  232. this.list = this.list.concat(res.rows)
  233. }
  234. }).catch(() => {
  235. uni.hideLoading();
  236. })
  237. },
  238. // 切换分类
  239. changeClassify(e) {
  240. this.classifyIndex = e.index
  241. },
  242. // 跳转点击事件
  243. toPage(item) {
  244. if (item.type == "link") {
  245. uni.navigateTo({
  246. url: `/packageOperate/webview/index?url=${ item.linkUrl }`,
  247. })
  248. } else if (item.type == "tag") {
  249. uni.navigateTo({
  250. url: `/packageGoods/goods/list?name=${ item.name }&tagIds=${ item.goodsTags ? item.goodsTags : '' }`
  251. })
  252. }
  253. },
  254. // 商品详情
  255. toGoodsDetail(item) {
  256. uni.navigateTo({
  257. url: `/packageGoods/goods/detail?id=${ item.goodsId }`
  258. })
  259. },
  260. // 商品列表
  261. toGoodsList() {
  262. uni.navigateTo({
  263. url: `/packageGoods/goods/list?title=${ this.goodsTitle }`
  264. })
  265. },
  266. // 商品标签
  267. toTagGoods(item) {
  268. uni.navigateTo({
  269. url: `/packageGoods/goods/list?name=${ item.name }&tagIds=${ item.tagId ? item.tagId : '' }`
  270. })
  271. },
  272. // 商品分类
  273. toCategoryGoods(index, indexs) {
  274. let list = this.classifyIndex == 0 ? this.classifyListFilter : this.classifyList[this.classifyIndex].list
  275. let item = list[index][indexs]
  276. uni.navigateTo({
  277. url: `/packageGoods/goods/list?name=${ item.name }&categoryId=${ item.categoryId ? item.categoryId : '' }`
  278. })
  279. },
  280. },
  281. onReachBottom() {
  282. // 判断是否有数据
  283. if (this.total > this.pageNum * 20) {
  284. setTimeout(() => {
  285. ++this.pageNum
  286. this.getList()
  287. }, 500)
  288. } else {
  289. uni.$u.toast('已经到底了')
  290. }
  291. },
  292. onShareAppMessage(res) {
  293. return {
  294. title: '盲票,玩的就是有趣',
  295. path: '/pages/index/index',
  296. // imageUrl:'../../static/icon/lucky_bg.png',
  297. }
  298. }
  299. }
  300. </script>
  301. <style lang="scss" scoped>
  302. .core {
  303. background-color: #fff;
  304. &-none {
  305. height: 120rpx;
  306. }
  307. }
  308. // 搜索
  309. .u-nav-slot {
  310. text {
  311. font-size: 32rpx;
  312. }
  313. &__input {
  314. position: relative;
  315. height: 70rpx;
  316. width: 518rpx;
  317. padding-left: 30rpx;
  318. background: #F4F5F6;
  319. border-radius: 35rpx;
  320. &__btn {
  321. z-index: 200;
  322. width: 140rpx;
  323. height: 70rpx;
  324. line-height: 70rpx;
  325. font-size: 30rpx;
  326. text-align: center;
  327. font-weight: bold;
  328. color: #fff;
  329. background-color: #FF8D0B;
  330. border-radius: 35rpx;
  331. }
  332. }
  333. }
  334. // 固定搜索、分类
  335. .fixed-top {
  336. position: fixed;
  337. z-index: 100;
  338. width: 100%;
  339. background-color: #fff;
  340. // 搜索
  341. &-search {
  342. justify-content: space-between;
  343. padding: 14rpx 30rpx 34rpx;
  344. &__input {
  345. position: relative;
  346. flex: 1;
  347. height: 84rpx;
  348. padding-left: 46rpx;
  349. background: #F4F5F6;
  350. border-radius: 20rpx;
  351. &__btn {
  352. position: absolute;
  353. right: 0;
  354. width: 110rpx;
  355. height: 76rpx;
  356. line-height: 76rpx;
  357. font-size: 34rpx;
  358. text-align: center;
  359. font-weight: bold;
  360. color: #FFC062;
  361. background-color: #333333;
  362. border-radius: 18rpx;
  363. }
  364. }
  365. image {
  366. width: 52rpx;
  367. height: 52rpx;
  368. margin-left: 50rpx;
  369. }
  370. }
  371. // 分类
  372. &-classify {
  373. padding-bottom: 20rpx;
  374. }
  375. }
  376. // 轮播
  377. .core-swiper {
  378. margin: 0 34rpx 20rpx;
  379. border-radius: 16rpx;
  380. &-centent {
  381. height: 300rpx;
  382. .swiper-item {
  383. width: 100%;
  384. height: 100%;
  385. image {
  386. width: 100%;
  387. height: 100%;
  388. border-radius: 16rpx;
  389. }
  390. }
  391. }
  392. }
  393. // 二级分类
  394. .core-category {
  395. width: 100%;
  396. height: 360rpx;
  397. margin-bottom: 34rpx;
  398. padding: 0 34rpx;
  399. &-swiper {
  400. width: 100%;
  401. height: 100%;
  402. .swiper-item {
  403. width: 100%;
  404. height: 100%;
  405. display: flex;
  406. flex-wrap: wrap;
  407. &__content {
  408. display: flex;
  409. align-items: center;
  410. flex-direction: column;
  411. justify-content: space-between;
  412. width: 20%;
  413. height: 50%;
  414. image {
  415. width: 90%;
  416. height: 70%;
  417. }
  418. }
  419. }
  420. }
  421. }
  422. // 标签商品
  423. .tag-goods {
  424. display: flex;
  425. align-items: center;
  426. position: relative;
  427. margin: 0 34rpx 34rpx;
  428. height: 350rpx;
  429. &-imgBg {
  430. position: absolute;
  431. top: 0;
  432. width: 100%;
  433. height: 350rpx;
  434. }
  435. &-content {
  436. width: 100%;
  437. position: absolute;
  438. top: 0;
  439. z-index: 5;
  440. padding: 26rpx 22rpx;
  441. &-nav {
  442. justify-content: space-between;
  443. height: 40rpx;
  444. margin-bottom: 10rpx;
  445. &__left {
  446. image {
  447. width: 40rpx;
  448. height: 30rpx;
  449. }
  450. .title {
  451. font-family: YouSheBiaoTiHei;
  452. font-weight: 400;
  453. font-size: 40rpx;
  454. color: #FFFFFF;
  455. padding: 0 36rpx;
  456. }
  457. }
  458. &__right {
  459. .title {
  460. font-family: YouSheBiaoTiHei;
  461. font-weight: 400;
  462. color: #FFFFFF;
  463. margin-right: 12rpx;
  464. }
  465. image {
  466. width: 22rpx;
  467. height: 20rpx;
  468. }
  469. }
  470. }
  471. &-list {
  472. display: flex;
  473. height: 260rpx;
  474. overflow-x: auto;
  475. &-item {
  476. flex-direction: column;
  477. margin-right: 14rpx;
  478. .image {
  479. width: 180rpx;
  480. height: 180rpx;
  481. background: #FFFFFF;
  482. box-shadow: 0px 0px 4px 0px rgba(100, 100, 100, 0.13);
  483. border-radius: 4rpx;
  484. margin-bottom: 24rpx;
  485. image {
  486. width: 100%;
  487. height: 100%;
  488. }
  489. }
  490. .title {
  491. text-align: center;
  492. line-height: 28rpx;
  493. color: #FFFFFF;
  494. }
  495. }
  496. }
  497. }
  498. }
  499. // 商品列表
  500. .core-goods {
  501. padding: 0 34rpx;
  502. &-list {
  503. width: 100%;
  504. justify-content: space-between;
  505. flex-wrap: wrap;
  506. &-item {
  507. flex-direction: column;
  508. justify-content: flex-start;
  509. width: 48%;
  510. padding-bottom: 32rpx;
  511. background: #FFFFFF;
  512. box-shadow: 0px 0px 3px 0px rgba(100, 100, 100, 0.1);
  513. border-radius: 16rpx;
  514. margin-bottom: 30rpx;
  515. .image-wrap {
  516. width: 100%;
  517. height: 320rpx;
  518. margin-bottom: 16rpx;
  519. image {
  520. width: 100%;
  521. height: 100%;
  522. border-radius: 16rpx 16rpx 0 0;
  523. }
  524. }
  525. .content {
  526. width: 100%;
  527. padding: 0 22rpx;
  528. &-title {
  529. height: 28rpx;
  530. font-size: 28rpx;
  531. line-height: 28rpx;
  532. font-weight: bold;
  533. margin-bottom: 30rpx;
  534. }
  535. &-coin {
  536. height: 30rpx;
  537. font-size: 24rpx;
  538. justify-content: space-between;
  539. margin-bottom: 24rpx;
  540. &__left {
  541. margin-right: 24rpx;
  542. font-size: 28rpx;
  543. font-weight: bold;
  544. text {
  545. font-weight: normal;
  546. }
  547. image {
  548. width: 34rpx;
  549. height: 30rpx;
  550. }
  551. }
  552. &__right {
  553. color: #666666;
  554. text-decoration: line-through;
  555. }
  556. }
  557. &-price {
  558. font-size: 24rpx;
  559. line-height: 24rpx;
  560. color: #666666;
  561. }
  562. }
  563. }
  564. &-item:last-child {
  565. box-shadow: none;
  566. }
  567. }
  568. }
  569. </style>
  570. <style lang="scss" scoped>
  571. </style>