Skip to content

Commit 4be6eba

Browse files
committed
修复问题
1 parent f026e38 commit 4be6eba

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+1737
-2523
lines changed

.github/copilot-instructions.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ manager.SetDB(db) // 注入数据库连接(配置读取现在以 config.yaml
3030
- **数据库持久化**:配置自动保存到 key_value 表,支持动态更新
3131
- **热重载机制**:通过 ReloadConfig() 方法实现运行时配置更新
3232
- **配置验证**:每个配置模块都有独立的验证方法
33-
- **分层映射**ToMap() 和 FromMap() 方法支持配置的序列化和反序列化
33+
- **类型安全配置**使用结构体 Clone() 方法和直接字段访问,避免 map 转换开销
3434

3535
### Route Architecture
3636
完全模块化的路由系统 (`internal/routes/`):

admin-test.html

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
<!DOCTYPE html>
2+
<html lang="zh-CN">
3+
<head>
4+
<meta charset="UTF-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
6+
<title>管理员API测试</title>
7+
</head>
8+
<body>
9+
<h1>管理员API测试</h1>
10+
11+
<div>
12+
<h2>1. 登录测试</h2>
13+
<button onclick="testLogin()">测试登录</button>
14+
<div id="login-result"></div>
15+
</div>
16+
17+
<div>
18+
<h2>2. 仪表板API测试</h2>
19+
<button onclick="testDashboard()">测试仪表板</button>
20+
<div id="dashboard-result"></div>
21+
</div>
22+
23+
<div>
24+
<h2>3. 用户列表API测试</h2>
25+
<button onclick="testUsers()">测试用户列表</button>
26+
<div id="users-result"></div>
27+
</div>
28+
29+
<script>
30+
let authToken = null;
31+
32+
async function testLogin() {
33+
try {
34+
const response = await fetch('/admin/login', {
35+
method: 'POST',
36+
headers: {
37+
'Content-Type': 'application/json'
38+
},
39+
body: JSON.stringify({
40+
username: 'testadmin',
41+
password: 'admin123'
42+
})
43+
});
44+
45+
const result = await response.json();
46+
47+
if (result.code === 200) {
48+
authToken = result.data.token;
49+
localStorage.setItem('user_token', authToken);
50+
document.getElementById('login-result').innerHTML =
51+
'<span style="color: green;">登录成功!Token: ' + authToken.substring(0, 50) + '...</span>';
52+
} else {
53+
document.getElementById('login-result').innerHTML =
54+
'<span style="color: red;">登录失败: ' + result.message + '</span>';
55+
}
56+
} catch (error) {
57+
document.getElementById('login-result').innerHTML =
58+
'<span style="color: red;">请求失败: ' + error.message + '</span>';
59+
}
60+
}
61+
62+
async function testDashboard() {
63+
if (!authToken) {
64+
authToken = localStorage.getItem('user_token');
65+
}
66+
67+
if (!authToken) {
68+
document.getElementById('dashboard-result').innerHTML =
69+
'<span style="color: red;">请先登录</span>';
70+
return;
71+
}
72+
73+
try {
74+
const response = await fetch('/admin/dashboard', {
75+
headers: {
76+
'Authorization': 'Bearer ' + authToken
77+
}
78+
});
79+
80+
const result = await response.json();
81+
82+
document.getElementById('dashboard-result').innerHTML =
83+
'<pre>' + JSON.stringify(result, null, 2) + '</pre>';
84+
} catch (error) {
85+
document.getElementById('dashboard-result').innerHTML =
86+
'<span style="color: red;">请求失败: ' + error.message + '</span>';
87+
}
88+
}
89+
90+
async function testUsers() {
91+
if (!authToken) {
92+
authToken = localStorage.getItem('user_token');
93+
}
94+
95+
if (!authToken) {
96+
document.getElementById('users-result').innerHTML =
97+
'<span style="color: red;">请先登录</span>';
98+
return;
99+
}
100+
101+
try {
102+
const response = await fetch('/admin/users', {
103+
headers: {
104+
'Authorization': 'Bearer ' + authToken
105+
}
106+
});
107+
108+
const result = await response.json();
109+
110+
document.getElementById('users-result').innerHTML =
111+
'<pre>' + JSON.stringify(result, null, 2) + '</pre>';
112+
} catch (error) {
113+
document.getElementById('users-result').innerHTML =
114+
'<span style="color: red;">请求失败: ' + error.message + '</span>';
115+
}
116+
}
117+
</script>
118+
</body>
119+
</html>

config.yaml

