123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167 |
- <template>
- <canvas ref="shareCanvas" :width="canvasWidth" :height="canvasHeight"></canvas>
- <Loading :visible="loading" />
- </template>
- <script setup>
- import { ref, watch } from 'vue'
- import { getJobAdvertisedShareQrcode } from '@/api/position'
- import { saveShareQuery } from '@/api/recruit/personal/jobFair'
- const emit = defineEmits(['success'])
- const props = defineProps({
- canvasWidth: {
- type: Number,
- default: 540
- },
- canvasHeight: {
- type: Number,
- default: 788
- },
- show: Boolean,
- enterpriseName: String,
- logoUrl: String,
- positionList: Array,
- jobFairId: String,
- enterpriseId: String,
- bgImg: String
- })
- const loading = ref(false)
- const shareCanvas = ref(null)
- const imgSrc = ref('')
- const drawCanvas = () => {
- loading.value = true
- const canvas = shareCanvas.value
- const ctx = canvas.getContext('2d')
- const img = new Image()
- img.crossOrigin = 'anonymous'
- img.onload = async () => {
- //清空画布
- ctx.clearRect(0, 0, props.canvasWidth, props.canvasHeight)
- // 设置背景图片
- ctx.drawImage(img, 0, 0, props.canvasWidth, props.canvasHeight)
- // 分享二维码
- const secondImg = new Image()
- secondImg.crossOrigin = 'anonymous'
- secondImg.onload = () => {
- // 分享二维码
- ctx.drawImage(secondImg, 80, 550, 110, 110)
- ctx.font = 'bold 18px Arial'
- ctx.fillStyle = '#000'
- ctx.fillText('海量职位火热招聘中', 280, 605)
- ctx.font = '15px Arial'
- ctx.fillStyle = '#999'
- ctx.fillText('长按图片识别二维码', 290, 625)
- const thirdImg = new Image()
- thirdImg.crossOrigin = 'anonymous'
- thirdImg.onload = () => {
- // 企业头像
- ctx.save()
- const secondImgWidth = 80
- const secondImgHeight = 80
- const x = (canvas.width - secondImgWidth) / 2
- const y = canvas.height - secondImgHeight - 460
-
- ctx.beginPath()
- ctx.arc(x + secondImgWidth / 2, y + secondImgHeight / 2, secondImgWidth / 2, 0, Math.PI * 2, true)
- ctx.clip()
- ctx.drawImage(thirdImg, x, y, secondImgWidth, secondImgHeight)
- ctx.restore()
- // 企业名称
- const maxTextWidth = 400
- const text = props.enterpriseName
- const fontStyle = 'bold 18px Arial'
- ctx.font = fontStyle
- let truncatedText = text
- while (ctx.measureText(truncatedText + '...').width > maxTextWidth && truncatedText.length > 0) {
- truncatedText = truncatedText.slice(0, -1)
- }
- if (truncatedText !== text) truncatedText += '...'
- const textX = x + (secondImgWidth - ctx.measureText(truncatedText).width) / 2
- const textY = y + secondImgHeight + 30
- ctx.fillStyle = '#000'
- ctx.fillText(truncatedText, textX, textY)
- // 职位标签
- const tagPaddingLeftRight = 20
- const tagPaddingTopBottom = 10
- const tagRadius = 8
- const tagSpacing = 30
- let tagY = textY + tagSpacing
- props.positionList.forEach((tag) => {
- let truncatedTag = tag
- while (ctx.measureText(truncatedTag + '...').width > maxTextWidth - 2 * tagPaddingLeftRight && truncatedTag.length > 0) {
- truncatedTag = truncatedTag.slice(0, -1)
- }
- if (truncatedTag !== tag) truncatedTag += '...'
- const tagWidth = ctx.measureText(truncatedTag).width + 2 * tagPaddingLeftRight
- const tagX = x + (secondImgWidth - tagWidth) / 2
- ctx.fillStyle = '#246a6c'
- ctx.beginPath()
- ctx.moveTo(tagX + tagRadius, tagY)
- ctx.lineTo(tagX + tagWidth - tagRadius, tagY)
- ctx.quadraticCurveTo(tagX + tagWidth, tagY, tagX + tagWidth, tagY + tagRadius)
- ctx.lineTo(tagX + tagWidth, tagY + tagPaddingTopBottom * 2)
- ctx.quadraticCurveTo(tagX + tagWidth, tagY + tagPaddingTopBottom * 2 + tagRadius, tagX + tagWidth - tagRadius, tagY + tagPaddingTopBottom * 2 + tagRadius)
- ctx.lineTo(tagX + tagRadius, tagY + tagPaddingTopBottom * 2 + tagRadius)
- ctx.quadraticCurveTo(tagX, tagY + tagPaddingTopBottom * 2 + tagRadius, tagX, tagY + tagPaddingTopBottom * 2)
- ctx.lineTo(tagX, tagY + tagRadius);
- ctx.quadraticCurveTo(tagX, tagY, tagX + tagRadius, tagY)
- ctx.closePath()
- ctx.fill()
- ctx.font = '16px Arial'
- ctx.fillStyle = '#fff'
- ctx.fillText(truncatedTag, tagX + tagPaddingLeftRight, tagY + tagPaddingTopBottom + 10)
- tagY += tagPaddingTopBottom * 2 + tagSpacing
- })
- imgSrc.value = canvas.toDataURL('image/png')
- loading.value = false
- emit('success', imgSrc.value)
- }
- thirdImg.src = props.logoUrl || 'https://minio.citupro.com/dev/menduner/company-avatar.png'
- }
-
- // 保存分享参数
- const result = await saveShareQuery({ id: '14304' })
- const query = {
- scene: 'id=' + result,
- path: 'pagesB/positionDetail/index',
- width: 200,
- autoColor: false,
- checkPath: true,
- hyaline: false
- }
- const data = await getJobAdvertisedShareQrcode(query)
- secondImg.src = 'data:image/png;base64,' + data
- }
- img.onerror = (error) => {
- console.error('Failed to load image:', error)
- loading.value = false
- }
- img.src = props.bgImg
- }
- watch(
- () => props.show,
- (val) => {
- if (val) drawCanvas()
- }
- )
- </script>
|