123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326 |
- <route lang="json">
- {
- "style": {
- "navigationBarTitleText": "我的荣誉",
- "navigationStyle": "custom"
- }
- }
- </route>
- <script setup lang="ts">
- import NavbarEvo from '@/components/navbar-evo.vue'
- import { getBanners, getDesignerInfo } from '../../../../core/libs/requests'
- import { Badge, BannerMode } from '../../../../core/libs/models'
- import { NetImages } from '../../../../core/libs/net-images'
- 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 show = ref<boolean>(false)
- const id = ref<string | number>('')
- const canvasHidden = ref<boolean>(false)
- const posterUrl = ref<string | any>()
- const userStore = useUserStore()
- const { userInfo } = storeToRefs(userStore)
- const badgePath = ref<any[]>([
- { badgeType: '游学徽章', path: '/pages-sub/home/study-tour/index' },
- { badgeType: '课程徽章', path: '/pages-sub/home/offline-activity/index' },
- { badgeType: '传播徽章', path: `/pages-sub/mine/homepage/index?id=${id.value}` },
- { badgeType: '积分徽章', path: '/pages-sub/home/mall/index' },
- { badgeType: '打卡徽章', path: '/pages/mine/index' },
- { badgeType: '活动徽章', path: '/pages-sub/home/offline-activity/index' },
- ])
- const panels = ref([
- {
- iconUrl: NetImages.savePosterIcon,
- title: '保存到本地',
- index: 0,
- },
- ])
- const { data: designer, run: setData } = useRequest(() => getDesignerInfo(id.value))
- /**
- * 生成分享海拔
- * */
- const createPoster = () => {
- return new Promise((resolve, reject) => {
- ;(async () => {
- uni.showLoading({ title: '生成中' })
- const [bgPath, badgePath, avatarPath, icon1, icon2] = await Promise.all(
- [
- NetImages.TopSpotlight,
- data.value.quantity ? data.value.activedImage : data.value.image,
- designer.value.headImgUrl || userInfo.value?.avatar || NetImages.DefaultAvatar,
- NetImages.Logo,
- designer.value?.homeUrl,
- ].map((it) => 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
- console.log(textDesWidth)
- canvas.FillText(data.value?.name, '#ffffff', 18, (345 - textNameWidth) / 2, 291)
- canvas.FillText(subTitle.value, '#ffffff', 14, (365 - 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
- userId: number
- quantity: number
- // 已获取的图片和未获取的图片
- image: string
- activedImage: string
- badgeType?: string
- badgeDescription?: string
- 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) => {
- if (type === '游学徽章' || type === '典藏勋章') {
- if (banners.value?.length > 0) {
- // url: `/pages-sub/home/study-tour/list?designStudyAbroadYear=${banners.value[0].designStudyAbroadYear}&designDesc=${banners.value[0].designDesc}`,
- uni.redirectTo({
- url: '/pages-sub/home/study-tour/index',
- })
- } else {
- uni.showToast({
- title: '暂无游学计划',
- icon: 'none',
- })
- }
- } else {
- if (type === '打卡徽章') {
- uni.switchTab({
- url: badgePath.value.find((it) => it.badgeType === type)?.path,
- })
- } else {
- uni.redirectTo({
- url: badgePath.value.find((it) => it.badgeType === type)?.path,
- })
- }
- }
- }
- const showActions = () => {
- show.value = true
- }
- const close = () => {
- show.value = false
- }
- const select = (item: any) => {
- console.log(item, '分享选择')
- let { index } = item
- if (index === 0) {
- save()
- }
- }
- const { data: banners, run: setBanners } = useRequest(
- () => getBanners({ mode: BannerMode.StudyTour }),
- { initialData: [] },
- )
- onLoad(async (query: { type: 'badge' | 'certificate'; data: string; id: number }) => {
- console.log(query, 'query2')
- if (query.type === 'badge') {
- id.value = query?.id
- const badge = JSON.parse(query.data) as Badge
- data.value = {
- name: badge.badgeName,
- userId: query.id,
- quantity: badge.quantity,
- image: badge.badgeNotObtainedImage,
- activedImage: badge.badgeYesObtainedImage,
- badgeType: badge.badgeType,
- badgeDescription: badge.badgeDescription,
- createTime: badge.createTime,
- }
- badgePath.value = badgePath.value.map((m) => {
- if (m.badgeType === '传播徽章') {
- m.path = `/pages-sub/mine/homepage/index?id=${id.value}`
- }
- return { ...m }
- })
- console.log('=======================', data)
- await setBanners()
- if (data.value.quantity > 0) {
- await setData()
- if (data.value.userId == userInfo.value.userId) {
- nextTick(async () => {
- posterUrl.value = await createPoster()
- })
- }
- }
- }
- })
- </script>
- <template>
- <div
- class="flex-grow bg-[#100f18] backdrop-blur-2xl flex flex-col items-center justify-between py-32 gap-4 relative"
- >
- <div class="absolute top-0 left-0 right-0">
- <wd-img
- width="100%"
- mode="widthFix"
- custom-clas="vertical-bottom"
- :src="NetImages.TopSpotlight"
- ></wd-img>
- </div>
- <div class="absolute top-20 left-0 right-0 flex flex-col items-center">
- <wd-img
- width="40%"
- mode="widthFix"
- custom-clas="vertical-bottom mx-auto"
- :src="NetImages.Stars"
- ></wd-img>
- </div>
- <NavbarEvo fixed dark transparent></NavbarEvo>
- <wd-img width="42%" mode="widthFix" :src="image"></wd-img>
- <div class="flex flex-col items-center gap-1">
- <div class="text-white text-[26px] font-normal font-['PingFang_SC'] uppercase">
- <!-- 东方研习营 -->
- {{ data.name }}
- </div>
- <div class="text-center text-white text-sm font-normal font-['PingFang_SC'] uppercase">
- <!-- 参加东方艺术设计研学营 -->
- {{ `${data.badgeDescription}` }}
- </div>
- <div class="mt-6 flex items-center gap-4">
- <div class="w-4 h-0.25 bg-white"></div>
- <div
- class="text-center text-white text-sm font-normal font-['PingFang_SC'] uppercase"
- v-if="data.quantity > 0"
- >
- {{ dayjs(data.createTime).format('YYYY年MM月DD日')
- }}{{ data.quantity > 1 ? '首次' : '' }}获得
- </div>
- <div
- class="text-center text-white text-sm font-normal font-['PingFang_SC'] uppercase"
- v-else
- >
- 暂未获得该徽章
- </div>
- <div class="w-4 h-0.25 bg-white"></div>
- </div>
- <div
- v-if="data.quantity > 1"
- class="text-center text-white text-sm font-normal font-['PingFang_SC'] uppercase"
- >
- 累计参与{{ data.quantity }}次
- </div>
- </div>
- <template v-if="data.userId == userInfo.userId">
- <wd-button
- custom-class="w-[161px] h-12 bg-[#0cbe7c]! rounded-[30px]"
- @click="showActions"
- v-if="data.quantity > 0"
- >
- 去分享
- </wd-button>
- <wd-button
- custom-class="w-[161px] h-12 bg-[#0cbe7c]! rounded-[30px]"
- @click="setBadgesPath(data.badgeType)"
- v-else
- >
- 去获得
- </wd-button>
- </template>
- <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>
|