1. 海报

This commit is contained in:
李琦
2026-08-03 10:22:04 +08:00
parent 807adbc6a4
commit 211305c10c
5 changed files with 137 additions and 41 deletions

View File

@@ -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_configsside 1 男方 /hb-n2 女方 /hb-nv -->
<!-- 海报独立 poster_configs1 男方 /hb-n2 女方 /hb-nv3 回门宴 /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-nside=2 女方 /hb-nv两侧可分别选择模板。"
message="海报配置独立存储。1 男方 /hb-n2 女方 /hb-nv3 回门宴 /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 || '海报配置保存失败')