index.vue 22 KB

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