index.vue 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501
  1. <template>
  2. <view class="container">
  3. <!-- 头部轮播 -->
  4. <view class="carousel-section">
  5. <!-- 标题栏和状态栏占位符 -->
  6. <view class="titleNview-placing"></view>
  7. <swiper class="carousel" autoplay="true" duration="400" interval="5000" >
  8. <swiper-item v-for="(item, index) in carouselList" :key="index" class="carousel-item" @click="bannerNavToUrl(item)"><image :src="item.pic" /></swiper-item>
  9. </swiper>
  10. </view>
  11. <u-tabs :list="typeList" active-color="#4E6CFF" name='name' bg-color='transparent' :current="typeIndex" @change="changeType"></u-tabs>
  12. <swiper class="list-box" @change="listChange" :style="{ height: swiperHeight + 'px' }" :current="typeIndex" >
  13. <swiper-item v-for="ls in typeList">
  14. <view class="guess-section">
  15. <view v-for="(item, index) in ls.list" :key="index" class="guess-item" @click="navToDetailPage(item)">
  16. <view class="image-wrapper"><image :src="item.image" mode="scaleToFill"></image></view>
  17. <text class="title clamp2 margin-c-20">{{ item.store_name }}</text>
  18. <view class="cmy-hr"></view>
  19. <view class="price margin-c-20 flex">
  20. <view>
  21. <image class="iconJf" src="../../static/icon/iconU1.png" mode="widthFix"></image>
  22. {{ item.price }}
  23. </view>
  24. <view class="font-size-sm">
  25. <text class="font-color-gray">{{ item.sales }}人购买</text>
  26. </view>
  27. </view>
  28. </view>
  29. </view>
  30. <u-loadmore :status="ls.load" />
  31. </swiper-item>
  32. </swiper>
  33. </view>
  34. </template>
  35. <script>
  36. import { loadIndexs } from '@/api/index.js';
  37. import { getUserInfo } from '@/api/user.js';
  38. import { interceptor } from '@/utils/loginUtils';
  39. import { mapState } from 'vuex';
  40. import { getCategoryList, getProducts} from '@/api/product.js';
  41. export default {
  42. data() {
  43. return {
  44. shareShow: false, //分享海报
  45. pageProportion: 0, //保存页面基于750宽度的比例
  46. swiperHeight: 0,
  47. swiperLength:0,
  48. carouselList: [], //轮播列表
  49. page: 1,
  50. limit: 5,
  51. // 商品分类数据
  52. typeList:[{
  53. }],
  54. //保存当前选中的分类
  55. typeIndex:0
  56. };
  57. },
  58. computed: {
  59. ...mapState('user', ['hasLogin','userInfo'])
  60. },
  61. onLoad: function(option) {
  62. // #ifndef MP
  63. if (option.spread) {
  64. // 存储其他邀请人
  65. uni.setStorageSync('spread', option.spread);
  66. }
  67. // #endif
  68. this.init();
  69. },
  70. //下拉刷新
  71. onPullDownRefresh() {
  72. this.init();
  73. },
  74. // #ifndef MP
  75. // 监听导航栏输入框点击事件
  76. onNavigationBarSearchInputClicked(e) {
  77. //跳转到搜索页面
  78. this.clickSearch();
  79. },
  80. // #endif
  81. onReachBottom(){
  82. this.getProducts(this.typeList[this.typeIndex])
  83. },
  84. methods: {
  85. // 初始化页面数据
  86. init(){
  87. this.loadData();
  88. // 获取分类
  89. this.getType();
  90. // 获取页面初始比例
  91. this.getBl();
  92. },
  93. // 获取初始化页面比例
  94. getBl(){
  95. let obj = this;
  96. obj.$nextTick(function() {
  97. uni.createSelectorQuery()
  98. .select('.container')
  99. .fields(
  100. {
  101. size: true
  102. },
  103. function(data) {
  104. obj.pageProportion = data.width / 750;
  105. }
  106. )
  107. .exec();
  108. });
  109. },
  110. // 设置切换高度
  111. getlistHeight(item){
  112. let obj = this;
  113. let bHeight = Math.ceil(item.length / 2);
  114. obj.swiperHeight = Math.ceil(obj.pageProportion * 520 * bHeight+30);
  115. },
  116. // tabs切换
  117. changeType(e){
  118. console.log(e,'dianji');
  119. this.typeIndex = e;
  120. // 判断是否已经加载过数据
  121. const item = this.typeList[this.typeIndex]
  122. if(!item.loding){
  123. this.getProducts(item)
  124. }
  125. },
  126. // sw切换
  127. listChange(e){
  128. if(e.detail.current!=this.typeIndex){
  129. this.typeIndex=e.detail.current;
  130. // 判断是否已经加载过数据
  131. const item = this.typeList[this.typeIndex]
  132. if(!item.loding){
  133. this.getProducts(item)
  134. }
  135. }
  136. },
  137. //商品详情页
  138. navToDetailPages(item) {
  139. let id = item.product_id;
  140. //let type = 2;
  141. uni.navigateTo({
  142. url: '/pages/product/product?id=' + id
  143. });
  144. },
  145. // 获取商品分类
  146. getType(){
  147. const obj = this;
  148. getCategoryList({})
  149. .then(({ data }) => {
  150. obj.typeList = data.map(function(s) {
  151. return {
  152. name:s.cate_name,
  153. id:s.id,
  154. page:1,
  155. limit:10,
  156. list:[],
  157. load:'loadmore',//loadmore/loading / nomore
  158. isLoding:false//用于判断是否已经载入过分类
  159. };
  160. });
  161. // 加载商品
  162. obj.getProducts(this.typeList[this.typeIndex])
  163. })
  164. .catch(err => {
  165. console.log(err);
  166. });
  167. },
  168. // 获取商品信息
  169. getProducts(item){
  170. // 判断是否已经没有数据
  171. if(item.load=='nomore'){
  172. return ;
  173. }
  174. // 判断是否加载中
  175. if(item.load=='loading'){
  176. return ;
  177. }
  178. // 判断是否为初次加载
  179. if(!item.isLoding){
  180. item.isLoding = true;
  181. }
  182. // 设置开始加载
  183. item.load = 'loading';
  184. getProducts({
  185. cid:item.id,
  186. page:item.page,
  187. limit:item.limit
  188. }).then((e) => {
  189. item.list =item.list.concat( e.data);
  190. if(item.list.length==item.limit){
  191. item.page++
  192. item.load = 'loadmore';
  193. }else{
  194. item.load = 'nomore';
  195. }
  196. // 初始化高度
  197. this.getlistHeight(item.list)
  198. }).catch((e) => {
  199. console.log(e);
  200. })
  201. },
  202. // 點擊搜索框
  203. clickSearch() {
  204. uni.navigateTo({
  205. url: '/pages/product/search'
  206. });
  207. },
  208. // 请求载入数据
  209. async loadData() {
  210. loadIndexs({})
  211. .then(({ data }) => {
  212. let goods = data.info;
  213. this.carouselList = data.banner;
  214. this.swiperLength = this.carouselList.length;
  215. this.menusList = data.menus;
  216. uni.stopPullDownRefresh();
  217. })
  218. .catch(e => {
  219. uni.stopPullDownRefresh();
  220. });
  221. },
  222. //详情页
  223. navToDetailPage(item) {
  224. let id = item.id;
  225. uni.navigateTo({
  226. url: '/pages/product/product?id=' + id
  227. });
  228. },
  229. // 轮播图跳转
  230. bannerNavToUrl(item) {
  231. // #ifdef H5
  232. if (item.wap_url.indexOf('http') > 0) {
  233. window.location.href = item.wap_url;
  234. }
  235. // #endif
  236. //测试数据没有写id,用title代替
  237. uni.navigateTo({
  238. url: item.wap_url
  239. });
  240. }
  241. }
  242. };
  243. </script>
  244. <style lang="scss">
  245. page {
  246. background: #f7f8f7;
  247. }
  248. .m-t {
  249. margin-top: 16rpx;
  250. }
  251. .list-box{
  252. margin-top: 30rpx;
  253. }
  254. /* 头部 轮播图 */
  255. .carousel-section {
  256. position: relative;
  257. padding-top: 10px;
  258. overflow: hidden;
  259. background: url(../../static/img/indexBg.png) no-repeat;
  260. background-size: 100% 100%;
  261. .titleNview-placing {
  262. height: var(--status-bar-height);
  263. padding-top: 44px;
  264. box-sizing: content-box;
  265. }
  266. .titleNview-background {
  267. position: absolute;
  268. top: 0;
  269. left: 0;
  270. width: 100%;
  271. height: 426rpx;
  272. transition: 0.4s;
  273. }
  274. .carousel {
  275. width: 680rpx;
  276. height: 340rpx;
  277. margin: 0 auto;
  278. .carousel-item {
  279. width: 100%;
  280. height: 100%;
  281. overflow: hidden;
  282. }
  283. image {
  284. width: 100%;
  285. height: 100%;
  286. border-radius: $border-radius-sm;
  287. }
  288. }
  289. }
  290. /*公用边框样式*/
  291. %icon {
  292. margin-right: 10rpx;
  293. display: inline-block;
  294. padding: 2rpx 10rpx;
  295. border: 1rpx solid $color-yellow;
  296. color: $color-yellow;
  297. line-height: 1;
  298. font-size: $font-base;
  299. border-radius: 10rpx;
  300. }
  301. .f-header {
  302. display: flex;
  303. align-items: center;
  304. height: 92rpx;
  305. padding: 6rpx 30rpx 8rpx;
  306. image {
  307. flex-shrink: 0;
  308. width: 80rpx;
  309. height: 80rpx;
  310. margin-right: 20rpx;
  311. }
  312. .tit-box {
  313. @extend %font-title-box;
  314. }
  315. .tit {
  316. @extend %font-title;
  317. }
  318. .iconenter {
  319. font-size: $font-lg + 2rpx;
  320. color: $font-color-light;
  321. }
  322. .f-left-icon {
  323. @extend %f-left-icon;
  324. }
  325. .iconfont {
  326. font-size: $font-sm - 2rpx;
  327. }
  328. }
  329. /* 商品列表 */
  330. .guess-section {
  331. display: flex;
  332. flex-wrap: wrap;
  333. padding: 0 30rpx;
  334. .guess-item {
  335. overflow: hidden;
  336. display: flex;
  337. flex-direction: column;
  338. width: 48%;
  339. margin-bottom: 4%;
  340. border-radius: $border-radius-sm;
  341. background-color: white;
  342. box-shadow: $box-shadow;
  343. &:nth-child(2n + 1) {
  344. margin-right: 4%;
  345. }
  346. }
  347. .image-wrapper {
  348. width: 100%;
  349. height: 330rpx;
  350. border-radius: 3px;
  351. overflow: hidden;
  352. image {
  353. width: 100%;
  354. height: 100%;
  355. opacity: 1;
  356. }
  357. }
  358. .title {
  359. padding-top: 10rpx;
  360. font-size: $font-base;
  361. color: $font-color-dark;
  362. font-weight: bold;
  363. line-height: 1.5;
  364. }
  365. .price {
  366. font-size: $font-lg;
  367. color: $base-color;
  368. font-weight: bold;
  369. line-height: 1;
  370. line-height: 80rpx;
  371. .iconJf{
  372. width: 23rpx;
  373. margin-right: 5rpx;
  374. }
  375. }
  376. .icon {
  377. @extend %icon;
  378. }
  379. .detail {
  380. line-height: 1;
  381. }
  382. .tip {
  383. color: white;
  384. background-color: $color-yellow;
  385. line-height: 1.5;
  386. font-size: $font-sm;
  387. padding-left: 20rpx;
  388. }
  389. }
  390. // 列表
  391. .list-box-h {
  392. height: 1550rpx;
  393. }
  394. .row {
  395. border-radius: 15rpx;
  396. margin: 25rpx;
  397. height: 155rpx;
  398. // width: 552rpx;
  399. overflow: hidden;
  400. background-color: #ffffff;
  401. padding-right: 25rpx;
  402. .list-interval {
  403. border: 1px dashed $border-color-light;
  404. height: 100%;
  405. .top,
  406. .bottom {
  407. border-radius: 100rpx;
  408. width: 30rpx;
  409. height: 30rpx;
  410. position: absolute;
  411. background-color: $page-color-base;
  412. right: -15rpx;
  413. }
  414. .top {
  415. top: -18rpx;
  416. }
  417. .bottom {
  418. bottom: -18rpx;
  419. }
  420. }
  421. .list-money {
  422. height: 100%;
  423. min-width: 155rpx;
  424. text-align: center;
  425. image {
  426. height: 100%;
  427. width: 20rpx;
  428. }
  429. .list-money-text {
  430. flex-grow: 1;
  431. padding: 0 25rpx;
  432. .tit {
  433. text-align: center;
  434. padding: 15rpx 0rpx;
  435. font-size: 55rpx;
  436. color: $color-red;
  437. font-weight: bold;
  438. &.noAction {
  439. color: $font-color-light;
  440. }
  441. }
  442. .price {
  443. padding-bottom: 25rpx;
  444. color: $font-color-light;
  445. }
  446. }
  447. }
  448. .row_list_right {
  449. // flex-grow: 1;
  450. min-width: 200rpx;
  451. padding-left: 25rpx;
  452. line-height: 1;
  453. .right_time {
  454. padding: 10rpx 0rpx;
  455. color: $font-color-light;
  456. font-size: $font-sm;
  457. }
  458. .right_top {
  459. margin: 15rpx 0;
  460. .right_name {
  461. font-size: $font-base;
  462. color: #bc253a;
  463. font-weight: bold;
  464. }
  465. .right_title {
  466. font-size: $font-base;
  467. color: $font-base;
  468. font-weight: bold;
  469. &.noAction {
  470. color: $font-color-light;
  471. }
  472. }
  473. }
  474. }
  475. .right_use {
  476. margin: 15rpx 0;
  477. padding: 10rpx;
  478. width: 160rpx;
  479. text-align: center;
  480. color: #fff;
  481. background-color: #bc253a;
  482. border-radius: 50rpx;
  483. font-size: $font-sm;
  484. &.noAction {
  485. background-color: $font-color-light;
  486. }
  487. }
  488. .iconlocation {
  489. font-size: 36rpx;
  490. color: $font-color-light;
  491. }
  492. }
  493. </style>