|
@@ -8,32 +8,99 @@
|
|
|
</route>
|
|
|
<script setup lang="ts">
|
|
|
import NavbarEvo from '@/components/navbar-evo.vue'
|
|
|
-import { getBadges, getCertificates } from '../../../../core/libs/requests'
|
|
|
+import { getDesignerInfo } from '../../../../core/libs/requests'
|
|
|
import { Badge } from '../../../../core/libs/models'
|
|
|
import { NetImages } from '../../../../core/libs/net-images'
|
|
|
+import { useMessage } from 'wot-design-uni'
|
|
|
+import { pick } from 'radash'
|
|
|
+import ImageEvo from '@/components/image-evo.vue'
|
|
|
import dayjs from 'dayjs'
|
|
|
+import { storeToRefs } from 'pinia'
|
|
|
+import { useUserStore } from '@/store'
|
|
|
+import { Canvas } from '@/core/utils/canvas'
|
|
|
|
|
|
-const active = ref('badge')
|
|
|
-const tabs = ref([
|
|
|
- { label: '徽章', value: 'badge' },
|
|
|
- { label: '证书', value: 'certificate' },
|
|
|
+const show = ref<boolean>(false)
|
|
|
+const canvasHidden = ref<boolean>(false)
|
|
|
+const posterUrl = ref<string | any>()
|
|
|
+const userStore = useUserStore()
|
|
|
+const { userInfo } = storeToRefs(userStore)
|
|
|
+const panels = ref([
|
|
|
+ {
|
|
|
+ iconUrl: NetImages.savePosterIcon,
|
|
|
+ title: '保存到本地',
|
|
|
+ index: 0,
|
|
|
+ },
|
|
|
])
|
|
|
-// 游学徽章,活动徽章,积分徽章,典藏勋章,传播徽章,打卡徽章,课程徽章
|
|
|
-const badgeTypes = ref([
|
|
|
- { label: '游学徽章', value: '游学徽章' },
|
|
|
- { label: '活动徽章', value: '活动徽章' },
|
|
|
- { label: '积分徽章', value: '积分徽章' },
|
|
|
- { label: '典藏勋章', value: '典藏勋章' },
|
|
|
- { label: '传播徽章', value: '传播徽章' },
|
|
|
- { label: '打卡徽章', value: '打卡徽章' },
|
|
|
- { label: '课程徽章', value: '课程徽章' },
|
|
|
-])
|
|
|
-const { data: badges, run: setBadges } = useRequest(() => getBadges({}), {
|
|
|
- initialData: {},
|
|
|
-})
|
|
|
-const { data: certificates, run: setCertificates } = useRequest(() => getCertificates({}), {
|
|
|
- initialData: [],
|
|
|
-})
|
|
|
+const { data: designer, run: setData } = useRequest(() => getDesignerInfo(userInfo.value.userId))
|
|
|
+/**
|
|
|
+ * 生成分享海拔
|
|
|
+ * */
|
|
|
+const createPoster = () => {
|
|
|
+ return new Promise((resolve, reject) => {
|
|
|
+ ;(async () => {
|
|
|
+ uni.showLoading({ title: '生成中' })
|
|
|
+ const [bgPath, badgePath, avatarPath, icon1, icon2, icon3, icon4] = await Promise.all(
|
|
|
+ [
|
|
|
+ NetImages.TopSpotlight,
|
|
|
+ data.value.quantity ? data.value.activedImage : data.value.image,
|
|
|
+ designer.value.headImgUrl || userInfo.value?.avatar || NetImages.DefaultAvatar,
|
|
|
+ data.value.quantity ? data.value.activedImage : data.value.image,
|
|
|
+ designer.value.headImgUrl || userInfo.value?.avatar || NetImages.DefaultAvatar,
|
|
|
+ 'https://image.zhuchaohui.com/zhucaohui/9f89604f285c33200b7e6fda9acc82e130f34c2f5687cfeb78f3541e1fabcc28.png',
|
|
|
+ 'https://image.zhuchaohui.com/zhucaohui/2467be55426018856150bd94bbd21865df3d73ce982bc1c82b7585cf26c822f0.png',
|
|
|
+ ].map((it) => uni.getImageInfo({ src: it }).then(({ path }) => path)),
|
|
|
+ )
|
|
|
+ const ctx = uni.createCanvasContext('firstCanvas')
|
|
|
+ ctx.fillStyle = '#141823'
|
|
|
+ ctx.fillRect(0, 0, 345, 500)
|
|
|
+ uni
|
|
|
+ .createSelectorQuery()
|
|
|
+ .select('#firstCanvas')
|
|
|
+ .fields({ size: true }, async ({ width: w, height: h }: any) => {
|
|
|
+ const canvas = new Canvas(ctx, { width: w, height: h }, { width: 345 })
|
|
|
+ canvas.FillImage(bgPath)
|
|
|
+ // ctx.drawImage(path, 0, 0, 16, 18)
|
|
|
+ canvas.CircleImage(avatarPath, 17, 20, 20)
|
|
|
+ canvas.Image(badgePath, 93, 74, 170, 180)
|
|
|
+ canvas.FillText(userInfo.value?.nickname, '#ffffff', 16, 63, 46)
|
|
|
+ const textNameWidth = ctx.measureText(data.value.name).width
|
|
|
+ const textDesWidth = ctx.measureText(subTitle.value).width
|
|
|
+ canvas.FillText(data.value?.name, '#ffffff', 18, (345 - textNameWidth) / 2, 291)
|
|
|
+ canvas.FillText(subTitle.value, '#ffffff', 14, (345 - textDesWidth) / 2, 326)
|
|
|
+
|
|
|
+ canvas.Image(icon1, 17, 415, 28, 28)
|
|
|
+ canvas.FillText('筑巢荟', '#ffffff', 18, 63, 436)
|
|
|
+ canvas.Image(icon2, 250, 393, 80, 80)
|
|
|
+
|
|
|
+ ctx.draw(true, () => {
|
|
|
+ uni.canvasToTempFilePath({
|
|
|
+ canvasId: 'firstCanvas',
|
|
|
+ width: 345,
|
|
|
+ height: 500,
|
|
|
+ success: (res) => {
|
|
|
+ // console.log('生成海报', res)
|
|
|
+ uni.hideLoading()
|
|
|
+ resolve(res.tempFilePath)
|
|
|
+ },
|
|
|
+ fail: (err) => {
|
|
|
+ // uni.hideLoading()
|
|
|
+ reject(err)
|
|
|
+ },
|
|
|
+ })
|
|
|
+ })
|
|
|
+ })
|
|
|
+ .exec()
|
|
|
+ })()
|
|
|
+ })
|
|
|
+}
|
|
|
+const save = async () => {
|
|
|
+ await uni.saveImageToPhotosAlbum({ filePath: posterUrl.value })
|
|
|
+ uni.showToast({ title: '已保存相册', icon: 'none' })
|
|
|
+}
|
|
|
+const cancelSaveImage = () => {
|
|
|
+ uni.showToast({ title: '取消保存', icon: 'none' })
|
|
|
+ show.value = false
|
|
|
+}
|
|
|
const data = ref<{
|
|
|
name: string
|
|
|
quantity: number
|
|
@@ -42,16 +109,21 @@ const data = ref<{
|
|
|
activedImage: string
|
|
|
badgeType?: string
|
|
|
badgeDescription?: string
|
|
|
- createTime?: number | Date
|
|
|
+ createTime?: number | Date | string
|
|
|
}>({
|
|
|
name: '',
|
|
|
quantity: 0,
|
|
|
image: '',
|
|
|
activedImage: '',
|
|
|
+ createTime: '',
|
|
|
})
|
|
|
const image = computed(() => (data.value.quantity ? data.value.activedImage : data.value.image))
|
|
|
+const subTitle = computed(() =>
|
|
|
+ data.value?.quantity > 1
|
|
|
+ ? `${dayjs(data.value.createTime).format('YYYY年MM月DD日')} 首次获得`
|
|
|
+ : `${dayjs(data.value.createTime).format('YYYY年MM月DD日')}获得`,
|
|
|
+)
|
|
|
const setBadgesPath = (type: string) => {
|
|
|
- console.log('========================', type)
|
|
|
if (type === '活动徽章') {
|
|
|
uni.redirectTo({
|
|
|
url: `/pages/home/offline-activity/index`,
|
|
@@ -62,9 +134,21 @@ const setBadgesPath = (type: string) => {
|
|
|
})
|
|
|
}
|
|
|
}
|
|
|
+const showActions = () => {
|
|
|
+ show.value = true
|
|
|
+}
|
|
|
+const close = () => {
|
|
|
+ show.value = false
|
|
|
+}
|
|
|
+const select = (item: any) => {
|
|
|
+ console.log(item, '分享选择')
|
|
|
+ let { index } = item
|
|
|
+ if (index === 0) {
|
|
|
+ save()
|
|
|
+ }
|
|
|
+}
|
|
|
onLoad(async (query: { type: 'badge' | 'certificate'; data: string }) => {
|
|
|
- console.log(JSON.parse(query.data))
|
|
|
-
|
|
|
+ console.log(query, 'query2')
|
|
|
if (query.type === 'badge') {
|
|
|
const badge = JSON.parse(query.data) as Badge
|
|
|
data.value = {
|
|
@@ -76,6 +160,10 @@ onLoad(async (query: { type: 'badge' | 'certificate'; data: string }) => {
|
|
|
badgeDescription: badge.badgeDescription,
|
|
|
createTime: badge.createTime,
|
|
|
}
|
|
|
+ if (data.value.quantity > 0) {
|
|
|
+ await setData()
|
|
|
+ posterUrl.value = await createPoster()
|
|
|
+ }
|
|
|
}
|
|
|
})
|
|
|
</script>
|
|
@@ -134,7 +222,11 @@ onLoad(async (query: { type: 'badge' | 'certificate'; data: string }) => {
|
|
|
累计参与{{ data.quantity }}次
|
|
|
</div>
|
|
|
</div>
|
|
|
- <wd-button custom-class="w-[161px] h-12 bg-[#0cbe7c]! rounded-[30px]" v-if="data.quantity > 0">
|
|
|
+ <wd-button
|
|
|
+ custom-class="w-[161px] h-12 bg-[#0cbe7c]! rounded-[30px]"
|
|
|
+ @click="showActions"
|
|
|
+ v-if="data.quantity > 0"
|
|
|
+ >
|
|
|
去分享
|
|
|
</wd-button>
|
|
|
<wd-button
|
|
@@ -144,5 +236,51 @@ onLoad(async (query: { type: 'badge' | 'certificate'; data: string }) => {
|
|
|
>
|
|
|
去获得
|
|
|
</wd-button>
|
|
|
+ <canvas
|
|
|
+ class="w-[347px] h-[494px] absolute rounded-[20px] top--1000"
|
|
|
+ canvas-id="firstCanvas"
|
|
|
+ id="firstCanvas"
|
|
|
+ ></canvas>
|
|
|
+ <wd-popup
|
|
|
+ v-model="show"
|
|
|
+ custom-class="!bg-[rgba(255,255,255,0)] !backdrop-blur-2xl"
|
|
|
+ position="bottom"
|
|
|
+ :safe-area-inset-bottom="true"
|
|
|
+ custom-style="height: 690px;"
|
|
|
+ @close="close"
|
|
|
+ >
|
|
|
+ <div class="rounded-[20px] mx-[14px]">
|
|
|
+ <div class="flex h-[500px]">
|
|
|
+ <ImageEvo
|
|
|
+ class="w-full h-full rounded-[20px] overflow-hidden"
|
|
|
+ :src="posterUrl"
|
|
|
+ @displayed="canvasHidden = true"
|
|
|
+ ></ImageEvo>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="bg-[#ffffff] rounded-[20px] mx-[14px] mt-[20px] py-4 px-6">
|
|
|
+ <div class="flex items-center gap-4">
|
|
|
+ <div
|
|
|
+ class="text-white text-[26px] font-normal font-['PingFang_SC'] uppercase text-center"
|
|
|
+ v-for="(item, index) in panels"
|
|
|
+ :key="index"
|
|
|
+ @click="select(item)"
|
|
|
+ >
|
|
|
+ <!-- 分享到 -->
|
|
|
+ <wd-img :src="item.iconUrl" width="40px" mode="widthFix"></wd-img>
|
|
|
+ <div class="text-center text-black text-sm font-normal font-['PingFang_SC'] uppercase">
|
|
|
+ {{ item.title }}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div
|
|
|
+ @click="cancelSaveImage"
|
|
|
+ class="bg-[rgb(240,240,240)] line-height-[40px] h-[40px] text-center rounded-[50px] mx-[4px] mt-[20px] text-black font-normal font-['PingFang_SC']"
|
|
|
+ >
|
|
|
+ 取消
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </wd-popup>
|
|
|
</div>
|
|
|
</template>
|