海报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) {
localStorage.setItem(
'saas_token',
'eyJpdiI6ImNoV0hTOFJCSjlSMklkYis4OHUrblE9PSIsInZhbHVlIjoicGZCZjFjS3d1UUl0ek1sUW52aVdqcGo2V0VwZGE4SCtpZTUrS1lGQ0czcDJLcDB2YlpENlNZd28xNkl1ZGJCTiIsIm1hYyI6IjhkYzlkMzAzZGQ2YTljMTVlY2YwOWIxMmQ2Y2I0ODE2M2Y5MDExNDdjMWMxZWU0ZDYyNWNmNmFkYTlhMmMzNTEifQ=='
'eyJpdiI6IlAzSFM4cHFJT01RN3R3OUMxV0ptM3c9PSIsInZhbHVlIjoiNFl6QUhcL3daME9QOTZjTVMzTFpJeUtJZ01NZ3hBb0ZtYmlRSlk5ZkVmK2l3Q1NSUGhRNm5GYXE2ZHo4TUtTVDQiLCJtYWMiOiJjODdkY2ZjYjc2NjI4MjkwMDUyNmQ3OGNmNjc1YTc0MGY5ZjNiZjYyZjBmMGYxZWNkMzEwNzhhMjZlMWJlY2FhIn0='
)
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 router from '@/router'
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
timeout: 12000, // request timeout
headers: {

View File

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