feat(建页方案): 本地开发目录只作为开发期 OSS 图片镜像使用,方便页面优先读取本地图片
This commit is contained in:
parent
daf57343de
commit
fb967f709e
@ -27,6 +27,8 @@
|
||||
7. 安全白名单片段和权限页面片段也使用 route path 自动生成,不留空。
|
||||
8. OSS 相对路径和本地开发目录根据页面类型和页面目录自动生成;用户后续可以自行修改。
|
||||
9. 如果用户要求,或 md 中“是否需要 Codex 自动创建本地开发目录”为“是”,创建 public/oss/h5/Azizi/... 本地图片目录。
|
||||
- 本地开发目录只作为开发期 OSS 图片镜像使用,方便页面优先读取本地图片;发布时图片由用户另行上传到真实 OSS,不随项目提交 Git。
|
||||
- 创建本地开发目录时只创建文件夹,不生成 `.gitkeep`;空目录不被 Git 追踪是正常现象。
|
||||
10. 如果本地开发目录已存在且里面有图片,扫描图片文件并预填 3.1 多语言图片清单。
|
||||
11. 根据页面类型、3.1 图片清单和模块预设,自动预填 3.2、3.3、4.x 模块配置。
|
||||
12. 可按 route path 生成路由、白名单、权限片段;是否立即写入 `src/router/index.js`、`src/config/security.js`、`src/utils/permissionManager.js` 取决于用户要求和当前是否需要保持构建通过。
|
||||
@ -75,7 +77,7 @@ src/views/Ranking/OverallSeason2
|
||||
```text
|
||||
scanDir = 专属 md 中的本地开发目录
|
||||
只扫描常见图片扩展名:png、jpg、jpeg、webp、gif、svg。
|
||||
忽略 .gitkeep 等非图片文件。
|
||||
忽略 .gitkeep 等非图片文件;历史遗留的 `.gitkeep` 按非图片文件处理,新建本地开发目录时不要生成 `.gitkeep`。
|
||||
文件名不带语言后缀时,记为 en 原图,例如 bg0.png -> bg0: en。
|
||||
文件名带 _ar、_bn、_tr 等语言后缀时,按基础名合并,例如 rankBt.png + rankBt_ar.png -> rankBt: en, ar。
|
||||
如果只有 rankBt_ar.png 且没有 rankBt.png,也生成 rankBt: ar,并在备注里标记缺少原图。
|
||||
@ -104,6 +106,7 @@ rankingTopBg 统一解释为“排行榜前几名展示区背景”;历史 top
|
||||
6. 只处理专属 md 中已填写的信息,未填写项跳过。
|
||||
7. 以专属页面信息 md 为唯一生成源,同步更新 page.config.js,把已填写的活动字段、预加载、tabs、sections、children、popups、features 写入配置。
|
||||
8. 如果专属 md 中“是否需要 Codex 自动创建本地开发目录”为“是”,创建 public/oss/h5/Azizi/... 本地图片目录。
|
||||
- 这里仍然保留自动创建文件夹的功能,用于开发期存放图片;不要为该目录生成 `.gitkeep`。
|
||||
9. 添加或确认路由。
|
||||
10. 补充或确认 src/config/security.js。
|
||||
11. 补充或确认 src/utils/permissionManager.js。
|
||||
|
||||
@ -30,6 +30,8 @@
|
||||
2. 在页面目录中创建 页面创建信息.md。
|
||||
3. 根据 页面创建信息.md 创建 page.config.js 初始配置。
|
||||
4. 按需要创建本地 OSS 图片目录。
|
||||
- 本地 OSS 图片目录仅用于开发期存放图片,方便页面读取本地资源;发布时图片由你上传到真实 OSS,不随项目提交 Git。
|
||||
- Codex 仍会按需要创建这个文件夹,但不会生成 `.gitkeep`;空文件夹不被 Git 追踪是正常现象。
|
||||
5. 预填 route、OSS、图片清单、预加载和模块配置。
|
||||
6. 不生成 index.vue,除非你明确要求继续创建页面。
|
||||
```
|
||||
@ -128,6 +130,8 @@ src/views/Activities/GulbenFestival/页面创建信息.md
|
||||
- 是否需要 Codex 自动创建本地开发目录:是 / 否
|
||||
- 图片是否已放入本地目录:是 / 否
|
||||
|
||||
说明:本地开发目录只作为开发期 OSS 图片镜像使用,Codex 需要保留创建文件夹的能力,便于你放入开发用图片;目录内图片和空目录占位文件不作为 Git 提交内容,新建时不要生成 `.gitkeep`。
|
||||
|
||||
### 3.1 多语言图片清单
|
||||
|
||||
| 图片名 | 支持语言 | 备注 |
|
||||
|
||||
@ -2,15 +2,21 @@ import vue from '@vitejs/plugin-vue'
|
||||
import Components from 'unplugin-vue-components/vite'
|
||||
|
||||
import { defineConfig } from 'vite'
|
||||
import fs from 'node:fs'
|
||||
import path from 'node:path'
|
||||
import { fileURLToPath, URL } from 'node:url'
|
||||
import { existsSync } from 'node:fs'
|
||||
import { isAbsolute, relative, resolve } from 'node:path'
|
||||
import { VantResolver } from 'unplugin-vue-components/resolvers'
|
||||
|
||||
const PRODUCTION_LIKE_MODES = new Set(['production', 'production-atu'])
|
||||
const STRIPPABLE_CONSOLE_METHODS = ['log', 'debug', 'info']
|
||||
const PUBLIC_DIR = fileURLToPath(new URL('./public', import.meta.url))
|
||||
const PUBLIC_ROOT = resolve(PUBLIC_DIR)
|
||||
const LOCAL_OSS_MIME_TYPES = {
|
||||
'.gif': 'image/gif',
|
||||
'.jpg': 'image/jpeg',
|
||||
'.jpeg': 'image/jpeg',
|
||||
'.png': 'image/png',
|
||||
'.svg': 'image/svg+xml',
|
||||
'.webp': 'image/webp',
|
||||
}
|
||||
|
||||
function isEscaped(code, index) {
|
||||
let backslashCount = 0
|
||||
@ -259,12 +265,56 @@ function createBuildLogControlPlugin(stripDebugLogs) {
|
||||
}
|
||||
}
|
||||
|
||||
function createLocalOssAssetPlugin() {
|
||||
const ossRoot = fileURLToPath(new URL('./public/oss', import.meta.url))
|
||||
|
||||
return {
|
||||
name: 'likei-local-oss-assets',
|
||||
apply: 'serve',
|
||||
configureServer(server) {
|
||||
server.middlewares.use('/oss', (req, res, next) => {
|
||||
const rawPath = req.url?.split('?')[0] || '/'
|
||||
let decodedPath = ''
|
||||
|
||||
try {
|
||||
decodedPath = decodeURIComponent(rawPath)
|
||||
} catch {
|
||||
next()
|
||||
return
|
||||
}
|
||||
|
||||
const normalizedPath = path.normalize(decodedPath).replace(/^(\.\.[/\\])+/, '')
|
||||
const filePath = path.join(ossRoot, normalizedPath)
|
||||
const safeRoot = `${ossRoot}${path.sep}`
|
||||
|
||||
if (!filePath.startsWith(safeRoot)) {
|
||||
next()
|
||||
return
|
||||
}
|
||||
|
||||
if (!fs.existsSync(filePath) || !fs.statSync(filePath).isFile()) {
|
||||
next()
|
||||
return
|
||||
}
|
||||
|
||||
const contentType = LOCAL_OSS_MIME_TYPES[path.extname(filePath).toLowerCase()]
|
||||
if (contentType) {
|
||||
res.setHeader('Content-Type', contentType)
|
||||
}
|
||||
|
||||
fs.createReadStream(filePath).pipe(res)
|
||||
})
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
export default defineConfig(({ mode }) => {
|
||||
const keepBuildLogs = process.env.LIKEI_KEEP_BUILD_LOGS === 'true'
|
||||
const stripDebugLogs = PRODUCTION_LIKE_MODES.has(mode) && !keepBuildLogs
|
||||
|
||||
return {
|
||||
plugins: [
|
||||
createLocalOssAssetPlugin(),
|
||||
vue(),
|
||||
Components({
|
||||
resolvers: [VantResolver()],
|
||||
@ -318,23 +368,6 @@ export default defineConfig(({ mode }) => {
|
||||
target: 'https://cdn.azizichat.com',
|
||||
changeOrigin: true,
|
||||
secure: true,
|
||||
bypass: (req) => {
|
||||
const requestUrl = req.url || ''
|
||||
|
||||
try {
|
||||
const pathname = decodeURIComponent(new URL(requestUrl, 'http://localhost').pathname)
|
||||
const localPublicFile = resolve(PUBLIC_ROOT, `.${pathname}`)
|
||||
const localPathInPublic = relative(PUBLIC_ROOT, localPublicFile)
|
||||
|
||||
if (!localPathInPublic.startsWith('..') && !isAbsolute(localPathInPublic) && existsSync(localPublicFile)) {
|
||||
return pathname
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn('Failed to check local OSS fallback:', error)
|
||||
}
|
||||
|
||||
return null
|
||||
},
|
||||
rewrite: (path) => path.replace(/^\/oss/, ''),
|
||||
configure: (proxy) => {
|
||||
proxy.on('proxyRes', (proxyRes) => {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user