From f99f6229778f1080920e4a5848c377d793a2158c Mon Sep 17 00:00:00 2001 From: eafonyang Date: Thu, 13 Aug 2026 16:48:05 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=20bug=EF=BC=8C=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E7=95=8C=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dashboard/docker-compose.yml | 3 +- dashboard/frontend/nginx.conf | 41 +++++++ dashboard/frontend/src/locales/langs/en-us.ts | 1 + dashboard/frontend/src/locales/langs/zh-cn.ts | 1 + .../frontend/src/router/elegant/imports.ts | 1 + .../frontend/src/router/elegant/routes.ts | 14 ++- .../frontend/src/router/elegant/transform.ts | 1 + .../frontend/src/typings/elegant-router.d.ts | 2 + .../views/www/components/SectionManager.vue | 48 +++++--- .../src/views/www/product/detail/index.vue | 103 ++++++++++++++++++ .../section/layouts/LayoutFullBanner.vue | 2 +- .../section/layouts/LayoutHeroSplit.vue | 2 +- .../section/layouts/LayoutSpecTable.vue | 10 +- .../section/layouts/LayoutSplitContent.vue | 2 +- .../section/layouts/LayoutTitleMedia.vue | 2 +- 15 files changed, 205 insertions(+), 28 deletions(-) create mode 100644 dashboard/frontend/nginx.conf create mode 100644 dashboard/frontend/src/views/www/product/detail/index.vue diff --git a/dashboard/docker-compose.yml b/dashboard/docker-compose.yml index 8a98177..dce1788 100644 --- a/dashboard/docker-compose.yml +++ b/dashboard/docker-compose.yml @@ -26,7 +26,8 @@ services: - "host.docker.internal:host-gateway" volumes: - /data/projects/source:/data/projects/source - # 素材库上传目录:容器内 /app/uploads ↔ 宿主机 /data/project/dashboard/backend/uploads + # 素材库上传目录:容器内 /app/uploads ↔ 宿主机 /data/project/dashboard/frontend/dist/uploads + # (与 frontend nginx 静态直出同一目录;若该目录被删除重建,需 force-recreate backend 重新挂载) - /data/project/dashboard/frontend/dist/uploads:/app/uploads frontend: diff --git a/dashboard/frontend/nginx.conf b/dashboard/frontend/nginx.conf new file mode 100644 index 0000000..8af1616 --- /dev/null +++ b/dashboard/frontend/nginx.conf @@ -0,0 +1,41 @@ +server { + listen 80; + server_name _; + + # 管理后台前端构建产物(dist 挂载到 /usr/share/nginx/html) + root /usr/share/nginx/html; + index index.html; + + # 与后端 multer 50MB 上传限制对齐,避免 /api 上传被 nginx 413 拦截 + client_max_body_size 50m; + gzip on; + gzip_types text/plain text/css application/json application/javascript image/svg+xml; + + # 带内容指纹的构建资源:长缓存(正则含 {},必须加引号避免被当作块定界符) + location ~* "\.[0-9a-f]{8}\.(js|css|png|jpg|jpeg|gif|webp|svg|woff2?)$" { + expires 365d; + add_header Cache-Control "public, immutable"; + try_files $uri =404; + } + + # 素材库静态文件:backend 上传目录挂载在 dist/uploads,前端直接静态直出 + location /uploads/ { + expires 7d; + try_files $uri =404; + } + + # SPA history 回退 + location / { + try_files $uri $uri/ /index.html; + } + + # API 反代到 backend 容器(compose 网络内服务名解析) + location /api/ { + proxy_pass http://backend:8000; + proxy_http_version 1.1; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + } +} diff --git a/dashboard/frontend/src/locales/langs/en-us.ts b/dashboard/frontend/src/locales/langs/en-us.ts index a162ff4..4dc635d 100644 --- a/dashboard/frontend/src/locales/langs/en-us.ts +++ b/dashboard/frontend/src/locales/langs/en-us.ts @@ -261,6 +261,7 @@ const local: App.I18n.Schema = { www_product: 'Products', www_product_series: 'Product Series', www_product_list: 'Product List', + www_product_detail: 'Product Detail', www_news: 'News', www_news_articles: 'Articles', www_media: 'Media Library', diff --git a/dashboard/frontend/src/locales/langs/zh-cn.ts b/dashboard/frontend/src/locales/langs/zh-cn.ts index 5006e7b..1eaa4da 100644 --- a/dashboard/frontend/src/locales/langs/zh-cn.ts +++ b/dashboard/frontend/src/locales/langs/zh-cn.ts @@ -258,6 +258,7 @@ const local: App.I18n.Schema = { www_product: '产品管理', www_product_series: '产品系列', www_product_list: '产品列表', + www_product_detail: '产品详情页', www_news: '新闻管理', www_news_articles: '新闻文章', www_media: '素材库', diff --git a/dashboard/frontend/src/router/elegant/imports.ts b/dashboard/frontend/src/router/elegant/imports.ts index 1d901b0..2707ce9 100644 --- a/dashboard/frontend/src/router/elegant/imports.ts +++ b/dashboard/frontend/src/router/elegant/imports.ts @@ -46,6 +46,7 @@ export const views: Record Promise import("@/views/www/page/news-list/index.vue"), "www_page_product-list": () => import("@/views/www/page/product-list/index.vue"), www_page_support: () => import("@/views/www/page/support/index.vue"), + www_product_detail: () => import("@/views/www/product/detail/index.vue"), www_product_list: () => import("@/views/www/product/list/index.vue"), www_product_series: () => import("@/views/www/product/series/index.vue"), }; diff --git a/dashboard/frontend/src/router/elegant/routes.ts b/dashboard/frontend/src/router/elegant/routes.ts index c85cf44..d321f72 100644 --- a/dashboard/frontend/src/router/elegant/routes.ts +++ b/dashboard/frontend/src/router/elegant/routes.ts @@ -423,7 +423,7 @@ export const generatedRoutes: GeneratedRoute[] = [ meta: { title: 'www_news_articles', i18nKey: 'route.www_news_articles', - icon: 'mdi:article-outline', + icon: 'fluent-mdl2:articles', order: 1, keepAlive: true } @@ -524,6 +524,18 @@ export const generatedRoutes: GeneratedRoute[] = [ order: 4 }, children: [ + { + name: 'www_product_detail', + path: '/www/product/detail', + component: 'view.www_product_detail', + meta: { + title: 'www_product_detail', + i18nKey: 'route.www_product_detail', + icon: 'mdi:file-document-edit-outline', + order: 3, + keepAlive: true + } + }, { name: 'www_product_list', path: '/www/product/list', diff --git a/dashboard/frontend/src/router/elegant/transform.ts b/dashboard/frontend/src/router/elegant/transform.ts index b30f864..c058c85 100644 --- a/dashboard/frontend/src/router/elegant/transform.ts +++ b/dashboard/frontend/src/router/elegant/transform.ts @@ -206,6 +206,7 @@ const routeMap: RouteMap = { "www_page_support": "/www/page/support", "www_page-seo": "/www/page-seo", "www_product": "/www/product", + "www_product_detail": "/www/product/detail", "www_product_list": "/www/product/list", "www_product_series": "/www/product/series" }; diff --git a/dashboard/frontend/src/typings/elegant-router.d.ts b/dashboard/frontend/src/typings/elegant-router.d.ts index 4068b8d..d36cc94 100644 --- a/dashboard/frontend/src/typings/elegant-router.d.ts +++ b/dashboard/frontend/src/typings/elegant-router.d.ts @@ -60,6 +60,7 @@ declare module "@elegant-router/types" { "www_page_support": "/www/page/support"; "www_page-seo": "/www/page-seo"; "www_product": "/www/product"; + "www_product_detail": "/www/product/detail"; "www_product_list": "/www/product/list"; "www_product_series": "/www/product/series"; }; @@ -152,6 +153,7 @@ declare module "@elegant-router/types" { | "www_page_news-list" | "www_page_product-list" | "www_page_support" + | "www_product_detail" | "www_product_list" | "www_product_series" >; diff --git a/dashboard/frontend/src/views/www/components/SectionManager.vue b/dashboard/frontend/src/views/www/components/SectionManager.vue index 3232186..d0222f9 100644 --- a/dashboard/frontend/src/views/www/components/SectionManager.vue +++ b/dashboard/frontend/src/views/www/components/SectionManager.vue @@ -678,7 +678,7 @@ onMounted(loadData); - + {{ opt.label }} @@ -699,22 +699,36 @@ onMounted(loadData); 标题+媒体布局仅水平方向生效(左对齐/居中/右对齐),垂直位置忽略 - - - 素材|文案 - 文案|素材 - - - -
- - 按页面视觉左右顺序标注({{ formData.config.media_position === 'right' ? '文案 : 素材' : '素材 : 文案' }}),默认五五等分;移动端(小屏)始终单列堆叠不受影响 -
-
+ +
+ + + {{ opt.label }} + + + + + 素材|文案 + 文案|素材 + + + + + + 按页面视觉左右顺序标注({{ formData.config.media_position === 'right' ? '文案 : 素材' : '素材 : 文案' }}),默认五五等分;移动端(小屏)始终单列堆叠不受影响 + + +
diff --git a/dashboard/frontend/src/views/www/product/detail/index.vue b/dashboard/frontend/src/views/www/product/detail/index.vue new file mode 100644 index 0000000..7857c46 --- /dev/null +++ b/dashboard/frontend/src/views/www/product/detail/index.vue @@ -0,0 +1,103 @@ + + + diff --git a/www/app/components/section/layouts/LayoutFullBanner.vue b/www/app/components/section/layouts/LayoutFullBanner.vue index 34b4fa0..ccdf53b 100644 --- a/www/app/components/section/layouts/LayoutFullBanner.vue +++ b/www/app/components/section/layouts/LayoutFullBanner.vue @@ -17,7 +17,7 @@ const { overline, title, subtitle, content, overlineStyle, titleStyle, bodyStyle

{{ subtitle }}

-
+
diff --git a/www/app/components/section/layouts/LayoutHeroSplit.vue b/www/app/components/section/layouts/LayoutHeroSplit.vue index 02e64c0..de6af32 100644 --- a/www/app/components/section/layouts/LayoutHeroSplit.vue +++ b/www/app/components/section/layouts/LayoutHeroSplit.vue @@ -76,7 +76,7 @@ const mediaClass = computed(() =>

{{ subtitle }}

-
+
diff --git a/www/app/components/section/layouts/LayoutSpecTable.vue b/www/app/components/section/layouts/LayoutSpecTable.vue index c897664..025289c 100644 --- a/www/app/components/section/layouts/LayoutSpecTable.vue +++ b/www/app/components/section/layouts/LayoutSpecTable.vue @@ -78,7 +78,7 @@ function onLeave(el: Element, done: () => void) {

{{ subtitle }}

-
+
@@ -107,10 +107,10 @@ function onLeave(el: Element, done: () => void) { class="flex items-baseline justify-between gap-24px py-16px border-b" :class="[isDark ? 'border-white/10' : 'border-gray-300 dark:border-dark-600', idx === fixedItems(group).length - 1 && (!needToggle(group) || !isExpanded(group)) ? 'border-b-0' : '']" > - + {{ isEn ? item.name_en : item.name_zh }} - + {{ isEn ? item.value_en : item.value_zh }}
@@ -124,10 +124,10 @@ function onLeave(el: Element, done: () => void) { class="flex items-baseline justify-between gap-24px py-16px border-b" :class="[isDark ? 'border-white/10' : 'border-gray-300 dark:border-dark-600', item.id === group.items?.at(-1)?.id ? 'border-b-0' : '']" > - + {{ isEn ? item.name_en : item.name_zh }} - + {{ isEn ? item.value_en : item.value_zh }}
diff --git a/www/app/components/section/layouts/LayoutSplitContent.vue b/www/app/components/section/layouts/LayoutSplitContent.vue index 3f76fa1..e35051f 100644 --- a/www/app/components/section/layouts/LayoutSplitContent.vue +++ b/www/app/components/section/layouts/LayoutSplitContent.vue @@ -70,7 +70,7 @@ const textWrapClass = computed(() =>

{{ subtitle }}

-
+
diff --git a/www/app/components/section/layouts/LayoutTitleMedia.vue b/www/app/components/section/layouts/LayoutTitleMedia.vue index 16859ac..46e1b9e 100644 --- a/www/app/components/section/layouts/LayoutTitleMedia.vue +++ b/www/app/components/section/layouts/LayoutTitleMedia.vue @@ -33,7 +33,7 @@ const hAlign = computed(() => {

{{ subtitle }}

-
+