homeComb.vue 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739
  1. <template>
  2. <view class="page_count">
  3. <view class="bg-img">
  4. <img :src="bgColor" alt="">
  5. </view>
  6. <!--搜索-->
  7. <view :class="{'my-main': true}">
  8. <view class="mp-header" :style="isScrolled?('background: linear-gradient(90deg, '+ bgColorLeft +' 50%, '+ bgColorRight +' 100%);'):''" :class="[isScrolled?'scrollColor':'',special?'on':'']" id="home">
  9. <view class="sys-head" :style="{ height: statusBarHeight + 'px' }" v-if="!special"></view>
  10. <view class="serch-box">
  11. <view class="serch-wrapper flex" :class="special?'on':''">
  12. <view v-if="logoConfig" class="logo skeleton-rect">
  13. <image :src="logoConfig" mode="heightFix"></image>
  14. </view>
  15. <navigator v-if="hotWords.length > 0 && hotWordShow" :url="'/pages/goods/goods_search/index?searchVal='+searchVal"
  16. :class="logoConfig ? 'input' : 'uninput'" hover-class="none" class="skeleton-rect">
  17. <view class='swiperTxt'>
  18. <swiper :indicator-dots="indicatorDots" :autoplay="autoplay" :interval="interval"
  19. :duration="duration" vertical="true" circular="true" @change="textChange">
  20. <block v-for="(item,index) in hotWords" :key='index'>
  21. <swiper-item catchtouchmove='catchTouchMove'>
  22. <view class='acea-row row-between-wrapper'>
  23. <view class='text acea-row row-between-wrapper'>
  24. <view class='newsTitle line1'>{{item.val}}</view>
  25. </view>
  26. </view>
  27. </swiper-item>
  28. </block>
  29. </swiper>
  30. </view>
  31. <text class="iconfont icon-sousuo"></text>
  32. </navigator>
  33. <navigator v-else url="/pages/goods/goods_search/index" :class="logoConfig ? 'input' : 'uninput'"
  34. hover-class="none" class="skeleton-rect">
  35. 搜索商品
  36. <text class="iconfont icon-sousuo"></text>
  37. </navigator>
  38. </view>
  39. </view>
  40. </view>
  41. <!--选项卡-->
  42. <view :style="'height:'+ (statusBarHeight+43) +'px'" v-if="!special"></view>
  43. <!-- <view v-if="isFixed" style="visibility: hidden;" :style="{ height: navHeight + 'px' }"></view> -->
  44. <view v-if="dataConfig.classShow.val" :style="isScrolled?('background: linear-gradient(90deg, '+ bgColorLeft +' 50%, '+ bgColorRight +' 100%);'):''" class="navTabBox tabNav" :class="[isScrolled?'scrollColor':'',special?'on':'']">
  45. <view class="longTab" :style='"width:"+mainWidth+"px"'>
  46. <scroll-view scroll-x="true" style="white-space: nowrap; display: flex;" scroll-with-animation
  47. :scroll-left="tabLeft" show-scrollbar="true">
  48. <view class="longItem" :data-index="index" :style="'color:'+(isScrolled?txtColor:'#fff')" :class="index===tabClick?'click':''"
  49. @click="changeTab(item,index)" v-for="(item,index) in tabTitle" :key="index"
  50. :id="'id'+index">{{item.cate_name}}</view>
  51. <view class="underlineBox" :style='"transform:translateX("+isLeft+"px);width:"+isWidth+"px"'>
  52. <view class="underline"></view>
  53. </view>
  54. </scroll-view>
  55. </view>
  56. <view class="category" @click="showCategory">
  57. <text class="iconfont icon-gengduofenlei" :style="'color:'+(isScrolled?txtColor:'#fff')"></text>
  58. </view>
  59. </view>
  60. <!--固定分类-->
  61. <view v-if="isCategory" class="category_count">
  62. <view class="sys-head tui-skeleton" :style="{ height: statusBarHeight + 'px' }"></view>
  63. <view class="title">精选类目</view>
  64. <view class="cate_count">
  65. <view class="category_item" :style="{background:index===tabClick?classColor:''}" :class="index===tabClick?'clicks':''" @click="changeTab(item,index)"
  66. v-for="(item,index) in tabTitle" :key="index" :id="'ids'+index">{{item.cate_name}}</view>
  67. </view>
  68. </view>
  69. </view>
  70. <!--轮播图-->
  71. <view style="height: 40px;" v-if="!special && dataConfig.classShow.val"></view>
  72. <view class="swiperBg" :style="{ paddingBottom: isMenu ? '40rpx' : '20rpx'}" v-if="tabId==-99">
  73. <block>
  74. <view class="swiper page_swiper" v-if="imgUrls.length">
  75. <swiper :autoplay="true" :circular="circular" :interval="intervals" :duration="duration"
  76. indicator-color="rgba(255,255,255,0.6)" indicator-active-color="#fff" :current="swiperCur"
  77. previous-margin="10rpx" next-margin="10rpx" @change="swiperChange">
  78. <block v-for="(item,index) in imgUrls" :key="index">
  79. <swiper-item :class="{ active: index == swiperCur,scalex:isScale }">
  80. <view @click="goDetail(item)" class='slide-navigator acea-row row-between-wrapper'>
  81. <image :src="item.img" class="slide-image aa"></image>
  82. </view>
  83. </swiper-item>
  84. </block>
  85. </swiper>
  86. <!--重置小圆点的样式 -->
  87. <view class="dots">
  88. <block v-for="(item,index) in imgUrls" :key="index">
  89. <view class="dot" :class="index == swiperCur ? ' active' : ''"></view>
  90. </block>
  91. </view>
  92. </view>
  93. </block>
  94. </view>
  95. <view v-if="isCategory" class="mask" @click="isCategory = false"></view>
  96. </view>
  97. </template>
  98. <script>
  99. import {
  100. getCategoryList
  101. } from '@/api/store.js';
  102. import { getCategoryVersion } from '@/api/api.js';
  103. let statusBarHeight = uni.getSystemInfoSync().statusBarHeight;
  104. export default {
  105. name: 'homeComb',
  106. props: {
  107. dataConfig: {
  108. type: Object,
  109. default: () => {}
  110. },
  111. isFixed: {
  112. type: Boolean,
  113. default: false
  114. },
  115. isScrolled: {
  116. type: Boolean,
  117. default: false
  118. },
  119. isScale: {
  120. type: Boolean,
  121. default: false
  122. },
  123. isMenu: {
  124. type: Boolean,
  125. default: false
  126. },
  127. special: {
  128. type: Number,
  129. default: 0
  130. }
  131. },
  132. data() {
  133. return {
  134. statusBarHeight: statusBarHeight,
  135. autoplay: true,
  136. interval: this.dataConfig.numConfig.val * 1000 || 2500,
  137. duration: 500,
  138. marTop: 0,
  139. logoConfig: this.dataConfig.logoConfig.url,
  140. hotWords: this.dataConfig.hotWords.list || [],
  141. tabClick: 0, //导航栏被点击
  142. isLeft: 0, //导航栏下划线位置
  143. isWidth: 0, //每个导航栏占位
  144. mainWidth: 0,
  145. tabLeft: 0,
  146. tabTitle: [],
  147. isTop: 0,
  148. navHeight: 38,
  149. homeTop: statusBarHeight,
  150. indicatorDots: false,
  151. circular: true,
  152. intervals: 3000,
  153. imgUrls: [], //图片轮播数据
  154. imageH: 310,
  155. swiperCur: 0,
  156. searchVal: '',
  157. bgColor: this.dataConfig.swiperConfig.list && this.dataConfig.swiperConfig.list[0]['img'],
  158. tabId: -99,
  159. isCategory: false,
  160. classColor: this.dataConfig.classColor.color[0].item,
  161. txtColor: this.dataConfig.txtColor.color[0].item,
  162. hotWordShow: false,
  163. bgColorLeft:this.dataConfig.bgColor.color[0].item,
  164. bgColorRight:this.dataConfig.bgColor.color[1].item,
  165. };
  166. },
  167. watch: {
  168. imageH(nVal, oVal) {
  169. let self = this
  170. this.imageH = nVal
  171. },
  172. },
  173. created() {
  174. var that = this
  175. // 获取设备宽度
  176. uni.getSystemInfo({
  177. success(e) {
  178. that.mainWidth = e.windowWidth
  179. that.isWidth = (e.windowWidth - 65) / 8
  180. }
  181. })
  182. const query = uni.createSelectorQuery().in(that);
  183. that.$nextTick(() => {
  184. query.select('.navTabBox').boundingClientRect(data => {
  185. that.navHeight = data.height > 42 ? data.height : 42
  186. }).exec();
  187. })
  188. that.isTop = (this.statusBarHeight + 43) + 'px'
  189. that.imgUrls = that.dataConfig.swiperConfig.list
  190. that.getAllCategory();
  191. },
  192. mounted() {
  193. let that = this;
  194. that.hotWords.forEach(item=>{
  195. if(item.val){
  196. this.hotWordShow = true;
  197. }
  198. })
  199. uni.setStorageSync('hotList', that.hotWords);
  200. setTimeout(() => {
  201. // 获取小程序头部高度
  202. let info = uni.createSelectorQuery().in(this).select(".mp-header");
  203. info.boundingClientRect(function(data) {
  204. that.marTop = data.height
  205. }).exec()
  206. }, 100)
  207. that.$nextTick(function() {
  208. uni.getImageInfo({
  209. src: that.setDomain(that.imgUrls[0].img),
  210. success: function(res) {
  211. that.$set(that, 'imageH', res.height);
  212. },
  213. fail: function(error) {
  214. that.$set(that, 'imageH', 310);
  215. }
  216. })
  217. // const menuButton = uni.getMenuButtonBoundingClientRect();
  218. const query = uni.createSelectorQuery().in(this);
  219. query
  220. .select('#home')
  221. .boundingClientRect(data => {
  222. //this.homeTop = menuButton.top * 2 + menuButton.height - data.height;
  223. })
  224. .exec();
  225. })
  226. },
  227. methods: {
  228. setCategory(data) {
  229. data.unshift({
  230. "id": -99,
  231. 'cate_name': '首页'
  232. })
  233. this.tabTitle = data;
  234. // #ifdef MP || APP-PLUS
  235. this.isTop = (uni.getSystemInfoSync().statusBarHeight + 43) + 'px'
  236. // #endif
  237. // #ifdef H5
  238. this.isTop = 0
  239. // #endif
  240. },
  241. getCategory() {
  242. getCategoryList().then(res => {
  243. let data = res.data;
  244. let datas = [...data];
  245. data.unshift({
  246. "id": -99,
  247. 'cate_name': '首页'
  248. })
  249. uni.setStorageSync('category', JSON.stringify(datas));
  250. this.tabTitle = data;
  251. })
  252. },
  253. // 获取导航
  254. getAllCategory: function() {
  255. let category = uni.getStorageSync('category');
  256. if (category) {
  257. getCategoryVersion().then(res => {
  258. let categoryVersion = uni.getStorageSync('categoryVersion');
  259. if (res.data.version === categoryVersion) {
  260. this.setCategory(JSON.parse(category));
  261. } else{
  262. uni.setStorageSync('categoryVersion', res.data.version);
  263. this.getCategory();
  264. }
  265. });
  266. } else{
  267. this.getCategory();
  268. }
  269. },
  270. goDetail(url) {
  271. let urls = url.info[1].value
  272. this.$util.JumpPath(urls);
  273. },
  274. //替换安全域名
  275. setDomain: function(url) {
  276. url = url ? url.toString() : '';
  277. //本地调试打开,生产请注销
  278. if (url.indexOf("https://") > -1) return url;
  279. else return url.replace('http://', 'https://');
  280. },
  281. swiperChange(e) {
  282. let {
  283. current,
  284. source
  285. } = e.detail;
  286. if (source === 'autoplay' || source === 'touch') {
  287. this.swiperCur = e.detail.current;
  288. this.bgColor = this.imgUrls[e.detail.current]['img']
  289. }
  290. },
  291. textChange(e) {
  292. let {
  293. current,
  294. source
  295. } = e.detail;
  296. if (source === 'autoplay' || source === 'touch') {
  297. this.searchVal = this.hotWords[e.detail.current]['val']
  298. }
  299. },
  300. /**显示全部分类*/
  301. showCategory() {
  302. this.isCategory = true;
  303. },
  304. /*跳转为页面*/
  305. changeTab(item, index) {
  306. if (this.tabClick == index) return;
  307. this.tabClick = index; //设置导航点击了哪一个
  308. this.isLeft = index * this.isWidth + 16; //设置下划线位置
  309. // this.bgColor = item.id ? item.img : this.dataConfig.swiperConfig.list[0]['img']
  310. // this.imgUrls = item.id ? [{
  311. // img: item.img
  312. // }] : this.dataConfig.swiperConfig.list
  313. this.isCategory = false;
  314. this.tabId = item.id;
  315. this.$emit('bindSortId', item.id);
  316. }
  317. },
  318. }
  319. </script>
  320. <style lang="scss" scoped>
  321. .scrollColor{
  322. transition: background-color .5s ease;
  323. background-color: #fff;
  324. color: #333 !important;
  325. .longItem{
  326. // color: #333 !important;
  327. &.click{
  328. &::after{
  329. background: #333 !important;
  330. }
  331. }
  332. }
  333. }
  334. .page_count {
  335. position: relative;
  336. overflow: hidden;
  337. .bg-img {
  338. position: absolute;
  339. width: 100%;
  340. height: 100%;
  341. top: 0;
  342. z-index: 0;
  343. filter: blur(0);
  344. overflow: hidden;
  345. img {
  346. width: 100%;
  347. height: 100%;
  348. filter: blur(30rpx);
  349. transform: scale(1.5);
  350. }
  351. }
  352. }
  353. .my-main {
  354. transition: background-color .5s ease;
  355. }
  356. .swiperTxt {
  357. width: 300rpx;
  358. height: 100%;
  359. line-height: 58rpx;
  360. overflow: hidden;
  361. }
  362. .swiperTxt .text {
  363. width: 480rpx;
  364. }
  365. .swiperTxt .text .label {
  366. font-size: 20rpx;
  367. color: #ff4c48;
  368. width: 64rpx;
  369. height: 30rpx;
  370. border-radius: 40rpx;
  371. text-align: center;
  372. line-height: 28rpx;
  373. border: 2rpx solid #ff4947;
  374. }
  375. .swiperTxt .text .newsTitle {
  376. width: 300rpx;
  377. font-size: 24rpx;
  378. color: #fff;
  379. }
  380. .swiperTxt swiper {
  381. height: 100%;
  382. }
  383. .mp-header {
  384. z-index: 99;
  385. position: fixed;
  386. left: 0;
  387. top:0;
  388. width: 100%;
  389. &.on{
  390. position: relative;
  391. }
  392. .serch-box{
  393. height: 43px;
  394. }
  395. .logo {
  396. height: 60rpx;
  397. margin-right: 20rpx;
  398. image{
  399. width: 100%;
  400. height: 100%;
  401. }
  402. }
  403. .serch-wrapper {
  404. align-items: center;
  405. /* #ifdef MP */
  406. padding: 0 220rpx 0 30rpx;
  407. /* #endif */
  408. /* #ifndef MP */
  409. padding: 0 30rpx;
  410. /* #endif */
  411. height: 100%;
  412. &.on{
  413. padding: 0 30rpx;
  414. }
  415. .input,
  416. .uninput {
  417. flex: 1;
  418. display: flex;
  419. align-items: center;
  420. width: 330rpx;
  421. height: 58rpx;
  422. padding: 0 50rpx 0 30rpx;
  423. background: rgba(0, 0, 0, .22);
  424. border-radius: 29rpx;
  425. color: #fff;
  426. font-size: 26rpx;
  427. position: relative;
  428. box-sizing: border-box;
  429. .iconfont {
  430. position: absolute;
  431. right: 20rpx;
  432. top: 13rpx;
  433. }
  434. }
  435. }
  436. }
  437. .tabNav {
  438. padding-top: 10rpx;
  439. }
  440. .navTabBox {
  441. width: 100%;
  442. color: rgba(255, 255, 255, 1);
  443. padding: 0 80rpx 0 30rpx;
  444. z-index: 99;
  445. position: fixed;
  446. left: 0;
  447. width: 100%;
  448. padding-top: 5px;
  449. &.on{
  450. position: relative;
  451. }
  452. scroll-view {
  453. /* #ifdef MP */
  454. width: 640rpx;
  455. /* #endif */
  456. /* #ifndef MP */
  457. width: 666rpx;
  458. /* #endif */
  459. padding-right: 30rpx;
  460. height: 70rpx;
  461. }
  462. .click {
  463. color: white;
  464. }
  465. .longTab {
  466. height: 34px;
  467. .longItem {
  468. display: inline-block;
  469. text-align: center;
  470. font-size: 28rpx;
  471. color: #FFFFFF;
  472. max-width: 160rpx;
  473. margin-right: 30rpx;
  474. position: relative;
  475. font-weight: 400;
  476. &:last-child {
  477. margin-right: 0;
  478. }
  479. &.click {
  480. font-weight: 600;
  481. font-size: 30rpx;
  482. color: #FFFFFF;
  483. &::after {
  484. content: '';
  485. transition: .5s;
  486. // width: 20rpx;
  487. height: 3rpx;
  488. background: #FFFFFF;
  489. position: absolute;
  490. bottom: -7rpx;
  491. left: 50%;
  492. margin-left: -10rpx;
  493. }
  494. }
  495. }
  496. }
  497. .category {
  498. position: absolute;
  499. right: 0;
  500. top: 8rpx;
  501. width: 60rpx;
  502. height: 45rpx;
  503. line-height: 45rpx;
  504. z-index: 10;
  505. .iconfont{
  506. font-size: 35rpx;
  507. }
  508. }
  509. &.isFixed {
  510. z-index: 10;
  511. position: fixed;
  512. left: 0;
  513. width: 100%;
  514. }
  515. }
  516. .category_count {
  517. width: 100%;
  518. background: #fff;
  519. padding: 0 32rpx 16rpx 32rpx;
  520. position: fixed;
  521. top: 0;
  522. left: 0;
  523. z-index: 100;
  524. .title {
  525. color: #292929;
  526. font-size: 28rpx;
  527. /* #ifdef MP */
  528. padding-top: 11px;
  529. /* #endif */
  530. /* #ifndef MP */
  531. padding-top: 14px;
  532. /* #endif */
  533. }
  534. .cate_count {
  535. margin-top: 32rpx;
  536. display: flex;
  537. flex-wrap: wrap;
  538. .category_item {
  539. margin-right: 20rpx;
  540. width: 24%;
  541. padding: 0 20rpx;
  542. height: 72rpx;
  543. text-align: center;
  544. line-height: 72rpx;
  545. word-wrap: break-word;
  546. overflow: hidden;
  547. text-overflow: ellipsis;
  548. white-space: nowrap;
  549. margin-right: calc(4% /3);
  550. background-color: #F5F5F5;
  551. border-radius: 8rpx;
  552. margin-bottom: 16rpx;
  553. font-size: 24rpx;
  554. &.clicks {
  555. color: #fff;
  556. }
  557. &:nth-child(4n) {
  558. margin-right: 0;
  559. }
  560. }
  561. }
  562. }
  563. .mask {
  564. position: fixed;
  565. top: 0;
  566. left: 0;
  567. width: 100%;
  568. height: 100%;
  569. background: rgba(0, 0, 0, .7);
  570. z-index: 22;
  571. }
  572. .scrolled {
  573. z-index: 99;
  574. position: fixed;
  575. left: 0;
  576. top: 0;
  577. width: 100%;
  578. background-color: #fff;
  579. .longItem,
  580. .click,
  581. .category text {
  582. color: #000 !important;
  583. }
  584. .underline {
  585. background: #000 !important;
  586. }
  587. .input,
  588. .uninput {
  589. background: rgba(0, 0, 0, 0.22) !important;
  590. }
  591. .click {
  592. &::after {
  593. background-color: #fff !important;
  594. }
  595. }
  596. }
  597. .swiperBg {
  598. z-index: 1;
  599. .colorBg {
  600. position: absolute;
  601. left: 0;
  602. top: 0;
  603. height: 130rpx;
  604. width: 100%;
  605. }
  606. .page_swiper {
  607. position: relative;
  608. width: 100%;
  609. height: auto;
  610. margin: 0 auto;
  611. border-radius: 10rpx;
  612. overflow-x: hidden;
  613. z-index: 20;
  614. padding: 0 10rpx;
  615. swiper-item {
  616. border-radius: 10rpx;
  617. }
  618. .swiper-item,
  619. image,
  620. .acea-row.row-between-wrapper {
  621. width: 100%;
  622. height: 100%;
  623. margin: 0 auto;
  624. border-radius: 10rpx;
  625. }
  626. swiper {
  627. width: 100%;
  628. display: block;
  629. }
  630. image {
  631. transform: scale(0.93);
  632. transition: all 0.6s ease;
  633. // &.scalex{
  634. // transform: scale(1);
  635. // transition: none;
  636. // }
  637. }
  638. swiper-item.active,
  639. swiper-item.scalex {
  640. image {
  641. transform: scale(1);
  642. }
  643. }
  644. /*用来包裹所有的小圆点 */
  645. .dots {
  646. width: 156rpx;
  647. height: 36rpx;
  648. display: flex;
  649. flex-direction: row;
  650. position: absolute;
  651. left: 320rpx;
  652. bottom: 0;
  653. }
  654. /*未选中时的小圆点样式 */
  655. .dot {
  656. width: 16rpx;
  657. height: 6rpx;
  658. border-radius: 6rpx;
  659. margin-right: 6rpx;
  660. background-color: rgba(255, 255, 255, .4);
  661. /*选中以后的小圆点样式 */
  662. &.active {
  663. width: 32rpx;
  664. height: 6rpx;
  665. background-color: rgba(255, 255, 255, .4);
  666. }
  667. }
  668. }
  669. }
  670. /deep/.dot0 .uni-swiper-dots-horizontal {
  671. left: 10%;
  672. }
  673. /deep/.dot1 .uni-swiper-dots-horizontal {
  674. left: 50%;
  675. }
  676. /deep/.dot2 .uni-swiper-dots-horizontal {
  677. left: 90%;
  678. }
  679. </style>