index.vue 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677
  1. <template>
  2. <div class="Appindex">
  3. <!-- 顶部 -->
  4. <view class="head">
  5. <!-- 轮播图 -->
  6. <swiper-banner :radius="1" imgScale="5:2" :imgArr="BannerImg" :duration="1000" :interval="5000" :circular="true" :autoplay="true" @goList="goList" :indicator-dots="true" indicator-active-color="#12B280" indicator-color="rgba(255, 255, 255, .82)"></swiper-banner>
  7. <!-- 轮播图-end -->
  8. <!-- 公告 -->
  9. <view class="head_notice clearfix">
  10. <view class="notice_title" @click="goNoticeList">
  11. <image class="gg_img" src="@/static/img/gg.png"></image>
  12. </view>
  13. <swiper class="notice_swiper" vertical autoplay circular :interval="5000" :duration="1000">
  14. <swiper-item v-for="(item, index) in not_list" :key="index" @click="toDetail(item.article_id)">
  15. <text class="not_list ellipsis">{{ item.title }}</text>
  16. <text class="not_ico iconfont">&#xe62e;</text>
  17. </swiper-item>
  18. </swiper>
  19. </view>
  20. <!-- 公告-end -->
  21. <!-- 专区入口 -->
  22. <div class="l_tabBar flex_r flex_jb">
  23. <div class="search-box flex_r flex_jb flex_ac">
  24. <div class="district" @click="showAddress = !showAddress">
  25. <span>{{ LocationCity }}</span>
  26. <span class="iconfont">&#xe62f;</span>
  27. </div>
  28. <div class="search flex_r flex_jb flex_ac">
  29. <span class="iconfont">&#xe661;</span>
  30. <input v-model="searchKey" @confirm="toSearch" class="inp" placeholder="搜索你要的内容">
  31. <span class="search_btn" @click="toSearch">搜索</span>
  32. </div>
  33. <!-- <div class="scan-ico iconfont">&#xe8cf;</div> -->
  34. </div>
  35. <div class="item" v-for="(i,s) in tabs" :key="s" @click="goto(i.url)">
  36. <img :src="i.ico" alt="" class="ico">
  37. <!-- <div class="tit">{{ i.tit }}</div> -->
  38. </div>
  39. </div>
  40. <!-- 专区-end -->
  41. <!-- 活动 -->
  42. <view class="activity" v-if="homeImg.length">
  43. <image class="act_img act_one_img" :src="homeImg[0].image" @click="toActivePage(homeImg[0])" mode=""></image>
  44. <view class="act_other">
  45. <image class="act_img act_two_img" :src="homeImg[1].image" mode="" @click="toActivePage(homeImg[1])"></image>
  46. <image class="act_img act_two_img" :src="homeImg[2].image" @click="toActivePage(homeImg[2])" mode=""></image>
  47. </view>
  48. </view>
  49. <!-- 活动-end -->
  50. </view>
  51. <view class="bou_head flex_r flex_ac flex_jc">
  52. <image class="bou_img" src="/static/sgin/left.png" mode=""></image>
  53. <view class="bou_title">今日推荐</view>
  54. <image class="bou_img" src="/static/sgin/right.png" mode=""></image>
  55. </view>
  56. <view class="list_bar">
  57. <view class="product-list">
  58. <view class="product" v-for="(i, s) in productList" :key="s" @click="NavToGoodsDetail(i.id, i.type)">
  59. <view class="image-view">
  60. <image class="product-image" :src="i.original_img"></image>
  61. </view>
  62. <view class="content-view">
  63. <view :class="['product-title', 'ellipsis']">{{ i.goods_name }}</view>
  64. <view class="product-price">
  65. <template v-if="i.type == 1">
  66. <text class="product-price-original">{{ i.total_amount }}</text>
  67. <text class="product-price-msg">(含服务费{{$h.Mul(i.service,2)}}元)</text>
  68. </template>
  69. <text class="product-price-original" v-else>{{ i.price }}</text>
  70. <text class="product-text" v-if="[3,4].includes(i.type)">赠<text class="corFE2C15">{{ i.give_cha_bao }}</text>茶宝</text>
  71. </view>
  72. <view class="product-txt" v-if="i.type == 4">
  73. <text class="product-price-favour">{{i.market_price}}</text>
  74. <text class="product-text">消费金抵</text>
  75. <span class="corFE2C15">¥{{ Number(i.consume) }}</span>
  76. </view>
  77. <!-- <view class="product-txt" v-if="i.type == 1">赠送{{ i.give_integral + "批发券" }}</view> -->
  78. <view class="product-txt" v-if="[3].includes(i.type)">限时赠送<text class="corFE2C15">{{ i.teac }}</text>TeaC</view>
  79. <view class="product-txt fenxiang" v-if="[3].includes(i.type)">
  80. <text class="iconfont red">&#xe62b;</text>
  81. <text class="red">分享约获得 {{ i.first_teac }} {{i.type==3?'TeaC':'现金'}}</text>
  82. </view>
  83. <view v-if="[4].includes(i.type)" class="flex_r flex_ac">
  84. <view class="product-txt">赠<text class="corFE2C15">{{ i.teac }}</text>TeaC</view>
  85. <!-- <view class="product-txt fenxiang flex_r flex_ac" style="background-color: rgba(0, 0, 0, 0);">
  86. <text class="iconfont red">&#xe62b;</text>
  87. <text class="red">{{ i.first_teac }}</text>
  88. </view> -->
  89. </view>
  90. </view>
  91. </view>
  92. </view>
  93. </view>
  94. <view class="fz_w_text">让数字经济赋能美好生活!</view>
  95. <!-- 城市选择 -->
  96. <h-address @select="selectaddress" :visible.sync="showAddress" />
  97. <!-- 隐私指引 -->
  98. <!-- <xh-privacy title="隐私保护指引" color="#18bb88"></xh-privacy> -->
  99. <!-- #ifdef APP-PLUS -->
  100. <uni-popup ref="popup">
  101. <view class="progressBox">
  102. <icon type="loading" size="26"/>
  103. <text class="words">下载中 请勿退出 {{ totalBytesWritten + " / " + totalBytesExpectedToWrite }}</text>
  104. </view>
  105. </uni-popup>
  106. <!-- #endif -->
  107. </div>
  108. </template>
  109. <script>
  110. // import xhPrivacy from "@/components/xh-privacy/xh-privacy.vue"; //隐私保护指引
  111. import swiperBanner from "@/components/swiperBanner/index.vue"; //轮播
  112. import hAddress from "@/components/h-address/address.vue"; //城市选择
  113. // import tabs from '@/static/js/tabs' //专区入口
  114. import { post } from "@/request/api.js";
  115. import { formatBytes } from "@/utils/index";
  116. export default {
  117. name: "Appindex",
  118. components: {
  119. swiperBanner, //轮播
  120. hAddress
  121. // xhPrivacy,
  122. },
  123. data() {
  124. return {
  125. BannerImg: [], // 轮播图列表
  126. not_list: [], // 公告列表
  127. homeImg: "", //活动列表
  128. productList: [], //商品数据
  129. searchKey: "", //搜索关键词
  130. LocationCity: "中国",
  131. showAddress: false,
  132. tabs: [],
  133. totalBytesWritten: "0B", // 已经下载的数据长度
  134. totalBytesExpectedToWrite: "0B", // 预期需要下载的数据总长度
  135. filePath:"",
  136. percentVal:0,
  137. newAppInfo:{}
  138. };
  139. },
  140. onLoad(option) {
  141. this.getToCity()
  142. this.loadData()
  143. // uni.Luserfun()
  144. // #ifdef APP-PLUS
  145. this.getNewVersion()
  146. // #endif
  147. },
  148. onShow() {
  149. this.getBanner(); //获取轮播图
  150. this.getAnnounce(); //获取公告列表
  151. this.gethomeImg(); //活动列表
  152. this.getTabs(); //获取专区
  153. },
  154. onHide() {},
  155. methods: {
  156. loadData() {
  157. post("v1/goods/indexGoods").then((res) => {
  158. if (res.code === 0) {
  159. this.productList = res.data.data;
  160. }
  161. });
  162. },
  163. getNewVersion(){
  164. post("v1/getAppVersion").then((res) => {
  165. if (res.code === 0) {
  166. console.log(res.data.data);
  167. if(plus.os.name == "Android"){
  168. this.filePath = res.data.data.android.url
  169. this.newAppInfo = res.data.data.android
  170. // 获取当前版本
  171. plus.runtime.getProperty(plus.runtime.appid, (wgtinfo) => {
  172. console.log();
  173. if(wgtinfo.versionCode < this.newAppInfo.version){
  174. this.update()
  175. }
  176. });
  177. }
  178. }
  179. });
  180. },
  181. // 跳转到商品详情页
  182. NavToGoodsDetail(id, type) {
  183. this.goto("/pages/product/p_details", { id, type });
  184. },
  185. // 获取轮播图
  186. getBanner() {
  187. post("v1/banner").then((res) => {
  188. if (res.code === 0) {
  189. this.BannerImg = [];
  190. res.data.data.forEach((e) => {
  191. if (e.image) this.BannerImg.push(e.image);
  192. });
  193. }
  194. });
  195. },
  196. // 获取专区
  197. getTabs() {
  198. post("local/menu/list").then((res) => {
  199. if (res.code === 0) {
  200. this.tabs = res.data
  201. }
  202. });
  203. },
  204. // 活动列表
  205. gethomeImg() {
  206. post("v1/homeImg").then((res) => {
  207. if (res.code === 0) {
  208. this.homeImg = res.data.data
  209. }
  210. });
  211. },
  212. // 跳转公告列表页
  213. goNoticeList() {
  214. this.goto("/pages/consultation-list/index");
  215. },
  216. // 获取公告列表
  217. getAnnounce() {
  218. post("v1/notice", { is_index: 1 }).then((res) => {
  219. if (res.code === 0) {
  220. this.not_list = res.data.data;
  221. }
  222. });
  223. },
  224. //跳转公告详情
  225. toDetail(id) {
  226. this.goto("/pages/notice/detail", { id });
  227. },
  228. // 轮播图跳转
  229. goList(e) {},
  230. // 金刚区跳转
  231. setPageUrl(item) {
  232. if ([1, 3, 4, 6].includes(item.type)) {
  233. this.goto("/pages/product/productRetail", { type: item.type });
  234. } else if (item.type == 2) {
  235. this.goto("/pages/product/productWholesale", { type: 2 });
  236. } else if (item.type == 5) {
  237. this.goto("/pages/product/productTeaBaby", { type: item.type });
  238. } else {
  239. appEv.errTips("此功能暂未开放!");
  240. return false;
  241. }
  242. },
  243. toActivePage(item){
  244. let istab = item.url.indexOf('tab=1')
  245. if(istab>0){
  246. let url = item.url.split('?')[0]
  247. uni.switchTab({
  248. url: url
  249. })
  250. }else{
  251. this.goto(item.url)
  252. }
  253. },
  254. goVipGift() {
  255. this.goto("/pages/product/productRetail", { type: 4, is_vip: 1 });
  256. },
  257. // 搜索
  258. toSearch() {
  259. this.goto("/pagesC/settledMerchant/index", { key: this.searchKey });
  260. },
  261. // 获取当前城市
  262. async getToCity() {
  263. let { lat, lng } = await uni.Location();
  264. post("local/hotel/city", { longitude: lng, latitude: lat }).then(res => {
  265. if (res.code == 0) {
  266. let da = res.data
  267. // this.LocationCity = da.cityName;
  268. }
  269. })
  270. },
  271. // 选择城市
  272. selectaddress(da) {
  273. this.LocationCity = da.cityName;
  274. this.showAddress = false;
  275. },
  276. update(){
  277. const _this = this;
  278. uni.showModal({
  279. title: "版本更新",
  280. content: "APP有新版本发布,点击 立即更新 进行最新版本下载。",
  281. showCancel: this.newAppInfo.is_mast == 1 ? true: false,
  282. confirmText: "立即更新",
  283. cancelText: "稍后进行",
  284. success: function (res) {
  285. if (res.confirm) {
  286. _this.$refs.popup.open()
  287. // _this.show = true; // show变量控制一个下载进度弹框(这个UI样式自己写即可)
  288. // 创建一个下载任务,并根据后端返回的apk静态资源地址filePath进行下载
  289. let downloadTask = uni.downloadFile({
  290. url: _this.filePath,
  291. success: (res) => {
  292. console.log(res, "下载成功");
  293. this.updateProgressShow = false;
  294. if (res.statusCode === 200) {
  295. _this.$refs.popup.close()
  296. plus.runtime.install(
  297. res.tempFilePath,
  298. {},
  299. function () {
  300. console.log("install success...");
  301. plus.runtime.restart();
  302. // uni.hideLoading();
  303. uni.setStorageSync("wgtinfo", null);
  304. },
  305. function (e) {
  306. uni.showToast({
  307. icon: "error",
  308. title: "更新失败",
  309. duration: 1500,
  310. });
  311. }
  312. );
  313. } else {
  314. _this.$refs.popup.close()
  315. uni.showToast({
  316. icon: "error",
  317. title: "更新失败",
  318. duration: 1500,
  319. });
  320. }
  321. },
  322. fail: (err) => {
  323. _this.$refs.popup.close()
  324. uni.showToast({
  325. icon: "error",
  326. title: "更新失败",
  327. duration: 1500,
  328. });
  329. },
  330. });
  331. downloadTask.onProgressUpdate((res) => {
  332. // console.log(res, "进度");
  333. // console.log("下载进度" + res.progress);
  334. // console.log("已经下载的数据长度" + res.totalBytesWritten);
  335. // console.log(
  336. // "预期需要下载的数据总长度" + res.totalBytesExpectedToWrite
  337. // );
  338. let totalBytesWritten = formatBytes(res.totalBytesWritten);
  339. let totalBytesExpectedToWrite = formatBytes(
  340. res.totalBytesExpectedToWrite
  341. );
  342. let num1 = totalBytesWritten.fileSize.split(
  343. totalBytesWritten.matchUnit.unitName
  344. );
  345. let num2 = totalBytesExpectedToWrite.fileSize.split(
  346. totalBytesExpectedToWrite.matchUnit.unitName
  347. );
  348. _this.totalBytesWritten =
  349. Math.floor(num1[0] * 100) / 100 +
  350. totalBytesWritten.matchUnit.unitName;
  351. _this.totalBytesExpectedToWrite =
  352. Math.floor(num2[0] * 100) / 100 +
  353. totalBytesExpectedToWrite.matchUnit.unitName;
  354. _this.percentVal = res.progress;
  355. });
  356. } else if (res.cancel) {
  357. console.log("稍后更新");
  358. }
  359. },
  360. });
  361. }
  362. },
  363. computed: {},
  364. watch: {},
  365. };
  366. </script>
  367. <style scoped lang='scss'>
  368. .head {
  369. padding: 12rpx 28rpx;
  370. }
  371. .head_search {
  372. width: 100%;
  373. height: 64rpx;
  374. line-height: 64rpx;
  375. background: #f3f5f7;
  376. border-radius: 32rpx;
  377. text-align: center;
  378. font-size: 28rpx;
  379. color: #bbbbbb;
  380. margin-bottom: 26rpx;
  381. .search_text {
  382. margin-left: 14rpx;
  383. }
  384. }
  385. .head_notice {
  386. margin: 30rpx 0;
  387. .notice_title {
  388. width: 130rpx;
  389. height: 40rpx;
  390. float: left;
  391. .gg_img {
  392. width: 100%;
  393. height: 40rpx;
  394. }
  395. }
  396. .notice_swiper {
  397. height: 40rpx;
  398. padding-left: 20rpx;
  399. font-size: 28rpx;
  400. float: left;
  401. box-sizing: border-box;
  402. width: calc(100% - 130rpx);
  403. .not_list {
  404. width: calc(100% - 50rpx);
  405. }
  406. .not_ico {
  407. width: 30rpx;
  408. font-size: 28rpx;
  409. color: #999;
  410. }
  411. .not_list,
  412. .not_ico {
  413. display: inline-block;
  414. vertical-align: middle;
  415. height: 40rpx;
  416. line-height: 40rpx;
  417. }
  418. }
  419. }
  420. .l_tabBar {
  421. margin: 32rpx 0;
  422. background-color: #fff;
  423. padding: 10rpx 20rpx;
  424. border-radius: 10rpx;
  425. box-shadow: 4rpx 4rpx 8rpx 4rpx rgba(0, 0, 0, 0.12);
  426. flex-wrap: wrap;
  427. .search-box {
  428. width: 100%;
  429. padding: 10rpx;
  430. margin-bottom: 12rpx;
  431. .district {
  432. font-size: 32rpx;
  433. font-weight: 600;
  434. color: #333;
  435. .iconfont {
  436. font-size: 20rpx;
  437. margin-left: 12rpx;
  438. }
  439. }
  440. .search {
  441. border: 1px solid #D78C2E;
  442. height: 60rpx;
  443. line-height: 60rpx;
  444. padding-left: 20rpx;
  445. border-radius: 31rpx;
  446. .iconfont {
  447. font-size: 30rpx;
  448. }
  449. .inp {
  450. font-size: 25rpx;
  451. padding: 0 8rpx;
  452. width: 300rpx;
  453. }
  454. .search_btn {
  455. background-color: #D78C2E;
  456. height: 100%;
  457. color: #fff;
  458. border-radius: 31rpx;
  459. font-size: 28rpx;
  460. padding: 0 28rpx;
  461. }
  462. }
  463. .scan-ico {
  464. font-size: 55rpx;
  465. }
  466. }
  467. .item {
  468. width: 105rpx;
  469. margin: 10rpx 10rpx;
  470. }
  471. .ico {
  472. width: 100%;
  473. height: 138rpx;
  474. }
  475. // .tit{
  476. // font-size: 26rpx;
  477. // text-align: center;
  478. // }
  479. }
  480. .bou_head {
  481. width: 100%;
  482. height: 114rpx;
  483. // margin-top: 50rpx;
  484. .bou_img {
  485. width: 92rpx;
  486. height: 30rpx;
  487. }
  488. .bou_title {
  489. height: 30rpx;
  490. line-height: 30rpx;
  491. font-size: 36rpx;
  492. color: #121212;
  493. font-weight: bold;
  494. margin: 0 36rpx;
  495. }
  496. }
  497. // 活动
  498. .activity {
  499. .act_one_img {
  500. display: inline-block;
  501. width: 300rpx;
  502. height: 378rpx;
  503. margin-right: 10rpx;
  504. }
  505. .act_other {
  506. display: inline-block;
  507. width: calc(100% - 300rpx - 10rpx);
  508. }
  509. .act_two_img {
  510. width: 100%;
  511. height: 185rpx;
  512. }
  513. .act_img {
  514. border-radius: 10rpx;
  515. }
  516. }
  517. // 活动-end
  518. // 商品列表
  519. .list_bar {
  520. .tit {
  521. text-align: center;
  522. font-size: 36rpx;
  523. color: #121212;
  524. padding: 40rpx 0 20rpx;
  525. font-weight: bold;
  526. }
  527. }
  528. .product-list {
  529. width: 100%;
  530. display: flex;
  531. flex-wrap: wrap;
  532. flex-direction: row;
  533. padding: 0 30rpx;
  534. .product {
  535. width: 48.5%;
  536. margin-bottom: 20rpx;
  537. padding-bottom: 12rpx;
  538. border-radius: 10rpx;
  539. box-shadow: 4rpx 4rpx 8rpx 4rpx rgba(0, 0, 0, 0.12);
  540. &:nth-child(2n) {
  541. margin-left: 3%;
  542. }
  543. }
  544. .product-image {
  545. border-radius: 10rpx 10rpx 0 0;
  546. width: 100%;
  547. height: 42.3vw;
  548. object-fit: cover;
  549. }
  550. .content-view {
  551. padding: 0 16rpx;
  552. }
  553. .product-title {
  554. width: 100%;
  555. overflow: hidden;
  556. line-height: 1.5;
  557. font-size: 28rpx;
  558. color: #121212;
  559. }
  560. .product-price {
  561. color: #121212;
  562. font-size: 28rpx;
  563. position: relative;
  564. }
  565. .product-price-original {
  566. color: #18bb88;
  567. font-size: 32rpx;
  568. font-weight: bold;
  569. &:before {
  570. content: "¥";
  571. font-size: 20rpx;
  572. }
  573. }
  574. .product-price-favour {
  575. color: #888888;
  576. text-decoration: line-through;
  577. margin-left: 20rpx;
  578. }
  579. .product-tip {
  580. position: absolute;
  581. right: 20rpx;
  582. background-color: #ff3333;
  583. color: #ffffff;
  584. padding: 0 20rpx;
  585. border-radius: 10rpx;
  586. }
  587. .product-unit {
  588. font-size: 24rpx;
  589. color: #18bb88;
  590. }
  591. .product-txt,
  592. .product-text {
  593. font-size: 22rpx;
  594. color: #787878;
  595. .iconfont {
  596. margin-right: 3rpx;
  597. }
  598. }
  599. .product-price-msg {
  600. font-size: 20rpx;
  601. color: #ff6d44;
  602. }
  603. .product-text {
  604. margin-left: 16rpx;
  605. }
  606. .red {
  607. color: #FA2E18;
  608. }
  609. .fenxiang {
  610. font-size: 20rpx;
  611. background: rgba(250, 46, 24, 0.08);
  612. display: inline-block;
  613. border-radius: 6rpx;
  614. padding: 0 16rpx;
  615. }
  616. }
  617. .progressBox{
  618. padding: 40rpx;
  619. border-radius: 4rpx;
  620. background-color: #fff;
  621. }
  622. </style>