Lines changed: 65 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,54 +1,71 @@
11
base:
2-
data_path: /tmp/filecodebox_test
3-
description: 开箱即用的文件快传系统
4-
host: 0.0.0.0
5-
name: FileCodeBox
6-
port: 12346
7-
production: false
2+
name: FileCodeBox
3+
description: 开箱即用的文件快传系统
4+
keywords: ""
5+
port: 12346
6+
host: 0.0.0.0
7+
datapath: /Users/zhangyi/zy/FileCodeBox/data
8+
production: false
89
database:
9-
host: ""
10-
name: ./data/filecodebox.db
11-
port: 0
12-
ssl: disable
13-
type: sqlite
14-
user: ""
10+
type: sqlite
11+
host: ""
12+
port: 0
13+
name: ./data/filecodebox.db
14+
user: ""
15+
pass: ""
16+
ssl: disable
17+
transfer:
18+
upload:
19+
openupload: 1
20+
uploadsize: 10485760
21+
enablechunk: 0
22+
chunksize: 2097152
23+
maxsaveseconds: 0
24+
download:
25+
enableconcurrentdownload: 1
26+
maxconcurrentdownloads: 10
27+
downloadtimeout: 300
28+
storage:
29+
type: ""
30+
storagepath: ""
31+
s3: null
32+
webdav: null
33+
onedrive: null
34+
nfs: null
35+
user:
36+
allowuserregistration: 1
37+
requireemailverify: 0
38+
useruploadsize: 52428800
39+
userstoragequota: 1073741824
40+
sessionexpiryhours: 168
41+
maxsessionsperuser: 5
42+
jwtsecret: FileCodeBox2025JWT
1543
mcp:
16-
host: 0.0.0.0
17-
port: 8081
18-
storage: {}
44+
enablemcpserver: 0
45+
mcpport: ""
46+
mcphost: ""
47+
notifytitle: ""
48+
notifycontent: ""
1949
ui:
20-
allow_user_registration: 0
21-
background: ""
22-
chunk_size: 2097152
23-
download_timeout: 300
24-
enable_chunk: 0
25-
enable_concurrent_download: 1
26-
enable_mcp_server: 0
27-
error_count: 1
28-
error_minute: 1
29-
file_storage: local
30-
jwt_secret: FileCodeBox2025JWT
31-
keywords: FileCodeBox, 文件快递柜, 口令传送箱, 匿名口令分享文本, 文件
32-
max_concurrent_downloads: 10
33-
max_save_seconds: 0
34-
max_sessions_per_user: 5
35-
notify_content: "欢迎使用 FileCodeBox,本程序开源于 <a href=\"https://github.com/zy84338719/FileCodeBox\" target=\"_blank\">Github</a> ,欢迎Star和Fork。"
36-
notify_title: 系统通知
37-
opacity: 0
38-
open_upload: 1
39-
page_explain: "请勿上传或分享违法内容。根据《中华人民共和国网络安全法》、《中华人民共和国刑法》、《中华人民共和国治安管理处罚法》等相关规定。 传播或存储违法、违规内容,会受到相关处罚,严重者将承担刑事责任。本站坚决配合相关部门,确保网络内容的安全,和谐,打造绿色网络环境。"
40-
require_email_verify: 0
41-
robots_text: |-
50+
themes_select: themes/2025
51+
background: ""
52+
page_explain: 请勿上传或分享违法内容。根据《中华人民共和国网络安全法》、《中华人民共和国刑法》、《中华人民共和国治安管理处罚法》等相关规定。 传播或存储违法、违规内容,会受到相关处罚,严重者将承担刑事责任。本站坚决配合相关部门,确保网络内容的安全,和谐,打造绿色网络环境。
53+
robots_text: |-
54+
User-agent: *
55+
Disallow: /
56+
show_admin_addr: 0
57+
opacity: 0
58+
themes_select: themes/2025
59+
robots_text: |-
4260
User-agent: *
4361
Disallow: /
44-
session_expiry_hours: 168
45-
show_admin_address: 0
46-
storage_path: ""
47-
sys_start: 1757914992279
48-
themes_select: themes/2025
49-
upload_count: 10
50-
upload_minute: 1
51-
upload_size: 100
52-
user_storage_quota: 1073741824
53-
user_upload_size: 52428800
54-
user: {}
62+
page_explain: 请勿上传或分享违法内容。根据《中华人民共和国网络安全法》、《中华人民共和国刑法》、《中华人民共和国治安管理处罚法》等相关规定。 传播或存储违法、违规内容,会受到相关处罚,严重者将承担刑事责任。本站坚决配合相关部门,确保网络内容的安全,和谐,打造绿色网络环境。
63+
show_admin_addr: 0
64+
opacity: 0
65+
background: ""
66+
sys_start: ""
67+
upload_minute: 0
68+
upload_count: 0
69+
error_minute: 0
70+
error_count: 0
71+
expire_style: []

docs/CONFIG_REFACTOR_SUMMARY.md

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,6 @@
7575
每个配置模块都实现以下标准接口:
7676
```go
7777
- Validate() error // 配置验证
78-
- ToMap() map[string]string // 转换为键值对
79-
- FromMap(map[string]string) error // 从键值对加载
8078
- Update(map[string]interface{}) error // 更新配置
8179
- Clone() *ConfigType // 克隆配置
8280
```

docs/changelogs/REFACTOR_SUMMARY.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ internal/
9090

