You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

448 lines
9.7 KiB

<template>
<div class="body" id="signed">
<u-image class="bkg" :src="require('@/static/certificate-bkg.png')" mode="widthFix"></u-image>
<u-image class="city" mode="widthFix" width="100vw" :src="require('@/static/city.png')"></u-image>
<u-image class="people" mode="widthFix" :width="298" :src="require('@/static/people.png')"></u-image>
<u-image mode="widthFix" width="100vw" class="piaodai" :src="require('@/static/piaodai.png')"></u-image>
<u-image id="share-img" v-show="!isHidden" class="share-img" mode="scaleToFill" :width="99" :height="99" :src="require('@/static/share.png')" @click="$u.throttle(share)"> mode=</u-image>
<div class="content">
<u-image style="display:flex;align-items: center;margin: auto;" mode="widthFix" :width="335" :src="require('@/static/certificate-word.png')"></u-image>
<div class="container">
<u-image class="container__jiangbei" :height="206" mode="heightFix" :src="require('@/static/jiangbei.png')"></u-image>
<u-image class="container__bkg" height="100%" width="100%" mode="scaleToFill" :src="require('@/static/container-bkg.png')"></u-image>
<div class="container__text">
<div class="container__text--title">
<span>王晓明</span>同学,
</div>
<div class="container__text--total">
你已完成2023年“我是党史记录人——红色少年行”未成年人研学线上打卡。
</div>
<div class="container__text--total">
学党史悟精神聚力量,你是第<span>2023</span>位完成者,快邀请你的同学一起完成线上打卡吧!
</div>
</div>
</div>
</div>
<div class="footer">
主办单位:中共苏州市委党史工作办公室 <br>
承办单位:江苏有线苏州分公司
</div>
<transition name="share-pop" enter-active-class="fade-in" leave-to-class="fade-out">
<view class="share_cover" v-show="isShare" @click="isShare = false">
<image src="/static/toShare.png" class="share_cover_arrow"></image>
<view class="share_cover_word">
请点击右上角将它发送给指定朋友或分享到朋友圈
</view>
</view>
</transition>
<view class="share" v-if="isHidden">
<view class="share-mask" @click="isHidden = false">
</view>
<view class="share-page">
<image :src="imgData" mode="widthFix"></image>
<view class="share-page__btn">
<view class="share-page__btn--share" @click="isShare = true">分享</view>
<view class="share-page__btn--save" @click="save">保存</view>
</view>
</view>
</view>
</div>
</template>
<script>
import {
ROOTPATH
} from '@/common/config.js'
import {base64ToFile} from '@/common/util'
import html2canvas from '@/lib/html2canvas.min.js'
export default {
data() {
return {
isShare: false,
isHidden: false,
imgData: '',
};
},
methods: {
showShare () {
this.isShare = true
},
share() {
this.isHidden = true
uni.showLoading({
title: '图片生成中..'
})
let dom = document.querySelector('#signed')
html2canvas(dom, {
width: dom.clientWidth, //dom 原始宽度
height: dom.clientHeight,
scrollY: 0,
scrollX: 0,
useCORS: true,
ignoreElements:(element) => {
return element.attributes.id == 'share-img'
}
}).then(cnv => {
uni.hideLoading()
this.imgData = cnv.toDataURL('image/png', 1)
}).catch(err => {
uni.showToast({
title: '生成失败,请重试',
icon: 'error'
})
this.isHidden = false
console.log(err);
})
},
save() {
this.$u.throttle(() => {
let sysinfo = uni.getSystemInfoSync();
console.log(sysinfo)
if (sysinfo) {
if (sysinfo.platform === 'android') {
uni.showToast({
title: "请长按分享图片进行保存或者分享",
icon: "none"
})
} else {
let a = document.createElement("a")
a.href = this.imgData
a.setAttribute("download", "gmesign")
a.click()
}
} else {
uni.showToast({
title: "请长按分享图片进行保存或者分享",
icon: "none"
})
}
let form = new FormData()
form.append('file', base64ToFile(this.imgData, 'sign'))
form.append('active_tag', 'map_point')
let vuex_token = this.vuex_token;
form.append('token', vuex_token)
let xhr = new XMLHttpRequest()
xhr.open('post', `${ROOTPATH}/api/mobile/upload-file`)
xhr.onreadystatechange = () => {
if (xhr.status === 200 && xhr.readyState === 4) {
let val = JSON.parse(xhr.responseText);
console.log(val);
this.$u.api.savePoster({
upload_id: val.id,
type: 1
}).then(res => {
// uni.showToast({
// title: "保存成功",
// icon: "none"
// })
}).catch(err => {
// uni.showToast({
// title: "保存成功",
// icon: "none"
// })
})
}
}
xhr.send(form)
})
}
}
}
</script>
<style lang="scss">
.body {
min-height: 100vh;
position: relative;
}
.footer {
text-align: center;
font-size: 18rpx;
font-weight: 400;
color: #F8DB97;
padding: 20rpx 0;
position: absolute;
bottom: 0;
left: 0;
right: 0;
}
/* ----------------------------------------------
* Generated by Animista on 2023-6-26 17:51:36
* Licensed under FreeBSD License.
* See http://animista.net/license for more info.
* w: http://animista.net, t: @cssanimista
* ---------------------------------------------- */
/**
* ----------------------------------------
* animation jello-horizontal
* ----------------------------------------
*/
@keyframes jello-horizontal {
0% {
transform: scale3d(1, 1, 1);
}
15% {
transform: scale3d(1.25, 0.75, 1);
}
20% {
transform: scale3d(0.75, 1.25, 1);
}
25% {
transform: scale3d(1.15, 0.85, 1);
}
33% {
transform: scale3d(0.95, 1.05, 1);
}
38% {
transform: scale3d(1.05, 0.95, 1);
}
50% {
transform: scale3d(1, 1, 1);
}
}
.share-img {
animation: jello-horizontal 3.2s both infinite;
position: fixed;
left: 55rpx;
bottom: 86rpx;
}
.people {
position: absolute;
right: 23rpx;
bottom: 0;
}
.city {
position: absolute;
left: 0;
right: 0;
bottom: 154rpx;
}
.piaodai {
position: absolute;
left: 0;
right: 0;
bottom: -22rpx;
}
.bkg {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
.content {
padding-top: 143rpx;
position: relative;
.container {
z-index: 2;
margin-top: 23rpx;
position: relative;
&__jiangbei {
display: flex;
justify-content: center;
z-index: 3;
position: relative;
}
&__bkg {
z-index: 1;
position: absolute;
top: 103rpx;
bottom: 0;
left: 0;
right: 0;
}
&__text {
z-index: 4;
padding: 61rpx 63rpx 0 104rpx;
position: relative;
&--title {
font-weight: 400;
color: #6F6F6F;
font-size: 28rpx;
line-height: 56rpx;
& > span {
color: #FD4949;
line-height: 56rpx;
text-decoration-color: #6F6F6F;
text-decoration: underline;
}
}
&--total {
text-indent: 56rpx;
font-weight: 400;
color: #6F6F6F;
font-size: 28rpx;
line-height: 56rpx;
& > span {
color: #FD4949;
line-height: 56rpx;
text-decoration-color: #6F6F6F;
text-decoration: underline;
}
}
}
}
}
.share_cover {
background: rgba(0, 0, 0, 0.8);
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
height: 100vh;
width: 100vw;
z-index: 100000;
.share_cover_word {
color: #FFFFFF;
font-size: 48rpx;
width: 60%;
margin: 400rpx auto;
text-align: center;
line-height: 40px;
}
.share_cover_arrow {
position: absolute;
right: 0;
top: 0;
width: 300rpx;
height: 400rpx;
}
}
.share {
min-height: 100vh;
overflow-y: scroll;
padding: 278rpx 0;
z-index: 2;
position: fixed;
top: 0;
left: 0;
right: 0;
&-mask {
background: rgba(0, 0, 0, 0.4);
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
&-page {
width: fit-content;
overflow: scroll;
transform: translate(-50%, -50%);
position: absolute;
top: 50%;
left: 50%;
right: 0;
&>image {
width: 520rpx;
height: auto;
display: block;
border: 6rpx solid #F8E3CF;
box-shadow: 0rpx 4rpx 20rpx 0rpx rgba(19, 1, 2, 0.71);
margin: auto;
}
&__btn {
display: flex;
justify-content: center;
padding-top: 52rpx;
&>view {
width: 230rpx;
height: 66rpx;
background: linear-gradient(0deg, #EFC495, #E9BC8A);
border-radius: 34rpx;
text-align: center;
font-weight: 400;
line-height: 66rpx;
font-size: 26rpx;
letter-spacing: 8rpx;
color: #C93E31;
}
&--share {
margin-right: 60rpx;
}
}
}
}
.fade-in {
animation: fade-in 1s cubic-bezier(0.390, 0.575, 0.565, 1.000) both;
}
@keyframes fade-in {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
.fade-out {
animation: fade-out .8s ease-out both;
}
@keyframes fade-out {
0% {
opacity: 1;
}
100% {
opacity: 0;
}
}
</style>