cm-share-popup.vue 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. <template>
  2. <view class="cm-share-popup">
  3. <!-- 分享弹窗 -->
  4. <simple-share-popup ref="sharePopup" :posterUrl="posterUrl" @click="onPopupClick" @close="onClose">
  5. <slot name="title"></slot>
  6. </simple-share-popup>
  7. <!-- 海报画布 -->
  8. <canvas canvas-id="poster" class="poster-canvas"></canvas>
  9. </view>
  10. </template>
  11. <script>
  12. import DrawPoster from './draw-poster.js'
  13. import { getUserProfile } from '@/common/auth.js'
  14. import { generateWxUnlimited } from '@/common/share.helper.js'
  15. export default {
  16. name: 'cm-share-popup',
  17. props: {
  18. data: {
  19. type: Object,
  20. default: () => {}
  21. },
  22. type: {
  23. type: String,
  24. default: 'normal',
  25. validator: value => {
  26. return ['product', 'normal', 'activity'].indexOf(value) > -1
  27. }
  28. }
  29. },
  30. data() {
  31. return {
  32. posterUrl: '',
  33. posterData: {
  34. /* 用户信息 */
  35. avatar: '', // 用户头像
  36. username: '', // 用户名
  37. /* 页面参数 */
  38. query: '', // 查询参数字符串
  39. path: '', // 页面路径
  40. qrCodeImage: '', //页面二维码,小程序二维码
  41. /* 产品参数 */
  42. porductName: '', // 产品名
  43. productPrice: '', // 产品价格
  44. productOriginPrice: '', // 产品原价
  45. productImage: '', // 产品图片
  46. /* 活动参数 */
  47. activityName:
  48. '活动名称活动名称活动名称活动名称活动名称活动名称活动名称活动名称活动名称活动名称活动名称活动名称活动名称活动名称活动名称活动名称', // 活动名称
  49. activityImage: 'https://picsum.photos/400/400' //活动封面
  50. }
  51. }
  52. },
  53. methods: {
  54. // 分享操作
  55. onPopupClick(e) {
  56. if (e.type === 'create-poster') {
  57. console.log('生成海报')
  58. this.createPoster()
  59. } else {
  60. console.log('普通分享')
  61. this.$refs.sharePopup.close()
  62. this.onShare()
  63. }
  64. },
  65. // 打开弹窗
  66. open() {
  67. this.$refs.sharePopup.open()
  68. this.$emit('open')
  69. },
  70. close() {
  71. this.$refs.sharePopup.close()
  72. },
  73. onClose() {
  74. uni.hideLoading()
  75. this.$emit('close')
  76. },
  77. onShare() {
  78. this.$emit('share')
  79. console.log('分享')
  80. },
  81. // 创建海报
  82. async createPoster() {
  83. try {
  84. uni.showLoading({ title: '正在生成海报' })
  85. if (!this.posterUrl) {
  86. this.posterData = { ...this.posterData, ...this.data }
  87. // 从本地缓存中获取微信用户基本信息
  88. let userProfile = this.$getStorage('USER_PROFILE')
  89. if (!userProfile) {
  90. userProfile = await getUserProfile()
  91. this.$setStorage('USER_PROFILE', userProfile)
  92. }
  93. this.posterData.avatar = userProfile.avatarUrl
  94. this.posterData.username = userProfile.nickName
  95. const { data: qrCodeImage } = await generateWxUnlimited({
  96. pagePath: this.posterData.path,
  97. queryStr: this.posterData.query
  98. })
  99. this.posterData.qrCodeImage = qrCodeImage
  100. switch (this.type) {
  101. case 'product':
  102. await this.createProductPoster()
  103. break
  104. case 'activity':
  105. await this.createActivityPoster()
  106. break
  107. default:
  108. await this.createNormalPoster()
  109. }
  110. const { tempFilePath } = await this.canvasToTempFilePath()
  111. this.posterUrl = tempFilePath
  112. }
  113. uni.hideLoading()
  114. // 下载完成后转发
  115. wx.showShareImageMenu({ path: this.posterUrl })
  116. this.onShare()
  117. } catch (e) {
  118. console.log(e)
  119. } finally {
  120. uni.hideLoading()
  121. }
  122. },
  123. // 画布转图片临时链接
  124. canvasToTempFilePath() {
  125. return new Promise((resolve, reject) => {
  126. uni.canvasToTempFilePath(
  127. {
  128. canvasId: 'poster',
  129. success: res => {
  130. resolve(res)
  131. },
  132. fail() {
  133. reject(false)
  134. }
  135. },
  136. this
  137. )
  138. })
  139. },
  140. // 生成绘制文本数组
  141. generateTextArray() {
  142. const textArray = []
  143. const { productPrice, productOriginPrice, porductName, activityName } = this.posterData
  144. // 处理价格
  145. let priceText = ''
  146. if (this.type === 'product') {
  147. if (productPrice) {
  148. priceText += productPrice
  149. }
  150. if (productOriginPrice) {
  151. priceText += '¥' + productOriginPrice
  152. }
  153. }
  154. textArray.push(priceText)
  155. // 处理产品名称
  156. if (porductName || activityName) {
  157. const nameStr = porductName || activityName
  158. textArray.push(nameStr.substring(0, 12))
  159. if (nameStr.length > 24) {
  160. textArray.push(nameStr.substring(12, 23) + '...')
  161. } else {
  162. textArray.push(nameStr.substring(12))
  163. }
  164. }
  165. return textArray
  166. },
  167. // 商品海报
  168. async createProductPoster() {
  169. try {
  170. const ctx = uni.createCanvasContext('poster', this)
  171. const drawPoster = new DrawPoster(ctx, {
  172. avatarUrl: this.posterData.avatar,
  173. userName: this.posterData.username,
  174. subTitle: '强烈为你推荐该商品',
  175. coverUrl: this.posterData.productImage,
  176. ewmUrl: this.posterData.qrCodeImage,
  177. textArray: this.generateTextArray()
  178. })
  179. return await drawPoster.draw()
  180. } catch (e) {
  181. throw e
  182. }
  183. },
  184. // 活动页面
  185. async createActivityPoster() {
  186. try {
  187. const ctx = uni.createCanvasContext('poster', this)
  188. const drawPoster = new DrawPoster(ctx, {
  189. avatarUrl: this.posterData.avatar,
  190. userName: this.posterData.username,
  191. subTitle: '强烈为你推荐该活动',
  192. coverUrl: this.posterData.activityImage,
  193. ewmUrl: this.posterData.qrCodeImage,
  194. textArray: this.generateTextArray()
  195. })
  196. return await drawPoster.draw()
  197. } catch (e) {
  198. throw e
  199. }
  200. },
  201. // 普通海报
  202. async createNormalPoster() {
  203. try {
  204. const ctx = uni.createCanvasContext('poster', this)
  205. const drawPoster = new DrawPoster(ctx, {
  206. avatarUrl: this.posterData.avatar,
  207. userName: this.posterData.username,
  208. subTitle: '强烈为你推荐该商城',
  209. textArray: ['', '护肤上颜选,正品', '有好货~~']
  210. })
  211. return await drawPoster.draw()
  212. } catch (e) {
  213. throw e
  214. }
  215. }
  216. }
  217. }
  218. </script>
  219. <style lang="scss" scoped>
  220. .poster-canvas {
  221. position: fixed;
  222. top: -9999px;
  223. left: -9999px;
  224. width: 375px;
  225. height: 610px;
  226. }
  227. </style>