QrCodePopup.vue 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. <template>
  2. <u-popup v-model="visible" mode="bottom" border-radius="24" :mask-close-able="true">
  3. <view class="qr-sheet">
  4. <view class="sheet-title">{{ tableNo }}桌号二维码</view>
  5. <view class="qr-block">
  6. <text class="qr-label">小程序二维码</text>
  7. <image class="qr-img" :src="miniQrUrl" mode="aspectFit"></image>
  8. </view>
  9. <view class="qr-block" v-if="officialQrUrl">
  10. <text class="qr-label">公众号二维码</text>
  11. <image class="qr-img" :src="officialQrUrl" mode="aspectFit"></image>
  12. </view>
  13. <view class="btn primary sheet-btn" :class="{ disabled: saving }" @click="handleSave">保存二维码</view>
  14. </view>
  15. <canvas
  16. canvas-id="qrPosterCanvas"
  17. class="poster-canvas"
  18. :style="{ width: posterSize.width + 'px', height: posterSize.height + 'px' }"
  19. ></canvas>
  20. </u-popup>
  21. </template>
  22. <script>
  23. import { saveQrPoster, posterSize } from '@/utils/saveQrPoster.js'
  24. export default {
  25. name: 'QrCodePopup',
  26. props: {
  27. value: {
  28. type: Boolean,
  29. default: false
  30. },
  31. tableNo: {
  32. type: String,
  33. default: ''
  34. },
  35. miniQrUrl: {
  36. type: String,
  37. default: ''
  38. },
  39. officialQrUrl: {
  40. type: String,
  41. default: ''
  42. }
  43. },
  44. data() {
  45. return {
  46. saving: false,
  47. posterSize
  48. }
  49. },
  50. computed: {
  51. visible: {
  52. get() {
  53. return this.value
  54. },
  55. set(val) {
  56. this.$emit('input', val)
  57. }
  58. }
  59. },
  60. methods: {
  61. handleSave() {
  62. if (this.saving) return
  63. if (!this.miniQrUrl) {
  64. uni.showToast({ title: '暂无二维码', icon: 'none' })
  65. return
  66. }
  67. this.saving = true
  68. uni.showLoading({ title: '保存中', mask: true })
  69. saveQrPoster({
  70. tableNo: this.tableNo,
  71. qrUrl: this.miniQrUrl,
  72. canvasId: 'qrPosterCanvas',
  73. vm: this
  74. }).then(() => {
  75. // #ifdef H5
  76. uni.showToast({ title: '已保存到本地', icon: 'success' })
  77. // #endif
  78. // #ifndef H5
  79. uni.showToast({ title: '已保存到相册', icon: 'success' })
  80. // #endif
  81. this.$emit('save')
  82. }).catch(() => {
  83. uni.showToast({ title: '保存失败,请稍后重试', icon: 'none' })
  84. }).finally(() => {
  85. this.saving = false
  86. uni.hideLoading()
  87. })
  88. }
  89. }
  90. }
  91. </script>
  92. <style lang="scss" scoped>
  93. .qr-sheet {
  94. padding: 0 80rpx calc(40rpx + env(safe-area-inset-bottom));
  95. background: #fff;
  96. }
  97. .sheet-title {
  98. text-align: center;
  99. font-weight: 500;
  100. font-size: 32rpx;
  101. color: #1D2129;
  102. padding: 56rpx 0 52rpx;
  103. }
  104. .qr-block {
  105. padding: 48rpx 0 70rpx;
  106. display: flex;
  107. flex-direction: column;
  108. align-items: center;
  109. position: relative;
  110. background: linear-gradient(-190deg, #DEEEFF 0%, #FFFFFF 18%);
  111. border-radius: 24rpx;
  112. &::before {
  113. content: '';
  114. position: absolute;
  115. top: 0;
  116. left: 0;
  117. right: 0;
  118. bottom: 0;
  119. border-radius: 24rpx;
  120. padding: 2rpx;
  121. background: linear-gradient(360deg, rgba(16, 173, 255, 0) 35%, rgba(33, 101, 246, 1) 190%);
  122. -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
  123. -webkit-mask-composite: xor;
  124. mask-composite: exclude;
  125. }
  126. .qr-img {
  127. width: 200rpx;
  128. height: 200rpx;
  129. background: #f5f6f8;
  130. }
  131. .qr-label {
  132. font-weight: 500;
  133. font-size: 28rpx;
  134. color: #165DFF;
  135. margin-bottom: 44rpx;
  136. }
  137. }
  138. .sheet-btn {
  139. margin-top: 22rpx;
  140. }
  141. .btn {
  142. height: 88rpx;
  143. line-height: 88rpx;
  144. text-align: center;
  145. border-radius: 44rpx;
  146. font-size: 32rpx;
  147. font-weight: 500;
  148. &.primary {
  149. background: linear-gradient(88deg, #0FB0FF 0%, #2260F6 100%);
  150. color: #fff;
  151. }
  152. &.disabled {
  153. opacity: 0.6;
  154. }
  155. }
  156. .poster-canvas {
  157. position: fixed;
  158. left: -9999px;
  159. top: -9999px;
  160. pointer-events: none;
  161. }
  162. </style>