<template>
  <BasePage>
    <div class="paycode-page">
      <div class="paycode-wrap">
        <!-- 生成后的图片 -->
        <div v-if="generatedImage" class="paycode-generated">
          <img :src="generatedImage" alt="收款码">
        </div>
        <!-- 原始元素 -->
        <div v-else class="paycode-original" ref="paycodeOriginalRef">
          <img src="/img/paycode.jpg" alt="" style="width: 100%; display: block;" class="bg-img" @load="onBgLoad">
          <div class="user-info">
            <div class="info">
              <img :src="$file(shopimg)" alt="" style="border-radius: 50%;">
            </div>
            <div class="name">
              <span>{{ shopname?.length > 8 ? shopname.slice(0, 8) + '...' : shopname }}</span>
            </div>
          </div>
          <div class="code">
            <vue-qr v-if="link" :margin="0" :text="link" backgroundColor="rgb(255,255,255)"
              colorLight="rgb(255,255,255)"></vue-qr>
          </div>
        </div>
      </div>
      <div class="save-btn">
        <van-button type="primary" color="#ca2904" round block :loading="loading" @click="handleSave">{{ loading ?
          '生成中...' : ('保存图片')
        }}</van-button>
      </div>
    </div>
  </BasePage>
</template>

<script>
import { toDataURL } from '@/utils/html2image'

export default {
  name: 'PayCode',
  data() {
    return {
      shopname: '',
      shopimg: '',
      link: '',
      loading: false,
      generatedImage: '',
      bgLoaded: false,
    }
  },
  mounted() {
    this.init()
  },
  methods: {
    init() {
      const id = this.$route.query.id
      this.$get(`/v1/client/DShopsClient/${id}`).then(res => {
        this.shopname = res.data.shopname
        this.shopimg = res.data.shopimg
        this.link = `${location.origin}${location.pathname}#/Checkout?id=${res.data.userid}`
      }).catch(err => {
        this.$showFailToast('加载失败')
      })
    },

    onBgLoad() {
      this.bgLoaded = true
      // 背景图加载完成后自动生成图片
      this.generateImage()
    },

    async generateImage() {
      if (!this.bgLoaded || this.loading) return
      this.loading = true
      try {
        await this.$nextTick()
        await document.fonts.ready
        await new Promise(resolve => setTimeout(resolve, 300))
        const el = this.$refs.paycodeOriginalRef
        this.generatedImage = await toDataURL(el, { format: 'png', pixelRatio: 3, useCORS: true })
      } catch (e) {
        this.$showFailToast('生成失败')
      } finally {
        this.loading = false
      }
    },

    async handleSave() {
      if (this.loading) return
      // 如果已生成图片，直接下载
      if (this.generatedImage) {
        this.downloadByBlob(this.generatedImage, `收款码_${this.shopname}.png`)
        this.$showSuccessToast('保存成功')
        return
      }
      // 否则生成图片
      await this.generateImage()
      if (this.generatedImage) {
        this.downloadByBlob(this.generatedImage, `收款码_${this.shopname}.png`)
        this.$showSuccessToast('保存成功')
      }
    },

    downloadByBlob(dataUrl, filename) {
      const arr = dataUrl.split(',')
      const mime = arr[0].match(/:(.*?);/)[1]
      const bstr = atob(arr[1])
      let n = bstr.length
      const u8arr = new Uint8Array(n)
      while (n--) {
        u8arr[n] = bstr.charCodeAt(n)
      }
      const blob = new Blob([u8arr], { type: mime })
      const url = URL.createObjectURL(blob)
      const link = document.createElement('a')
      link.download = filename
      link.href = url
      document.body.appendChild(link)
      link.click()
      document.body.removeChild(link)
      URL.revokeObjectURL(url)
    },
  },
}
</script>

<style lang="less" scoped>
.paycode-page {
  // min-height: 100vh;
  background: #f5f5f5;
  padding-bottom: 20px;
}

.paycode-generated {
  img {
    width: 100%;
    display: block;
  }
}

.paycode-original {
  position: relative;
  width: 100%;
  font-family: 'PingFang SC';

  >img {
    width: 100%;
    display: block;
  }

  .user-info {
    position: absolute;
    left: 50%;
    transform: translateX(-50%);
    top: 32.27vw;
    display: flex;
    align-items: center;
  }

  .info {
    display: flex;
    align-items: center;

    img {
      width: 6.4vw;
      height: 6.4vw;
      border-radius: 50%;
    }
  }

  .name {
    margin-left: 2.67vw;
    // margin-bottom: 2.4vw;

    span {
      font-size: 4vw;
      color: #333;
    }
  }

  .code {
    position: absolute;
    top: 42.4vw;
    left: 23.33vw;

    canvas,
    img {
      width: 53.33vw;
      height: 53.33vw;
    }
  }
}

.save-btn {
  margin: 20px;
}
</style>