fix(web): 关注我们图片多 URL 回退(public→promotion),移除部署路径提示;Nginx 增加 /social/
Made-with: Cursor
This commit is contained in:
@@ -63,7 +63,7 @@
|
||||
</el-form-item>
|
||||
<el-form-item label="保留原文件名">
|
||||
<el-switch v-model="uploadPreserveFilename" />
|
||||
<span class="form-hint">开启后覆盖同名文件;产品视频请上传到 <code>promotion/social/</code>(英文文件名,见仓库 <code>web/promotion/social/README.md</code>)</span>
|
||||
<span class="form-hint">开启后将按原文件名保存,同名文件会被覆盖</span>
|
||||
</el-form-item>
|
||||
<el-form-item label="允许下载">
|
||||
<el-switch v-model="uploadDownloadable" />
|
||||
|
||||
@@ -27,6 +27,12 @@ server {
|
||||
try_files $uri =404;
|
||||
}
|
||||
|
||||
# web/public/social/ → 关注我们二维码等(挂载 /var/www/yh-public)
|
||||
location ^~ /social/ {
|
||||
alias /var/www/yh-public/social/;
|
||||
add_header Cache-Control "public, max-age=300";
|
||||
}
|
||||
|
||||
# 推广素材:文件必须真实存在,禁止落到 SPA index.html(否则前端误判「静态存在」、视频拿到 HTML)
|
||||
# 宿主机 ./web/promotion 挂载覆盖本路径,改 social 下文件无需重新 npm build
|
||||
location ^~ /promotion/ {
|
||||
|
||||
@@ -25,6 +25,11 @@ server {
|
||||
try_files $uri =404;
|
||||
}
|
||||
|
||||
location ^~ /social/ {
|
||||
alias /var/www/yh-public/social/;
|
||||
add_header Cache-Control "public, max-age=300";
|
||||
}
|
||||
|
||||
location ^~ /promotion/ {
|
||||
try_files $uri =404;
|
||||
add_header Cache-Control "public, max-age=86400";
|
||||
|
||||
@@ -1,15 +1,12 @@
|
||||
# `public/` 静态资源目录
|
||||
# `web/public/` 静态资源
|
||||
|
||||
[Vite 约定](https://cn.vitejs.dev/guide/assets.html#the-public-directory):此目录下的文件会**原样**复制到构建后的站点根目录(`dist/`),访问路径为 **`/<文件名>`**。
|
||||
构建后会出现在站点根路径(`/logo.png`);Docker 下整个目录挂载为容器内 `/var/www/yh-public`。
|
||||
|
||||
## 当前文件
|
||||
## 可选子目录 `social/`
|
||||
|
||||
| 文件 | 用途 |
|
||||
|------|------|
|
||||
| `logo.png` | **标签页图标**(`index.html` 的 `rel="icon"` / `apple-touch-icon`)+ **首页与宣传册导航**(`Home.vue`、`BrochurePage.vue`) |
|
||||
「关注我们」二维码可放在 **`public/social/`**,访问路径为 **`/social/文件名`**。
|
||||
若此处没有对应文件,前端会自动尝试 **`/promotion/social/`**(`web/promotion/social/` 挂载)。
|
||||
|
||||
更新品牌时替换本目录下的 `logo.png` 即可。
|
||||
## 根目录文件示例
|
||||
|
||||
**Docker 部署**:`docker-compose` 已将 **`web/public` → 容器内 `/var/www/yh-public`** 只读挂载,`deploy/web/default.conf` 中配置了「根路径下单段静态文件名优先读挂载、否则回退 `dist`」。**改宿主机 `web/public/` 内文件后无需 `npm run build`**,刷新即可(注意浏览器缓存)。
|
||||
|
||||
**注意**:引用时用**根路径** `/logo.png`,不要用 `src/assets` 的 import 方式写 public 资源。
|
||||
- `logo.png`:导航栏与 favicon(见 `index.html`、`Home.vue`)
|
||||
|
||||
@@ -1,34 +1,38 @@
|
||||
import { promotionUrl } from '../utils/promotionAssets'
|
||||
|
||||
/**
|
||||
* 「关注我们」素材统一放在 web/promotion/social/
|
||||
* 线上访问:/promotion/social/<文件名>(与视频同源部署)
|
||||
* 「关注我们」二维码图加载顺序(前者 404 时 img @error 自动换下一项):
|
||||
* 1. /social/<file> → web/public/social/(Docker 挂载 /var/www/yh-public/social)
|
||||
* 2. /<file> → web/public/ 根目录
|
||||
* 3. /promotion/social/<file> → web/promotion/social/(挂载或 dist)
|
||||
*/
|
||||
const social = (file) => promotionUrl(`social/${file}`)
|
||||
export function socialFollowImageCandidates(filename) {
|
||||
return [`/social/${filename}`, `/${filename}`, promotionUrl(`social/${filename}`)]
|
||||
}
|
||||
|
||||
export const PROMOTION_SOCIAL_FOLLOW = [
|
||||
{
|
||||
id: 'xiaohongshu',
|
||||
label: '小红书',
|
||||
image: social('xiaohongshu.png'),
|
||||
imageCandidates: socialFollowImageCandidates('xiaohongshu.png'),
|
||||
href: 'https://www.xiaohongshu.com/'
|
||||
},
|
||||
{
|
||||
id: 'douyin',
|
||||
label: '抖音',
|
||||
image: social('douyin.png'),
|
||||
imageCandidates: socialFollowImageCandidates('douyin.png'),
|
||||
href: 'https://www.douyin.com/'
|
||||
},
|
||||
{
|
||||
id: 'wechat-official',
|
||||
label: '公众号',
|
||||
image: social('wechat-official.png'),
|
||||
imageCandidates: socialFollowImageCandidates('wechat-official.png'),
|
||||
href: 'https://mp.weixin.qq.com/'
|
||||
},
|
||||
{
|
||||
id: 'wechat-channels',
|
||||
label: '视频号',
|
||||
image: social('wechat-channels.jpg'),
|
||||
imageCandidates: socialFollowImageCandidates('wechat-channels.jpg'),
|
||||
href: 'https://channels.weixin.qq.com/'
|
||||
}
|
||||
]
|
||||
|
||||
@@ -135,7 +135,6 @@
|
||||
|
||||
<section class="social-section" id="social-follow">
|
||||
<h3 class="social-title">关注我们</h3>
|
||||
<p class="social-desc">点击按钮查看二维码;图片资源统一部署在 <code class="social-code">/promotion/social/</code> 即可线上访问</p>
|
||||
<div class="social-links">
|
||||
<button
|
||||
v-for="item in socialFollowItems"
|
||||
@@ -145,7 +144,15 @@
|
||||
@click="openSocialFollow(item)"
|
||||
>
|
||||
<span class="social-pill-icon-wrap">
|
||||
<img :src="item.image" :alt="item.label" class="social-pill-icon" width="32" height="32" loading="lazy" />
|
||||
<img
|
||||
:src="item.imageCandidates[0]"
|
||||
:alt="item.label"
|
||||
class="social-pill-icon"
|
||||
width="32"
|
||||
height="32"
|
||||
loading="lazy"
|
||||
@error="(e) => onSocialFollowListImgError(e, item)"
|
||||
/>
|
||||
</span>
|
||||
<span class="social-pill-label">{{ item.label }}</span>
|
||||
</button>
|
||||
@@ -212,7 +219,6 @@
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- 产品视频:web/promotion/social/ 下英文文件名,见 promotionVideos.js -->
|
||||
<section class="video-section" id="videos">
|
||||
<div class="section-title">
|
||||
<h2>产品视频</h2>
|
||||
@@ -297,7 +303,13 @@
|
||||
<button type="button" class="close-modal" aria-label="关闭" @click="closeSocialFollow">×</button>
|
||||
<h4 class="social-qr-title">{{ socialQrTitle }}</h4>
|
||||
<div class="social-qr-frame">
|
||||
<img v-show="socialQrOpen && socialQrImage" :src="socialQrImage" :alt="socialQrTitle" class="social-qr-img" />
|
||||
<img
|
||||
v-show="socialQrOpen && socialQrImage"
|
||||
:src="socialQrImage"
|
||||
:alt="socialQrTitle"
|
||||
class="social-qr-img"
|
||||
@error="onSocialQrImgError"
|
||||
/>
|
||||
</div>
|
||||
<a
|
||||
v-if="socialQrHref"
|
||||
@@ -361,6 +373,9 @@ const socialQrOpen = ref(false)
|
||||
const socialQrTitle = ref('')
|
||||
const socialQrImage = ref('')
|
||||
const socialQrHref = ref('')
|
||||
/** 二维码大图:与列表相同的多 URL 回退 */
|
||||
const socialQrCandidates = ref([])
|
||||
const socialQrCandidateIdx = ref(0)
|
||||
|
||||
const defaultData = () => ({
|
||||
logo_text: 'YUHENG ONE',
|
||||
@@ -524,7 +539,9 @@ function closeVideoModal() {
|
||||
|
||||
function openSocialFollow(item) {
|
||||
socialQrTitle.value = item.label
|
||||
socialQrImage.value = item.image
|
||||
socialQrCandidates.value = item.imageCandidates || []
|
||||
socialQrCandidateIdx.value = 0
|
||||
socialQrImage.value = item.imageCandidates?.[0] || ''
|
||||
socialQrHref.value = item.href || ''
|
||||
socialQrOpen.value = true
|
||||
}
|
||||
@@ -533,6 +550,29 @@ function closeSocialFollow() {
|
||||
socialQrOpen.value = false
|
||||
socialQrImage.value = ''
|
||||
socialQrHref.value = ''
|
||||
socialQrCandidates.value = []
|
||||
socialQrCandidateIdx.value = 0
|
||||
}
|
||||
|
||||
/** public /social、public 根路径无图时依次尝试 /promotion/social/ */
|
||||
function onSocialFollowListImgError(e, item) {
|
||||
const img = e.target
|
||||
const list = item.imageCandidates || []
|
||||
let i = Number(img.dataset.fi || 0)
|
||||
if (i + 1 < list.length) {
|
||||
img.dataset.fi = String(i + 1)
|
||||
img.src = list[i + 1]
|
||||
}
|
||||
}
|
||||
|
||||
function onSocialQrImgError() {
|
||||
const list = socialQrCandidates.value
|
||||
let i = socialQrCandidateIdx.value
|
||||
if (i + 1 < list.length) {
|
||||
i += 1
|
||||
socialQrCandidateIdx.value = i
|
||||
socialQrImage.value = list[i]
|
||||
}
|
||||
}
|
||||
|
||||
function toggleFaq(i) {
|
||||
@@ -949,13 +989,9 @@ onUnmounted(() => {
|
||||
|
||||
.social-section { padding: 72px 20px; text-align: center; position: relative; z-index: 10; }
|
||||
.social-title {
|
||||
font-family: 'Exo 2', sans-serif; font-size: clamp(20px, 3vw, 26px); margin-bottom: 12px;
|
||||
font-family: 'Exo 2', sans-serif; font-size: clamp(20px, 3vw, 26px); margin-bottom: 28px;
|
||||
color: var(--star-white); letter-spacing: 4px;
|
||||
}
|
||||
.social-desc {
|
||||
font-size: 12px; color: rgba(255,255,255,0.4); margin-bottom: 28px; max-width: 520px; margin-left: auto; margin-right: auto;
|
||||
}
|
||||
.social-code { font-family: ui-monospace, Consolas, monospace; font-size: 11px; color: rgba(0, 212, 255, 0.8); }
|
||||
.social-links { display: flex; justify-content: center; gap: 14px; flex-wrap: wrap; align-items: center; }
|
||||
.social-pill {
|
||||
display: inline-flex; align-items: center; gap: 10px;
|
||||
|
||||
Reference in New Issue
Block a user