import { Canvas, Image, Text, View } from '@tarojs/components' import Taro, { useReady } from '@tarojs/taro' import { useRef, useState } from 'react' import styles from './index.module.scss' import useLogin from '@/use/useLogin' import { alert, goLink } from '@/common/common' import { GenBarCodeOrQrCode, GetInvitationInfo, GetInvitationInfoApi, GetInviteCodeList, GetInviteeRecord } from '@/api/user' import { getFilterData } from '@/common/util' import LayoutBlock from '@/components/layoutBlock' import { getCDNSource } from '@/common/constant' import NormalButton from '@/components/normalButton' import Dialog from '@/components/Dialog' import IconText from '@/components/iconText' import BindSalesManDialog from '@/components/bindSalesManDialog' // 获取业务员信息 interface Param { inviter_id: number; inviter_name: string; phone: string } const BindSalesman = () => { useLogin() const [inviteInfo, setInviteInfo] = useState({}) const [salesMan, setSalesMan] = useState(null) // const { fetchData: GetInvitationInfoFetchData } = GetInvitationInfoApi() // const getInvitationInfo = async() => { // const res = await GetInvitationInfoFetchData(getFilterData({ ...inviteInfo })) // res.success ? setSalesMan(res.data) : setSalesMan(null) // } // 获取被邀请记录 const { fetchData: getInviteeRecordAPI } = GetInviteeRecord() const getInviteeRecord = async() => { const res = await getInviteeRecordAPI() if (res.success) { setSalesMan(res.data) } } const { fetchData } = GetInvitationInfo() // 获取邀请码 const getInviteCode = async() => { const res = await fetchData() if (res.success) { setInviteInfo(res.data) // getInvitationInfo() } } const [invite, setInvite] = useState(0) const { fetchData: getInvitationListAPI } = GetInviteCodeList() const getInvitationList = async() => { const res = await getInvitationListAPI() if (res.success) { console.log('getInviteCode', res) setInvite(res.data.total) } } const canvasNode = useRef(null) const ctx = useRef(null) const [showPopup, setShowPopup] = useState(false) const [loading, setLoading] = useState(false) const { fetchData: genCode } = GenBarCodeOrQrCode() // 生成二维码 const genQRcode = async() => { const res = await genCode({ content: `InviteCode:${inviteInfo.invitation_code}` }) if (res.success) { return res.data.qrcode_base64 } else { setLoading(false) } } const inviteDialog = useRef(null) const getImageObject = (canvas: Taro.Canvas, src: string) => { return new Promise((resolve, reject) => { console.log('getImageObject param', canvas, src) const img = canvas.createImage() img.src = src img.onload = () => { console.log('image===>', img) resolve(img) } img.onerror = (err) => { console.log('image error===>', err) alert.error('图片加载失败') reject(err) } }) } const doublePick = (num, minus = false) => { if (minus) { return num / 2 } else { return num * 2 } } const [targetImageUrl, setTargetImageUrl] = useState('') // canvas 生成 图片 const saveCanvasToImage = (canvas) => { Taro.canvasToTempFilePath({ canvas, fileType: 'png', success: (res) => { console.log('tempFilePath', res.tempFilePath) setTargetImageUrl(res.tempFilePath) }, fail: (error) => { console.log('error', error) }, complete: () => { setLoading(false) }, }) } const [, setForceUpdate] = useState({}) // 初始化 canvas const initCanvas = async() => { return new Promise((resolve, reject) => { Taro.nextTick(() => { const query = Taro.createSelectorQuery() query.select('#canvas').node(({ node: canvas }: { node: Taro.Canvas }) => { console.log('canvas==>', canvas) const context = canvas.getContext('2d') console.log('ctx', context) canvasNode.current = canvas ctx.current = context console.log('canvas', canvas) setForceUpdate({}) resolve(true) }).exec() }) }) } const [canvasStyle, setCanvasStyle] = useState({}) const startPaint = async(ctx: Taro.RenderingContext, canvas: Taro.Canvas, image: Taro.Image) => { // 开始绘制 const { width, height } = canvas console.log('startPaint param', ctx, canvas, image) const cCanvasCtx = ctx as any cCanvasCtx.clearRect(0, 0, width, height) cCanvasCtx.drawImage(image, 0, 0, width, height) cCanvasCtx.save() cCanvasCtx.font = `${doublePick(40)}px 微软雅黑` cCanvasCtx.fillStyle = '#000000' cCanvasCtx.fillText('陆盈商城', doublePick(40), doublePick(80)) // text up above canvas cCanvasCtx.save() cCanvasCtx.font = `${doublePick(26)}px 微软雅黑` cCanvasCtx.fillStyle = '#8f9398' cCanvasCtx.fillText('邀请好友加入', doublePick(40), doublePick(130)) // text up above canvas cCanvasCtx.save() cCanvasCtx.font = `${doublePick(24)}px 微软雅黑` cCanvasCtx.fillStyle = '#a6a6a6' cCanvasCtx.fillText('请前往陆盈商城,进行填写或扫描邀请', doublePick(100), doublePick(630)) // text up above canvas cCanvasCtx.save() cCanvasCtx.font = `${doublePick(36)}px 微软雅黑` cCanvasCtx.fillStyle = '#7f7f7f' cCanvasCtx.fillText('邀 请 码', doublePick(72), doublePick(730)) // text up above canvas cCanvasCtx.save() cCanvasCtx.font = `${doublePick(24)}px 微软雅黑` cCanvasCtx.fillStyle = '#cccccc' cCanvasCtx.fillText('|', doublePick(258), doublePick(724)) // text up above canvas cCanvasCtx.save() cCanvasCtx.font = `${doublePick(36)}px 微软雅黑` cCanvasCtx.fillStyle = '#7f7f7f' cCanvasCtx.fillText(`${inviteInfo.invitation_code}`, doublePick(311), doublePick(730)) // text up above canvas cCanvasCtx.save() const codeUrl = await genQRcode() try { const code = await getImageObject(canvas, codeUrl) cCanvasCtx.drawImage(code, doublePick(110), doublePick(213), doublePick(342), doublePick(342)) } catch (err) { console.error('合成二维邀请码失败', err) setLoading(false) throw new Error('合成二维邀请码失败') } saveCanvasToImage(canvas) } // 绘制最终的海报,图片使用两倍大小,canvas大小是图片的二分之一 就能让canvas生成出来的图片清晰了 const drawPictorial = async() => { // eslint-disable-next-line no-async-promise-executor return new Promise(async(resolve, reject) => { setLoading(true) if (!ctx.current) { // 重新初始化canvas await initCanvas() } const canvas = canvasNode.current! Taro.getImageInfo({ src: getCDNSource('/user/inviteCodePopup.png'), success: (res) => { console.log('res==>', res) canvas.width = res.width canvas.height = res.height setCanvasStyle({ width: `${doublePick(canvas.width, true)}px`, height: `${doublePick(canvas.height, true)}px`, }) getImageObject(canvas, `${res.path}`).then(async(image) => { try { // 开始绘制 await startPaint(ctx.current!, canvas, image) resolve(true) } catch (err) { console.log(err) setLoading(false) reject(new Error('绘制失败')) } }).catch((error) => { setLoading(false) throw new Error(error) }) }, }) }) } // 复制二维码 const handleCopyInviteCode = () => { Taro.setClipboardData({ data: inviteInfo.invitation_code, }) } const handleChange = (value: boolean) => { setShowPopup(value) } useReady(() => { getInviteCode() getInvitationList() getInviteeRecord() setTimeout(() => { initCanvas() }, 200) }) const handleQRcodeShare = async() => { try { const flag = await drawPictorial() if (flag) { setShowPopup(true) } } catch (err) { throw new Error('弹出二维码失败') } } // 邀请记录 const handleInviteCord = () => { goLink('/pages/inviteCode/inviteCord/index') } const handleBindSalesMan = () => { inviteDialog.current.handleChange(true) } const handleBindSuccess = () => { getInviteeRecord() } return ( 陆盈商城 邀请好友加入 {inviteInfo.invitation_code ? inviteInfo.invitation_code : '暂无邀请码'} 您的专属邀请码 我的邀请记录: {invite === 0 && 暂无邀请信息} {invite !== 0 && {invite}人} 朋友邀请我: {!salesMan?.inviter_id && 未绑定} {!!salesMan?.inviter_id && 已绑定 {salesMan.inviter_name}({salesMan.phone}) } {!salesMan?.inviter_id && } 温馨提示:邀请码确定绑定后,不支持解绑。 {/* 已踩坑,这里必须设置canvas的style的width和height,单单只设置canvas实例的width和height是不行的。会模糊! */} 二维码分享 复制邀请码 {/* showMenuByLongpress 属性只对 小程序有效 */} 长按图片保存到手机 ) } export default BindSalesman