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.
374 lines
9.1 KiB
374 lines
9.1 KiB
<template>
|
|
|
|
<BaseContainer class="sign-in">
|
|
<NavBar title="签到" />
|
|
|
|
<view class="header">
|
|
<view class="cont">
|
|
<navigator class="image" url="/pages/mine/index">
|
|
<image :src="userInfo.avatar" class="img" />
|
|
</navigator>
|
|
<navigator class="text" url="/pages/mine/index">
|
|
<view class="name" v-html="userInfo.nickname"></view>
|
|
<view class="info">{{ gold_name }}: {{ userInfo.gold_num }}</view>
|
|
</navigator>
|
|
<navigator class="btn" url="/pages/my/sign_in_list">明细</navigator>
|
|
</view>
|
|
</view>
|
|
<view class="main">
|
|
<view class="head">
|
|
<view class="list">
|
|
<view class="item">
|
|
<image
|
|
mode="aspectFit"
|
|
:src="
|
|
isSign
|
|
? getImgPath('/wap/first/zsff/images/stars2.png')
|
|
: getImgPath('/wap/first/zsff/images/stars1.png')
|
|
"
|
|
class="star"
|
|
/>
|
|
<view class="day">每日签到获得{{ gold_coin }}{{ gold_name }}</view>
|
|
</view>
|
|
</view>
|
|
<button
|
|
class="btn flex flex-center"
|
|
v-if="isSign"
|
|
type="button"
|
|
@click="show_sign_image"
|
|
>
|
|
已签到
|
|
</button>
|
|
<button class="btn flex flex-center" v-else type="button" @click="sign">
|
|
立即签到
|
|
</button>
|
|
</view>
|
|
<view class="foot">
|
|
<image
|
|
mode="widthFix"
|
|
:src="getImgPath('/wap/first/zsff/images/lock.png')"
|
|
class="lock"
|
|
/>
|
|
<view class="panel">
|
|
<view class="name">已累计签到</view>
|
|
<view class="count">
|
|
<view class="cont">
|
|
<view class="wrap">
|
|
<view
|
|
v-for="(item, index) in updateTotal"
|
|
:key="index"
|
|
class="item"
|
|
>
|
|
{{ item }}
|
|
</view>
|
|
</view>
|
|
<view class="unit">天</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
<view v-if="records.length" class="record">
|
|
<view v-for="(item, index) in records" :key="index" class="item">
|
|
<view class="text">
|
|
<view class="name">签到</view>
|
|
<view class="time">{{ item.add_time }}</view>
|
|
</view>
|
|
<view class="num">+{{ item.number }}</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- <view style="height: 100vh;"></view> -->
|
|
|
|
<TkiQrcode
|
|
loadMake
|
|
v-if="isQrcodeCanvasVisable"
|
|
ref="qrcode"
|
|
:showLoading="false"
|
|
:val="qrcodeText"
|
|
@result="handleQrcodeCreateSuccess"
|
|
/>
|
|
<canvas
|
|
canvas-id="poster"
|
|
v-if="isPosterCanvasVisable"
|
|
class="poster-canvas"
|
|
/>
|
|
</BaseContainer>
|
|
</template>
|
|
|
|
<script>
|
|
import {
|
|
getUserInfo,
|
|
getUserSignList,
|
|
getUserSignPoster,
|
|
setUserSign,
|
|
getMiniprogramQrcodeByPage,
|
|
} from "@/api/auth";
|
|
import { getSignInfoApi } from "@/api/user";
|
|
import dayjs from "dayjs";
|
|
|
|
export default {
|
|
data() {
|
|
return {
|
|
userInfo: {},
|
|
total: 0,
|
|
isSign: false,
|
|
records: [],
|
|
poster: "",
|
|
sign_talk: "",
|
|
url: "",
|
|
gold_name: "",
|
|
gold_coin: 0,
|
|
|
|
qrcodeText: "",
|
|
isQrcodeCanvasVisable: false,
|
|
isPosterCanvasVisable: false,
|
|
};
|
|
},
|
|
computed: {
|
|
updateTotal: function () {
|
|
let str = "0000",
|
|
total = this.total,
|
|
len = 0;
|
|
if (!total) {
|
|
return str;
|
|
}
|
|
if (typeof total === "number") {
|
|
total = total.toString();
|
|
}
|
|
len = total.length;
|
|
if (len >= 4) {
|
|
return total;
|
|
}
|
|
str += total;
|
|
str = str.substring(len);
|
|
return str;
|
|
},
|
|
},
|
|
created() {
|
|
this.getUserSignInfo();
|
|
this.getUserInfo();
|
|
this.getUserSignList();
|
|
},
|
|
methods: {
|
|
async sign() {
|
|
try {
|
|
const data = await setUserSign();
|
|
|
|
this.isSign = true;
|
|
this.userInfo.gold_num++;
|
|
this.total++;
|
|
this.getUserSignList();
|
|
this.getPoster();
|
|
this.$util.showMsg(data.msg);
|
|
} catch (err) {
|
|
this.isSign = false;
|
|
}
|
|
},
|
|
show_sign_image() {
|
|
this.getPoster();
|
|
},
|
|
getUserSignInfo() {
|
|
getSignInfoApi().then(({ data }) => {
|
|
Object.assign(this, {
|
|
total: data.signCount,
|
|
isSign: data.signed,
|
|
gold_name: data.gold_name,
|
|
gold_coin: data.gold_coin,
|
|
});
|
|
});
|
|
},
|
|
getUserSignList() {
|
|
getUserSignList().then((res) => {
|
|
this.records = res.data;
|
|
});
|
|
},
|
|
getUserInfo() {
|
|
getUserInfo().then((res) => {
|
|
this.userInfo = res.data;
|
|
});
|
|
},
|
|
// 获取海报信息
|
|
async getPoster() {
|
|
uni.showLoading({ mask: true });
|
|
|
|
try {
|
|
const res = await getUserSignPoster();
|
|
uni.hideLoading();
|
|
|
|
let data = res.data;
|
|
this.poster = data.poster;
|
|
this.sign_talk = data.sign_talk;
|
|
this.url = data.url;
|
|
this.createPoster();
|
|
} catch (err) {
|
|
uni.hideLoading();
|
|
}
|
|
},
|
|
handleQrcodeCreateSuccess(path) {
|
|
this.x_cb(path);
|
|
},
|
|
async pathToQrcodePath() {
|
|
// #ifdef MP
|
|
let { full_path, scene } = this.$util.getFullPath({
|
|
spread_uid: this.userInfo.uid,
|
|
});
|
|
|
|
return getMiniprogramQrcodeByPage(full_path, scene).then((res) => {
|
|
return this.$util.getImagePath(
|
|
res.data.url + "?t=" + new Date().getTime()
|
|
);
|
|
});
|
|
|
|
// #endif
|
|
|
|
// #ifndef MP
|
|
let path = this.url;
|
|
|
|
this.qrcodeText = path;
|
|
|
|
return new Promise((resolve) => {
|
|
this.x_cb = (v) => {
|
|
this.isQrcodeCanvasVisable = false;
|
|
resolve(v);
|
|
};
|
|
|
|
this.isQrcodeCanvasVisable = true;
|
|
});
|
|
// #endif MP
|
|
},
|
|
renderPoster(
|
|
bgPath,
|
|
codePath,
|
|
WIDTH = 600,
|
|
HEIGHT = 800,
|
|
site_name = "知识付费"
|
|
) {
|
|
return new Promise((resolve, reject) => {
|
|
const id = "poster";
|
|
let context = uni.createCanvasContext(id, this);
|
|
const monthArr = [
|
|
"一",
|
|
"二",
|
|
"三",
|
|
"四",
|
|
"五",
|
|
"六",
|
|
"七",
|
|
"八",
|
|
"九",
|
|
"十",
|
|
"十一",
|
|
"十二",
|
|
],
|
|
weekdayArr = ["日", "一", "二", "三", "四", "五", "六"];
|
|
|
|
context.fillStyle = "#FFFFFF";
|
|
context.fillRect(0, 0, WIDTH, HEIGHT);
|
|
context.drawImage(bgPath, 30, 30, 540, 540);
|
|
|
|
context.drawImage(codePath, 50, 620, 130, 130);
|
|
|
|
context.font = "22px sans-serif";
|
|
context.fillStyle = "#282828";
|
|
|
|
let index = 0,
|
|
length = this.sign_talk.length,
|
|
start = 0,
|
|
line = 0;
|
|
for (; index < length; index++) {
|
|
if (
|
|
context.measureText(this.sign_talk.slice(start, index)).width > 350
|
|
) {
|
|
context.fillText(
|
|
this.sign_talk.slice(start, index),
|
|
210,
|
|
33 * line + 610
|
|
);
|
|
start = index;
|
|
line++;
|
|
}
|
|
}
|
|
if (start < length - 1) {
|
|
context.fillText(this.sign_talk.slice(start), 210, 33 * line + 610);
|
|
}
|
|
context.font = "64px sans-serif";
|
|
context.fillStyle = "#FF0000";
|
|
context.fillText(dayjs().date(), 326, 753);
|
|
context.font = "24px sans-serif";
|
|
context.fillStyle = "#333333";
|
|
context.fillText(monthArr[dayjs().month()] + "月", 410, 713);
|
|
context.strokeRect(405, 732, 58, 26);
|
|
context.font = "16px sans-serif";
|
|
context.fillText("星期" + weekdayArr[dayjs().month()], 410, 753);
|
|
|
|
context.draw(true, () => {
|
|
uni.canvasToTempFilePath(
|
|
{
|
|
canvasId: id,
|
|
fileType: "png",
|
|
destWidth: WIDTH,
|
|
destHeight: HEIGHT,
|
|
success: (res) => {
|
|
resolve(res.tempFilePath);
|
|
context = null;
|
|
},
|
|
fail: (err) => {
|
|
reject(err.errMsg);
|
|
context = null;
|
|
},
|
|
},
|
|
this
|
|
);
|
|
});
|
|
});
|
|
},
|
|
// 创建海报
|
|
async createPoster() {
|
|
// return;
|
|
|
|
uni.showLoading({
|
|
mask: true,
|
|
});
|
|
|
|
const task1 = this.$util.getImagePath(
|
|
this.poster + "?t=" + new Date().getTime()
|
|
);
|
|
|
|
const task2 = this.pathToQrcodePath();
|
|
|
|
try {
|
|
const [bgPath, codePath] = await Promise.all([task1, task2]);
|
|
|
|
this.isPosterCanvasVisable = true;
|
|
|
|
await this.$util.asyncNextTick(this);
|
|
|
|
const result = await this.renderPoster(bgPath, codePath);
|
|
|
|
this.isPosterCanvasVisable = false;
|
|
uni.hideLoading();
|
|
|
|
uni.previewImage({
|
|
current: 0,
|
|
urls: [result],
|
|
});
|
|
} catch (err) {
|
|
console.log(err);
|
|
uni.hideLoading();
|
|
this.isPosterCanvasVisable = false;
|
|
this.$util.showMsg(err);
|
|
return;
|
|
}
|
|
},
|
|
},
|
|
};
|
|
</script>
|
|
|
|
<style scoped>
|
|
.poster-canvas {
|
|
margin-top: 100vh;
|
|
width: 600px;
|
|
height: 800px;
|
|
}
|
|
</style>
|
|
|