| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191 | <!-- 分享招聘会 --><template>  <view style="position: relative;">    <view v-if="shareUrl" class="d-flex align-center flex-column justify-center" style="height: 100vh;">      <image v-if="!!shareUrl" :style="imgStyle" @click="handlePreviewSharePoster" :src="shareUrl" :show-menu-by-longpress="true"></image>      <view class="color-999 ss-m-t-20 font-size-14 ss-m-b-50">点击图片预览,长按图片保存</view>    </view>		<canvas canvas-id="posterCanvas" class="shareCanvas" :style="`width: ${canvasWidth}px; height: ${canvasHeight}px;`"></canvas>  </view></template><script setup>import { ref, computed } from 'vue'import { onLoad } from '@dcloudio/uni-app'import { getJobAdvertisedShareQrcode } from '@/api/user'import { getJobFair, saveShareQuery } from '@/api/jobFair'const canvasWidth = 500const canvasHeight = 900const shareUrl = ref('')const windowWidth = ref(0)let jobFairId = '' // 分享会IDlet isEnt = false // 招聘会类型let shareImg = '' // 分享背景图片-底图// let shareImg = 'https://menduner.citupro.com:3443/dev/4dd7dd3c9ef350d62fcbc814b88c1ac1916f484a3ee8d8531ae7a2698a289670.jpg' // 分享背景图片-底图onLoad(async (options) => {  jobFairId = options.jobFairId  await getJobFairDetail()  const windowInfo = wx.getWindowInfo()  windowWidth.value = windowInfo.windowWidth  console.log(windowWidth.value, '当前机型屏幕宽')})const getJobFairDetail = async () => {  if (!jobFairId) return  const { data } = await getJobFair(jobFairId)  shareImg = data?.shareImg || ''  isEnt = Number(data?.category)  if (shareImg) createPoster()}const imgStyle = computed(() => {  if (windowWidth.value <= 320) return `width: 259px; height: ${Math.round((canvasHeight*259)/canvasWidth)}px;`  if (windowWidth.value > 320 && windowWidth.value <= 375) return `width: 313px; height: ${Math.round((canvasHeight*313)/canvasWidth)}px;`  if (windowWidth.value > 375) return `width: 328px; height: ${Math.round((canvasHeight*328)/canvasWidth)}px;`})// 图片预览const handlePreviewSharePoster = () => {	uni.previewImage({		current: 0,		longPressActions: {			itemList: ['发送给朋友', '保存图片', '收藏']		},		urls: [shareUrl.value]	})}const getImageTempRatio = (url) => {  return new Promise((req, rej)=>{    wx.getImageInfo({      src:url,      success:(res) =>{        req(res)      }    })  })}// const getToLocal = (base64data) => {//   const fsm = wx.getFileSystemManager()//   const FILE_BASE_NAME = 'tmp_base64src'; //自定义文件名//   const [, format, bodyData] = /data:image\/(\w+);base64,(.*)/.exec(base64data) || []//   if (!format) {//     return (new Error('ERROR_BASE64SRC_PARSE'))//   }//   const filePath = `${wx.env.USER_DATA_PATH}/${FILE_BASE_NAME}.${format}`//   const buffer = wx.base64ToArrayBuffer(bodyData);//   fsm.writeFile({//     filePath,//     data: buffer,//     encoding: 'binary',//     success(r) {//       console.log(filePath,'filePath')//       qrCode.value = filePath//     },//     fail() {//       return (new Error('ERROR_BASE64SRC_WRITE'))//     }//   })// }const getToLocal = (base64data) => {  return new Promise((resolve, reject) => {    const fsm = wx.getFileSystemManager()    const FILE_BASE_NAME = `tmp_${new Date().getTime()}` // 自定义文件名    const [, format, bodyData] = /data:image\/(\w+);base64,(.*)/.exec(base64data) || []    if (!format) {      reject(new Error('ERROR_BASE64SRC_PARSE'))      return    }    const filePath = `${wx.env.USER_DATA_PATH}/${FILE_BASE_NAME}.${format}`    const buffer = wx.base64ToArrayBuffer(bodyData)    fsm.writeFile({      filePath,      data: buffer,      encoding: 'binary',      success(r) {        resolve(filePath) // 成功时返回 filePath      },      fail() {        reject(new Error('ERROR_BASE64SRC_WRITE'))      },    })  })}// 生成分享二维码const qrCode = ref()const handleShareCode = async () => {  const result = await saveShareQuery({ jobFairId })	const query = {    scene: 'id=' + result.data,    path: `pagesB/jobFair/${!isEnt ? 'enterprisesClassification' : 'positionClassification'}`,		width: 200,		autoColor: false,		checkPath: true,		hyaline: false // 二维码背景颜色为透明	}  console.log(result.data, query.scene, '=========================')	const res = await getJobAdvertisedShareQrcode(query, { noAuth: true })	const data = res?.data ? 'data:image/png;base64,' + res.data : ''  const filePath = await getToLocal(data) // 等待 getToLocal 完成  qrCode.value = filePath}const createPoster = async () => {  uni.showLoading({ title: '生成中...', mask: true })  await handleShareCode() // 生产分享二维码  var context = uni.createCanvasContext('posterCanvas')  //清空画布  context.clearRect(0, 0, canvasWidth, canvasHeight)  //背景图片   const { path: bgUrl } = await getImageTempRatio(shareImg)  context.drawImage(bgUrl, 0, 0, canvasWidth, canvasHeight) // 路径、x、y、宽、高    //分享二维码  const qrCodeWidth = 127  const qrCodeHeight = 127  const qrCodeX = 188  const qrCodeY = 585  console.log('dddd', qrCode.value)  context.drawImage(qrCode.value, qrCodeX, qrCodeY, qrCodeWidth, qrCodeHeight)    context.font = 'bold 16px Arial'  context.fillStyle = '#10325d'  const text = '诚挚邀约 共享机遇'  const textWidth = context.measureText(text).width  const textX = qrCodeX + (qrCodeWidth - textWidth) / 2  const textY = qrCodeY + qrCodeHeight + 30  context.fillText(text, textX, textY)    context.draw(false, () =>{    wx.canvasToTempFilePath({       canvasId: 'posterCanvas',      success:(res)=>{        shareUrl.value = res.tempFilePath        console.log('canvas-success', shareUrl.value)        uni.hideLoading({})      },      fail:(err)=>{        uni.hideLoading({})        console.log('canvas-fail', err)      }    })  })}</script><style scoped lang="scss">.shareCanvas {	position: fixed;	top: -99999upx;	left: -99999upx;	z-index: -99999;}</style>
 |