index.html 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363
  1. {extend name="public/container"}
  2. {block name="head_top"}
  3. <link rel="stylesheet" href="{__PLUG_PATH}swiper/swiper-3.4.1.min.css">
  4. <script type="text/javascript" src="{__PLUG_PATH}swiper/swiper-3.4.1.jquery.min.js"></script>
  5. <script type="text/javascript" src="{__PLUG_PATH}jquery-slide-up.js"></script>
  6. <script type="text/javascript" src="{__WAP_PATH}crmeb/js/jquery.downCount.js"></script>
  7. <script type="text/javascript" src="{__WAP_PATH}crmeb/js/car-model.js"></script>
  8. <script type="text/javascript" src="{__WAP_PATH}crmeb/js/base.js"></script>
  9. <script type="text/javascript" src="{__WAP_PATH}crmeb/js/lottie.min.js"></script>
  10. {/block}
  11. {block name="title"}
  12. <?= \service\SystemConfigService::get('site_name') ?>
  13. {/block}
  14. {block name="content"}
  15. <div class="page-index" id="app-index">
  16. <section ref="bsDom">
  17. <div>
  18. <div class="search-wrapper">
  19. <form method="post" @submit.prevent="goSearch">
  20. <div class="search-box flex"><input type="text" v-model="keyword" placeholder="商品搜索: 请输入商品关键词"> <a
  21. class="index-icon home-btn" href="{:url('my/notice')}">
  22. {gt name="notice" value="0"} <b class="count-num">{$notice}</b> {/gt} </a></div>
  23. </form>
  24. </div>
  25. <!-- 滑动导航 -->
  26. <div class="common-slider-nav" ref="xScroll">
  27. <ul class="swiper-wrapper">
  28. <li class="swiper-slide on"><a href="javascript:void(0);">商城优选</a></li>
  29. {volist name="category" id="vo"}
  30. <li class="swiper-slide"><a href="{:Url('store/index',['cid'=>$vo['id']])}">{$vo.cate_name}</a></li>
  31. {/volist}
  32. </ul>
  33. </div>
  34. {notempty name="banner"}
  35. <div class="banner" ref="banners">
  36. <ul class="swiper-wrapper">
  37. {volist name="banner" id="vo"}
  38. <li class="swiper-slide"><a href="<?= empty($vo['url']) ? 'javascript:void(0);' : $vo['url']; ?>">
  39. <img src="{$vo.pic|unThumb}"/> </a></li>
  40. {/volist}
  41. </ul>
  42. <div class="swiper-pagination"></div>
  43. </div>
  44. {/notempty}
  45. {notempty name="menus"}
  46. <div class="nav">
  47. <ul class="flex"> {volist name="menus" id="vo"}
  48. <li><a href="<?= empty($vo['url']) ? 'javascript:void(0);' : $vo['url']; ?>"> <img src="{$vo.icon|unThumb}">
  49. <p>{$vo.name}</p></a></li>
  50. {/volist}
  51. </ul>
  52. </div>
  53. {/notempty}
  54. {notempty name="roll_news"}
  55. <div class="hot-txt-roll border-1px flex">
  56. <div class="hot-icon"><img src="{__WAP_PATH}crmeb/images/hot-icon.png"></div>
  57. <div class="txt-list">
  58. <ul class="line"> {volist name="roll_news" id="vo"}
  59. <li style="overflow: hidden;white-space: nowrap;text-overflow: ellipsis;"><a
  60. style="display: block;"
  61. href="<?= empty($vo['url']) ? 'javascript:void(0);' : $vo['url']; ?>">{$vo.info}</a>
  62. </li>
  63. {/volist}
  64. </ul>
  65. </div>
  66. </div>
  67. {/notempty}
  68. <div class="coupon-wrapper" v-cloak="" v-show="couponList.length > 0" style="overflow:hidden;">
  69. <!--<div ref="xCoupon">-->
  70. <!-- 已使用 typethree -->
  71. <div class="coupon-list">
  72. <div class="swiper-wrapper">
  73. <div class="swiper-slide coupon-item flex" v-for="item in couponList"
  74. :class="[(isValidCoupon(item) && !item.is_use) ? 'typeone' : 'typethree']">
  75. <div class="count-num flex"><em><i class="small-symbol">¥</i>{{item.coupon_price}}</em>
  76. <p>满{{item.use_min_price}}元可用</p></div>
  77. <div class="count-btn flex" v-text="isValidCoupon(item) ? (item.is_use !== true ? '点击领取' : '您已领取') : '已经领完' "
  78. @click="isValidCoupon(item) && item.is_use !== true && userGetCoupon(item)"></div>
  79. </div>
  80. </div>
  81. </div>
  82. <!--</div>-->
  83. <a class="more-wrapper" href="{:Url('store/issue_coupon')}" v-show="couponList.length >= 2">查看更多 ></a>
  84. </div>
  85. <!-- 秒杀列表 -->
  86. {notempty name="storeSeckill"}
  87. <div class="hotspike-list">
  88. <div class="index-common-title border-1px">限时秒杀 <a href="{:Url('store/seckill_index')}"><i class="icon"></i></a></div>
  89. <ul>
  90. {volist name="storeSeckill" id="vo"}
  91. <li class="flex">
  92. <div class="picture"><img src="{$vo.image}" alt="">
  93. <div class="count-down flex countdown" data-time="{$vo.stop_time|date='Y/m/d H:i:s',###}">
  94. <span class="hours">00</span>
  95. <em>:</em>
  96. <span class="minutes">00</span>
  97. <em>:</em>
  98. <span class="seconds">00</span>
  99. </div>
  100. </div>
  101. <div class="text-info flex">
  102. <div class="title">{$vo.title}</div>
  103. <div class="price-wrapper"><span class="price"><i>¥</i>{$vo.price}</span> <span class="old-price">¥{$vo.ot_price}</span>
  104. </div>
  105. <div class="schedule flex">
  106. <span>已抢{$vo.round}%</span>
  107. <span class="schedule-bar" ><i class="schedule-weight" data-width="{$vo.round}%"></i></span></div>
  108. <a class="link" href="{:url('store/seckill_detail',['id'=>$vo.id])}">马上抢</a></div>
  109. </li>
  110. {/volist}
  111. </ul>
  112. </div>
  113. {/notempty}
  114. <!-- 商品分类模板 -->
  115. <div class="template-prolist" v-cloak="" v-for="item in cateGroupList" v-show="cateGroupList.length > 0">
  116. <div class="index-common-title border-1px">
  117. <a :href="'/wap/store/index/cid/'+item.id">
  118. {{item.cate_name}} <i class="icon"></i> </a></div>
  119. <div class="product-banner"><img :src="unThumb(item.pic)" v-show="item.pic != ''"></div>
  120. <ul class="flex">
  121. <li v-for="pro in item.product"><a :href="'/wap/store/detail/id/'+pro.id">
  122. <div class="picture"><img :src="pro.image"></div>
  123. <div class="product-info"><p class="title" v-text="pro.store_name"></p>
  124. <p class="count-wrapper flex"><span class="price"
  125. v-html="getPriceStr(pro.price)"></span> <span
  126. class="count">已售{{pro.sales}}{{pro.unit_name || '件'}}</span></p></div>
  127. </a></li>
  128. </ul>
  129. </div> <!-- 商品分类模板 -->
  130. <div class="template-prolist">
  131. <div class="title-like flex" v-show="page.list.length > 0" v-cloak=""><span class="title-line left"></span> <span class="icon"></span>
  132. <span>新品推荐</span> <span class="title-line right"></span></div>
  133. <ul class="flex">
  134. <li v-for="item in page.list" v-cloak=""><a :href="'/wap/store/detail/id/'+item.id">
  135. <div class="picture"><img :src="item.image"></div>
  136. <div class="product-info"><p class="title" v-text="item.store_name"></p>
  137. <p class="count-wrapper flex"><span class="price"
  138. v-html="getPriceStr(item.price)"></span> <span
  139. class="count">已售{{item.sales}}{{item.unit_name || '件'}}</span></p></div>
  140. </a></li>
  141. </ul>
  142. </div>
  143. <p class="loading-line" v-show="loading == true"><i></i><span>正在加载中</span><i></i></p>
  144. <p class="loading-line" v-show="loading == false && page.loaded == false" v-cloak="" @click="getList">
  145. <i></i><span>点击加载</span><i></i></p>
  146. <p class="loading-line" v-show="loading == false && page.loaded == true" v-cloak="">
  147. <i></i><span>没有更多了</span><i></i></p></div>
  148. </section>
  149. {include file="public/store_menu"}
  150. </div>
  151. <div class="flex" id="bubble-txt" style="display: none;">
  152. <div class="avatar">
  153. <img src="" alt="" class="avater-pink">
  154. </div>
  155. <span class="nickname"></span>
  156. </div>
  157. <div class="lottie-bg"><div id="lottie"></div></div>
  158. <script>
  159. var anim;
  160. var elem = document.getElementById('lottie');
  161. //elem.style.display = 'none';
  162. var animData = {
  163. container: elem,
  164. renderer: 'svg',
  165. loop: true,
  166. autoplay: true,
  167. rendererSettings: {
  168. progressiveLoad:false,
  169. imagePreserveAspectRatio: 'xMidYMid meet'
  170. },
  171. path: '{__WAP_PATH}crmeb/js/animation.json'
  172. };
  173. anim = lottie.loadAnimation(animData);
  174. anim.setSubframe(false);
  175. setTimeout(
  176. function () {
  177. $('.lottie-bg').hide();
  178. },2000)
  179. </script>
  180. <script type="text/javascript">
  181. var base = new Base64();
  182. (function () {
  183. var $pinkListUser = <?php echo json_encode($storePink);?>;
  184. if($pinkListUser.length > 0){
  185. var $i = 0,dom = $('#bubble-txt'),src = $('.avater-pink'),name = $('.nickname'),pinkShow = function (item) {
  186. src.attr('src',item['src']);
  187. name.html(item['nickname']);
  188. dom.show().addClass('bubble-txt');
  189. setTimeout(function () {
  190. dom.hide().removeClass('bubble-txt');
  191. },5100);
  192. },si = setInterval(function () {
  193. if(document.readyState=="complete"){
  194. window.clearInterval(si);
  195. pinkShow($pinkListUser[$i++]);
  196. setInterval(function () {
  197. if($pinkListUser.length <= $i) $i = 0;
  198. pinkShow($pinkListUser[$i++]);
  199. },6500);
  200. }
  201. },500);
  202. }
  203. requirejs(['vue', 'store', 'helper', 'better-scroll'], function (Vue, storeApi, $h, BScroll) {
  204. new Vue({
  205. el: '#app-index',
  206. data: {
  207. couponList: [],
  208. cateGroupList: [],
  209. page: {first: 0, limit: 20, list: [], loaded: false},
  210. loading: false,
  211. scroll: null,
  212. keyword: '',
  213. gettingCoupon: false,
  214. combinationList:[],
  215. pinkData:{
  216. src:'',
  217. nickname:''
  218. },
  219. isPinkOne:false
  220. },
  221. methods: {
  222. unThumb:function(src){
  223. return src.replace('/s_','/');
  224. },
  225. formatPrice: function (price) {
  226. var format = price.toString().split('.');
  227. if (format[1] == undefined) format[1] = '00';
  228. if (format[1].length == 1) format[1] += '0';
  229. return format;
  230. },
  231. getPriceStr: function (price) {
  232. var format = this.formatPrice(price);
  233. return "<i>¥</i>" + format[0] + "<i>." + format[1] + "</i>";
  234. },
  235. userGetCoupon: function (coupon) {
  236. if (this.gettingCoupon) return;
  237. this.gettingCoupon = true;
  238. var that = this;
  239. storeApi.goLogin() && storeApi.userGetCoupon(coupon.id, function () {
  240. coupon.is_use = true;
  241. $h.pushMsgOnce('领取成功!');
  242. setTimeout(function () {
  243. that.gettingCoupon = false;
  244. }, 300);
  245. }, function () {
  246. setTimeout(function () {
  247. that.gettingCoupon = false;
  248. }, 300);
  249. return true;
  250. });
  251. },
  252. isValidCoupon: function (coupon) {
  253. return !(coupon.total_count > 0 && coupon.remain_count == 0);
  254. },
  255. goSearch: function () {
  256. if (!this.keyword) return;
  257. location.href = $h.U({c: 'store', a: 'index', p: {keyword: base.encode(this.keyword)}});
  258. },
  259. getIssueCouponList: function () {
  260. var that = this;
  261. storeApi.getIssueCouponList(4, function (res) {
  262. that.couponList = res.data.data;
  263. that.$nextTick(function () {
  264. var sliderProduct = new Swiper('.coupon-list', { freeMode: true, freeModeMomentumRatio: 0, slidesPerView: 'auto', });
  265. })
  266. });
  267. },
  268. getCateData: function () {
  269. var that = this;
  270. storeApi.getCategoryProductList(4, function (res) {
  271. that.cateGroupList = res.data.data;
  272. // that.$nextTick(function () {
  273. // that.scroll.refresh();
  274. // })
  275. })
  276. },
  277. getCombinationList:function () {
  278. var that = this;
  279. storeApi.baseGet($h.U({
  280. c:"public_api",
  281. a:"get_pink_host",
  282. p:{limit:2}
  283. }),function (res) {
  284. that.combinationList = res.data.data;
  285. // that.$nextTick(function () {
  286. // that.scroll.refresh();
  287. // })
  288. })
  289. },
  290. elInit: function () {
  291. that = this;
  292. setTimeout(function(){
  293. var child = that.$refs.xScroll.children[0],liDom = child.getElementsByTagName('li');
  294. if(liDom.length > 0 ){
  295. child.style.width = (liDom[0].offsetWidth * liDom.length)+'px';
  296. new BScroll(that.$refs.xScroll,{eventPassthrough : 'vertical',scrollX: true, scrollY: false,observeDOM:false,click:true,probeType:1,cancelable:false});
  297. // that.$nextTick(function(){
  298. // that.scroll.refresh();
  299. // });
  300. }
  301. });
  302. setTimeout(function () {
  303. if(!that.$refs.banners) return ;
  304. var child = that.$refs.banners.children[0],liDom = child.getElementsByTagName('li');
  305. if(liDom.length > 0 ){
  306. child.style.width = (document.body.offsetWidth * liDom.length)+'px';
  307. Array.prototype.slice.call(liDom).forEach(function (item) {
  308. item.style.width = document.body.offsetWidth+'px';
  309. });
  310. new BScroll(that.$refs.banners,{eventPassthrough : 'vertical',scrollX: true, scrollY: false,observeDOM:false,click:true,probeType:1,cancelable:false,momentum: false,snap: {loop: false, threshold: 0.1, stepX: document.body.offsetWidth}});
  311. // that.$nextTick(function(){
  312. // that.scroll.refresh();
  313. // });
  314. }
  315. });
  316. $('.schedule-weight').each(function() {
  317. var _this = $(this);
  318. var width = _this.attr('data-width');
  319. _this.css("width",width);
  320. });
  321. $('.countdown').each(function () {
  322. var _this = $(this);
  323. var count = _this.attr('data-time');
  324. _this.downCount({date: count, offset: +8});
  325. });
  326. $(".line").slideUp({"li_h": $('.txt-list').height()});
  327. },
  328. getList: function () {
  329. if (this.loading) return;
  330. var that = this, group = that.page;
  331. if (group.loaded) return;
  332. this.loading = true;
  333. storeApi.getBestProductList({first: group.first, limit: group.limit}, function (res) {
  334. var list = res.data.data;
  335. group.loaded = list.length < group.limit;
  336. group.first += list.length;
  337. group.list = group.list.concat(list);
  338. that.$set(that, 'page', group);
  339. that.loading = false;
  340. // that.$nextTick(function () {
  341. // if (list.length) that.scroll.refresh();
  342. // that.scroll.finishPullUp();
  343. // });
  344. }, function () {
  345. that.loading = false
  346. });
  347. },
  348. },
  349. mounted: function () {
  350. var that = this;
  351. this.elInit();
  352. this.getIssueCouponList();
  353. this.getCateData();
  354. this.getCombinationList();
  355. setTimeout(function() {
  356. that.getList();
  357. },0);
  358. }
  359. })
  360. });
  361. }());</script>{/block}