cm-share-popup.vue 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  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 { mapState } from 'vuex'
  14. import { generateWxUnlimited, enCodeQueryStr } from '@/pages/goods/mixins/share.helper.js'
  15. import simpleSharePopup from './simple-share-popup/simple-share-popup.vue'
  16. export default {
  17. name: 'cm-share-popup',
  18. components: {
  19. simpleSharePopup
  20. },
  21. props: {
  22. data: {
  23. type: Object,
  24. default: () => {}
  25. },
  26. type: {
  27. type: String,
  28. default: 'normal',
  29. validator: value => {
  30. return ['product', 'normal', 'activity'].indexOf(value) > -1
  31. }
  32. }
  33. },
  34. data() {
  35. return {
  36. posterUrl: '',
  37. ctx: '',
  38. posterData: {
  39. /* 用户信息 */
  40. image: '', // 用户头像
  41. qrCode: '', // 用户二维码
  42. linkMan: '', // 用户名
  43. contractMobile: '', // 用户手机号
  44. /* 页面参数 */
  45. query: '', // 查询参数字符串
  46. path: '', // 页面路径
  47. qrCodeImage: '', //页面二维码,小程序二维码
  48. /* 产品参数 */
  49. porductName: '', // 产品名
  50. productPrice: '', // 产品价格
  51. productOriginPrice: '', // 产品原价
  52. productImage: '', // 产品图片
  53. id: '', //商品id
  54. /* 活动参数 */
  55. activityName: '', // 活动名称
  56. activityImage: 'https://picsum.photos/400/400' //活动封面
  57. }
  58. }
  59. },
  60. computed: {
  61. ...mapState(['userInfo'])
  62. },
  63. methods: {
  64. async getUserInfo() {
  65. const { data } = await this.SellerService.GetSellerHome({ userId: this.userInfo.userId })
  66. this.posterData.image =
  67. data.image === 'undefined' || !data.image
  68. ? 'https://static.caimei365.com/app/img/icon/default-head.png'
  69. : data.image // 用户头像
  70. this.posterData.qrCode = data.qrCode // 用户二维码
  71. this.posterData.linkMan = data.linkMan // 用户名
  72. this.posterData.contractMobile = data.contractMobile // 用户手机号
  73. },
  74. // 分享操作
  75. onPopupClick(e) {
  76. if (e.type === 'create-poster') {
  77. console.log('生成海报')
  78. this.createPoster()
  79. } else {
  80. console.log('普通分享')
  81. this.$refs.sharePopup.close()
  82. this.onShare()
  83. }
  84. },
  85. // 打开弹窗
  86. open() {
  87. this.$refs.sharePopup.open()
  88. this.$emit('open')
  89. },
  90. close() {
  91. this.$refs.sharePopup.close()
  92. },
  93. onClose() {
  94. uni.hideLoading()
  95. this.$emit('close')
  96. },
  97. onShare() {
  98. this.$emit('share')
  99. console.log('分享')
  100. },
  101. // 创建海报
  102. async createPoster() {
  103. try {
  104. uni.showLoading({ title: '正在生成海报' })
  105. if (!this.posterUrl) {
  106. await this.getUserInfo()
  107. this.posterData = { ...this.posterData, ...this.data }
  108. const { data: qrCodeImage } = await generateWxUnlimited(this, {
  109. pagePath: this.posterData.path,
  110. queryStr: 'sellerUserId=' + this.userInfo.userId + '&id=' + this.posterData.id
  111. })
  112. this.posterData.qrCodeImage = qrCodeImage
  113. switch (this.type) {
  114. case 'product':
  115. await this.createProductPoster()
  116. break
  117. }
  118. const { tempFilePath } = await this.canvasToTempFilePath()
  119. this.posterUrl = tempFilePath
  120. }
  121. uni.hideLoading()
  122. // 下载完成后转发
  123. wx.showShareImageMenu({ path: this.posterUrl })
  124. this.onShare()
  125. } catch (e) {
  126. console.log(e)
  127. } finally {
  128. uni.hideLoading()
  129. }
  130. },
  131. // 画布转图片临时链接
  132. canvasToTempFilePath() {
  133. return new Promise((resolve, reject) => {
  134. uni.canvasToTempFilePath(
  135. {
  136. canvasId: 'poster',
  137. success: res => {
  138. resolve(res)
  139. },
  140. fail() {
  141. reject(false)
  142. }
  143. },
  144. this
  145. )
  146. })
  147. },
  148. // 生成绘制文本数组
  149. generateTextArray() {
  150. const textArray = []
  151. const { productPrice, productOriginPrice, productName, activityName } = this.posterData
  152. // 处理价格
  153. let priceText = ''
  154. if (this.type === 'product') {
  155. if (productPrice) {
  156. priceText += productPrice
  157. }
  158. if (productOriginPrice) {
  159. priceText += '¥' + productOriginPrice
  160. }
  161. }
  162. textArray.push(priceText)
  163. // 处理产品名称
  164. if (productName) {
  165. const nameStr = productName || activityName
  166. textArray.push(nameStr.substring(0, 12))
  167. if (nameStr.length > 24) {
  168. textArray.push(nameStr.substring(12, 23) + '...')
  169. } else {
  170. textArray.push(nameStr.substring(12))
  171. }
  172. }
  173. return textArray
  174. },
  175. // 商品海报
  176. async createProductPoster() {
  177. try {
  178. const [error, result] = await uni.downloadFile({ url: this.posterData.productImage })
  179. const [error2, result2] = await uni.downloadFile({ url: this.posterData.qrCodeImage })
  180. this.posterData.productImage = result.tempFilePath
  181. this.posterData.qrCodeImage = result2.tempFilePath
  182. const ctx = uni.createCanvasContext('poster', this)
  183. const drawPoster = new DrawPoster(ctx, {
  184. avatarUrl: this.posterData.avatar,
  185. userName: this.posterData.username,
  186. coverUrl: this.posterData.productImage,
  187. ewmUrl: this.posterData.qrCodeImage,
  188. textArray: this.generateTextArray(),
  189. image: this.posterData.image,
  190. qrCode: this.posterData.qrCode, // 用户二维码
  191. linkMan: this.posterData.linkMan, // 用户名
  192. contractMobile: this.posterData.contractMobile.replace(/(?=(\d{4})+$)/g,"-") // 用户手机号
  193. })
  194. return await drawPoster.draw()
  195. } catch (e) {
  196. throw e
  197. }
  198. }
  199. }
  200. }
  201. </script>
  202. <style lang="scss" scoped>
  203. .poster-canvas {
  204. position: fixed;
  205. top: -9999px;
  206. left: -9999px;
  207. width: 375px;
  208. height: 620px;
  209. }
  210. </style>