Compare commits
2 Commits
5d6b84380b
...
b35ec1aef7
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b35ec1aef7 | ||
|
|
6804a7300f |
@ -1,3 +0,0 @@
|
|||||||
{
|
|
||||||
"pages": {}
|
|
||||||
}
|
|
||||||
@ -1,16 +0,0 @@
|
|||||||
{
|
|
||||||
"polyfillFiles": [
|
|
||||||
"static/chunks/polyfills.js"
|
|
||||||
],
|
|
||||||
"devFiles": [],
|
|
||||||
"ampDevFiles": [],
|
|
||||||
"lowPriorityFiles": [
|
|
||||||
"static/development/_buildManifest.js",
|
|
||||||
"static/development/_ssgManifest.js"
|
|
||||||
],
|
|
||||||
"rootMainFiles": [],
|
|
||||||
"pages": {
|
|
||||||
"/_app": []
|
|
||||||
},
|
|
||||||
"ampFirstPages": []
|
|
||||||
}
|
|
||||||
@ -1 +0,0 @@
|
|||||||
{"type": "commonjs"}
|
|
||||||
@ -1 +0,0 @@
|
|||||||
{}
|
|
||||||
@ -1 +0,0 @@
|
|||||||
{}
|
|
||||||
@ -1 +0,0 @@
|
|||||||
self.__INTERCEPTION_ROUTE_REWRITE_MANIFEST="[]"
|
|
||||||
@ -1,18 +0,0 @@
|
|||||||
self.__BUILD_MANIFEST = {
|
|
||||||
"polyfillFiles": [
|
|
||||||
"static/chunks/polyfills.js"
|
|
||||||
],
|
|
||||||
"devFiles": [],
|
|
||||||
"ampDevFiles": [],
|
|
||||||
"lowPriorityFiles": [],
|
|
||||||
"rootMainFiles": [],
|
|
||||||
"pages": {
|
|
||||||
"/_app": []
|
|
||||||
},
|
|
||||||
"ampFirstPages": []
|
|
||||||
};
|
|
||||||
self.__BUILD_MANIFEST.lowPriorityFiles = [
|
|
||||||
"/static/" + process.env.__NEXT_BUILD_ID + "/_buildManifest.js",
|
|
||||||
,"/static/" + process.env.__NEXT_BUILD_ID + "/_ssgManifest.js",
|
|
||||||
|
|
||||||
];
|
|
||||||
@ -1,6 +0,0 @@
|
|||||||
{
|
|
||||||
"version": 3,
|
|
||||||
"middleware": {},
|
|
||||||
"functions": {},
|
|
||||||
"sortedMiddleware": []
|
|
||||||
}
|
|
||||||
@ -1 +0,0 @@
|
|||||||
self.__REACT_LOADABLE_MANIFEST="{}"
|
|
||||||
@ -1 +0,0 @@
|
|||||||
self.__NEXT_FONT_MANIFEST="{\"pages\":{},\"app\":{},\"appUsingSizeAdjust\":false,\"pagesUsingSizeAdjust\":false}"
|
|
||||||
@ -1 +0,0 @@
|
|||||||
{"pages":{},"app":{},"appUsingSizeAdjust":false,"pagesUsingSizeAdjust":false}
|
|
||||||
@ -1 +0,0 @@
|
|||||||
{}
|
|
||||||
@ -1 +0,0 @@
|
|||||||
self.__RSC_SERVER_MANIFEST="{\n \"node\": {},\n \"edge\": {},\n \"encryptionKey\": \"process.env.NEXT_SERVER_ACTIONS_ENCRYPTION_KEY\"\n}"
|
|
||||||
@ -1,5 +0,0 @@
|
|||||||
{
|
|
||||||
"node": {},
|
|
||||||
"edge": {},
|
|
||||||
"encryptionKey": "29r7Ms7DcgtmNMSCLyvmj7peV+rATABBPVNlBdLbZzs="
|
|
||||||
}
|
|
||||||
File diff suppressed because one or more lines are too long
@ -1 +0,0 @@
|
|||||||
self.__BUILD_MANIFEST = {__rewrites:{afterFiles:[],beforeFiles:[],fallback:[]},sortedPages:["\u002F_app"]};self.__BUILD_MANIFEST_CB && self.__BUILD_MANIFEST_CB()
|
|
||||||
@ -1 +0,0 @@
|
|||||||
self.__SSG_MANIFEST=new Set;self.__SSG_MANIFEST_CB&&self.__SSG_MANIFEST_CB()
|
|
||||||
File diff suppressed because one or more lines are too long
@ -1 +0,0 @@
|
|||||||
{"type": "module"}
|
|
||||||
@ -23,7 +23,8 @@ IMAGE_VERSION="v1.0.0"
|
|||||||
USERNAME="742065561@qq.com"
|
USERNAME="742065561@qq.com"
|
||||||
|
|
||||||
# Registry 登录密码
|
# Registry 登录密码
|
||||||
# 为安全起见,不在脚本中硬编码密码
|
# 为安全起见,不在脚本中硬编码密码 #vH#DYxZij8zk^Jr
|
||||||
|
echo "默认密码:#vH#DYxZij8zk^Jr"
|
||||||
PASSWORD=""
|
PASSWORD=""
|
||||||
|
|
||||||
REGISTRY_HOST="registry.${REGISTRY_REGION}.aliyuncs.com"
|
REGISTRY_HOST="registry.${REGISTRY_REGION}.aliyuncs.com"
|
||||||
|
|||||||
@ -36,8 +36,8 @@ export async function POST(request) {
|
|||||||
const buffer = Buffer.from(await file.arrayBuffer());
|
const buffer = Buffer.from(await file.arrayBuffer());
|
||||||
fs.writeFileSync(filePath, buffer);
|
fs.writeFileSync(filePath, buffer);
|
||||||
|
|
||||||
// 返回文件路径(相对于 public 的路径)
|
// 返回动态访问路径,避免生产环境下 public 目录新增文件 404
|
||||||
const publicPath = `/uploads/${fileName}`;
|
const publicPath = `/api/config/logo?file=${encodeURIComponent(fileName)}`;
|
||||||
|
|
||||||
return Response.json({
|
return Response.json({
|
||||||
path: publicPath,
|
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 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -2,15 +2,31 @@ export const dynamic = "force-dynamic";
|
|||||||
import getDb from '@/lib/db';
|
import getDb from '@/lib/db';
|
||||||
import { getUserFromRequest, unauthorizedResponse, forbiddenResponse, checkRole } from '@/lib/auth';
|
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 - 获取系统配置(公开,无需认证)
|
// GET /api/config - 获取系统配置(公开,无需认证)
|
||||||
export async function GET() {
|
export async function GET() {
|
||||||
try {
|
try {
|
||||||
const db = await getDb();
|
const db = await getDb();
|
||||||
const configs = db.prepare('SELECT config_key, config_value FROM system_config').all();
|
const configs = db.prepare('SELECT config_key, config_value FROM system_config').all();
|
||||||
const result = {};
|
const result = normalizeConfig(configs);
|
||||||
for (const config of configs) {
|
|
||||||
result[config.config_key] = config.config_value;
|
|
||||||
}
|
|
||||||
return Response.json(result);
|
return Response.json(result);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('获取系统配置失败:', error);
|
console.error('获取系统配置失败:', error);
|
||||||
@ -46,12 +62,8 @@ export async function PUT(request) {
|
|||||||
});
|
});
|
||||||
updateMany();
|
updateMany();
|
||||||
|
|
||||||
// 返回更新后的配置
|
|
||||||
const configs = db.prepare('SELECT config_key, config_value FROM system_config').all();
|
const configs = db.prepare('SELECT config_key, config_value FROM system_config').all();
|
||||||
const result = {};
|
const result = normalizeConfig(configs);
|
||||||
for (const config of configs) {
|
|
||||||
result[config.config_key] = config.config_value;
|
|
||||||
}
|
|
||||||
return Response.json(result);
|
return Response.json(result);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('更新系统配置失败:', error);
|
console.error('更新系统配置失败:', error);
|
||||||
|
|||||||
53
src/app/uploads/[file]/route.js
Normal file
53
src/app/uploads/[file]/route.js
Normal 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 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user