海报update

This commit is contained in:
lanzhihui 2026-04-15 16:13:19 +08:00
parent ac431927b7
commit 7c1fdb0647
3 changed files with 212 additions and 154 deletions

View File

@ -118,7 +118,7 @@ router.beforeEach((to, from, next) => {
if (!IS_PROD) { if (!IS_PROD) {
localStorage.setItem( localStorage.setItem(
'saas_token', 'saas_token',
'eyJpdiI6ImNoV0hTOFJCSjlSMklkYis4OHUrblE9PSIsInZhbHVlIjoicGZCZjFjS3d1UUl0ek1sUW52aVdqcGo2V0VwZGE4SCtpZTUrS1lGQ0czcDJLcDB2YlpENlNZd28xNkl1ZGJCTiIsIm1hYyI6IjhkYzlkMzAzZGQ2YTljMTVlY2YwOWIxMmQ2Y2I0ODE2M2Y5MDExNDdjMWMxZWU0ZDYyNWNmNmFkYTlhMmMzNTEifQ==' 'eyJpdiI6IlAzSFM4cHFJT01RN3R3OUMxV0ptM3c9PSIsInZhbHVlIjoiNFl6QUhcL3daME9QOTZjTVMzTFpJeUtJZ01NZ3hBb0ZtYmlRSlk5ZkVmK2l3Q1NSUGhRNm5GYXE2ZHo4TUtTVDQiLCJtYWMiOiJjODdkY2ZjYjc2NjI4MjkwMDUyNmQ3OGNmNjc1YTc0MGY5ZjNiZjYyZjBmMGYxZWNkMzEwNzhhMjZlMWJlY2FhIn0='
) )
localStorage.setItem('authorize_at', '2022-01-17 10:39:24') localStorage.setItem('authorize_at', '2022-01-17 10:39:24')
} }

View File

@ -6,7 +6,7 @@ import { baseApi, baseApiV2 } from '@/config'
import store from '@/store' import store from '@/store'
import router from '@/router' import router from '@/router'
const service = axios.create({ const service = axios.create({
baseURL: location.href.includes('https') ? '/api' : baseApiV2, // url = base api url + request url baseURL: location.href.includes('https') ? '/api' : 'https://love.ufutx.cn/api', // url = base api url + request url
withCredentials: false, // send cookies when cross-domain requests withCredentials: false, // send cookies when cross-domain requests
timeout: 12000, // request timeout timeout: 12000, // request timeout
headers: { headers: {

View File

@ -25,10 +25,17 @@
<span class="confirm-btn" @click="showActivityPicker = false">确定</span> <span class="confirm-btn" @click="showActivityPicker = false">确定</span>
</div> </div>
<div class="scroll-wrapper"> <div class="scroll-wrapper">
<van-list v-model:loading="listLoading" :finished="listFinished" finished-text="没有更多活动了" <van-list
v-model:loading="listLoading"
:finished="listFinished"
finished-text="没有更多活动了"
@load="onLoadMore"> @load="onLoadMore">
<div v-for="item in activityList" :key="item.id" class="activity-item" <div
:class="{ active: selectedActivity?.id === item.id }" @click="onSelectActivity(item)"> v-for="item in activityList"
:key="item.id"
class="activity-item"
:class="{ active: selectedActivity?.id === item.id }"
@click="onSelectActivity(item)">
<div class="activity-title">{{ item.title }}</div> <div class="activity-title">{{ item.title }}</div>
<div class="activity-time">{{ item.Subtitle }} | {{ formatDateToShow(item.end_time) }}</div> <div class="activity-time">{{ item.Subtitle }} | {{ formatDateToShow(item.end_time) }}</div>
</div> </div>
@ -91,99 +98,118 @@
</div> </div>
</template> </template>
<script setup> <script>
import { nextTick, onMounted, ref, watch } from 'vue' import { nextTick } from 'vue' // Vue 2 vue nextTick使 this.$nextTick
import html2canvas from 'html2canvas' import html2canvas from 'html2canvas'
import { showDialog, showImagePreview, showLoadingToast, showToast } from 'vant' import { ImagePreview, Icon, Loading } from 'vant'
import requestApp from '@/utils/requestApp' import { $toastText, $toastSuccess, $toastLoading, $toastClear } from '@/config/toast'
import requestApp from '@/utils/request'
import QRCode from 'qrcode' import QRCode from 'qrcode'
import { weXinShare } from '@/plugins/wxShare' import Vue from 'vue'
// 🔥 Vue.use(Icon)
const sponsorName = ref('') Vue.use(Loading)
const posterRef = ref(null) export default {
const posterImg = ref('') name: 'ActivityPoster',
const isGenerating = ref(false) data() {
const isWeChatEnv = ref(false) return {
const qrcodeCanvas = ref(null) // ( ref reactive)
sponsorName: '',
const activityList = ref([]) posterImg: '',
const selectedActivity = ref(null) isGenerating: false,
const selectedActivityTitle = ref('') isWeChatEnv: false,
const showActivityPicker = ref(false) activityList: [],
const listLoading = ref(false) selectedActivity: null,
const listFinished = ref(true) selectedActivityTitle: '',
const openId = ref('') showActivityPicker: false,
listLoading: false,
// + listFinished: true,
watch(selectedActivity, async (newVal) => { openId: ''
if (newVal && newVal.id && qrcodeCanvas.value) { // qrcodeCanvas DOM mounted this.$refs 访
//
sponsorName.value = newVal.sponsor || ''
openId.value = localStorage.getItem('openid')
const link = `https://love.ufutx.cn/api/official/live/wechat/FamilyAuth?merchant_id=44&serve_tab=&from_openid=${openId.value}&url=https%3A%2F%2Flove.ufutx.cn%2Fpu%2F%23%2FactivityDetails%2F${newVal.id}`
await QRCode.toCanvas(qrcodeCanvas.value, link, {
width: 76,
margin: 1,
color: { dark: '#000000', light: '#ffffff' }
})
} }
}) },
mounted() {
// onMounted
this.detectWeChatEnv()
this.getData()
console.log('33')
},
methods: {
// script setup
async getData() {
console.log('33455')
const vm = this
const getData = () => { this.listLoading = true
listLoading.value = true // weXinShare Vue 2
weXinShare('https://image.fulllinkai.com/202310/28/88e931a50ec0a8094fb46191b389457e.png', `https://health.ufutx.cn/go_html/role_apply#/activityPoster`, '活动海报生成「saas」', '查看详情') vm.$nextTick(() => {
requestApp({ url: '/sh5/uftx/community/activity/list', method: 'get' }) setTimeout(() => {
.then((res) => { // if (vm.$store.state.app.configData) {
if (res.code === 0 && Array.isArray(res.data)) { const urls = `${vm.$shareCallback}/api/official/live/wechat/FamilyAuth?from_openid=${localStorage.getItem('openid')}&merchant_id=${vm.$store.state.app.merchant_id}&spread_merchant_id=${vm.$store.state.app.spread_merchant_id}&url=` + encodeURIComponent(`${vm.$shareCallback}/pu/#/VIPDetail/${vm.id}`)
activityList.value = res.data vm.$shareList(
// 'https://image.fulllinkai.com/202310/28/88e931a50ec0a8094fb46191b389457e.png?x-oss-process=image/resize,w_200,h_200',
// if (res.data.length > 0) { urls,
// onSelectActivity(res.data[0]); '查看详情',
'活动海报生成「saas」'
)
// } // }
}, 300)
})
// vm.$shareList('https://image.fulllinkai.com/202310/28/88e931a50ec0a8094fb46191b389457e.png',
// `https://health.ufutx.cn/go_html/role_apply#/activityPoster`,
// '', 'saas')
try {
const res = await requestApp({
url: '/s/h5/uftx/community/activity/list',
method: 'get'
})
console.log(res, 'res---')
if (Array.isArray(res)) {
this.activityList = res
} else { } else {
showToast('活动列表获取失败') $toastText('活动列表获取失败')
} }
}) console.log(this.activityList, ' this.activityList')
.catch((err) => { } catch (err) {
console.error('获取活动列表失败:', err) console.error('获取活动列表失败:', err)
showToast('活动列表获取失败,请重试') $toastText('活动列表获取失败,请重试')
}) } finally {
.finally(() => { this.listLoading = false
listLoading.value = false this.listFinished = true
listFinished.value = true $toastClear()
})
} }
},
const detectWeChatEnv = () => { detectWeChatEnv() {
const userAgent = navigator.userAgent.toLowerCase() const userAgent = navigator.userAgent.toLowerCase()
isWeChatEnv.value = /micromessenger/.test(userAgent) this.isWeChatEnv = /micromessenger/.test(userAgent)
} },
// onSelectActivity(item) {
const onSelectActivity = (item) => { this.selectedActivity = item
selectedActivity.value = item this.selectedActivityTitle = item.title
selectedActivityTitle.value = item.title this.showActivityPicker = false
showActivityPicker.value = false this.generatePoster()
generatePoster() },
}
const onLoadMore = () => { onLoadMore() {
listLoading.value = false this.listLoading = false
listFinished.value = true this.listFinished = true
} },
const formatDateToShow = (timeStr) => { formatDateToShow(timeStr) {
if (!timeStr) return '' if (!timeStr) return ''
const date = new Date(timeStr) const date = new Date(timeStr)
const year = date.getFullYear() const year = date.getFullYear()
const month = String(date.getMonth() + 1).padStart(2, '0') const month = String(date.getMonth() + 1).padStart(2, '0')
const day = String(date.getDate()).padStart(2, '0') const day = String(date.getDate()).padStart(2, '0')
return `${year}${month}${day}` return `${year}${month}${day}`
} },
const formatDateToChinese = (timeStr) => { formatDateToChinese(timeStr) {
if (!timeStr) { if (!timeStr) {
const now = new Date() const now = new Date()
const year = now.getFullYear() const year = now.getFullYear()
@ -194,37 +220,38 @@ const formatDateToChinese = (timeStr) => {
const [datePart] = timeStr.split(' ') const [datePart] = timeStr.split(' ')
const [year, month, day] = datePart.split('-') const [year, month, day] = datePart.split('-')
return `${year}/${month}/${day}` return `${year}/${month}/${day}`
} },
const formatTime = (timeStr) => { formatTime(timeStr) {
if (!timeStr) return '14:00' if (!timeStr) return '14:00'
const [, timePart] = timeStr.split(' ') const [, timePart] = timeStr.split(' ')
return timePart.slice(0, 5) return timePart.slice(0, 5)
} },
const showImagePreviewFn = (img) => { showImagePreviewFn(img) {
return showImagePreview([img]) return ImagePreview({
} images: [img],
showIndex: true
})
},
const generatePoster = async () => { async generatePoster() {
try { try {
if (!selectedActivity.value) { if (!this.selectedActivity) {
showDialog({ message: '请先选择活动!' }) $toastText('请先选择活动!')
return return
} }
this.isGenerating = true
$toastLoading('海报生成中...')
isGenerating.value = true // Vue 2 使 $nextTick
const toast = showLoadingToast({ await this.$nextTick()
message: '海报生成中...',
forbidClick: true,
duration: 0
})
await nextTick() // 使 ref="posterRef" this.$refs 访
const posterElement = posterRef.value const posterElement = this.$refs.posterRef
if (!posterElement) { if (!posterElement) {
isGenerating.value = false this.isGenerating = false
toast.close() $toastClear()
return return
} }
@ -236,32 +263,56 @@ const generatePoster = async () => {
imageTimeout: 10000 imageTimeout: 10000
}) })
posterImg.value = canvas.toDataURL('image/png', 1.0) this.posterImg = canvas.toDataURL('image/png', 1.0)
toast.close() $toastClear()
showToast({ message: '海报生成成功!', icon: 'success' }) $toastSuccess('海报生成成功')
} catch (err) { } catch (err) {
console.error('生成海报失败:', err) console.error('生成海报失败:', err)
showToast({ message: '生成海报失败,请重试!', icon: 'fail' }) $toastText('生成海报失败,请重试!')
} finally { } finally {
isGenerating.value = false this.isGenerating = false
} $toastClear()
} }
},
function downloadPoster() { downloadPoster() {
if (!posterImg.value) return if (!this.posterImg) return
const link = document.createElement('a') const link = document.createElement('a')
link.href = posterImg.value link.href = this.posterImg
// / const fileName = `[${this.selectedActivity?.title || '活动'}]海报.png`
const fileName = `[${selectedActivity.value?.title || '活动'}]海报.png`
link.download = fileName.replace(/[\\/:*?"<>|]/g, '') link.download = fileName.replace(/[\\/:*?"<>|]/g, '')
link.click() link.click()
URL.revokeObjectURL(link.href) URL.revokeObjectURL(link.href)
} }
},
watch: {
// ( watch(selectedActivity, ...))
selectedActivity: {
handler(newVal) {
if (newVal && newVal.id) {
//
this.sponsorName = newVal.sponsor || ''
this.openId = localStorage.getItem('openid')
onMounted(() => { // Vue 2 this.$refs 访 DOM
detectWeChatEnv() const canvas = this.$refs.qrcodeCanvas
getData() if (canvas) {
const link = `https://love.ufutx.cn/api/official/live/wechat/FamilyAuth?merchant_id=44&serve_tab=&from_openid=${this.openId}&url=https%3A%2F%2Flove.ufutx.cn%2Fpu%2F%23%2FactivityDetails%2F${newVal.id}`
QRCode.toCanvas(canvas, link, {
width: 76,
margin: 1,
color: { dark: '#000000', light: '#ffffff' }
}).catch(err => {
console.error('生成二维码失败:', err)
}) })
}
}
},
immediate: true // immediate
}
}
}
</script> </script>
<style scoped> <style scoped>
@ -538,6 +589,12 @@ img {
color: #9ca3af; color: #9ca3af;
font-size: 14px; font-size: 14px;
flex-shrink: 0; flex-shrink: 0;
width: 16px;
height: 16px;
.vant-select-icon{
width: 16px;
height: 16px;
}
} }
/* 弹窗样式 */ /* 弹窗样式 */
@ -581,6 +638,7 @@ img {
.scroll-wrapper { .scroll-wrapper {
flex: 1; flex: 1;
overflow-y: auto; overflow-y: auto;
margin-bottom: 100px;
} }
.activity-item { .activity-item {