parent
fbb19687ff
commit
65973d3b75
|
|
@ -8,6 +8,10 @@
|
|||
font-family: "pangmen";
|
||||
src: url("../fonts/PangMenZhengDaoBiaoTiTiMianFeiBan-2.ttf");
|
||||
}
|
||||
@font-face {
|
||||
font-family: "sanjikai";
|
||||
src: url("../fonts/SanJiXingKaiJianTi-Cu-2.ttf");
|
||||
}
|
||||
@font-face {
|
||||
font-family: "alibaba";
|
||||
src: url("../fonts/ALIBABA-PUHUITI-MEDIUM.TTF");
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -1,17 +1,20 @@
|
|||
import React, { useEffect, useState } from 'react';
|
||||
import { Modal, Button } from 'antd';
|
||||
|
||||
import { Modal, Button, Form, Input } from 'antd';
|
||||
import cookie from 'react-cookies';
|
||||
|
||||
import IconImg from '../img/user/icon1.png';
|
||||
import TemplateImg from '../img/user/template.png';
|
||||
|
||||
import { applyAward } from '../api';
|
||||
import { httpUrl } from '../fetch';
|
||||
|
||||
import '../indexUser.scss';
|
||||
|
||||
function UserAward({ visible , onCancel , onSure , member , id }) {
|
||||
function UserAward({ visible , onCancel , onSure , member , id, form }) {
|
||||
const [ loading , setLoading ] = useState(false);
|
||||
const [ score , setScore ] = useState(0);
|
||||
const [ scoreLeft , setScoreLeft ] = useState(0);
|
||||
const { getFieldDecorator, validateFields, getFieldsValue } = form;
|
||||
|
||||
useEffect(()=>{
|
||||
if(visible && member && member.zonePointsAccount && member.zonePointsAccount.availablePoints) {
|
||||
|
|
@ -21,12 +24,116 @@ function UserAward({ visible , onCancel , onSure , member , id }) {
|
|||
},[visible, member])
|
||||
|
||||
function onOk() {
|
||||
setLoading(true);
|
||||
applyAward(id).then(res => {
|
||||
if (res && res.data && res.data.code === 200) {
|
||||
onSure(res.data.msg);
|
||||
validateFields(async (err, values) => {
|
||||
if (!err) {
|
||||
try{
|
||||
setLoading(true);
|
||||
let imgInfo = await createImg(values.realName);
|
||||
|
||||
let certificateUrl = '';
|
||||
if (imgInfo && imgInfo.code == 200 && imgInfo.url) {
|
||||
certificateUrl = imgInfo.url || '';
|
||||
}
|
||||
|
||||
const res = await applyAward({zoneId: id, sourceData: certificateUrl});
|
||||
setLoading(false);
|
||||
|
||||
if (res && res.data && res.data.code === 200) {
|
||||
onSure(res.data.msg);
|
||||
}
|
||||
}finally{
|
||||
setLoading(false);
|
||||
}
|
||||
}
|
||||
}).finally(() => { setLoading(false) })
|
||||
});
|
||||
}
|
||||
|
||||
async function waitFontLoaded() {
|
||||
// 等待自定义字体加载完成
|
||||
if (document.fonts) {
|
||||
await document.fonts.ready;
|
||||
if(!document.fonts.check('64px sanjikai')) {
|
||||
try {
|
||||
const font = new FontFace('sanjikai', 'url(/fonts/SanJiXingKaiJianTi-Cu-2.ttf)');
|
||||
await font.load();
|
||||
document.fonts.add(font);
|
||||
} catch (e) {
|
||||
console.warn('sanjikai 字体加载失败:', e);
|
||||
}
|
||||
}
|
||||
|
||||
if(!document.fonts.check('18px alibabaReg')) {
|
||||
try {
|
||||
const font = new FontFace('alibabaReg', 'url(/fonts/ALIBABA-PUHUITI-REGULAR.TTF)');
|
||||
await font.load();
|
||||
document.fonts.add(font);
|
||||
} catch (e) {
|
||||
console.warn('alibabaReg 字体加载失败:', e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
async function createImg(realName) {
|
||||
const canvas = document.createElement('canvas');
|
||||
const ctx = canvas.getContext('2d');
|
||||
|
||||
const img = new Image();
|
||||
img.crossOrigin = 'anonymous';
|
||||
img.src = TemplateImg;
|
||||
|
||||
await new Promise((resolve, reject) => {
|
||||
img.onload = resolve;
|
||||
img.onerror = reject;
|
||||
});
|
||||
|
||||
// 等待字体加载完成后再绘制
|
||||
await waitFontLoaded();
|
||||
|
||||
canvas.width = img.width;
|
||||
canvas.height = img.height;
|
||||
ctx.drawImage(img, 0, 0);
|
||||
|
||||
const memberName = realName || member?.name || member?.nickname || '学员';
|
||||
const awardDate = new Date().toLocaleDateString('zh-CN', { year: 'numeric', month: 'long', day: 'numeric' });
|
||||
|
||||
// 设置文字样式
|
||||
ctx.font = '64px sanjikai';
|
||||
ctx.fillStyle = '#04060c';
|
||||
ctx.textAlign = 'center';
|
||||
ctx.textBaseline = 'bottom';
|
||||
ctx.fillText(memberName, canvas.width / 2, 705);
|
||||
|
||||
ctx.font = '18px alibabaReg';
|
||||
ctx.fillStyle = '#04060c';
|
||||
ctx.textAlign = 'left';
|
||||
ctx.textBaseline = 'middle';
|
||||
ctx.fillText(awardDate, 240, 1008);
|
||||
|
||||
// TODO
|
||||
const dataUrl = canvas.toDataURL('image/png');
|
||||
const link = document.createElement('a');
|
||||
link.download = `荣誉证书_${memberName}_${new Date().getTime()}.png`;
|
||||
link.href = dataUrl;
|
||||
link.click();
|
||||
|
||||
const blob = await new Promise(resolve => canvas.toBlob(resolve, 'image/png'));
|
||||
const formData = new FormData();
|
||||
formData.append('file', blob, `member_${member.id}.png`);
|
||||
formData.append('type', 'resource');
|
||||
|
||||
const uploadRes = await fetch(`${httpUrl}/file/common/upload`, {
|
||||
method: 'POST',
|
||||
body: formData,
|
||||
headers: {
|
||||
// Authorization: '6d72497d7f197eb9dc8a15db038881cd31afea7a',
|
||||
Authorization: cookie.load('autologin_trustie'),
|
||||
}
|
||||
});
|
||||
|
||||
const uploadData = await uploadRes.json();
|
||||
return uploadData;
|
||||
}
|
||||
|
||||
return(
|
||||
|
|
@ -56,8 +163,22 @@ function UserAward({ visible , onCancel , onSure , member , id }) {
|
|||
>
|
||||
<div className="info">
|
||||
<p className="award">您将消耗<label> 200 积分 </label>兑换「专属电子荣誉证书」,当前可用积分 {score.toLocaleString()} 分,兑换后剩余 {scoreLeft.toLocaleString()} 分。积分扣除后将自动生成证书,无法退回,请确认操作。请确认是否兑换专属电子荣誉证书?</p>
|
||||
<Form form={form}>
|
||||
<Form.Item label="真实姓名">
|
||||
{getFieldDecorator('realName', {
|
||||
rules: [
|
||||
{
|
||||
required: true,
|
||||
message: '请输入真实姓名'
|
||||
}
|
||||
],
|
||||
})(
|
||||
<Input placeholder="请输入真实姓名" maxLength={20} />,
|
||||
)}
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</div>
|
||||
</Modal>
|
||||
)
|
||||
}
|
||||
export default UserAward;
|
||||
export default Form.create()(UserAward);
|
||||
|
|
@ -45,7 +45,7 @@ function ApplyActivity({ visible, onCancel, onSure, form, member, zoneName, }) {
|
|||
<img alt="头像" src={IconImg} style={{width: '48px', height: '48px'}}></img>
|
||||
<div className="txt">
|
||||
<h4>
|
||||
专家一对一答疑
|
||||
线下参观/沙龙报名
|
||||
</h4>
|
||||
<p>{zoneName}<span> · </span>线下参观/沙龙报名</p>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@ function ZoneUser(props){
|
|||
const [ qaVisible , setQaVisible ] = useState(false);
|
||||
const [ successVisible , setSuccessVisible ] = useState(false);
|
||||
const [ timeNum, setTimeNum] = useState(3);
|
||||
const [ memberAccountInfo, setMemberAccountInfo ] = useState([]);
|
||||
|
||||
const { id, showNotification, checkIfLogin, showLoginDialog, temp, sectionMemberTitle } = props;
|
||||
|
||||
|
|
@ -71,6 +72,36 @@ function ZoneUser(props){
|
|||
}
|
||||
},[id])
|
||||
|
||||
useEffect(() => {
|
||||
let temp = awardsInfoData.map(item => {
|
||||
let tempData = Object.assign({}, item);
|
||||
if(!memberInfo) return tempData;
|
||||
|
||||
if(item.key === 'certificate' && memberInfo.pointsEvent?.id) {
|
||||
tempData.exist = true;
|
||||
tempData.txt = '下载证书';
|
||||
}
|
||||
if(item.key === 'acitvity' && Array.isArray(memberInfo.applyList)) {
|
||||
let index = memberInfo.applyList.findIndex(item => item.applyType === 'offlineActivityFreeze');
|
||||
if(index !== -1) {
|
||||
tempData.disabled = true;
|
||||
tempData.txt = '等待审核';
|
||||
}
|
||||
}
|
||||
if(item.key === 'qa' && Array.isArray(memberInfo.applyList)) {
|
||||
let index = memberInfo.applyList.findIndex(item => item.applyType === 'expertQaFreeze');
|
||||
if(index !== -1) {
|
||||
tempData.disabled = true;
|
||||
tempData.txt = '等待审核';
|
||||
}
|
||||
}
|
||||
|
||||
return tempData;
|
||||
})
|
||||
|
||||
setMemberAccountInfo(temp);
|
||||
}, [memberInfo])
|
||||
|
||||
useEffect(() => {
|
||||
if (successVisible) {
|
||||
const pid = setInterval(() => {
|
||||
|
|
@ -225,8 +256,16 @@ function ZoneUser(props){
|
|||
}
|
||||
|
||||
function pointsCustom(item) {
|
||||
if(item.disabled) return;
|
||||
console.log('iii', item)
|
||||
if(item.key == 'certificate') {
|
||||
setAwardVisible(true);
|
||||
if(!item.exist) {
|
||||
setAwardVisible(true);
|
||||
} else {
|
||||
let url = memberInfo.pointsEvent?.sourceData;
|
||||
console.log('uuu', url)
|
||||
window.open(url, '_blank');
|
||||
}
|
||||
} else if(item.key == 'doc') {
|
||||
setDocVisible(true);
|
||||
} else if(item.key == 'acitvity') {
|
||||
|
|
@ -305,16 +344,16 @@ function ZoneUser(props){
|
|||
</div>
|
||||
<div className="awards">
|
||||
{
|
||||
awardsInfoData.map((item, index) => (
|
||||
memberAccountInfo.map((item, index) => (
|
||||
<div className="award">
|
||||
<h3><img src={item.img} alt="" style={{marginRight: 16}}/> {item.title}</h3>
|
||||
<p>{item.desc}</p>
|
||||
<div className="action">
|
||||
<span><label>{item.score}积分</label>/{item.unit}</span>
|
||||
{memberInfo?.zonePointsAccount?.availablePoints >= item.score ? (
|
||||
<div className="btn" onClick={() => pointsCustom(item)}>
|
||||
{item.txt}
|
||||
</div>
|
||||
{memberInfo?.zonePointsAccount?.availablePoints >= item.score ? (
|
||||
<div className={`btn ${item.disabled ? 'disabled' : ''}`} onClick={() => pointsCustom(item)}>
|
||||
{item.txt}
|
||||
</div>
|
||||
) : (
|
||||
<div className="btn disabled">
|
||||
积分不足
|
||||
|
|
@ -342,10 +381,10 @@ function ZoneUser(props){
|
|||
onCancel={()=>setDocVisible(false)} onSure={() => { setDocVisible(false); setSuccessVisible(true);getInfo();}}
|
||||
/>
|
||||
<ApplyAcitvity visible={acitvityVisible} member={memberInfo} zoneName={zoneInfo?.name}
|
||||
onCancel={()=>setAcitvityVisible(false)} onSure={() => { setQaVisible(false); getInfo();}}
|
||||
onCancel={()=>setAcitvityVisible(false)} onSure={() => { showNotification(msg); setAcitvityVisible(false); getInfo();}}
|
||||
/>
|
||||
<ApplyQA visible={qaVisible} member={memberInfo} zoneName={zoneInfo?.name}
|
||||
onCancel={()=>setQaVisible(false)} onSure={() => { setQaVisible(false); getInfo();}}
|
||||
onCancel={()=>setQaVisible(false)} onSure={() => { showNotification(msg); setQaVisible(false); getInfo();}}
|
||||
/>
|
||||
|
||||
<Modal
|
||||
|
|
|
|||
|
|
@ -642,10 +642,11 @@ export function deleteMemberProject(ids){
|
|||
})
|
||||
}
|
||||
|
||||
export function applyAward(id) {
|
||||
export function applyAward(data) {
|
||||
return fetch({
|
||||
url: `/zone/points/account/certificate/redeem/${id}`,
|
||||
method: 'post'
|
||||
url: `/zone/points/account/certificate/redeem`,
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
export function doApplyQA(data) {
|
||||
|
|
|
|||
|
|
@ -764,6 +764,7 @@
|
|||
line-height:32px;
|
||||
color:#4a5377;
|
||||
font-size:15px;
|
||||
margin-bottom: 30px;
|
||||
label{
|
||||
font-family: alibaba;
|
||||
color: #f5383b;
|
||||
|
|
|
|||
Loading…
Reference in New Issue