This commit is contained in:
haomingming 2026-06-26 17:34:15 +08:00
parent 5d6b84380b
commit 6804a7300f
4 changed files with 129 additions and 12 deletions

View File

@ -23,7 +23,8 @@ IMAGE_VERSION="v1.0.0"
USERNAME="742065561@qq.com"
# Registry 登录密码
# 为安全起见,不在脚本中硬编码密码
# 为安全起见,不在脚本中硬编码密码 #vH#DYxZij8zk^Jr
echo "默认密码:#vH#DYxZij8zk^Jr"
PASSWORD=""
REGISTRY_HOST="registry.${REGISTRY_REGION}.aliyuncs.com"

View File

@ -36,8 +36,8 @@ export async function POST(request) {
const buffer = Buffer.from(await file.arrayBuffer());
fs.writeFileSync(filePath, buffer);
// 返回文件路径(相对于 public 的路径)
const publicPath = `/uploads/${fileName}`;
// 返回动态访问路径,避免生产环境下 public 目录新增文件 404
const publicPath = `/api/config/logo?file=${encodeURIComponent(fileName)}`;
return Response.json({
path: publicPath,
@ -51,3 +51,54 @@ export async function POST(request) {
);
}
}
// GET /api/config/logo?file=xxx - 动态读取并返回 Logo 文件
export async function GET(request) {
try {
const { searchParams } = new URL(request.url);
const file = searchParams.get('file');
if (!file) {
return Response.json(
{ error: '缺少文件名' },
{ status: 400 }
);
}
const cleanFile = path.basename(file);
const filePath = path.join(process.cwd(), 'public', 'uploads', cleanFile);
if (!fs.existsSync(filePath)) {
return Response.json(
{ error: '文件不存在' },
{ status: 404 }
);
}
const buffer = fs.readFileSync(filePath);
const ext = path.extname(cleanFile).toLowerCase();
let contentType = 'application/octet-stream';
if (ext === '.png') contentType = 'image/png';
else if (ext === '.jpg' || ext === '.jpeg') contentType = 'image/jpeg';
else if (ext === '.gif') contentType = 'image/gif';
else if (ext === '.webp') contentType = 'image/webp';
else if (ext === '.bmp') contentType = 'image/bmp';
else if (ext === '.svg') contentType = 'image/svg+xml';
return new Response(buffer, {
headers: {
'Content-Type': contentType,
'Content-Length': buffer.length.toString(),
'Content-Disposition': `inline; filename="${encodeURIComponent(cleanFile)}"`,
'Cache-Control': 'public, max-age=31536000, immutable'
}
});
} catch (error) {
console.error('获取 Logo 失败:', error);
return Response.json(
{ error: '服务器内部错误' },
{ status: 500 }
);
}
}

View File

@ -2,15 +2,31 @@ export const dynamic = "force-dynamic";
import getDb from '@/lib/db';
import { getUserFromRequest, unauthorizedResponse, forbiddenResponse, checkRole } from '@/lib/auth';
function normalizeConfig(configs) {
const result = {};
for (const config of configs) {
let value = config.config_value;
if (config.config_key === 'company_logo' && value) {
const match = value.match(/^\/uploads\/(.+)$/);
if (match) {
value = `/api/config/logo?file=${encodeURIComponent(match[1])}`;
}
}
result[config.config_key] = value;
}
return result;
}
// GET /api/config - 获取系统配置(公开,无需认证)
export async function GET() {
try {
const db = await getDb();
const configs = db.prepare('SELECT config_key, config_value FROM system_config').all();
const result = {};
for (const config of configs) {
result[config.config_key] = config.config_value;
}
const result = normalizeConfig(configs);
return Response.json(result);
} catch (error) {
console.error('获取系统配置失败:', error);
@ -46,12 +62,8 @@ export async function PUT(request) {
});
updateMany();
// 返回更新后的配置
const configs = db.prepare('SELECT config_key, config_value FROM system_config').all();
const result = {};
for (const config of configs) {
result[config.config_key] = config.config_value;
}
const result = normalizeConfig(configs);
return Response.json(result);
} catch (error) {
console.error('更新系统配置失败:', error);

View File

@ -0,0 +1,53 @@
export const dynamic = "force-dynamic";
import path from 'path';
import fs from 'fs';
// GET /uploads/:file - 兼容历史 Logo 直链
export async function GET(request, { params }) {
try {
const file = params?.file;
if (!file) {
return Response.json(
{ error: '缺少文件名' },
{ status: 400 }
);
}
const cleanFile = path.basename(file);
const filePath = path.join(process.cwd(), 'public', 'uploads', cleanFile);
if (!fs.existsSync(filePath)) {
return Response.json(
{ error: '文件不存在' },
{ status: 404 }
);
}
const buffer = fs.readFileSync(filePath);
const ext = path.extname(cleanFile).toLowerCase();
let contentType = 'application/octet-stream';
if (ext === '.png') contentType = 'image/png';
else if (ext === '.jpg' || ext === '.jpeg') contentType = 'image/jpeg';
else if (ext === '.gif') contentType = 'image/gif';
else if (ext === '.webp') contentType = 'image/webp';
else if (ext === '.bmp') contentType = 'image/bmp';
else if (ext === '.svg') contentType = 'image/svg+xml';
return new Response(buffer, {
headers: {
'Content-Type': contentType,
'Content-Length': buffer.length.toString(),
'Content-Disposition': `inline; filename="${encodeURIComponent(cleanFile)}"`,
'Cache-Control': 'public, max-age=31536000, immutable'
}
});
} catch (error) {
console.error('获取上传文件失败:', error);
return Response.json(
{ error: '服务器内部错误' },
{ status: 500 }
);
}
}