828 lines
19 KiB
Vue
828 lines
19 KiB
Vue
<template>
|
||
<div class="poster-generator-container">
|
||
|
||
<div class="input-card">
|
||
<div class="card-header">
|
||
<span class="header-icon">📋</span>
|
||
<span class="header-title">选择活动</span>
|
||
</div>
|
||
<div class="activity-selector" @click="showActivityPicker = true">
|
||
<div class="selector-label">活动名称</div>
|
||
<div class="selector-value" :class="{ placeholder: !selectedActivityTitle }">
|
||
<span class="selector-text">{{ selectedActivityTitle || '点击选择活动' }}</span>
|
||
</div>
|
||
<div class="selector-arrow">
|
||
<van-icon name="arrow" />
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 活动选择弹窗 -->
|
||
<van-popup v-model:show="showActivityPicker" position="bottom" round class="activity-popup">
|
||
<div class="activity-picker-header">
|
||
<span class="cancel-btn" @click="showActivityPicker = false">取消</span>
|
||
<span class="title">选择活动</span>
|
||
<span class="confirm-btn" @click="showActivityPicker = false">确定</span>
|
||
</div>
|
||
<div class="scroll-wrapper">
|
||
<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 class="activity-title">{{ item.title }}</div>
|
||
<div class="activity-time">{{ item.Subtitle }} | {{ formatDateToShow(item.end_time) }}</div>
|
||
</div>
|
||
</van-list>
|
||
</div>
|
||
</van-popup>
|
||
|
||
<!-- 隐藏海报区域(样式保持原样) -->
|
||
<div ref="posterRef" class="poster-wrapper hidden-poster">
|
||
<div class="poster-card">
|
||
<div class="poster-content">
|
||
<img src="https://images.health.ufutx.com/202604/15/a90d31b444dd5f8f974b502b42bd4872.jpeg" alt="海报背景图" />
|
||
<div class="poster-content-wrapper">
|
||
<div class="poster-title">
|
||
<p class="poster-title-text">{{ formattedTitle }}</p>
|
||
</div>
|
||
<div class="poster-subtitle">
|
||
<p class="poster-subtitle-text">{{ selectedActivity?.Subtitle || '河南·襄城站' }}</p>
|
||
</div>
|
||
<div class="sponsor-name">
|
||
<p class="name">主办:{{ sponsorName }}</p>
|
||
</div>
|
||
|
||
<div class="poster-qrcode">
|
||
<canvas ref="qrcodeCanvas" class="poster-qrcode-image"></canvas>
|
||
</div>
|
||
|
||
<div class="poster-time-wrap">
|
||
<div class="poster-date">{{ formatDateToChinese(selectedActivity?.end_time) }}</div>
|
||
<div class="poster-time">
|
||
<span class="start-time">{{ formatTime(selectedActivity?.start_time) }}</span>
|
||
<span class="end-time">{{ formatTime(selectedActivity?.end_time) }}</span>
|
||
</div>
|
||
</div>
|
||
<div class="poster-address">
|
||
<div class="_text-warp">
|
||
<div class="_title">活动地点:</div>
|
||
<div class="_text">{{ selectedActivity?.address || '广东省深圳市南山区阳光科创' }}</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 操作按钮组 -->
|
||
<div class="btn-group">
|
||
<button class="btn btn-primary" :disabled="isGenerating" @click="generatePoster">
|
||
<van-loading v-if="isGenerating" size="20px" color="#fff" />
|
||
<span v-else>✨ 生成海报</span>
|
||
</button>
|
||
<button v-if="posterImg && !isWeChatEnv" class="btn btn-secondary" @click="downloadPoster">📥 下载海报</button>
|
||
</div>
|
||
|
||
<!-- 生成预览区域 -->
|
||
<div v-if="posterImg" class="generated-poster-preview">
|
||
<div class="preview-header">
|
||
<div class="preview-icon">🎉</div>
|
||
<h4 class="preview-title">{{ isWeChatEnv ? '长按图片保存到手机' : '点击图片预览大图' }}</h4>
|
||
</div>
|
||
<img :src="posterImg" alt="生成的海报" class="preview-img" @click="showImagePreviewFn(posterImg)" />
|
||
</div>
|
||
</div>
|
||
</template>
|
||
|
||
<script>
|
||
|
||
import html2canvas from 'html2canvas'
|
||
import { ImagePreview } from 'vant'
|
||
import { $toastText, $toastSuccess, $toastLoading, $toastClear } from '@/config/toast'
|
||
import requestApp from '@/utils/request'
|
||
import QRCode from 'qrcode'
|
||
|
||
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')
|
||
},
|
||
computed: {
|
||
formattedTitle() {
|
||
if (!this.selectedActivity?.title) return ''
|
||
const parts = this.selectedActivity.title.split('•')
|
||
console.log('computed parts:', parts)
|
||
const lastPart = parts[parts.length - 1].trim()
|
||
console.log('computed formattedTitle:', lastPart)
|
||
return lastPart
|
||
}
|
||
},
|
||
methods: {
|
||
// 格式化标题:切割 · 符号,取最后一个
|
||
// formatTitle(title) {
|
||
// if (!title) return ''
|
||
// // 按 · 分割,取最后一部分,并去除首尾空格
|
||
// debugger
|
||
// const parts = title.split('·')
|
||
// console.log(parts)
|
||
// debugger
|
||
// const lastPart = parts[parts.length - 1].trim()
|
||
// return lastPart
|
||
// },
|
||
|
||
// 替代 script setup 中的函数
|
||
async getData() {
|
||
console.log('33455')
|
||
const vm = this
|
||
|
||
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/#/activityPoster`)
|
||
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 {
|
||
$toastText('活动列表获取失败')
|
||
}
|
||
console.log(this.activityList, ' this.activityList')
|
||
} catch (err) {
|
||
console.error('获取活动列表失败:', err)
|
||
$toastText('活动列表获取失败,请重试')
|
||
} finally {
|
||
this.listLoading = false
|
||
this.listFinished = true
|
||
$toastClear()
|
||
}
|
||
},
|
||
|
||
detectWeChatEnv() {
|
||
const userAgent = navigator.userAgent.toLowerCase()
|
||
this.isWeChatEnv = /micromessenger/.test(userAgent)
|
||
},
|
||
|
||
onSelectActivity(item) {
|
||
this.selectedActivity = item
|
||
this.selectedActivityTitle = item.title
|
||
this.showActivityPicker = false
|
||
this.generatePoster()
|
||
},
|
||
|
||
onLoadMore() {
|
||
this.listLoading = false
|
||
this.listFinished = true
|
||
},
|
||
|
||
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}日`
|
||
},
|
||
|
||
formatDateToChinese(timeStr) {
|
||
if (!timeStr) {
|
||
const now = new Date()
|
||
const year = now.getFullYear()
|
||
const month = String(now.getMonth() + 1).padStart(2, '0')
|
||
const day = String(now.getDate()).padStart(2, '0')
|
||
return `${year}/${month}/${day}`
|
||
}
|
||
const [datePart] = timeStr.split(' ')
|
||
const [year, month, day] = datePart.split('-')
|
||
return `${year}/${month}/${day}`
|
||
},
|
||
|
||
formatTime(timeStr) {
|
||
if (!timeStr) return '14:00'
|
||
const [, timePart] = timeStr.split(' ')
|
||
return timePart.slice(0, 5)
|
||
},
|
||
|
||
showImagePreviewFn(img) {
|
||
return ImagePreview({
|
||
images: [img],
|
||
showIndex: true
|
||
})
|
||
},
|
||
|
||
async generatePoster() {
|
||
try {
|
||
console.log(this.selectedActivity, 'pp--')
|
||
if (!this.selectedActivity) {
|
||
console.log('fd')
|
||
$toastText('请先选择活动!')
|
||
return
|
||
}
|
||
this.isGenerating = true
|
||
$toastLoading('海报生成中...')
|
||
|
||
// Vue 2 中使用 $nextTick
|
||
await this.$nextTick()
|
||
|
||
// 注意:原代码中使用了 ref="posterRef",这里通过 this.$refs 访问
|
||
const posterElement = this.$refs.posterRef
|
||
if (!posterElement) {
|
||
this.isGenerating = false
|
||
$toastClear()
|
||
return
|
||
}
|
||
|
||
const canvas = await html2canvas(posterElement, {
|
||
useCORS: true,
|
||
scale: 3,
|
||
backgroundColor: null,
|
||
logging: false,
|
||
imageTimeout: 10000
|
||
})
|
||
|
||
this.posterImg = canvas.toDataURL('image/png', 1.0)
|
||
$toastClear()
|
||
$toastSuccess('海报生成成功')
|
||
} catch (err) {
|
||
console.error('生成海报失败:', err)
|
||
$toastText('生成海报失败,请重试!')
|
||
} finally {
|
||
this.isGenerating = false
|
||
setTimeout(() => {
|
||
$toastClear()
|
||
}, 1200)
|
||
}
|
||
},
|
||
|
||
downloadPoster() {
|
||
if (!this.posterImg) return
|
||
const link = document.createElement('a')
|
||
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')
|
||
|
||
// 注意: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>
|
||
img {
|
||
display: inline-block !important;
|
||
max-width: 100%;
|
||
max-height: 100%;
|
||
}
|
||
|
||
.poster-wrapper {
|
||
width: 375px;
|
||
height: 788px;
|
||
overflow: hidden;
|
||
}
|
||
|
||
.hidden-poster {
|
||
position: absolute;
|
||
left: -9999px;
|
||
top: -9999px;
|
||
z-index: -1;
|
||
pointer-events: none;
|
||
}
|
||
|
||
.poster-card {
|
||
width: 100%;
|
||
height: 100%;
|
||
color: #ffffff;
|
||
box-sizing: border-box;
|
||
display: flex;
|
||
flex-direction: column;
|
||
justify-content: space-between;
|
||
background: #333333;
|
||
position: relative;
|
||
}
|
||
|
||
.poster-content img {
|
||
object-fit: cover;
|
||
}
|
||
|
||
.poster-content {
|
||
width: 100%;
|
||
height: 100%;
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 20px;
|
||
position: relative;
|
||
}
|
||
|
||
.poster-title {
|
||
position: absolute;
|
||
left: 0;
|
||
top: 130px;
|
||
width: 100%;
|
||
letter-spacing: 4px;
|
||
font-size: 32px;
|
||
font-weight: 900;
|
||
display: flex;
|
||
justify-content: center;
|
||
padding: 0;
|
||
}
|
||
|
||
.poster-title .poster-title-text {
|
||
text-align: center;
|
||
width: 300px;
|
||
color: #0d2f73;
|
||
line-height: 1.6;
|
||
padding: 2px 0;
|
||
margin: 0;
|
||
display: -webkit-box;
|
||
-webkit-line-clamp: 2;
|
||
-webkit-box-orient: vertical;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
}
|
||
.poster-subtitle {
|
||
position: absolute;
|
||
left: 0;
|
||
top: 262px;
|
||
width: 100%;
|
||
letter-spacing: 4px;
|
||
font-size: 20px;
|
||
font-weight: 400;
|
||
display: flex;
|
||
justify-content: center;
|
||
padding: 0;
|
||
}
|
||
|
||
.poster-subtitle .poster-subtitle-text {
|
||
text-align: center;
|
||
width: 300px;
|
||
color: #0d2f73;
|
||
line-height: 1.6;
|
||
padding: 2px 0;
|
||
margin: 0;
|
||
display: -webkit-box;
|
||
-webkit-line-clamp: 2;
|
||
-webkit-box-orient: vertical;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
}
|
||
.sponsor-name {
|
||
position: absolute;
|
||
left: 0;
|
||
top: 446px;
|
||
width: 100%;
|
||
letter-spacing: 0.8px;
|
||
display: flex;
|
||
justify-content: center;
|
||
padding: 0;
|
||
}
|
||
|
||
.sponsor-name .name {
|
||
font-size: 14px;
|
||
color: #0e2965;
|
||
}
|
||
|
||
.poster-qrcode {
|
||
position: absolute;
|
||
left: 0;
|
||
top: 532px;
|
||
width: 100%;
|
||
display: flex;
|
||
justify-content: center;
|
||
padding: 0;
|
||
}
|
||
|
||
.poster-qrcode-image {
|
||
width: 76px;
|
||
height: 76px;
|
||
border-radius: 8px;
|
||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
|
||
background-color: #ffffff;
|
||
padding: 3px;
|
||
}
|
||
|
||
.poster-time-wrap {
|
||
position: absolute;
|
||
left: 0;
|
||
top: 630px;
|
||
width: 100%;
|
||
text-align: center;
|
||
justify-content: center;
|
||
letter-spacing: 1px;
|
||
}
|
||
|
||
.poster-date {
|
||
font-size: 24px;
|
||
font-weight: 500;
|
||
color: #0e2866;
|
||
}
|
||
|
||
.poster-time {
|
||
font-weight: 400;
|
||
font-size: 22px;
|
||
color: #0e2866;
|
||
margin-top: 14px;
|
||
}
|
||
|
||
.start-time {
|
||
margin-right: 30px;
|
||
}
|
||
|
||
.poster-address {
|
||
position: absolute;
|
||
left: 0;
|
||
top: 720px;
|
||
width: 100%;
|
||
max-height: 50px;
|
||
display: flex;
|
||
text-align: center;
|
||
justify-content: center;
|
||
letter-spacing: 1px;
|
||
}
|
||
|
||
.poster-address ._text-warp {
|
||
max-width: 80%;
|
||
font-size: 14px;
|
||
color: #0f2967;
|
||
font-weight: 500;
|
||
background: white;
|
||
border-radius: 32px;
|
||
padding: 4px 16px;
|
||
display: flex;
|
||
justify-content: space-between;
|
||
}
|
||
|
||
.poster-address ._title {
|
||
width: 76px;
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.poster-address ._text {
|
||
text-align: left;
|
||
display: -webkit-box;
|
||
-webkit-line-clamp: 2;
|
||
-webkit-box-orient: vertical;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
}
|
||
|
||
/* ========== 以下为美化后的外部样式(选择器、按钮、预览区域) ========== */
|
||
.poster-generator-container {
|
||
min-height: 100vh;
|
||
padding: 20px 16px 40px;
|
||
background: linear-gradient(135deg, #f5f7fa 0%, #e9eef3 100%);
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
gap: 24px;
|
||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
|
||
}
|
||
|
||
/* 输入卡片 */
|
||
.input-card {
|
||
width: 100%;
|
||
max-width: 400px;
|
||
background: #ffffff;
|
||
border-radius: 24px;
|
||
box-shadow: 0 8px 20px rgba(0, 0, 0, 0.06);
|
||
overflow: hidden;
|
||
transition: transform 0.2s, box-shadow 0.2s;
|
||
}
|
||
|
||
.input-card:hover {
|
||
box-shadow: 0 12px 28px rgba(0, 0, 0, 0.1);
|
||
}
|
||
|
||
.card-header {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 8px;
|
||
padding: 16px 20px 0;
|
||
font-size: 16px;
|
||
font-weight: 600;
|
||
color: #1f2937;
|
||
}
|
||
|
||
.header-icon {
|
||
font-size: 20px;
|
||
}
|
||
|
||
.header-title {
|
||
background: linear-gradient(135deg, #18ca6e, #0f9d58);
|
||
background-clip: text;
|
||
-webkit-background-clip: text;
|
||
-webkit-text-fill-color: transparent;
|
||
}
|
||
|
||
.activity-selector {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
padding: 12px 20px 12px 20px;
|
||
cursor: pointer;
|
||
transition: background 0.2s;
|
||
}
|
||
|
||
.activity-selector:active {
|
||
background: #f8fafc;
|
||
}
|
||
|
||
.selector-label {
|
||
font-size: 14px;
|
||
color: #6b7280;
|
||
font-weight: 500;
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.selector-value {
|
||
flex: 1;
|
||
margin: 0 12px;
|
||
font-size: 15px;
|
||
font-weight: 500;
|
||
color: #1f2937;
|
||
text-align: right;
|
||
display: flex;
|
||
justify-content: flex-end;
|
||
align-items: center;
|
||
min-height: 42px;
|
||
}
|
||
|
||
.selector-text {
|
||
display: -webkit-box;
|
||
-webkit-line-clamp: 2;
|
||
-webkit-box-orient: vertical;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
word-break: break-word;
|
||
max-width: 100%;
|
||
line-height: 1.4;
|
||
}
|
||
|
||
.selector-value.placeholder .selector-text {
|
||
color: #9ca3af;
|
||
font-weight: 400;
|
||
}
|
||
|
||
.selector-arrow {
|
||
color: #9ca3af;
|
||
font-size: 14px;
|
||
flex-shrink: 0;
|
||
width: 16px;
|
||
height: 16px;
|
||
}
|
||
|
||
.selector-arrow .van-icon {
|
||
width: 16px;
|
||
height: 16px;
|
||
}
|
||
|
||
/* 弹窗样式 */
|
||
.activity-popup {
|
||
height: 85vh;
|
||
display: flex;
|
||
flex-direction: column;
|
||
border-radius: 20px 20px 0 0;
|
||
overflow: hidden;
|
||
}
|
||
|
||
.activity-picker-header {
|
||
flex-shrink: 0;
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
padding: 16px 20px;
|
||
border-bottom: 1px solid #f0f0f0;
|
||
background: #fff;
|
||
}
|
||
|
||
.cancel-btn {
|
||
font-size: 15px;
|
||
color: #9ca3af;
|
||
cursor: pointer;
|
||
}
|
||
|
||
.title {
|
||
font-size: 17px;
|
||
font-weight: 600;
|
||
color: #1f2937;
|
||
}
|
||
|
||
.confirm-btn {
|
||
font-size: 15px;
|
||
color: #18ca6e;
|
||
font-weight: 600;
|
||
cursor: pointer;
|
||
}
|
||
|
||
.scroll-wrapper {
|
||
flex: 1;
|
||
overflow-y: auto;
|
||
padding-bottom: 20px;
|
||
}
|
||
|
||
.activity-item {
|
||
padding: 16px 20px;
|
||
border-bottom: 1px solid #f5f5f5;
|
||
cursor: pointer;
|
||
transition: background 0.2s;
|
||
}
|
||
|
||
.activity-item:active {
|
||
background: #f8fafc;
|
||
}
|
||
|
||
.activity-item.active {
|
||
background: #f0fdf4;
|
||
border-left: 3px solid #18ca6e;
|
||
}
|
||
|
||
.activity-title {
|
||
font-size: 15px;
|
||
font-weight: 600;
|
||
color: #1f2937;
|
||
margin-bottom: 6px;
|
||
}
|
||
|
||
.activity-time {
|
||
font-size: 12px;
|
||
color: #9ca3af;
|
||
}
|
||
|
||
/* 按钮组 */
|
||
.btn-group {
|
||
display: flex;
|
||
gap: 16px;
|
||
width: 100%;
|
||
max-width: 400px;
|
||
}
|
||
|
||
.btn {
|
||
flex: 1;
|
||
padding: 14px 20px;
|
||
border: none;
|
||
border-radius: 60px;
|
||
font-size: 16px;
|
||
font-weight: 600;
|
||
cursor: pointer;
|
||
transition: all 0.25s ease;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
gap: 8px;
|
||
}
|
||
|
||
.btn-primary {
|
||
background: linear-gradient(135deg, #18ca6e, #0f9d58);
|
||
color: white;
|
||
box-shadow: 0 4px 12px rgba(24, 202, 110, 0.3);
|
||
}
|
||
|
||
.btn-primary:active {
|
||
transform: scale(0.97);
|
||
box-shadow: 0 2px 6px rgba(24, 202, 110, 0.3);
|
||
}
|
||
|
||
.btn-primary:disabled {
|
||
opacity: 0.7;
|
||
transform: none;
|
||
cursor: not-allowed;
|
||
}
|
||
|
||
.btn-secondary {
|
||
background: #2c3e50;
|
||
color: white;
|
||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||
}
|
||
|
||
.btn-secondary:active {
|
||
transform: scale(0.97);
|
||
}
|
||
|
||
/* 预览区域 */
|
||
.generated-poster-preview {
|
||
width: 100%;
|
||
max-width: 400px;
|
||
background: white;
|
||
border-radius: 28px;
|
||
padding: 20px;
|
||
box-shadow: 0 12px 30px rgba(0, 0, 0, 0.1);
|
||
transition: all 0.3s;
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
.preview-header {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
gap: 8px;
|
||
margin-bottom: 16px;
|
||
}
|
||
|
||
.preview-icon {
|
||
font-size: 22px;
|
||
}
|
||
|
||
.preview-title {
|
||
font-size: 15px;
|
||
font-weight: 500;
|
||
color: #374151;
|
||
margin: 0;
|
||
}
|
||
|
||
.preview-img {
|
||
width: 100%;
|
||
border-radius: 16px;
|
||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
|
||
cursor: pointer;
|
||
transition: transform 0.2s;
|
||
}
|
||
|
||
.preview-img:active {
|
||
transform: scale(0.99);
|
||
}
|
||
|
||
/* 适配小屏幕 */
|
||
@media (max-width: 420px) {
|
||
.poster-generator-container {
|
||
padding: 16px 12px 32px;
|
||
}
|
||
|
||
.btn {
|
||
padding: 12px 16px;
|
||
font-size: 14px;
|
||
}
|
||
}
|
||
</style>
|