| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177 |
- <template>
- <section class="cert-id">
- <section class="cert-id-box">
- <template v-if="detail.name">
- <h1>{{detail.name}}证书</h1>
- <div class="hr"></div>
- <canvas ref="canvas" width="850" height="520">对不起, 您的浏览器不支持绘图功能, 请更新浏览器.</canvas>
- <img ref="img" class="img" src="~@/assets/img/cert/bg.png" alt="img">
- <img ref="qrImg" class="img" src="/api/cert/certQrCode" alt="qrImg">
- <section style="width: 850px;">
- <a :href="userinfo.seo_uri">开发者个人主页 ></a>
- <br>
- <a :href="`/cert/freelancer?id=${detail.id}`">{{detail.name}}认证标准 ></a>
- </section>
- </template>
- <h1 v-else>未查询到证书</h1>
- </section>
- </section>
- </template>
- <script>
- import http from '@/plugins/http'
- import bg from '@/assets/img/cert/bg.png'
- import { mapState } from 'vuex'
- let canvas = null
- , ctx = null
- , img = null
- , interval = null
- , qrLoaded = false
- , imgLoaded = false
- , userinfoLoaded = false
- export default {
- async asyncData(ctx) {
- let res = await http.post(`/api/cert/getCertDetail`, { cert_no: ctx.query.no })
- , detail = {}
- if(res) {
- detail = res.data
- }
- return {
- detail
- }
- },
- head() {
- return {
- title: `${this.detail.name}证书-程序员客栈`,
- }
- },
- data() {
- return { detail: {} }
- },
- computed: {
- ...mapState(['userinfo']),
- },
- mounted() {
- if(!this.detail.name) return
- this.initCanvas()
- this.checkInfoFull()
- interval = setInterval(this.checkInfoFull, 500)
- },
- methods: {
- checkInfoFull() {
- this.$refs.qrImg.onload = () => qrLoaded = true
- this.$refs.img.onload = () => imgLoaded = true
- if(this.userinfo.uid) userinfoLoaded = true
- if(qrLoaded && imgLoaded && userinfoLoaded) {
- this.fillingCanvas()
- clearInterval(interval)
- }
- },
- initCanvas() {
- canvas = this.$refs.canvas
- ctx = canvas.getContext('2d')
- img = this.$refs.img
- },
- fillingCanvas() {
- let detail = this.detail
- , userinfo = this.userinfo
- , canvasWidth = 850
- , textWidth = 0
- , text = ''
- // 背景
- ctx.drawImage(img, 0, 0, 850, 520)
- // 真实姓名
- let realname = detail.realname
- ctx.font = '43px 微软雅黑'
- textWidth = ctx.measureText(realname).width
- ctx.fillText(realname, canvasWidth / 2 - textWidth / 2, 280)
- // 用户信息
- let id = userinfo.uid
- , nickname = userinfo.nickname
- ctx.font = '14px 微软雅黑'
- ctx.fillStyle = '#666'
- text = `ID ${id} | 昵称 ${nickname}`
- textWidth = ctx.measureText(text).width
- ctx.fillText(text, canvasWidth / 2 - textWidth / 2, 320)
- // 内容
- let content = detail.content
- ctx.font = '16px 微软雅黑'
- ctx.fillStyle = '#000'
- textWidth = 660
- let lineWidth = 0
- , fullWidth = 0
- for(let i = 0; i < content.length; i++) {
- lineWidth += ctx.measureText(content[i]).width
- if(lineWidth < textWidth) {
- ctx.fillText(content[i], canvasWidth / 2 - textWidth / 2 + lineWidth, 350)
- fullWidth = lineWidth
- } else {
- ctx.fillText(content[i], canvasWidth / 2 + lineWidth - fullWidth - 76, 370)
- }
- }
- // 二维码
- let qr = detail.qr
- ctx.drawImage(this.$refs.qrImg, 70, 380, 76, 76)
- // 证书编号
- let certNO = detail.cert_no
- ctx.font = '12px 微软雅黑'
- ctx.fillStyle = '#666'
- ctx.fillText(`证书编号 ${certNO}`, 160, 410)
- // 起始时间
- let startDate = detail.start_date
- , endDate = detail.end_date
- , statusName = detail.cert_status_name
- text = `有效时间 ${startDate} - ${endDate} ${statusName}`
- ctx.font = '12px 微软雅黑'
- ctx.fillText(text, 160, 430)
- // 状态框
- let boxWidth = ctx.measureText(statusName).width + 10
- ctx.rect(ctx.measureText(text).width - boxWidth + 165, 414, boxWidth, 22)
- ctx.stroke()
- }
- }
- }
- </script>
- <style scoped>
- .cert-id-box {
- display: flex;
- flex-direction: column;
- align-items: center;
- width: 1000px;
- padding-bottom: 30px;
- margin-top: 20px;
- background: white;
- }
- h1 {
- font-size: 26px;
- font-family: PingFangSC-Medium;
- font-weight: 500;
- color: #1d2a3a;
- margin: 28px 0 24px;
- }
- .hr {
- width: 960px;
- height: 1px;
- background: #eee;
- margin-bottom: 12px;
- }
- .img {
- width: 850px;
- height: 520px;
- display: none;
- }
- a {
- line-height: 28px;
- margin-left: 12px;
- text-decoration: underline;
- font-size: 14px;
- font-family: PingFangSC-Regular;
- color: #666;
- }
- </style>
|