invite.vue 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  1. <template>
  2. <view>
  3. <!--promote/invite/invite.wxml-->
  4. <image
  5. :src="posterList[currentTab] + '?x-oss-process=style/w750-auto'"
  6. mode="widthFix" class="bgimg"></image>
  7. <!-- <view class="invite">
  8. <view class="logo dflex">
  9. <image :src="config.CONFIG_PROJECT_LOGO" mode="aspectFit" class="logoimg"></image>
  10. <view class="flex">{{config.CONFIG_PROJECT_TITLE}}</view>
  11. </view>
  12. </view> -->
  13. <view class="bot">
  14. <view class="code">
  15. <image :src="codeUrl"></image>
  16. </view>
  17. <!-- <view class="btn">
  18. <view class="share" @tap="saveImage">保存到相册</view>
  19. </view> -->
  20. </view>
  21. <view class="bott">
  22. <view class="poster-list">
  23. <scroll-view scroll-x="true">
  24. <view :class="'li' + (currentTab==index?' active':'')" v-for="(item,index) in posterList" :key="index" @click="switchTab(index)">
  25. <image :src="item" mode="widthFix"></image>
  26. </view>
  27. </scroll-view>
  28. </view>
  29. </view>
  30. <canvas canvas-id="invite" class="canvas" style="width:414px;height:795px;"></canvas>
  31. <view class="share" @tap="saveImage"><image src="../static/promote/images/download.png"></image></view>
  32. </view>
  33. </template>
  34. <script>
  35. // promote/invite/invite.js
  36. const app = getApp();
  37. const utils = require("../../utils/util.js");
  38. const req = require("../../utils/request.js");
  39. export default {
  40. data() {
  41. return {
  42. config: {},
  43. codeUrl: '',
  44. imgUrl: '',
  45. posterList: [
  46. req.public.picUrls + 'scrm/poster_pic0.jpg',
  47. req.public.picUrls + 'scrm/poster_pic1.jpg',
  48. req.public.picUrls + 'scrm/poster_pic2.jpg'
  49. ],
  50. currentTab: 0
  51. };
  52. },
  53. components: {},
  54. props: {},
  55. onLoad: async function(options) {
  56. await this.getConfig();
  57. await this.getCodeUrl();
  58. await this.generatePoster();
  59. },
  60. methods: {
  61. switchTab(index){
  62. if(this.currentTab == index) return false;
  63. this.currentTab = index;
  64. this.generatePoster();
  65. },
  66. getConfig() {
  67. var _this = this;
  68. return new Promise((resolve, reject) => {
  69. req.g('/api/config', res => {
  70. // console.log('配置数据====' + JSON.stringify(res));
  71. _this.setData({
  72. config: res
  73. });
  74. resolve();
  75. }, true);
  76. });
  77. },
  78. getCodeUrl() {
  79. let that = this; //获取小程序码
  80. let page = 'pages/index/index'
  81. const params = {
  82. page: page,
  83. // page: 'pages/authorize/authorize',
  84. scene: req.getStorage('userInfo').id// + '_' + 'isPromote'
  85. };
  86. if(req.getStorage('appId')) params.scene += '_'+ req.getStorage('appId');
  87. return new Promise((resolve, reject) => {
  88. req.getRequest('/api/program/codev', params, url => {
  89. // console.log(url);
  90. that.setData({
  91. codeUrl: url
  92. });
  93. resolve();
  94. });
  95. });
  96. },
  97. generatePoster() {
  98. let that = this;
  99. that.generate(imgUrl => {
  100. that.setData({
  101. imgUrl: imgUrl
  102. });
  103. });
  104. },
  105. isAuth(fun) {
  106. if (!uni.saveImageToPhotosAlbum) {
  107. uni.showModal({
  108. title: '提示',
  109. content: '当前微信版本过低,无法使用该功能,请升级到最新微信版本后重试。'
  110. });
  111. return;
  112. }
  113. ; //可以通过 wx.getSetting 先查询一下用户是否授权了 "scope.writePhotosAlbum" 这个 scope
  114. // #ifndef H5
  115. uni.getSetting({
  116. success(res) {
  117. // console.log(res);
  118. if (!res.authSetting['scope.writePhotosAlbum']) {
  119. // 接口调用询问
  120. uni.authorize({
  121. scope: 'scope.writePhotosAlbum',
  122. success() {
  123. // console.log("2-授权《保存图片》权限成功");
  124. fun(true);
  125. },
  126. fail() {
  127. fun(false);
  128. }
  129. });
  130. } else {
  131. // 拒绝授权
  132. fun(true);
  133. }
  134. },
  135. fail(res) {
  136. fun(false);
  137. }
  138. });
  139. // #endif
  140. },
  141. saveImage() {
  142. let that = this;
  143. that.isAuth(success => {
  144. if (success) {
  145. // console.log("图片地址=====" + that.imgUrl);
  146. uni.saveImageToPhotosAlbum({
  147. filePath: that.imgUrl,
  148. success(res) {
  149. uni.showToast({
  150. title: '图片保存成功',
  151. icon: 'none',
  152. success() {},
  153. fail() {
  154. uni.showToast({
  155. title: '图片保存失败'
  156. });
  157. }
  158. });
  159. }
  160. });
  161. }
  162. });
  163. },
  164. getImageInfo(url) {
  165. return new Promise((resolve, reject) => {
  166. if (!url) {
  167. resolve();
  168. return false;
  169. }
  170. uni.getImageInfo({
  171. src: url,
  172. success: resolve,
  173. fail: reject
  174. });
  175. });
  176. },
  177. generate(success) {
  178. // 获取商品图片
  179. const picPromise = this.getImageInfo(this.posterList[this.currentTab]);
  180. // const picPromise = this.getImageInfo(this.config.Distribution_Poster_Background);
  181. const avatarPromise = this.getImageInfo(this.config.CONFIG_PROJECT_LOGO); // 获取小程序码图
  182. const codePromise = this.getImageInfo(this.codeUrl);
  183. let that = this;
  184. Promise.all([picPromise, avatarPromise, codePromise]).then(([pic, avatar, code]) => {
  185. // 创建绘图上下文
  186. const ctx = uni.createCanvasContext('invite', this); // 绘制背景,填充满整个canvas画布
  187. let width = 414,
  188. height = 795; //默认背景
  189. ctx.drawImage(pic ? pic.path : "/promote/static/promote/images/fenxiaobg.jpg", 0, 0, width,
  190. height); //白色背景
  191. ctx.save();
  192. that.roundRect(ctx, 139, 415, 135, 135, 0);
  193. ctx.restore();
  194. ctx.drawImage(code.path, 139, 415, 135, 135);
  195. // ctx.fillStyle = '#fff';
  196. // ctx.font = "16px PingFang SC";
  197. // ctx.fillText(that.config.CONFIG_PROJECT_TITLE, 65, 40); //logo
  198. // ctx.save();
  199. // ctx.beginPath();
  200. // ctx.arc(35, 35, 20, 0, 2 * Math.PI, true); //画一个圆形裁剪区域
  201. // ctx.clip(); //裁剪
  202. // ctx.drawImage(avatar.path, 15, 15, 40, 40); //绘制图片
  203. // 完成作画
  204. ctx.draw(false, function() {
  205. uni.canvasToTempFilePath({
  206. canvasId: 'invite',
  207. success: function(res) {
  208. success.call(this, res.tempFilePath);
  209. },
  210. fail: function(res) {
  211. // console.log(res);
  212. }
  213. }, that);
  214. });
  215. });
  216. },
  217. /**
  218. *
  219. * @param {CanvasContext} ctx canvas上下文
  220. * @param {number} x 圆角矩形选区的左上角 x坐标
  221. * @param {number} y 圆角矩形选区的左上角 y坐标
  222. * @param {number} w 圆角矩形选区的宽度
  223. * @param {number} h 圆角矩形选区的高度
  224. * @param {number} r 圆角的半径
  225. */
  226. roundRect: function(ctx, x, y, w, h, r) {
  227. // 开始绘制
  228. ctx.beginPath(); // 因为边缘描边存在锯齿,最好指定使用 transparent 填充
  229. // 这里是使用 fill 还是 stroke都可以,二选一即可
  230. ctx.setFillStyle('white'); // ctx.setStrokeStyle('transparent')
  231. // 左上角
  232. ctx.arc(x + r, y + r, r, Math.PI, Math.PI * 1.5); // border-top
  233. ctx.moveTo(x + r, y);
  234. ctx.lineTo(x + w - r, y);
  235. ctx.lineTo(x + w, y + r); // 右上角
  236. ctx.arc(x + w - r, y + r, r, Math.PI * 1.5, Math.PI * 2); // border-right
  237. ctx.lineTo(x + w, y + h - r);
  238. ctx.lineTo(x + w - r, y + h); // 右下角
  239. ctx.arc(x + w - r, y + h - r, r, 0, Math.PI * 0.5); // border-bottom
  240. ctx.lineTo(x + r, y + h);
  241. ctx.lineTo(x, y + h - r); // 左下角
  242. ctx.arc(x + r, y + h - r, r, Math.PI * 0.5, Math.PI); // border-left
  243. ctx.lineTo(x, y + r);
  244. ctx.lineTo(x + r, y); // 这里是使用 fill 还是 stroke都可以,二选一即可,但是需要与上面对应
  245. ctx.fill(); // ctx.stroke()
  246. ctx.closePath(); // 剪切
  247. ctx.clip();
  248. }
  249. }
  250. };
  251. </script>
  252. <style>
  253. @import "./invite.css";
  254. </style>