From 98126c62ecd03bd99eaa9430d789df5389f5271f Mon Sep 17 00:00:00 2001 From: wm <2747639460@qq.com> Date: Wed, 22 Jul 2026 15:33:29 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E8=87=AA=E6=89=98=E7=AE=A1=E8=B6=85?= =?UTF-8?q?=E5=88=86=E5=AA=92=E4=BD=93=20+=20=E8=AF=A6=E6=83=85=E9=A1=B5?= =?UTF-8?q?=E4=BC=98=E5=85=88=E6=B8=85=E6=99=B0JPG?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 后端 main.ts: 新增 /media 静态服务(指向容器内 /app/media,由卷挂载) 配合 MEDIA_BASE_URL 指向本服务 /media,彻底脱离 jsDelivr 依赖 - 详情页 hero 优先用超分 JPG(720px),GIF/JPG 互为降级兜底 --- backend/src/main.ts | 11 ++++++++++- miniprogram/pages/detail/detail.js | 12 +++++++----- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/backend/src/main.ts b/backend/src/main.ts index b2076a0..12e8691 100644 --- a/backend/src/main.ts +++ b/backend/src/main.ts @@ -1,9 +1,18 @@ import { NestFactory } from '@nestjs/core'; import { ValidationPipe } from '@nestjs/common'; +import { NestExpressApplication } from '@nestjs/platform-express'; +import { join } from 'path'; +import { existsSync, mkdirSync } from 'fs'; import { AppModule } from './app.module'; async function bootstrap() { - const app = await NestFactory.create(AppModule); + const app = await NestFactory.create(AppModule); + + // 自托管媒体(超分图/动图)静态服务:/media/** -> /app/media/** + // 容器内 /app/media 通过卷挂载服务器目录,MEDIA_BASE_URL 指向本服务 /media + const mediaRoot = join(__dirname, '..', 'media'); + if (!existsSync(mediaRoot)) mkdirSync(mediaRoot, { recursive: true }); + app.useStaticAssets(mediaRoot, { prefix: '/media' }); if (process.env.CORS_ENABLED !== 'false') { app.enableCors(); diff --git a/miniprogram/pages/detail/detail.js b/miniprogram/pages/detail/detail.js index 99c650f..d998ddd 100644 --- a/miniprogram/pages/detail/detail.js +++ b/miniprogram/pages/detail/detail.js @@ -37,8 +37,8 @@ Page({ load() { this.setData({ loading: true }); svc.getExercise(this.data.id).then((ex) => { - // 详情页用 GIF 演示动作;记录当前图源以便失败时降级到 JPG / 占位 - const heroSrc = ex && (ex.gifUrl || ex.image) ? (ex.gifUrl || ex.image) : ''; + // 详情大图优先用超分 JPG(720px 清晰);失败再降级到 GIF / 占位 + const heroSrc = ex && (ex.image || ex.gifUrl) ? (ex.image || ex.gifUrl) : ''; this.setData({ exercise: ex, heroSrc, heroError: false, loading: false }); if (ex && ex.target) { svc.listExercises({ target: ex.target, pageSize: 6 }).then((res) => { @@ -110,11 +110,13 @@ Page({ } }, - // 详情大图加载失败:GIF→JPG→emoji 占位,三级降级保证不空白 + // 详情大图加载失败:JPG↔GIF 互为降级,最后 emoji 占位,保证不空白 onHeroError() { const ex = this.data.exercise || {}; - const showingGif = this.data.heroSrc && ex.gifUrl && this.data.heroSrc === ex.gifUrl; - if (showingGif && ex.image) { + const cur = this.data.heroSrc; + if (cur === ex.image && ex.gifUrl) { + this.setData({ heroSrc: ex.gifUrl }); + } else if (cur === ex.gifUrl && ex.image) { this.setData({ heroSrc: ex.image }); } else { this.setData({ heroError: true });