9191
### 配置管理增强
9292
- **分层配置结构**:每个功能模块都有独立的配置结构体
93-
- **序列化支持**`ToMap()``FromMap()` 方法支持配置的序列化和反序列化
93+
- **类型安全**使用结构体 Clone() 方法和直接字段访问,避免 map 转换开销
9494
- **配置验证**:每个配置模块都有 `Validate()` 方法进行配置验证
9595
- **热重载**`ReloadConfig()` 支持运行时配置更新,无需重启应用
9696

docs/config.new.yaml

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
# FileCodeBox 新版 config.yaml 示例
2+
# 完全分层、无平铺字段,所有配置项归属功能模块
3+
4+
base:
5+
name: 文件快递柜 - FileCodeBox
6+
description: "开箱即用的文件快传系统"
7+
keywords: "FileCodeBox, 文件快递柜, 匿名口令分享, 文件"
8+
port: 12345
9+
host: "0.0.0.0"
10+
data_path: "./data"
11+
production: false
12+
13+
transfer:
14+
upload:
15+
open_upload: 1
16+
upload_size: 10485760
17+
enable_chunk: 1
18+
chunk_size: 2097152
19+
max_save_seconds: 0
20+
download:
21+
enable_concurrent_download: 1
22+
max_concurrent_downloads: 10
23+
download_timeout: 300
24+
25+
user:
26+
allow_user_registration: 1
27+
require_email_verify: 0
28+
user_upload_size: 10485760
29+
user_storage_quota: 1073741824
30+
session_expiry_hours: 72
31+
max_sessions_per_user: 5
32+
jwt_secret: "your_jwt_secret"
33+
34+
ui:
35+
notify_title: "欢迎使用 FileCodeBox"
36+
notify_content: "安全、便捷的文件快传系统"
37+
themes_select: "themes/2025"
38+
opacity: 0.95
39+
background: ""
40+
page_explain: "本系统支持大文件快传、断点续传、匿名分享等功能。"
41+
robots_text: "User-agent: *\nDisallow: /admin/"
42+
show_admin_addr: 1
43+
44+
mcp:
45+
enable_mcp_server: 1
46+
mcp_port: "12346"
47+
mcp_host: "127.0.0.1"
48+
49+
storage:
50+
type: "local"
51+
local:
52+
path: "./uploads"
53+
s3:
54+
endpoint: ""
55+
access_key: ""
56+
secret_key: ""
57+
bucket: ""
58+
region: ""
59+
webdav:
60+
url: ""
61+
username: ""
62+
password: ""
63+
onedrive:
64+
client_id: ""
65+
client_secret: ""
66+
refresh_token: ""
67+
drive_id: ""
68+
69+
database:
70+
type: "sqlite"
71+
sqlite:
72+
path: "./data/filecodebox.db"
73+
mysql:
74+
dsn: ""
75+
postgres:
76+
dsn: ""

docs/config_migration_advice.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# FileCodeBox 配置协议重构迁移建议
2+
3+
1. config.yaml 迁移:
4+
- 所有平铺字段(如 notify_title、opacity、themes_select 等)全部归入对应功能模块(如 ui、base、transfer、user 等)。
5+
- 结构调整后,所有配置项都在一级模块下,便于维护和热重载。
6+
7+
2. Go struct 迁移:
8+
- ConfigManager 及所有子 struct 按 config.yaml 完全分层,字段命名、类型、json/yaml tag 保持一致。
9+
- AdminConfigRequest/Response 直接复用 ConfigManager,无需再单独定义冗余字段。
10+
11+
3. handler 层迁移:
12+
- /admin/config 响应直接返回 ConfigManager 对象,无需 hack、无需字段展开。
13+
- 更新配置时,直接反序列化为 ConfigManager 结构体。
14+
15+
4. 前端迁移:
16+
- 只需按模块对象解析(如 config.base.name、config.ui.notify_title),无需兼容处理。
17+
- 配置表单、展示、保存等全部按分层结构处理。
18+
19+
5. 兼容建议:
20+
- 迁移期间可保留旧字段一段时间,前后端同步切换。
21+
- 配置热重载、持久化、校验等逻辑建议全部基于新版分层结构实现。
22+
23+
6. 未来扩展:
24+
- 新增模块/字段时只需在 config.yaml、ConfigManager、前端 schema 同步添加即可。
25+
- 支持自动生成配置文档、前端表单 schema、API 文档等。
26+
27+
如需自动迁移脚本或批量转换工具,可进一步定制!

internal/common/response.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"net/http"
55

66
"github.com/gin-gonic/gin"
7+
"github.com/sirupsen/logrus"
78
"github.com/zy84338719/filecodebox/internal/models/web"
89
)
910

@@ -44,6 +45,8 @@ func BadRequestResponse(c *gin.Context, message string) {
4445

4546
// UnauthorizedResponse 401 未授权响应
4647
func UnauthorizedResponse(c *gin.Context, message string) {
48+
// log the unauthorized response with request path to aid debugging
49+
logrus.WithField("path", c.Request.URL.Path).Infof("UnauthorizedResponse: %s", message)
4750
c.JSON(http.StatusUnauthorized, web.ErrorResponse{
4851
Code: http.StatusUnauthorized,
4952
Message: message,

0 commit comments

Comments
 (0)