index.vue 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595
  1. <template>
  2. <div class="home">
  3. <meta name="keywords" content="电商,购物,商城" />
  4. <!-- 头部 -->
  5. <div class="head">
  6. <div class="content">
  7. <nuxt-link to="/" class="logo">
  8. <img class="logo-img" v-if="webConfigData.pcLogoImgText" :src="webConfigData.pcLogoImgText"/>
  9. <!-- <div class="name">-->
  10. <!-- <span class="cn">蓝海创新科技</span>-->
  11. <!-- <span class="en">Blue Ocean Mall</span>-->
  12. <!-- </div>-->
  13. </nuxt-link>
  14. <div :class="['menu',this.$store.state.locale == 'en'?'menu-en':'']">
  15. <nuxt-link to="/" class="item item-on">{{ $t('commonHead.home') }}</nuxt-link>
  16. <nuxt-link class="item" to="/list?st=0">{{ $t('commonHead.productList') }}</nuxt-link>
  17. <nuxt-link class="item" to="/list?st=1">{{ $t('commonHead.newProducts') }}</nuxt-link>
  18. <nuxt-link class="item" to="/special-discount">{{ $t('commonHead.limitedTimeOffer') }}</nuxt-link>
  19. <nuxt-link class="item" to="/group-buy">{{ $t('commonHead.groupDiscount') }}</nuxt-link>
  20. <nuxt-link class="item" to="/flash-sale">{{ $t('commonHead.spikeSpecial') }}</nuxt-link>
  21. <!-- <nuxt-link class="item" to="/coupons">领券中心</nuxt-link> -->
  22. <a class="item" href="javascript:void(0)" @click="toCoupons">{{ $t('commonHead.voucherCenter') }}</a>
  23. </div>
  24. <div class="search">
  25. <input
  26. type="text"
  27. class="search-input"
  28. :placeholder="$t('searchByStOrpN')"
  29. />
  30. <input type="submit" class="search-btn" value="搜索" />
  31. </div>
  32. </div>
  33. </div>
  34. <!-- /头部 -->
  35. <!-- 下滑时候的头部 -->
  36. <transition name="fade">
  37. <div v-if="showHeadScroll" class="head-scroll">
  38. <div class="content">
  39. <nuxt-link to="/" class="logo">
  40. <img class="logo-img" v-if="webConfigData.pcLogoImgText" :src="webConfigData.pcLogoImgText"/>
  41. <!-- <div class="name">-->
  42. <!-- <span class="cn">蓝海创新科技</span>-->
  43. <!-- <span class="en">Blue Ocean Mall</span>-->
  44. <!-- </div>-->
  45. </nuxt-link>
  46. <div :class="['menu',this.$store.state.locale == 'en'?'menu-en':'']">
  47. <nuxt-link class="item item-on" to="/">{{ $t('commonHead.home') }}</nuxt-link>
  48. <nuxt-link to="/list?st=0" class="item">{{ $t('commonHead.productList') }}</nuxt-link>
  49. <nuxt-link to="/list?st=1" class="item">{{ $t('commonHead.newProducts') }}</nuxt-link>
  50. <nuxt-link to="/special-discount" class="item">{{ $t('commonHead.limitedTimeOffer') }}</nuxt-link>
  51. <nuxt-link to="/group-buy" class="item">{{ $t('commonHead.groupDiscount') }}</nuxt-link>
  52. <nuxt-link to="/flash-sale" class="item">{{ $t('commonHead.spikeSpecial') }}</nuxt-link>
  53. <!-- <nuxt-link to="/coupons" class="item">领券中心</nuxt-link> -->
  54. <a href="javascript:void(0)" class="item" @click="toCoupons">{{ $t('commonHead.voucherCenter') }}</a>
  55. </div>
  56. <div class="right">
  57. <div class="search">
  58. <input
  59. type="text"
  60. v-model="topsearchTerms"
  61. @keyup.enter="topSearchProd"
  62. class="search-input"
  63. :placeholder="$t('searchByStOrpN')"
  64. />
  65. <input
  66. type="submit"
  67. @click="topSearchProd"
  68. class="search-btn"
  69. value="搜索"
  70. />
  71. </div>
  72. <div class="scroll-cart" @click="toCart">
  73. <span class="number" v-if="totalCartCount">{{ totalCartCount > 99 ? '99+' : totalCartCount }}</span>
  74. </div>
  75. </div>
  76. </div>
  77. </div>
  78. </transition>
  79. <!-- 下滑时候的头部 -->
  80. <!-- 分类筛选 -->
  81. <CategroySidebar />
  82. <!-- /分类筛选 -->
  83. <!-- banner -->
  84. <div class="banner" v-if="banners.length">
  85. <el-carousel height="450px" style="overflow-y: hidden;">
  86. <el-carousel-item
  87. v-for="banner in banners"
  88. :key="banner.imgUrl"
  89. :style="{cursor:(banner.type !== 0 ? 'default' : 'pointer')}"
  90. class="banner-item"
  91. >
  92. <img
  93. :src="banner.imgUrl"
  94. style="width:100%;height:100%;"
  95. @click="imgToProd(banner)"
  96. />
  97. </el-carousel-item>
  98. </el-carousel>
  99. </div>
  100. <!-- /banner -->
  101. <!-- 搜索 -->
  102. <div :class="['home-search',banners.length?'':'up']" :style="hotSearchList.length?'':'justify-content: flex-end;'">
  103. <div class="hot-word" v-if="hotSearchList.length"
  104. >
  105. <div class="tit" :style=" this.$store.state.locale == 'en'? 'width:95px;':'width:75px;' ">{{$t('index.popularSearches')}}:</div>
  106. <div :class="['con',this.$store.state.locale == 'en'?'con-en':'']">
  107. <span
  108. :title="hot.title"
  109. class="item"
  110. v-for="(hot, index) in hotSearchList"
  111. :key="index"
  112. @click="onHistSearch(hot.content)"
  113. >{{ hot.title }}</span
  114. >
  115. </div>
  116. </div>
  117. <div class="search-msg" onselectstart="return false">
  118. <div class="search-input-box">
  119. <input
  120. type="text"
  121. class="search-input"
  122. :style=" this.$store.state.locale == 'en'? 'width:58%;':'width:63%;' "
  123. v-model="searchTerms"
  124. @keyup.enter="toSearchProdPage"
  125. :placeholder="$t('searchByStOrpN')"
  126. />
  127. <div class="select-search" @click="selectChoose">
  128. <div class="select-box">
  129. <span >{{ searchItem }}</span>
  130. <img src="~/assets/images/switch.png" class="switch-icon" alt="">
  131. </div>
  132. </div>
  133. <ul class="select-list" v-if="showSelectItem">
  134. <li class="select-item" @click="selectSearchItem(0)">{{$t('index.prod')}}</li>
  135. <li class="select-item" @click="selectSearchItem(1)">{{$t('index.shop')}}</li>
  136. </ul>
  137. </div>
  138. <input
  139. type="submit"
  140. class="search-btn"
  141. :value="$t('index.search')"
  142. @click="toSearchProdPage"
  143. :style="$t('language')=='en'?'':'letter-spacing: 2px;'"
  144. />
  145. </div>
  146. <div class="cart-btn" @click="toCart">
  147. {{$t('index.shoppingCart')}}
  148. <span class="number" v-if="totalCartCount">{{ totalCartCount > 99 ? '99+' : totalCartCount }}</span>
  149. </div>
  150. </div>
  151. <!-- /搜索 -->
  152. <div class="content">
  153. <!-- 快捷入口 -->
  154. <div class="shortcut" v-if="false">
  155. <div class="item item01">
  156. <div class="text">
  157. <div class="cn">{{$t('index.newProduct')}}</div>
  158. </div>
  159. <div class="img">
  160. <img src="~/assets/img/short-01.png" alt />
  161. </div>
  162. </div>
  163. <div class="item item02">
  164. <div class="text">
  165. <div class="cn">{{$t('index.limitedTimeOffer')}}</div>
  166. </div>
  167. <div class="img">
  168. <img src="~/assets/img/short-02.png" alt />
  169. </div>
  170. </div>
  171. <div class="item item03">
  172. <div class="text">
  173. <div class="cn">{{$t('index.groupDiscount')}}</div>
  174. </div>
  175. <div class="img">
  176. <img src="~/assets/img/short-03.png" alt />
  177. </div>
  178. </div>
  179. <div class="item item04">
  180. <div class="text">
  181. <div class="cn">{{$t('index.specialSale')}}</div>
  182. </div>
  183. <div class="img">
  184. <img src="~/assets/img/short-04.png" alt />
  185. </div>
  186. </div>
  187. <div class="item item05">
  188. <div class="text">
  189. <div class="cn">{{$t('index.couponsCenter')}}</div>
  190. </div>
  191. <div class="img">
  192. <img src="~/assets/img/short-05.png" alt />
  193. </div>
  194. </div>
  195. </div>
  196. <!-- 广告 -->
  197. <nuxt-link to="/flash-sale" class="adv" v-if="snapUpList.length">
  198. <img src="~/assets/img/adv1.jpg" alt />
  199. </nuxt-link>
  200. <!-- 秒杀专区 -->
  201. <div class="goods-list flash-sale" v-if="snapUpList.length">
  202. <div class="list-tit">
  203. <div class="text">
  204. <span class="tit">{{$t('index.secondKillZone')}}</span>
  205. <span class="description">{{$t('index.selectedProductsLimited')}}</span>
  206. </div>
  207. <nuxt-link to="/flash-sale" class="view-more">
  208. {{$t('index.seeMore')}}
  209. <span class="arrow">></span>
  210. </nuxt-link>
  211. </div>
  212. <ProdItem :pale-list="snapUpList" :list-type="2" />
  213. </div>
  214. <!-- 广告 -->
  215. <nuxt-link to="/group-buy" class="adv" v-if="composeGroup.length">
  216. <img src="~/assets/img/adv2.jpg" alt />
  217. </nuxt-link>
  218. <!-- 优惠团购 -->
  219. <div class="goods-list group-list" v-if="composeGroup.length">
  220. <div class="list-tit">
  221. <div class="text">
  222. <span class="tit">{{$t('index.groupDiscount')}}</span>
  223. <span class="description">{{$t('index.recommendGoodThings')}}</span>
  224. </div>
  225. <nuxt-link to="/group-buy" class="view-more">
  226. {{$t('index.seeMore')}}
  227. <span class="arrow">></span>
  228. </nuxt-link>
  229. </div>
  230. <ProdItem :pale-list="composeGroup" :list-type="1" />
  231. </div>
  232. <!-- 广告 -->
  233. <nuxt-link to="/list" class="adv" v-if="hotSalesList.records[0].products.length">
  234. <img src="~/assets/img/adv3.jpg" alt />
  235. </nuxt-link>
  236. <!-- 商城热销 -->
  237. <div class="goods-list group-list" v-if="hotSalesList.records[0].products.length">
  238. <div class="list-tit">
  239. <div class="text">
  240. <span class="tit">{{$t('index.hotSale')}}</span>
  241. <span class="description">{{$t('index.wordGoodiesInfiniteRepurchase')}}</span>
  242. </div>
  243. <nuxt-link to="/list?st=0" class="view-more">
  244. {{$t('index.seeMore')}}
  245. <span class="arrow">></span>
  246. </nuxt-link>
  247. </div>
  248. <ProdItem :pale-list="hotSalesList.records[0].products" :list-type="0"/>
  249. </div>
  250. <!-- 广告 -->
  251. <nuxt-link v-if="hotShopList.length" to="/shopList?type=1" class="adv">
  252. <img src="~/assets/img/adv4.jpg" alt />
  253. </nuxt-link>
  254. <!-- 优选好店 -->
  255. <div v-if="hotShopList.length" class="goods-list shop-list">
  256. <div class="list-tit">
  257. <div class="text">
  258. <span class="tit">{{$t('index.preferredStores')}}</span>
  259. <span class="description">{{$t('index.recommendGoodThingsTogetherWithTheGroup')}}</span>
  260. </div>
  261. <nuxt-link to="/shopList?type=1" class="view-more">
  262. {{$t('index.seeMore')}}
  263. <span class="arrow">></span>
  264. </nuxt-link>
  265. </div>
  266. <ShopItem :shop-list="hotShopList" />
  267. </div>
  268. <!-- /优选好店 -->
  269. </div>
  270. <!-- 登录弹窗组件 -->
  271. <LoginPopup v-if="showLogin" v-on:hideLoginPop="hideLoginPop" />
  272. <!-- /登录弹窗组件 -->
  273. </div>
  274. </template>
  275. <script>
  276. import Cookie from 'js-cookie'
  277. import LoginPopup from '~/components/login-popup'
  278. import ProdItem from '~/components/prod-item'
  279. import ShopItem from '~/components/shop-item'
  280. import CategroySidebar from '~/components/categroy-sidebar'
  281. import util from '~/plugins/util'
  282. export default {
  283. layout: 'home',
  284. components: {
  285. ProdItem,
  286. ShopItem,
  287. CategroySidebar,
  288. LoginPopup
  289. },
  290. //在页面加载之前先加载数据
  291. async asyncData ({ app, query }) {
  292. let [requestWebConfigData, requestSnapUp, requestTeamBuy, requestHotSales,requestHotShops] = await Promise.all([
  293. // 网站配置信息
  294. app.$axios.get('/webConfig/getPcWebConfig'),
  295. // 秒杀商品
  296. app.$axios.get('/search/page', {
  297. params: {
  298. current: 1,
  299. size: 4,
  300. prodType: 2,
  301. isActive: 1 // 过滤掉活动商品
  302. }
  303. }),
  304. // 团购商品
  305. app.$axios.get('/search/page', {
  306. params: {
  307. current: 1,
  308. size: 4,
  309. prodType: 1,
  310. isActive: 1 // 过滤掉活动商品
  311. }
  312. }),
  313. // 热销商品
  314. app.$axios.get('/search/page', {
  315. params: {
  316. current: 1,
  317. size: 12,
  318. sort: 2,
  319. orderBy: 1,
  320. isActive: 1 // 过滤掉活动商品
  321. }
  322. }),
  323. // 好店
  324. app.$axios.get('/shop/hotShops'),
  325. ])
  326. return {
  327. snapUpList: requestSnapUp.data.records[0].products, // 秒杀
  328. composeGroup: requestTeamBuy.data.records[0].products, // 团购
  329. hotSalesList: requestHotSales.data, //热销
  330. hotShopList: requestHotShops.data, //好店
  331. webConfigData: requestWebConfigData.data //网站配置信息
  332. }
  333. },
  334. data () {
  335. return {
  336. showLogin: false,
  337. showHeadScroll: false, //头部显隐
  338. banners: [], //轮播图
  339. hotSearchList: [], //热搜
  340. snapUpList: [], //秒杀专场
  341. composeGroup: [], //优惠团购
  342. hotSalesList: [], //商城热销
  343. current: 1,
  344. size: 10,
  345. sort: 1,
  346. orderBy: 1,
  347. showSelectItem: false, //搜索下拉选择框显隐
  348. searchItem: this.$t('index.prod'), //搜索下拉框选择店铺或商品
  349. searchTerms: '', //搜索词
  350. topsearchTerms: '', //上滑头部搜索词
  351. hotShopList: [], //优选好店
  352. searchType: 0, //搜索类型 0商品 1店铺
  353. totalCartCount: 0, // 购物车总数量
  354. webConfigData: {}, //网站配置信息
  355. language: this.$store.state.locale
  356. }
  357. },
  358. mounted () {
  359. // 缓存到本地
  360. localStorage.setItem('webConfig', JSON.stringify(this.webConfigData))
  361. util.changeFavicon()
  362. // 设置网页标题文本和图标
  363. document.title = this.webConfigData.pcTitleContentCn || ''
  364. // 监听页面滚动
  365. window.addEventListener('scroll', this.scrollToTop);
  366. //轮播图
  367. this.getIndexBanner()
  368. //热搜
  369. this.getHotSearch(this.searchType)
  370. //优选好店
  371. this.getHotShopsHead()
  372. // 获取购物车数量
  373. this.getCartCount()
  374. },
  375. watch:{
  376. },
  377. methods: {
  378. /**
  379. * 获取购物车商品总数
  380. */
  381. getCartCount () {
  382. if (Cookie.get('token')) {
  383. this.$axios.get('/p/shopCart/prodCount').then(({ data }) => {
  384. this.totalCartCount = data
  385. this.$store.commit('cartNumber/changeCartNumber', data)
  386. })
  387. }
  388. },
  389. /**
  390. * 页面滚动事件
  391. */
  392. scrollToTop () {
  393. let scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop;
  394. this.showHeadScroll = scrollTop > 90 ? true : false;
  395. },
  396. /**
  397. * 领券中心
  398. */
  399. toCoupons () {
  400. // if (Cookie.get('token')) {
  401. // console.log('token1:',Cookie.get('token'))
  402. // this.$router.push({ path: '/coupons' })
  403. // } else {
  404. // console.log('token2:',Cookie.get('token'))
  405. // this.showLogin = true
  406. // }
  407. this.$router.push({ path: '/coupons' })
  408. },
  409. /**
  410. * 隐藏登录弹窗
  411. */
  412. hideLoginPop () {
  413. this.showLogin = false
  414. },
  415. /**
  416. * 轮播图
  417. */
  418. getIndexBanner () {
  419. this.$axios.get('/indexImgs/0', {
  420. params: {
  421. imgType: 1
  422. }
  423. }).then(({ data }) => { this.banners = data || [] })
  424. },
  425. /**
  426. * 热搜词
  427. */
  428. getHotSearch () {
  429. let url = this.searchType ? '/shop/hotShops' : '/search/hotSearch'
  430. this.$axios.get(url, {
  431. params: {
  432. number: 4,
  433. sort: 1,
  434. }
  435. }).then(({ data }) => {
  436. if(this.searchType){
  437. this.hotSearchList = []
  438. for(let i=0;i<(data.length > 6 ? 6 : data.length);i++){
  439. let shoInfo = {
  440. title : data[i].shopName,
  441. hotSearchId : data[i].shopId,
  442. content: data[i].shopName
  443. }
  444. this.hotSearchList.push(shoInfo)
  445. }
  446. }else {
  447. this.hotSearchList = data
  448. }
  449. })
  450. },
  451. /** 搜索框选择 */
  452. selectChoose () {
  453. this.showSelectItem = !this.showSelectItem
  454. },
  455. /** 点击选择 店铺 || 商品 */
  456. selectSearchItem (sts) {
  457. if (sts === 0) {
  458. this.searchItem = this.$t('index.prod')
  459. this.showSelectItem = false
  460. this.searchType = 0 //商品
  461. } else if (sts === 1) {
  462. this.searchItem = this.$t('index.shop')
  463. this.showSelectItem = false
  464. this.searchType = 1 //店铺
  465. }
  466. this.getHotSearch()
  467. },
  468. /**
  469. * 搜索
  470. */
  471. toSearchProdPage () {
  472. var searchType = this.searchType
  473. var searchTerms = this.searchTerms.trim() //去除字符串的头尾空格
  474. if (searchType == 0) {
  475. if (!searchTerms) {
  476. this.$message({
  477. message: this.$t('commonHead.productNameCannotBeEmpty'),
  478. type: 'error',
  479. duration: 1000
  480. })
  481. return
  482. }
  483. // 跳转到商品列表页
  484. this.$router.push({ path: '/list?pn=' + searchTerms })
  485. } else if (searchType == 1) {
  486. if (!searchTerms) {
  487. this.$message({
  488. message: this.$t('commonHead.storeNameCannotBeEmpty'),
  489. type: 'error',
  490. duration: 1000
  491. })
  492. return
  493. }
  494. // 跳转到店铺列表页
  495. this.$router.push({ path: '/shopList?shopName=' + searchTerms })
  496. }
  497. },
  498. topSearchProd () {
  499. var searchTerms = this.topsearchTerms.trim() //去除字符串的头尾空格
  500. if (!searchTerms) {
  501. this.$message({
  502. message: this.$t('commonHead.productNameCannotBeEmpty'),
  503. type: 'error',
  504. duration: 1000
  505. })
  506. return
  507. }
  508. // 跳转到商品列表页
  509. this.$router.push({ path: '/list?pn=' + searchTerms })
  510. },
  511. /**
  512. * 点击热搜词搜索商品
  513. */
  514. onHistSearch (name) {
  515. this.searchTerms = name
  516. // this.searchType = 1
  517. this.toSearchProdPage();
  518. },
  519. /**
  520. * 商城热销
  521. */
  522. // getHotSalesProds () {
  523. // this.$axios.get('/search/searchProdPage', {
  524. // params: {
  525. // current: this.current,
  526. // size: 12,
  527. // sort: 1,
  528. // orderBy: 1
  529. // }
  530. // }).then(({ data }) => {
  531. // this.hotSalesList = data.records
  532. // })
  533. // },
  534. /**
  535. * 优选好店
  536. */
  537. getHotShopsHead () {
  538. this.$axios.get('/shop/hotShops').then(({ data }) => { this.hotShopList = data })
  539. },
  540. /**
  541. * 跳转购物车页面
  542. */
  543. toCart () {
  544. this.$router.push('/cart')
  545. },
  546. /**
  547. * 轮播图跳转到商品
  548. */
  549. imgToProd (banner) {
  550. if (banner.type !==0 ) {
  551. return
  552. }
  553. const prodId = banner.relation
  554. this.$axios.get('/prod/isStatus', {
  555. params: {
  556. prodId: prodId
  557. }
  558. }).then(({ data }) => {
  559. if (data) {
  560. this.$router.push({ name: 'detail-prodId', params: {prodId:prodId, bannerEnter: '1' } })
  561. }
  562. })
  563. }
  564. },
  565. destroyed () {
  566. // 页面销毁时移除监听
  567. window.removeEventListener('scroll', this.scrollToTop);
  568. }
  569. }
  570. </script>
  571. <style scoped src='~/assets/css/home.css'>
  572. </style>