C端小程序
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

492 行
15 KiB

  1. const Http = require("../../../../utils/HttpBasics");
  2. const imgurl = require("../../../../utils/imgurl");
  3. const config = require("../../../../config/config");
  4. const extConfig = wx.getExtConfigSync ? wx.getExtConfigSync() : {}
  5. let imgOrgUrl = extConfig.attr.imgOrgUrl;
  6. let imgOrgUrl1 = extConfig.attr.imgOrgUrl1;
  7. let imgNewUrl = extConfig.attr.imgNewUrl;
  8. let app = getApp();
  9. Page({
  10. /**
  11. * 页面的初始数据
  12. */
  13. data: {
  14. poterbg: imgurl.poterbg.url,
  15. teljpgUrl: imgurl.teljpg.url,
  16. share01: imgurl.share01.url,
  17. actUrl: imgurl.act.url,
  18. poster: './../../../../assets/images/picture.png',
  19. page: 1,
  20. imglist: null,
  21. shopVoList: [],
  22. couponList: [], //活动劵列表
  23. qrCodeL:'',//小程序码
  24. currentTab: 0,
  25. isshare: false,
  26. showpost: false,
  27. imgHeight: 0,
  28. id: null,
  29. windowWidth: wx.getSystemInfoSync().windowWidth,
  30. windowHeight: wx.getSystemInfoSync().screenHeight,
  31. totalHeight: 0,
  32. canvasScale: 1.0, // 画布放大的倍数,因为如果保存的是一倍的分享图片的话,分享图会有点虚。所以保存的时候,canvasScale设置为2.0,wxss 里面的left: 500%;打开注释。就可保存两倍的分享图
  33. },
  34. /**
  35. * 分享海报的生成
  36. */
  37. //关闭海报
  38. closePoste: function() {
  39. this.setData({
  40. showpost: false
  41. })
  42. },
  43. /**
  44. * 生命周期函数--监听页面加载
  45. */
  46. onLoad: function(options) {
  47. let that = this;
  48. if (options && options.id) {
  49. this.setData({
  50. id: options.id
  51. });
  52. that.getList(options.id);
  53. that.getCouponList(options.id);
  54. this.setData({
  55. currentTab: 0
  56. })
  57. }
  58. this.getUserInfo()
  59. },
  60. /**
  61. * 绘制分享海报
  62. */
  63. begainDrawShareImage() {
  64. wx.showLoading({
  65. title: '生成中...',
  66. })
  67. var that = this
  68. // 适配屏幕
  69. let scale = this.data.windowWidth / 375.0
  70. this.setData({
  71. totalHeight: 767 * scale
  72. })
  73. // 获取Canvas
  74. let ctx = wx.createCanvasContext('myCanvas')
  75. // 获取宽高
  76. let wW = that.data.windowWidth;
  77. let wH = that.data.windowHeight;
  78. // 放大 因为不放大的话,生成的分享图会模糊。暂时先注释
  79. ctx.scale(this.data.canvasScale, this.data.canvasScale)
  80. // 绘制背景图
  81. let bgimg1 = this.data.poterbg + `?imageView/2/w/${wW}/h/${wH}`
  82. let bgimg2 = bgimg1.replace(imgOrgUrl1, imgNewUrl)
  83. ctx.drawImage(bgimg2, 0, 0, wW, wH);
  84. //绘制头像
  85. let avatar1 = this.data.avatarUrl + `?imageView/2/w/${wW}/h/${wH}`
  86. let avatar2 = avatar1.replace(imgOrgUrl, imgNewUrl)
  87. ctx.drawImage(avatar2, 15, 10, 30*scale,30*scale);
  88. // 首先要绘制顶部的背景图片,因为它在最底层,然后才能绘制其他内容
  89. let topImageWidth = parseInt(315 * scale) // 因为小数有时候会请求不到图片,所以转成int
  90. let topImageHeight = parseInt(200 * scale)
  91. let src1 = this.data.data.merchantImgUrl + `?imageView/2/w/${topImageWidth}/h/${topImageHeight}`
  92. let src2 = src1.replace(imgOrgUrl, imgNewUrl)
  93. wx.getImageInfo({
  94. src: src2,
  95. success: function(res) {
  96. // 绘制白色背景
  97. ctx.setFillStyle('#fff')
  98. ctx.fillRect(25,45, topImageWidth+10, topImageHeight+10)
  99. ctx.draw()
  100. ctx.drawImage(res.path, 30,50, topImageWidth, topImageHeight)
  101. that.drawOtherContent(ctx, scale)
  102. that.drawOtherImage(ctx, scale)
  103. }
  104. })
  105. },
  106. //获取头像和昵称
  107. getUserInfo: function () {
  108. let that = this;
  109. // 获取用户信息
  110. Http.get({
  111. url: config.api.getScore,
  112. data: {}
  113. })
  114. .then(res => {
  115. console.log(res)
  116. that.setData({
  117. nickName: res.data.nickName,
  118. avatarUrl: res.data.avatarUrl
  119. })
  120. })
  121. },
  122. // 绘制除了图片之外的剩余内容
  123. drawOtherContent(ctx, scale) {
  124. //昵称
  125. this.drawNormalText(ctx, this.data.nickName+" 向您推荐", 50 * scale, 25 * scale, 16 * scale, '#fff', 'left', 'middle', scale);
  126. //店铺名
  127. this.drawNormalText(ctx, this.data.data.merchantName, 180 * scale, 280 * scale, 30 * scale, '#fff', 'center', 'middle', scale);
  128. //店铺电话
  129. // this.drawNormalText(ctx, "商铺电话:"+this.data.data.merchantLinkPhone, 100 * scale, 405 * scale, 16 * scale, '#000', 'left', 'middle', scale);
  130. if (this.data.couponList.length>0) {
  131. for (let i = 0; i < this.data.couponList.length; i++) {
  132. // 第一个商品信息
  133. this.drawNormalText(ctx, this.substrTile(this.data.couponList[1].title), 40 * scale, 396 * scale, 14 * scale, '#000', 'left', 'middle', scale);
  134. this.drawNormalText(ctx, "价格:"+this.data.couponList[1].salePrice, 40 * scale, 416 * scale, 14 * scale, '#FF3232', 'left', 'middle', scale);
  135. //第二个商品信息
  136. this.drawNormalText(ctx, this.substrTile(this.data.couponList[2].title), 155 * scale, 396 * scale, 14 * scale, '#000', 'left', 'middle', scale);
  137. this.drawNormalText(ctx, "价格:"+this.data.couponList[2].salePrice, 155 * scale, 416 * scale, 14 * scale, '#FF3232', 'left', 'middle', scale);
  138. //第三个商品信息
  139. this.drawNormalText(ctx, this.substrTile(this.data.couponList[3].title), 270 * scale, 396 * scale, 14 * scale, '#000', 'left', 'middle', scale);
  140. this.drawNormalText(ctx, "价格:"+this.data.couponList[3].salePrice, 270 * scale, 416 * scale, 14 * scale, '#FF3232', 'left', 'middle', scale);
  141. }
  142. }
  143. this.drawNormalText(ctx, "长按二维码识别小程序进店逛逛", 85 * scale, 570 * scale, 16 * scale, '#000', 'left', 'middle', scale);
  144. ctx.draw(true)
  145. },
  146. //截取商品名
  147. substrTile(str){
  148. return str.substr(0,5)+'...'
  149. },
  150. // 绘制活动图片
  151. drawOtherImage(ctx, scale) {
  152. var that = this
  153. // 如果该商户有活动商品
  154. if (that.data.couponList.length>0) {
  155. let cotentImageWidth = parseInt(80 * scale)
  156. let cotentImageHeight = parseInt(80 * scale)
  157. for (let i = 0; i < that.data.couponList.length; i++) {
  158. let imageItem = that.data.couponList[i].coverImg
  159. let src1 = imageItem + `?imageView/2/w/${cotentImageWidth}/h/${cotentImageHeight}`
  160. let src2 = src1.replace(imgOrgUrl, imgNewUrl)
  161. wx.getImageInfo({
  162. src: src2,
  163. success: function(res) {
  164. // ctx.setFillStyle('rgba(255,255,255,0.3)')
  165. // ctx.fillRect(25,300, 300*scale, 200*scale)
  166. // ctx.draw(true)
  167. ctx.drawImage(res.path, 45 * scale + i * 110 * scale, 300 * scale, cotentImageWidth, cotentImageHeight)
  168. }
  169. })
  170. }
  171. }
  172. if (this.data.qrCode) {
  173. let coImageWidth = parseInt(120 * scale)
  174. let coImageHeight = parseInt(120 * scale)
  175. let src1 = this.data.qrCode + `?imageView/2/w/${coImageWidth}/h/${coImageHeight}`
  176. let src2 = src1.replace(imgOrgUrl, imgNewUrl)
  177. wx.getImageInfo({
  178. src: src2,
  179. success: function(res) {
  180. ctx.drawImage(res.path, 115 * scale, 425 * scale, coImageWidth, coImageHeight)
  181. ctx.draw(true)
  182. }
  183. })
  184. }
  185. wx.hideLoading()
  186. },
  187. // 绘制只有一行的文字
  188. drawNormalText(ctx, str, x, y, font, style, align, baseLine) {
  189. ctx.setFontSize(font);
  190. ctx.setFillStyle(style);
  191. ctx.setTextAlign(align);
  192. ctx.setTextBaseline(baseLine);
  193. ctx.fillText(str, x, y);
  194. },
  195. /*
  196. * 绘制多行文本,自动换行,超出添加...
  197. *
  198. str:要绘制的字符串
  199. canvas:canvas对象
  200. initX:绘制字符串起始x坐标
  201. initY:绘制字符串起始y坐标
  202. lineHeight:字行高,自己定义个值即可
  203. maxWidth: 文本最大宽度
  204. row: 最大行数
  205. */
  206. canvasTextAutoLine: function(str, ctx, initX, initY, lineHeight, maxWidth, row = 1) {
  207. var lineWidth = 0;
  208. var lastSubStrIndex = 0;
  209. var currentRow = 1;
  210. for (let i = 0; i < str.length; i++) {
  211. lineWidth += ctx.measureText(str[i]).width;
  212. if (lineWidth > maxWidth) {
  213. currentRow++;
  214. let newStr = str.substring(lastSubStrIndex, i)
  215. if (currentRow > row && str.length > i) {
  216. newStr = str.substring(lastSubStrIndex, i - 2) + '...'
  217. }
  218. ctx.fillText(newStr, initX, initY);
  219. initY += lineHeight;
  220. lineWidth = 0;
  221. lastSubStrIndex = i;
  222. if (currentRow > row) {
  223. break;
  224. }
  225. }
  226. if (i == str.length - 1) {
  227. ctx.fillText(str.substring(lastSubStrIndex, i + 1), initX, initY);
  228. }
  229. }
  230. },
  231. /**
  232. * 图片预览方法
  233. * 此处注意的一点就是,调用 "wx.previewImage"时,第二个参数要求为数组形式哦
  234. * 当然,做过图片上传功能的应该会注意到,如果涉及到多张图片预览,图片链接数组集合即为参数 urls!
  235. */
  236. previewImage: function() {
  237. wx.canvasToTempFilePath({
  238. x: 0,
  239. y: 0,
  240. width: this.data.windowWidth * this.data.canvasScale,
  241. height: this.data.totalHeight * this.data.canvasScale,
  242. canvasId: 'myCanvas',
  243. success: function (res) {
  244. var current = res.tempFilePath;
  245. wx.previewImage({
  246. current: current,
  247. urls: [current]
  248. })
  249. },
  250. fail: function (res) {
  251. wx.showToast({
  252. title: '图片生成失败',
  253. icon: 'none',
  254. duration: 2000
  255. })
  256. }
  257. })
  258. },
  259. // 保存图片
  260. saveImage(){
  261. let that = this
  262. wx.canvasToTempFilePath({
  263. x: 0,
  264. y: 0,
  265. width: this.data.windowWidth * this.data.canvasScale,
  266. height: this.data.totalHeight * this.data.canvasScale,
  267. canvasId: 'myCanvas',
  268. success: function (res) {
  269. that.saveImageToPhotos(res.tempFilePath);
  270. },
  271. fail: function (res) {
  272. wx.showToast({
  273. title: '图片生成失败',
  274. icon: 'none',
  275. duration: 2000
  276. })
  277. }
  278. })
  279. },
  280. saveImageToPhotos: function (tempFilePath) {
  281. wx.saveImageToPhotosAlbum({
  282. filePath: tempFilePath,
  283. success(result) {
  284. wx.showToast({
  285. title: '保存成功,从相册中分享到朋友圈吧',
  286. icon: 'none',
  287. duration: 4000
  288. })
  289. },
  290. fail: function (err) {
  291. if (err.errMsg === "saveImageToPhotosAlbum:fail:auth denied" || err.errMsg === "saveImageToPhotosAlbum:fail auth deny") {
  292. // 这边微信做过调整,必须要在按钮中触发,因此需要在弹框回调中进行调用
  293. wx.showModal({
  294. title: '提示',
  295. content: '需要您授权保存相册',
  296. showCancel: false,
  297. success:modalSuccess=>{
  298. wx.openSetting({
  299. success(settingdata) {
  300. console.log("settingdata", settingdata)
  301. if (settingdata.authSetting['scope.writePhotosAlbum']) {
  302. wx.showModal({
  303. title: '提示',
  304. content: '获取权限成功,再次点击图片即可保存',
  305. showCancel: false,
  306. })
  307. } else {
  308. wx.showModal({
  309. title: '提示',
  310. content: '获取权限失败,将无法保存到相册哦~',
  311. showCancel: false,
  312. })
  313. }
  314. },
  315. fail(failData) {
  316. console.log("failData",failData)
  317. },
  318. complete(finishData) {
  319. console.log("finishData", finishData)
  320. }
  321. })
  322. }
  323. })
  324. }
  325. },
  326. })
  327. },
  328. /**
  329. * 拨打电话
  330. */
  331. phone: function(e) {
  332. let that = this;
  333. wx.makePhoneCall({
  334. phoneNumber: e.target.dataset.merchantlinkphone
  335. });
  336. },
  337. /**
  338. * 显示分享弹框
  339. */
  340. showshare: function() {
  341. this.setData({
  342. isshare: true,
  343. })
  344. },
  345. /**
  346. * 隐藏分享弹框
  347. */
  348. hidemodal: function() {
  349. this.setData({
  350. isshare: false,
  351. })
  352. },
  353. //滑动切换
  354. swiperTabView: function(e) {
  355. this.setData({
  356. currentTab: e.detail.current
  357. });
  358. },
  359. /**
  360. * 隐藏分享海报
  361. */
  362. hideposter: function() {
  363. this.setData({
  364. showpost: false,
  365. })
  366. },
  367. /**
  368. * 显示分享海报
  369. */
  370. showPoster: function() {
  371. this.setData({
  372. showpost: true,
  373. })
  374. this.begainDrawShareImage();
  375. },
  376. //点击切换
  377. clickTab: function(e) {
  378. if (this.data.currentTab === e.target.dataset.current) {
  379. return false;
  380. } else {
  381. this.setData({
  382. currentTab: e.target.dataset.current
  383. })
  384. }
  385. },
  386. /**
  387. * 获取商户详情
  388. */
  389. getList: function(id) {
  390. let that = this;
  391. let data;
  392. data = {
  393. pageNum: that.data.page,
  394. pageSize: 15,
  395. id: id
  396. }
  397. Http.get({
  398. url: config.api.merchantList,
  399. data: data
  400. }).then(res => {
  401. let imgList = [];
  402. imgList.push(res.data.list[0].merchantImgUrl)
  403. that.setData({
  404. data: res.data.list[0],
  405. shopVoList: res.data.list[0].shopVoList,
  406. imglist: res.data.list[0].coverPicture == '[]' ? imgList:JSON.parse(res.data.list[0].coverPicture),
  407. })
  408. })
  409. .catch(err => {
  410. wx.showToast({
  411. title: err.errMsg,
  412. icon: 'none',
  413. duration: 2000,
  414. mask: false
  415. });
  416. })
  417. },
  418. /**
  419. * 获取商户活动信息 券类型(1.满减券,2.代金券,3.团购券,4.礼品券,5.停车券,6.多商户券,8.砍价券,9.团购券,50.积分券,51.积分停车券 100.消费卡)
  420. * 投放频道:(1.列表, 2.限时抢购, 3. banner图 4. 游戏 5.卡频道 6.砍价频道 7.拼团频道 8专题)
  421. */
  422. getCouponList: function(id) {
  423. let that = this;
  424. let data;
  425. data = {
  426. status: 0,
  427. merchantId: id,
  428. pageNum: that.data.page,
  429. pageSize: 15,
  430. }
  431. Http.get({
  432. url: config.api.listByMerchant,
  433. data: data
  434. }).then(res => {
  435. that.setData({
  436. couponList: res.data.page.list,
  437. qrCode:res.data.qrCode,
  438. })
  439. })
  440. .catch(err => {
  441. wx.showToast({
  442. title: err.errMsg,
  443. icon: 'none',
  444. duration: 2000,
  445. mask: false
  446. });
  447. })
  448. },
  449. /**
  450. * 获取多商铺列表
  451. */
  452. shopList: function(e) {
  453. wx.navigateTo({
  454. url: `/pages/index/merchantList/index?id=${e.currentTarget.dataset.id}`
  455. })
  456. },
  457. // onShareAppMessage: function(res) {
  458. // var that = this;
  459. // var shareObj = {
  460. // title: that.data.data.title,
  461. // path: `/pages/index/index?couponChannelId=${that.data.couponChannelId}`,
  462. // success: function(res) {
  463. // if (res.errMsg == 'shareAppMessage:ok') {}
  464. // },
  465. // fail: function(error) {
  466. // if (res.errMsg == 'shareAppMessage:fail cancel') {} else if (res.errMsg == 'shareAppMessage:fail') {}
  467. // }
  468. // };
  469. // // 来自页面内的按钮的转发
  470. // if (res.from === 'button') {
  471. // var eData = res.target.dataset.id;
  472. // shareObj.path = `/pages/index/index?couponChannelId=${eData}`;
  473. // }
  474. // // 返回shareObj
  475. // return shareObj;
  476. // },
  477. })