index.vue 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395
  1. <template>
  2. <view class="page">
  3. <view class='distribution-posters'>
  4. <swiper :indicator-dots="indicatorDots" :autoplay="autoplay" :circular="circular" :interval="interval"
  5. :duration="duration" @change="bindchange" previous-margin="40px" next-margin="40px">
  6. <block v-for="(item,index) in spreadList" :key="index">
  7. <swiper-item>
  8. <image :src="item.pic" class="slide-image" :class="swiperIndex == index ? 'active' : 'quiet'"
  9. mode='aspectFill' />
  10. </swiper-item>
  11. </block>
  12. </swiper>
  13. <!-- #ifdef APP-PLUS || MP-->
  14. <view class='keep' :style="{backgroundColor:bgColor}" @click='savePhoto(spreadList[swiperIndex].pic)'>保存海报
  15. </view>
  16. <!-- #endif -->
  17. <!-- #ifndef MP || APP-PLUS -->
  18. <div class="preserve acea-row row-center-wrapper">
  19. <div class="line"></div>
  20. <div class="tip">长按保存图片</div>
  21. <div class="line"></div>
  22. </div>
  23. <!-- #endif -->
  24. </view>
  25. <view class="canvas" v-if="canvasStatus">
  26. <canvas style="width:750px;height:1190px;" canvas-id="canvasOne"></canvas>
  27. <canvas canvas-id="qrcode" :style="{width: `${qrcodeSize}px`, height: `${qrcodeSize}px`}" />
  28. </view>
  29. </view>
  30. </template>
  31. <script>
  32. // +----------------------------------------------------------------------
  33. // | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
  34. // +----------------------------------------------------------------------
  35. // | Copyright (c) 2016~2025 https://www.crmeb.com All rights reserved.
  36. // +----------------------------------------------------------------------
  37. // | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
  38. // +----------------------------------------------------------------------
  39. // | Author: CRMEB Team <admin@crmeb.com>
  40. // +----------------------------------------------------------------------
  41. // #ifdef H5 || APP-PLUS
  42. import uQRCode from '@/js_sdk/Sansnn-uQRCode/uqrcode.js'
  43. // #endif
  44. // #ifdef APP-PLUS
  45. import {
  46. HTTP_H5_URL
  47. } from '@/config/app.js';
  48. // #endif
  49. import {
  50. spreadBanner
  51. } from '@/api/user.js';
  52. import {
  53. toLogin
  54. } from '@/libs/login.js';
  55. import {
  56. mapGetters
  57. } from "vuex";
  58. // #ifdef MP
  59. import {
  60. base64src
  61. } from '@/utils/base64src.js'
  62. import {
  63. mpQrcode
  64. } from '@/api/api.js';
  65. // #endif
  66. import {
  67. setThemeColor
  68. } from '@/utils/setTheme.js'
  69. import {
  70. imageBase64
  71. } from "@/api/public";
  72. export default {
  73. data() {
  74. return {
  75. imgUrls: [],
  76. indicatorDots: false,
  77. circular: false,
  78. autoplay: false,
  79. interval: 3000,
  80. duration: 500,
  81. swiperIndex: 0,
  82. spreadList: [],
  83. poster: '',
  84. qrcodeSize: 1000,
  85. PromotionCode: '',
  86. base64List: [],
  87. canvasStatus: true, //海报绘图标签
  88. bgColor: '#e93323'
  89. };
  90. },
  91. computed: mapGetters(['isLogin', 'uid', 'userInfo']),
  92. watch: {
  93. isLogin: {
  94. handler: function(newV, oldV) {
  95. if (newV) {
  96. this.userSpreadBannerList();
  97. }
  98. },
  99. deep: true
  100. }
  101. },
  102. onLoad() {
  103. this.bgColor = setThemeColor();
  104. if (this.isLogin) {
  105. // #ifdef MP
  106. this.PromotionCode = this.$Cache.get('wechatQRcode')
  107. // #endif
  108. // #ifndef MP
  109. this.make();
  110. // #endif
  111. this.userSpreadBannerList();
  112. } else {
  113. toLogin();
  114. }
  115. },
  116. // #ifdef MP
  117. /**
  118. * 用户点击右上角分享
  119. */
  120. onShareAppMessage: function() {
  121. return {
  122. title: this.userInfo.nickname + '-分销海报',
  123. imageUrl: this.spreadList[0].pic,
  124. path: `/pages/index/index?id=0&sd=${this.uid}`,
  125. };
  126. },
  127. // #endif
  128. onReady() {},
  129. methods: {
  130. userSpreadBannerList: function() {
  131. let that = this;
  132. uni.showLoading({
  133. title: '获取中',
  134. mask: true,
  135. })
  136. spreadBanner({
  137. page: 1,
  138. limit: 5
  139. }).then(res => {
  140. uni.hideLoading();
  141. that.getImageBase64(res.data);
  142. that.$set(that, 'spreadList', res.data);
  143. }).catch(err => {
  144. uni.hideLoading();
  145. });
  146. },
  147. getImageBase64: function(images) {
  148. uni.showLoading({
  149. title: '海报生成中',
  150. mask: true
  151. });
  152. let that = this;
  153. // #ifdef H5
  154. let spreadList = []
  155. // 生成一个Promise对象的数组
  156. images.forEach(item => {
  157. const oneApi = imageBase64({
  158. url: item.pic
  159. }).then(res => {
  160. return res.data.code;
  161. })
  162. spreadList.push(oneApi)
  163. })
  164. Promise.all(spreadList).then(result => {
  165. that.$set(that, 'base64List', result);
  166. that.setShareInfoStatus();
  167. setTimeout(()=>{
  168. that.getImgCanvas(this.base64List[0], 0)
  169. },100)
  170. })
  171. // #endif
  172. // #ifdef MP || APP-PLUS
  173. that.base64List = images.map(item => {
  174. return item.pic
  175. });
  176. let arrImagesUrl = "";
  177. uni.downloadFile({
  178. url: this.base64List[0],
  179. success: (res) => {
  180. arrImagesUrl = res.tempFilePath;
  181. this.getImgCanvas(arrImagesUrl, 0)
  182. }
  183. });
  184. // #endif
  185. },
  186. getImgCanvas(arrImagesUrl, index) {
  187. this.$nextTick(() => {
  188. this.PosterCanvas(arrImagesUrl, this.PromotionCode, this.userInfo
  189. .nickname, index)
  190. })
  191. },
  192. // 生成二维码;
  193. make() {
  194. let that = this;
  195. let href = '';
  196. // #ifdef H5
  197. href = window.location.href.split('/pages')[0];
  198. // #endif
  199. // #ifdef APP-PLUS
  200. href = HTTP_H5_URL;
  201. let routes = getCurrentPages(); // 获取当前打开过的页面路由数组
  202. let curRoute = routes[routes.length - 1].route //获取当前页面路由
  203. let curParam = routes[routes.length - 1].options; //获取路由参数
  204. // #endif
  205. uQRCode.make({
  206. canvasId: 'qrcode',
  207. text: href + '/pages/index/index?sd=' + that.uid,
  208. size: this.qrcodeSize,
  209. margin: 10,
  210. success: res => {
  211. that.PromotionCode = res;
  212. },
  213. complete: (res) => {},
  214. fail: res => {
  215. uni.hideLoading();
  216. that.$util.Tips({
  217. title: '海报二维码生成失败!'
  218. });
  219. }
  220. })
  221. },
  222. PosterCanvas: function(arrImages, code, nickname, index) {
  223. let context = uni.createCanvasContext('canvasOne')
  224. context.clearRect(0, 0, 0, 0);
  225. let that = this;
  226. uni.getImageInfo({
  227. src: arrImages,
  228. success: function(res) {
  229. context.drawImage(arrImages, 0, 0, 750, 1190);
  230. context.save();
  231. context.drawImage(code, 110, 925, 140, 140);
  232. context.restore();
  233. context.setFontSize(28);
  234. context.fillText(nickname, 270, 980);
  235. context.fillText('邀请您加入', 270, 1020);
  236. setTimeout(() => {
  237. context.draw(true, function() {
  238. uni.canvasToTempFilePath({
  239. destWidth: 750,
  240. destHeight: 1190,
  241. canvasId: 'canvasOne',
  242. fileType: 'jpg',
  243. success: function(res) {
  244. // 在H5平台下,tempFilePath 为 base64
  245. uni.hideLoading();
  246. that.spreadList[index].pic = res
  247. .tempFilePath;
  248. that.$set(that, 'poster', res
  249. .tempFilePath);
  250. that.$set(that, 'canvasStatus', false);
  251. }
  252. })
  253. })
  254. }, 100);
  255. },
  256. fail: function(err) {
  257. uni.hideLoading();
  258. that.$util.Tips({
  259. title: '无法获取图片信息'
  260. });
  261. }
  262. });
  263. },
  264. bindchange(e) {
  265. let base64List = this.base64List;
  266. let index = e.detail.current;
  267. this.swiperIndex = index;
  268. let arrImagesUrl = "";
  269. uni.downloadFile({
  270. url: base64List[index],
  271. success: (res) => {
  272. arrImagesUrl = res.tempFilePath;
  273. setTimeout(() => {
  274. this.$set(this, 'canvasStatus', true);
  275. this.PosterCanvas(arrImagesUrl, this.PromotionCode, this.userInfo.nickname,
  276. index);
  277. }, 300);
  278. }
  279. });
  280. },
  281. // 点击保存海报
  282. savePhoto: function(url) {
  283. let that = this;
  284. uni.saveImageToPhotosAlbum({
  285. filePath: url,
  286. success: function(res) {
  287. that.$util.Tips({
  288. title: '保存成功',
  289. icon: 'success'
  290. });
  291. },
  292. fail: function(res) {
  293. that.$util.Tips({
  294. title: '保存失败'
  295. });
  296. }
  297. });
  298. },
  299. setShareInfoStatus: function() {
  300. if (this.$wechat.isWeixin()) {
  301. let configAppMessage = {
  302. desc: '分销海报',
  303. title: this.userInfo.nickname + '-分销海报',
  304. link: '/pages/index/index?sd=' + this.uid,
  305. imgUrl: this.spreadList[0].pic
  306. };
  307. this.$wechat.wechatEvevt(["updateAppMessageShareData", "updateTimelineShareData"],
  308. configAppMessage)
  309. }
  310. }
  311. }
  312. }
  313. </script>
  314. <style lang="scss" scoped>
  315. // page {
  316. // background-color: #A2A2A2 !important;
  317. // height: 100vh;
  318. // overflow: auto;
  319. // }
  320. .page {
  321. height: 100vh;
  322. overflow: auto;
  323. background-color: #A2A2A2 !important;
  324. }
  325. .canvas {
  326. position: relative;
  327. }
  328. .distribution-posters {
  329. width: 100%;
  330. height: 100%;
  331. display: flex;
  332. flex-direction: column;
  333. justify-content: center;
  334. align-items: center;
  335. }
  336. .distribution-posters swiper {
  337. width: 100%;
  338. height: 1000rpx;
  339. position: relative;
  340. margin-top: 40rpx;
  341. }
  342. .distribution-posters .slide-image {
  343. width: 100%;
  344. height: 100%;
  345. margin: 0 auto;
  346. border-radius: 15rpx;
  347. }
  348. .distribution-posters .slide-image.active {
  349. transform: none;
  350. transition: all 0.2s ease-in 0s;
  351. }
  352. .distribution-posters .slide-image.quiet {
  353. transform: scale(0.8333333);
  354. transition: all 0.2s ease-in 0s;
  355. }
  356. .distribution-posters .keep {
  357. font-size: 30rpx;
  358. color: #fff;
  359. width: 600rpx;
  360. height: 80rpx;
  361. border-radius: 50rpx;
  362. text-align: center;
  363. line-height: 80rpx;
  364. margin: 38rpx auto;
  365. }
  366. .distribution-posters .preserve {
  367. color: #fff;
  368. text-align: center;
  369. margin-top: 38rpx;
  370. }
  371. .distribution-posters .preserve .line {
  372. width: 100rpx;
  373. height: 1px;
  374. background-color: #fff;
  375. }
  376. .distribution-posters .preserve .tip {
  377. margin: 0 30rpx;
  378. }
  379. </style>