[CMS-VISUAL] F5: 页脚结构示意图(六处位置标注+实时回显)+ favicon 1:1/二维码 4:3 占位框与比例预览(180 测试绿)
This commit is contained in:
@@ -0,0 +1,171 @@
|
||||
<script setup lang="ts">
|
||||
import { assetUrl } from "@/api/module/cms";
|
||||
/**
|
||||
* F5(docs/20)页脚结构示意图:页脚 Tab 内的固定示意图,标注各字段在门户页脚中的视觉位置——
|
||||
* 品牌区(站名+联系方式+多校区地址行)/ 二维码区(微信+微博,4:3)/ 社媒图标行 / 版权备案行。
|
||||
* 已填字段实时回显内容(填完即知页脚长什么样);空字段以灰字占位标注。
|
||||
*/
|
||||
const props = defineProps<{
|
||||
contact?: string;
|
||||
footerAddresses?: string;
|
||||
qrWechat?: string;
|
||||
qrWeibo?: string;
|
||||
socials?: { label: string; value?: string }[];
|
||||
copyright?: string;
|
||||
beian?: string;
|
||||
}>();
|
||||
|
||||
const addressLines = (props.footerAddresses || "")
|
||||
.split(/\r?\n/)
|
||||
.map(l => l.trim())
|
||||
.filter(Boolean)
|
||||
.slice(0, 3);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="footer-preview">
|
||||
<div class="fp-caption">页脚结构示意(下图与字段一一对应,已填内容实时回显)</div>
|
||||
<div class="fp-frame" role="img" aria-label="页脚结构示意图">
|
||||
<div class="fp-brand">
|
||||
<div class="fp-logo">
|
||||
<span class="fp-logo-mark">LOGO</span>
|
||||
<span class="fp-site">XX学校</span>
|
||||
</div>
|
||||
<p class="fp-line" :class="{ filled: contact }">
|
||||
{{ contact || "① 联系方式(页脚品牌区)" }}
|
||||
</p>
|
||||
<p v-for="(l, i) in addressLines" :key="i" class="fp-line small filled">{{ l }}</p>
|
||||
<p v-if="!addressLines.length" class="fp-line small">② 多校区地址(每行一个校区)</p>
|
||||
</div>
|
||||
<div class="fp-qr">
|
||||
<div class="fp-qr-box">
|
||||
<img v-if="qrWechat" :src="assetUrl(qrWechat)" alt="微信二维码预览" />
|
||||
<span v-else>微信二维码<br />③ 4:3</span>
|
||||
</div>
|
||||
<div class="fp-qr-box">
|
||||
<img v-if="qrWeibo" :src="assetUrl(qrWeibo)" alt="微博二维码预览" />
|
||||
<span v-else>微博二维码<br />③ 4:3</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="fp-social">
|
||||
<span class="fp-social-label">④ 社媒图标行:</span>
|
||||
<span v-for="s in socials" :key="s.label" class="fp-social-item" :class="{ on: s.value }">
|
||||
{{ s.label }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="fp-bottom">
|
||||
<span :class="{ filled: copyright }">{{ copyright || "⑤ 版权文字" }}</span>
|
||||
<span :class="{ filled: beian }" class="fp-beian">{{ beian || "⑥ 备案号" }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.footer-preview {
|
||||
margin-top: 6px;
|
||||
.fp-caption {
|
||||
color: #8a93a6;
|
||||
font-size: 12px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
.fp-frame {
|
||||
border: 1px solid #e9edf5;
|
||||
border-radius: 8px;
|
||||
background: linear-gradient(180deg, #1f3a5f 0%, #16294a 100%);
|
||||
color: rgba(255, 255, 255, 0.5);
|
||||
padding: 18px 22px 12px;
|
||||
display: grid;
|
||||
grid-template-columns: 1fr auto;
|
||||
gap: 10px 18px;
|
||||
font-size: 12px;
|
||||
line-height: 1.7;
|
||||
.fp-brand {
|
||||
.fp-logo {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
margin-bottom: 6px;
|
||||
.fp-logo-mark {
|
||||
border: 1px dashed rgba(255, 255, 255, 0.35);
|
||||
border-radius: 4px;
|
||||
padding: 2px 8px;
|
||||
font-size: 11px;
|
||||
}
|
||||
.fp-site {
|
||||
color: rgba(255, 255, 255, 0.75);
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
.fp-line {
|
||||
margin: 2px 0;
|
||||
&.small {
|
||||
font-size: 11px;
|
||||
opacity: 0.9;
|
||||
}
|
||||
&.filled {
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
.fp-qr {
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
align-items: flex-start;
|
||||
.fp-qr-box {
|
||||
width: 84px;
|
||||
height: 63px;
|
||||
border: 1px dashed rgba(255, 255, 255, 0.4);
|
||||
border-radius: 6px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
font-size: 10px;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
img {
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
object-fit: contain;
|
||||
}
|
||||
}
|
||||
}
|
||||
.fp-social {
|
||||
grid-column: 1 / -1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
flex-wrap: wrap;
|
||||
.fp-social-label {
|
||||
color: rgba(255, 255, 255, 0.45);
|
||||
}
|
||||
.fp-social-item {
|
||||
border: 1px solid rgba(255, 255, 255, 0.3);
|
||||
border-radius: 12px;
|
||||
padding: 1px 10px;
|
||||
font-size: 11px;
|
||||
opacity: 0.55;
|
||||
&.on {
|
||||
opacity: 1;
|
||||
border-color: rgba(255, 255, 255, 0.85);
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
.fp-bottom {
|
||||
grid-column: 1 / -1;
|
||||
border-top: 1px solid rgba(255, 255, 255, 0.15);
|
||||
padding-top: 8px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
gap: 12px;
|
||||
flex-wrap: wrap;
|
||||
font-size: 11px;
|
||||
.filled {
|
||||
color: rgba(255, 255, 255, 0.85);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -15,6 +15,9 @@ const props = defineProps<{
|
||||
/** 附件场景(空=不带 scene;svc 场景已迁办事大厅,CMS 内为 article/banner 等) */
|
||||
scene?: string;
|
||||
placeholder?: string;
|
||||
/** F5(docs/20):预览/占位框比例("1:1" favicon / "4:3" 二维码;缺省 8:5 通用横图),
|
||||
* 无值时按比例显示虚线占位框,帮助确认最终在门户中的尺寸感 */
|
||||
aspect?: "1:1" | "4:3";
|
||||
}>();
|
||||
const emit = defineEmits<{ (e: "update:modelValue", v: string): void }>();
|
||||
|
||||
@@ -76,12 +79,16 @@ function clearValue() {
|
||||
>
|
||||
<Button size="small" icon="ios-cloud-upload-outline" :loading="uploading">上传图片</Button>
|
||||
</Upload>
|
||||
<span v-else class="iaf-thumb">
|
||||
<span v-else class="iaf-thumb" :class="aspect ? 'iaf-thumb-' + aspect.replace(':', 'x') : ''">
|
||||
<img :src="previewSrc" alt="" />
|
||||
<span class="iaf-thumb-del" title="清除" @click="clearValue">
|
||||
<Icon type="ios-close" />
|
||||
</span>
|
||||
</span>
|
||||
<!-- F5:无值时按字段比例显示虚线占位框(尺寸感示意) -->
|
||||
<span v-if="!modelValue && aspect" class="iaf-holder" :class="'iaf-holder-' + aspect!.replace(':', 'x')">
|
||||
{{ aspect }} 位
|
||||
</span>
|
||||
<Button size="small" type="text" class="iaf-toggle" @click="manualOpen = !manualOpen">
|
||||
{{ manualOpen ? "收起" : "手动粘贴路径" }}
|
||||
</Button>
|
||||
@@ -123,6 +130,16 @@ function clearValue() {
|
||||
border: 1px solid #dcdee2;
|
||||
background: #f8f8f9;
|
||||
}
|
||||
&.iaf-thumb-1x1 img {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
object-fit: contain;
|
||||
}
|
||||
&.iaf-thumb-4x3 img {
|
||||
width: 88px;
|
||||
height: 66px;
|
||||
object-fit: contain;
|
||||
}
|
||||
.iaf-thumb-del {
|
||||
position: absolute;
|
||||
top: -7px;
|
||||
@@ -142,6 +159,24 @@ function clearValue() {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
.iaf-holder {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border: 1px dashed #cfd8e6;
|
||||
border-radius: 4px;
|
||||
color: #b4bfce;
|
||||
font-size: 11px;
|
||||
background: #fafbfd;
|
||||
&.iaf-holder-1x1 {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
}
|
||||
&.iaf-holder-4x3 {
|
||||
width: 88px;
|
||||
height: 66px;
|
||||
}
|
||||
}
|
||||
.iaf-manual {
|
||||
max-width: 420px;
|
||||
margin-top: 6px;
|
||||
|
||||
Reference in New Issue
Block a user