1. 海报
This commit is contained in:
@@ -23,7 +23,7 @@ func Register(api *gin.RouterGroup, database *gorm.DB, adminGuard func(*gin.Cont
|
||||
api.POST("/poster/config", handleSavePosterConfig)
|
||||
}
|
||||
|
||||
// resolveSide 返回 "1"(男方)或 "2"(女方);无法识别返回空
|
||||
// resolveSide 返回 "1"(男方)、"2"(女方)或 "3"(回门宴);无法识别返回空
|
||||
func resolveSide(raw string) string {
|
||||
v := strings.ToLower(strings.TrimSpace(raw))
|
||||
switch v {
|
||||
@@ -31,6 +31,8 @@ func resolveSide(raw string) string {
|
||||
return "1"
|
||||
case "2", "female", "nv", "f", "bride":
|
||||
return "2"
|
||||
case "3", "hm", "hmy", "return", "huimen":
|
||||
return "3"
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
@@ -40,7 +42,7 @@ func isLegacyFlat(m map[string]interface{}) bool {
|
||||
if m == nil {
|
||||
return false
|
||||
}
|
||||
for _, k := range []string{"1", "2", "male", "female"} {
|
||||
for _, k := range []string{"1", "2", "3", "male", "female", "hm"} {
|
||||
if _, ok := m[k]; ok {
|
||||
return false
|
||||
}
|
||||
@@ -73,7 +75,7 @@ func takeSide(raw map[string]interface{}, keys ...string) map[string]interface{}
|
||||
return emptyObj()
|
||||
}
|
||||
|
||||
// normalizeBundle 统一为 { "1", "2" };兼容旧 male/female 与扁平配置
|
||||
// normalizeBundle 统一为 { "1", "2", "3" };兼容旧 male/female 与扁平配置
|
||||
func normalizeBundle(raw map[string]interface{}) map[string]interface{} {
|
||||
if raw == nil {
|
||||
raw = emptyObj()
|
||||
@@ -81,6 +83,7 @@ func normalizeBundle(raw map[string]interface{}) map[string]interface{} {
|
||||
out := map[string]interface{}{
|
||||
"1": emptyObj(),
|
||||
"2": emptyObj(),
|
||||
"3": emptyObj(),
|
||||
}
|
||||
if isLegacyFlat(raw) {
|
||||
out["1"] = raw
|
||||
@@ -92,6 +95,9 @@ func normalizeBundle(raw map[string]interface{}) map[string]interface{} {
|
||||
if f := takeSide(raw, "2", "female"); len(f) > 0 {
|
||||
out["2"] = f
|
||||
}
|
||||
if h := takeSide(raw, "3", "hm", "hmy"); len(h) > 0 {
|
||||
out["3"] = h
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
/** 海报 side:1=男方(/hb-n),2=女方(/hb-nv) */
|
||||
/** 海报 side:1=男方(/hb-n),2=女方(/hb-nv),3=回门宴(/hb-hm) */
|
||||
|
||||
export const POSTER_SIDES = [
|
||||
{ key: 1, keyStr: '1', route: '/hb-n', label: '男方', short: 'n' },
|
||||
{ key: 2, keyStr: '2', route: '/hb-nv', label: '女方', short: 'nv' },
|
||||
{ key: 3, keyStr: '3', route: '/hb-hm', label: '回门宴', short: 'hm' },
|
||||
]
|
||||
|
||||
export const POSTER_TEMPLATES = [
|
||||
@@ -17,11 +18,13 @@ export const MOBILE_LAYOUTS = [
|
||||
{ value: 'landscape', label: '横屏展示', desc: '手机端强制左右分栏' },
|
||||
]
|
||||
|
||||
/** 解析为 1 | 2,无法识别返回 0 */
|
||||
/** 解析为 1 | 2 | 3,无法识别返回 0 */
|
||||
export function resolvePosterSide(input) {
|
||||
if (input === 1 || input === '1') return 1
|
||||
if (input === 2 || input === '2') return 2
|
||||
if (input === 3 || input === '3') return 3
|
||||
const v = String(input || '').trim().toLowerCase()
|
||||
if (v === 'hm' || v === 'hmy' || v === 'return' || v === 'huimen') return 3
|
||||
if (v === 'female' || v === 'nv' || v === 'f' || v === 'bride') return 2
|
||||
if (v === 'male' || v === 'n' || v === 'm' || v === 'groom') return 1
|
||||
return 0
|
||||
@@ -32,6 +35,11 @@ export function sideKey(side) {
|
||||
return String(s)
|
||||
}
|
||||
|
||||
export function posterSideMeta(side) {
|
||||
const s = resolvePosterSide(side) || 1
|
||||
return POSTER_SIDES.find((x) => x.key === s) || POSTER_SIDES[0]
|
||||
}
|
||||
|
||||
function baseFields(side) {
|
||||
return {
|
||||
side: resolvePosterSide(side) || 1,
|
||||
@@ -42,6 +50,9 @@ function baseFields(side) {
|
||||
/** 二维码中心图;空则显示圆圈大囍 */
|
||||
qrCenterImg: '',
|
||||
title: '婚礼邀请函',
|
||||
/** 浏览器标签 / 分享用页面标题与描述(可与海报主标题不同) */
|
||||
pageTitle: '',
|
||||
pageDescription: '',
|
||||
footer: '—诚挚邀请 ♥ 恭请光临—',
|
||||
loadingEffect: 'redSeal',
|
||||
enterEffect: 'fadeUp',
|
||||
@@ -68,22 +79,25 @@ export function defaultSide1PosterConfig() {
|
||||
...baseFields(1),
|
||||
side: 1,
|
||||
sonLabel: '儿子:',
|
||||
sonName: '张浩强',
|
||||
sonName: '李琦',
|
||||
daughterInLawLabel: '儿媳:',
|
||||
daughterInLawName: '刘佳怡',
|
||||
groomName: '张浩强',
|
||||
brideName: '刘佳怡',
|
||||
daughterInLawName: '李逸烁',
|
||||
groomName: '李琦',
|
||||
brideName: '李逸烁',
|
||||
verticalSlogan: '吾家有喜',
|
||||
dateText: '2026年9月4日 星期五',
|
||||
lunarText: '农历七月廿三',
|
||||
venueText: '山西省 阳泉市 芙蓉酒楼(阳泉店) 太行国际新城B区10号楼 二楼',
|
||||
lines: [
|
||||
'各位亲朋好友',
|
||||
'吾家有喜 儿子结婚',
|
||||
'良辰已定 吉日待访',
|
||||
'兹定于2026年10月3日 星期日',
|
||||
'农历九月初八 中午11:08分',
|
||||
'兹定于2026年9月4日 星期五',
|
||||
'农历七月廿三 中午11:08分',
|
||||
'为儿子儿媳举办结婚典礼',
|
||||
'敬备喜宴 诚邀您携家人光临',
|
||||
'地址:幸福大酒店二楼宴会厅',
|
||||
'张国栋 & 陈晓玲 夫 妇 敬邀',
|
||||
'地址:山西省 阳泉市 芙蓉酒楼(阳泉店) 二楼',
|
||||
'李国贞 & 赵红燕 夫 妇 敬邀',
|
||||
],
|
||||
}
|
||||
}
|
||||
@@ -93,27 +107,68 @@ export function defaultSide2PosterConfig() {
|
||||
return {
|
||||
...baseFields(2),
|
||||
side: 2,
|
||||
template: 'split',
|
||||
mobileLayout: 'landscape',
|
||||
sonLabel: '女儿:',
|
||||
sonName: '刘佳怡',
|
||||
sonName: '李逸烁',
|
||||
daughterInLawLabel: '女婿:',
|
||||
daughterInLawName: '张浩强',
|
||||
groomName: '张浩强',
|
||||
brideName: '刘佳怡',
|
||||
daughterInLawName: '李琦',
|
||||
groomName: '李琦',
|
||||
brideName: '李逸烁',
|
||||
verticalSlogan: '小女出阁',
|
||||
dateText: '2026年9月4日 星期五',
|
||||
lunarText: '农历七月廿三',
|
||||
venueText: '山西省 阳泉市 芙蓉酒楼(阳泉店) 太行国际新城B区10号楼 二楼',
|
||||
lines: [
|
||||
'各位亲朋好友',
|
||||
'吾家有喜 女儿出嫁',
|
||||
'良辰已定 吉日待访',
|
||||
'兹定于2026年10月3日 星期日',
|
||||
'农历九月初八 中午11:08分',
|
||||
'兹定于2026年9月4日 星期五',
|
||||
'农历七月廿三 中午11:08分',
|
||||
'为女儿女婿举办结婚典礼',
|
||||
'敬备喜宴 诚邀您携家人光临',
|
||||
'地址:幸福大酒店二楼宴会厅',
|
||||
'地址:山西省 阳泉市 芙蓉酒楼(阳泉店) 太行国际新城B区10号楼 二楼',
|
||||
'刘建国 & 王秀兰 夫 妇 敬邀',
|
||||
],
|
||||
}
|
||||
}
|
||||
|
||||
/** 回门宴(3) 默认:9月7日 */
|
||||
export function defaultSide3PosterConfig() {
|
||||
return {
|
||||
...baseFields(3),
|
||||
side: 3,
|
||||
template: 'classic',
|
||||
title: '回门宴邀请函',
|
||||
footer: '—回门宴请 ♥ 恭请光临—',
|
||||
sonLabel: '新郎:',
|
||||
sonName: '李琦',
|
||||
daughterInLawLabel: '新娘:',
|
||||
daughterInLawName: '李逸烁',
|
||||
groomName: '李琦',
|
||||
brideName: '李逸烁',
|
||||
verticalSlogan: '回门之喜',
|
||||
subSlogan1: '琴瑟和鸣',
|
||||
subSlogan2: '永结同心',
|
||||
dateText: '2026年9月7日 星期一',
|
||||
lunarText: '农历七月廿六',
|
||||
venueText: '山西省 阳泉市 芙蓉酒楼(阳泉店) 太行国际新城B区10号楼 二楼',
|
||||
enterEffect: 'curtain',
|
||||
loadingEffect: 'redSeal',
|
||||
lines: [
|
||||
'各位亲朋好友',
|
||||
'新婚燕尔 回门宴请',
|
||||
'良辰已定 吉日待访',
|
||||
'兹定于2026年9月7日 星期一',
|
||||
'农历七月廿六 中午11:08分',
|
||||
'为新婚夫妇举办回门宴',
|
||||
'敬备薄酒 诚邀您携家人光临',
|
||||
'地址:山西省 阳泉市 芙蓉酒楼(阳泉店) 太行国际新城B区10号楼 二楼',
|
||||
'李琦 & 李逸烁 敬邀',
|
||||
],
|
||||
}
|
||||
}
|
||||
|
||||
export function defaultMalePosterConfig() {
|
||||
return defaultSide1PosterConfig()
|
||||
}
|
||||
@@ -128,9 +183,17 @@ export function defaultPosterBundle() {
|
||||
return {
|
||||
'1': defaultSide1PosterConfig(),
|
||||
'2': defaultSide2PosterConfig(),
|
||||
'3': defaultSide3PosterConfig(),
|
||||
}
|
||||
}
|
||||
|
||||
export function defaultPosterForSide(side) {
|
||||
const s = resolvePosterSide(side) || 1
|
||||
if (s === 3) return defaultSide3PosterConfig()
|
||||
if (s === 2) return defaultSide2PosterConfig()
|
||||
return defaultSide1PosterConfig()
|
||||
}
|
||||
|
||||
export const LOADING_EFFECTS = [
|
||||
{ value: 'fade', label: '淡入加载' },
|
||||
{ value: 'redSeal', label: '红印囍字' },
|
||||
@@ -145,7 +208,7 @@ export const ENTER_EFFECTS = [
|
||||
|
||||
function isLegacyFlatPoster(raw) {
|
||||
if (!raw || typeof raw !== 'object') return false
|
||||
if (raw['1'] || raw['2'] || raw[1] || raw[2] || raw.male || raw.female) return false
|
||||
if (raw['1'] || raw['2'] || raw['3'] || raw[1] || raw[2] || raw[3] || raw.male || raw.female) return false
|
||||
return 'title' in raw || 'lines' in raw || 'heroImg' in raw || 'sonName' in raw || 'template' in raw
|
||||
}
|
||||
|
||||
@@ -154,12 +217,13 @@ function pickSideSource(loaded, side) {
|
||||
if (loaded[k] && typeof loaded[k] === 'object') return loaded[k]
|
||||
if (side === 1 && loaded.male && typeof loaded.male === 'object') return loaded.male
|
||||
if (side === 2 && loaded.female && typeof loaded.female === 'object') return loaded.female
|
||||
if (side === 3 && loaded.hm && typeof loaded.hm === 'object') return loaded.hm
|
||||
return null
|
||||
}
|
||||
|
||||
export function normalizePosterConfig(raw, side = 1) {
|
||||
const s = resolvePosterSide(side) || 1
|
||||
const base = s === 2 ? defaultSide2PosterConfig() : defaultSide1PosterConfig()
|
||||
const base = defaultPosterForSide(s)
|
||||
const loaded = raw && typeof raw === 'object' ? raw : {}
|
||||
const lines = Array.isArray(loaded.lines)
|
||||
? loaded.lines.map((l) => String(l ?? ''))
|
||||
@@ -205,18 +269,20 @@ export function normalizePosterConfig(raw, side = 1) {
|
||||
}
|
||||
}
|
||||
|
||||
/** 归一化为 { 1, 2 };兼容旧 male/female 与扁平数据 */
|
||||
/** 归一化为 { 1, 2, 3 };兼容旧 male/female 与扁平数据 */
|
||||
export function normalizePosterBundle(raw) {
|
||||
const loaded = raw && typeof raw === 'object' ? raw : {}
|
||||
if (isLegacyFlatPoster(loaded)) {
|
||||
return {
|
||||
'1': normalizePosterConfig(loaded, 1),
|
||||
'2': defaultSide2PosterConfig(),
|
||||
'3': defaultSide3PosterConfig(),
|
||||
}
|
||||
}
|
||||
return {
|
||||
'1': normalizePosterConfig(pickSideSource(loaded, 1) || {}, 1),
|
||||
'2': normalizePosterConfig(pickSideSource(loaded, 2) || {}, 2),
|
||||
'3': normalizePosterConfig(pickSideSource(loaded, 3) || {}, 3),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -24,6 +24,12 @@ const routes = [
|
||||
component: () => import('@/views/hb/index.vue'),
|
||||
meta: { posterSide: 2 },
|
||||
},
|
||||
{
|
||||
path: '/hb-hm',
|
||||
name: 'PosterReturnBanquet',
|
||||
component: () => import('@/views/hb/index.vue'),
|
||||
meta: { posterSide: 3 },
|
||||
},
|
||||
{
|
||||
path: '/login',
|
||||
name: 'Login',
|
||||
|
||||
@@ -19,8 +19,9 @@
|
||||
</a-button>
|
||||
<template #overlay>
|
||||
<a-menu>
|
||||
<a-menu-item key="1" @click="openPosterPreview(1)">男方(1) /hb-n</a-menu-item>
|
||||
<a-menu-item key="2" @click="openPosterPreview(2)">女方(2) /hb-nv</a-menu-item>
|
||||
<a-menu-item v-for="s in POSTER_SIDES" :key="s.key" @click="openPosterPreview(s.key)">
|
||||
{{ s.label }}({{ s.key }}) {{ s.route }}
|
||||
</a-menu-item>
|
||||
</a-menu>
|
||||
</template>
|
||||
</a-dropdown>
|
||||
@@ -410,23 +411,22 @@
|
||||
</a-card>
|
||||
</a-tab-pane>
|
||||
|
||||
<!-- 海报(独立 poster_configs:side 1 男方 /hb-n,2 女方 /hb-nv) -->
|
||||
<!-- 海报(独立 poster_configs:1 男方 /hb-n,2 女方 /hb-nv,3 回门宴 /hb-hm) -->
|
||||
<a-tab-pane key="poster" tab="海报">
|
||||
<a-card v-if="activeTab === 'poster'" :bordered="false" class="!shadow-sm">
|
||||
<a-alert
|
||||
type="info"
|
||||
show-icon
|
||||
class="mb-4"
|
||||
message="海报配置独立存储。side=1 男方 /hb-n,side=2 女方 /hb-nv;两侧可分别选择模板。"
|
||||
message="海报配置独立存储。1 男方 /hb-n,2 女方 /hb-nv,3 回门宴 /hb-hm;可分别选择模板。"
|
||||
/>
|
||||
<a-tabs v-model:activeKey="posterSideTab" size="small" type="card" class="mb-3">
|
||||
<a-tab-pane key="1" tab="男方(1)" />
|
||||
<a-tab-pane key="2" tab="女方(2)" />
|
||||
<a-tab-pane v-for="s in POSTER_SIDES" :key="s.keyStr" :tab="`${s.label}(${s.key})`" />
|
||||
</a-tabs>
|
||||
<a-form layout="vertical" :class="{ 'opacity-60 pointer-events-none': posterLoading }">
|
||||
<a-form-item label="所属方">
|
||||
<a-tag color="gold">{{ posterSideTab === '2' ? '2 · 女方' : '1 · 男方' }}</a-tag>
|
||||
<span class="text-[11px] text-[#8A8680] ml-2">路由 {{ posterSideTab === '2' ? '/hb-nv' : '/hb-n' }}</span>
|
||||
<a-tag color="gold">{{ currentPosterSide.key }} · {{ currentPosterSide.label }}</a-tag>
|
||||
<span class="text-[11px] text-[#8A8680] ml-2">路由 {{ currentPosterSide.route }}</span>
|
||||
</a-form-item>
|
||||
<a-form-item label="版式模板">
|
||||
<a-radio-group v-model:value="posterCfg.template" class="poster-tpl-group">
|
||||
@@ -475,13 +475,18 @@
|
||||
</a-form-item>
|
||||
</div>
|
||||
<a-form-item :label="posterCfg.template === 'split' ? '左侧照片' : '顶部照片'">
|
||||
<image-field v-model="posterCfg.heroImg" label="海报图片" @pick="setPosterHero" :uploading="uploading" />
|
||||
<image-field
|
||||
v-model="posterCfg.heroImg"
|
||||
label="海报图片"
|
||||
@pick="openUpload(setPosterHero)"
|
||||
:uploading="uploading"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="二维码中心图">
|
||||
<image-field
|
||||
v-model="posterCfg.qrCenterImg"
|
||||
label="中心图(可选)"
|
||||
@pick="setPosterQrCenter"
|
||||
@pick="openUpload(setPosterQrCenter)"
|
||||
:uploading="uploading"
|
||||
/>
|
||||
<div class="text-xs text-stone-500 mt-1">不配置时,二维码中心为圆圈大「囍」字</div>
|
||||
@@ -490,15 +495,15 @@
|
||||
<!-- classic 字段 -->
|
||||
<template v-if="posterCfg.template === 'classic'">
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-x-6">
|
||||
<a-form-item :label="posterSideTab === '2' ? '女儿称谓 / 姓名' : '儿子称谓 / 姓名'">
|
||||
<a-form-item :label="posterNameLabels.left">
|
||||
<div class="flex gap-2">
|
||||
<a-input v-model:value="posterCfg.sonLabel" class="!w-[100px]" :placeholder="posterSideTab === '2' ? '女儿:' : '儿子:'" />
|
||||
<a-input v-model:value="posterCfg.sonLabel" class="!w-[100px]" :placeholder="posterNameLabels.leftPh" />
|
||||
<a-input v-model:value="posterCfg.sonName" placeholder="姓名" />
|
||||
</div>
|
||||
</a-form-item>
|
||||
<a-form-item :label="posterSideTab === '2' ? '女婿称谓 / 姓名' : '儿媳称谓 / 姓名'">
|
||||
<a-form-item :label="posterNameLabels.right">
|
||||
<div class="flex gap-2">
|
||||
<a-input v-model:value="posterCfg.daughterInLawLabel" class="!w-[100px]" :placeholder="posterSideTab === '2' ? '女婿:' : '儿媳:'" />
|
||||
<a-input v-model:value="posterCfg.daughterInLawLabel" class="!w-[100px]" :placeholder="posterNameLabels.rightPh" />
|
||||
<a-input v-model:value="posterCfg.daughterInLawName" placeholder="姓名" />
|
||||
</div>
|
||||
</a-form-item>
|
||||
@@ -561,7 +566,7 @@
|
||||
<i class="fa-solid fa-floppy-disk mr-1"></i>保存海报配置
|
||||
</a-button>
|
||||
<a-button @click="openPosterPreview(posterSideTab)">
|
||||
<i class="fa-solid fa-eye mr-1"></i>打开 {{ posterSideTab === '2' ? '/hb-nv' : '/hb-n' }} 预览
|
||||
<i class="fa-solid fa-eye mr-1"></i>打开 {{ currentPosterSide.route }} 预览
|
||||
</a-button>
|
||||
</div>
|
||||
</a-form>
|
||||
@@ -909,7 +914,7 @@ import { resolveDanmakuSwatch } from '@/utils/danmakuColors'
|
||||
import { getSlotResizeSpecs, resizeSlotToFile, probeResizedMeta, metaHasFileSize } from '@/composables/resizeImage'
|
||||
import {
|
||||
defaultPosterBundle, normalizePosterBundle, normalizePosterConfig,
|
||||
LOADING_EFFECTS, ENTER_EFFECTS, POSTER_SIDES, POSTER_TEMPLATES, MOBILE_LAYOUTS, sideKey,
|
||||
LOADING_EFFECTS, ENTER_EFFECTS, POSTER_SIDES, POSTER_TEMPLATES, MOBILE_LAYOUTS, sideKey, posterSideMeta,
|
||||
} from '@/composables/posterDefaults'
|
||||
|
||||
echarts.use([PieChart, TooltipComponent, LegendComponent, CanvasRenderer])
|
||||
@@ -970,6 +975,17 @@ const uploadCfg = reactive(defaultUploadConfig())
|
||||
const posterSideTab = ref('1')
|
||||
const posterBundle = reactive(defaultPosterBundle())
|
||||
const posterCfg = computed(() => posterBundle[sideKey(posterSideTab.value)] || posterBundle['1'])
|
||||
const currentPosterSide = computed(() => posterSideMeta(posterSideTab.value))
|
||||
const posterNameLabels = computed(() => {
|
||||
const s = sideKey(posterSideTab.value)
|
||||
if (s === '2') {
|
||||
return { left: '女儿称谓 / 姓名', right: '女婿称谓 / 姓名', leftPh: '女儿:', rightPh: '女婿:' }
|
||||
}
|
||||
if (s === '3') {
|
||||
return { left: '新郎称谓 / 姓名', right: '新娘称谓 / 姓名', leftPh: '新郎:', rightPh: '新娘:' }
|
||||
}
|
||||
return { left: '儿子称谓 / 姓名', right: '儿媳称谓 / 姓名', leftPh: '儿子:', rightPh: '儿媳:' }
|
||||
})
|
||||
const posterLinesText = computed({
|
||||
get: () => {
|
||||
const lines = posterCfg.value?.lines
|
||||
@@ -1415,6 +1431,7 @@ async function loadPosterConfig() {
|
||||
const bundle = normalizePosterBundle(res.data || {})
|
||||
posterBundle['1'] = bundle['1']
|
||||
posterBundle['2'] = bundle['2']
|
||||
posterBundle['3'] = bundle['3']
|
||||
} catch (e) {
|
||||
message.error(e?.message || '海报配置加载失败')
|
||||
} finally {
|
||||
@@ -1430,6 +1447,7 @@ async function onSavePosterConfig() {
|
||||
const bundle = normalizePosterBundle(res.data || payload)
|
||||
posterBundle['1'] = bundle['1']
|
||||
posterBundle['2'] = bundle['2']
|
||||
posterBundle['3'] = bundle['3']
|
||||
message.success('海报配置已保存')
|
||||
} catch (e) {
|
||||
message.error(e?.message || '海报配置保存失败')
|
||||
|
||||
@@ -104,7 +104,7 @@ import { computed, nextTick, onMounted, onUnmounted, reactive, ref } from 'vue'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import html2canvas from 'html2canvas'
|
||||
import { getPosterConfig } from '@/api/wedding'
|
||||
import { normalizePosterConfig, resolvePosterSide } from '@/composables/posterDefaults'
|
||||
import { normalizePosterConfig, posterSideMeta, resolvePosterSide } from '@/composables/posterDefaults'
|
||||
import { renderFestiveQr } from '@/composables/renderFestiveQr'
|
||||
import ClassicPoster from '@/views/hb/templates/ClassicPoster.vue'
|
||||
import SplitPoster from '@/views/hb/templates/SplitPoster.vue'
|
||||
@@ -204,7 +204,7 @@ async function savePosterImage() {
|
||||
ignoreElements: (node) => !!node?.hasAttribute?.('data-html2canvas-ignore'),
|
||||
})
|
||||
const a = document.createElement('a')
|
||||
a.download = `婚礼海报-${cfg.side === 2 ? '女方' : '男方'}-${Date.now()}.png`
|
||||
a.download = `婚礼海报-${posterSideMeta(cfg.side).label}-${Date.now()}.png`
|
||||
a.href = canvas.toDataURL('image/png')
|
||||
a.click()
|
||||
} catch (e) {
|
||||
|
||||
Reference in New Issue
Block a user