cm-share-popup.vue 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  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 = this.posterData.image.length > 12 ? this.posterData.image : 'https://static.caimei365.com/app/img/icon/default-head-new.png' // 用户头像
  67. this.posterData.qrCode = data.qrCode // 用户二维码
  68. this.posterData.linkMan = data.linkMan // 用户名
  69. this.posterData.contractMobile = data.contractMobile // 用户手机号
  70. },
  71. // 分享操作
  72. onPopupClick(e) {
  73. if (e.type === 'create-poster') {
  74. console.log('生成海报')
  75. this.createPoster()
  76. } else {
  77. console.log('普通分享')
  78. this.$refs.sharePopup.close()
  79. this.onShare()
  80. }
  81. },
  82. // 打开弹窗
  83. open() {
  84. this.$refs.sharePopup.open()
  85. this.$emit('open')
  86. },
  87. close() {
  88. this.$refs.sharePopup.close()
  89. },
  90. onClose() {
  91. uni.hideLoading()
  92. this.$emit('close')
  93. },
  94. onShare() {
  95. this.$emit('share')
  96. console.log('分享')
  97. },
  98. // 创建海报
  99. async createPoster() {
  100. try {
  101. uni.showLoading({ title: '正在生成海报' })
  102. if (!this.posterUrl) {
  103. await this.getUserInfo()
  104. this.posterData = { ...this.posterData, ...this.data }
  105. const { data: qrCodeImage } = await generateWxUnlimited(this, {
  106. pagePath: this.posterData.path,
  107. queryStr: 'sellerUserId=' + this.userInfo.userId + '&id=' + this.posterData.id
  108. })
  109. this.posterData.qrCodeImage = qrCodeImage
  110. switch (this.type) {
  111. case 'product':
  112. await this.createProductPoster()
  113. break
  114. }
  115. const { tempFilePath } = await this.canvasToTempFilePath()
  116. this.posterUrl = tempFilePath
  117. }
  118. uni.hideLoading()
  119. // 下载完成后转发
  120. wx.showShareImageMenu({ path: this.posterUrl })
  121. this.onShare()
  122. } catch (e) {
  123. console.log(e)
  124. } finally {
  125. uni.hideLoading()
  126. }
  127. },
  128. // 画布转图片临时链接
  129. canvasToTempFilePath() {
  130. return new Promise((resolve, reject) => {
  131. uni.canvasToTempFilePath(
  132. {
  133. canvasId: 'poster',
  134. success: res => {
  135. resolve(res)
  136. },
  137. fail() {
  138. reject(false)
  139. }
  140. },
  141. this
  142. )
  143. })
  144. },
  145. // 生成绘制文本数组
  146. generateTextArray() {
  147. const textArray = []
  148. const { productPrice, productOriginPrice, productName, activityName } = this.posterData
  149. // 处理价格
  150. let priceText = ''
  151. if (this.type === 'product') {
  152. if (productPrice) {
  153. priceText += productPrice
  154. }
  155. if (productOriginPrice) {
  156. priceText += '¥' + productOriginPrice
  157. }
  158. }
  159. textArray.push(priceText)
  160. // 处理产品名称
  161. if (productName) {
  162. const nameStr = productName || activityName
  163. textArray.push(nameStr.substring(0, 12))
  164. if (nameStr.length > 24) {
  165. textArray.push(nameStr.substring(12, 23) + '...')
  166. } else {
  167. textArray.push(nameStr.substring(12))
  168. }
  169. }
  170. return textArray
  171. },
  172. // 商品海报
  173. async createProductPoster() {
  174. try {
  175. const [error, result] = await uni.downloadFile({ url: this.posterData.productImage })
  176. const [error2, result2] = await uni.downloadFile({ url: this.posterData.qrCodeImage })
  177. this.posterData.productImage = result.tempFilePath
  178. this.posterData.qrCodeImage = result2.tempFilePath
  179. const ctx = uni.createCanvasContext('poster', this)
  180. const drawPoster = new DrawPoster(ctx, {
  181. avatarUrl: this.posterData.avatar,
  182. userName: this.posterData.username,
  183. coverUrl: this.posterData.productImage,
  184. ewmUrl: this.posterData.qrCodeImage,
  185. textArray: this.generateTextArray(),
  186. image: this.posterData.image,
  187. qrCode: this.posterData.qrCode, // 用户二维码
  188. linkMan: this.posterData.linkMan, // 用户名
  189. contractMobile: this.posterData.contractMobile.replace(/(?=(\d{4})+$)/g,"-") // 用户手机号
  190. })
  191. return await drawPoster.draw()
  192. } catch (e) {
  193. throw e
  194. }
  195. }
  196. }
  197. }
  198. </script>
  199. <style lang="scss" scoped>
  200. .poster-canvas {
  201. position: fixed;
  202. top: -9999px;
  203. left: -9999px;
  204. width: 375px;
  205. height: 620px;
  206. }
  207. </style>