update
This commit is contained in:
parent
d4e7f83131
commit
cfaf82def3
12 changed files with 232 additions and 10 deletions
41
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
41
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
|
|
@ -0,0 +1,41 @@
|
||||||
|
---
|
||||||
|
name: Bug report
|
||||||
|
about: 报告问题与漏洞
|
||||||
|
title: "[BUG]"
|
||||||
|
labels: bug
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 问题描述
|
||||||
|
|
||||||
|
请简要描述发现的问题是什么,以及如何重现。
|
||||||
|
|
||||||
|
### 复现步骤
|
||||||
|
|
||||||
|
1. 打开...
|
||||||
|
2. 点击...
|
||||||
|
3. 观察到...
|
||||||
|
|
||||||
|
### 预期行为
|
||||||
|
|
||||||
|
请描述在正常情况下应该发生什么。
|
||||||
|
|
||||||
|
### 实际行为
|
||||||
|
|
||||||
|
请描述实际发生了什么。
|
||||||
|
|
||||||
|
### 截图
|
||||||
|
|
||||||
|
如果适用,请添加截图以帮助解释您的问题。
|
||||||
|
|
||||||
|
### 环境信息
|
||||||
|
|
||||||
|
- 发行版: [例如 Debian12, Alpine-Edge ]
|
||||||
|
- 部署方式: [可执行文件/Docker ]
|
||||||
|
- CaddyDash版本: [例如 1.0.0]
|
||||||
|
- Caddy版本: [例如 2.10.0-v25.07.01]
|
||||||
|
|
||||||
|
### 附加信息
|
||||||
|
|
||||||
|
请提供任何其他可能有助于我们解决问题的信息。
|
||||||
41
.github/ISSUE_TEMPLATE/bug_report_en.md
vendored
Normal file
41
.github/ISSUE_TEMPLATE/bug_report_en.md
vendored
Normal file
|
|
@ -0,0 +1,41 @@
|
||||||
|
---
|
||||||
|
name: Bug report (English)
|
||||||
|
about: Report issues and bugs
|
||||||
|
title: "[BUG]"
|
||||||
|
labels: bug
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Problem Description
|
||||||
|
|
||||||
|
Please briefly describe what the issue is and how to reproduce it.
|
||||||
|
|
||||||
|
### Steps to Reproduce
|
||||||
|
|
||||||
|
1. Open...
|
||||||
|
2. Click...
|
||||||
|
3. Observe...
|
||||||
|
|
||||||
|
### Expected Behavior
|
||||||
|
|
||||||
|
Please describe what should happen under normal circumstances.
|
||||||
|
|
||||||
|
### Actual Behavior
|
||||||
|
|
||||||
|
Please describe what actually happened.
|
||||||
|
|
||||||
|
### Screenshots
|
||||||
|
|
||||||
|
If applicable, please add screenshots to help explain your problem.
|
||||||
|
|
||||||
|
### Environment Information
|
||||||
|
|
||||||
|
- Distribution: [e.g., Debian12, Alpine-Edge ]
|
||||||
|
- Deployment Method: [Executable/Docker ]
|
||||||
|
- CaddyDash Version: [e.g., 1.0.0]
|
||||||
|
- Caddy Version: [e.g., 2.10.0-v25.07.01]
|
||||||
|
|
||||||
|
### Additional Information
|
||||||
|
|
||||||
|
Please provide any other information that might help us resolve the issue.
|
||||||
20
.github/ISSUE_TEMPLATE/features_request.md
vendored
Normal file
20
.github/ISSUE_TEMPLATE/features_request.md
vendored
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
---
|
||||||
|
name: Features request
|
||||||
|
about: 提出新功能建议
|
||||||
|
title: "[Features]"
|
||||||
|
labels: 改进
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 功能描述
|
||||||
|
|
||||||
|
请简要描述您希望增加的功能。
|
||||||
|
|
||||||
|
### 功能原因
|
||||||
|
|
||||||
|
请说明您为什么需要这个功能。
|
||||||
|
|
||||||
|
### 功能实现
|
||||||
|
|
||||||
|
请详细描述您期望的功能实现。
|
||||||
20
.github/ISSUE_TEMPLATE/features_request_en.md
vendored
Normal file
20
.github/ISSUE_TEMPLATE/features_request_en.md
vendored
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
---
|
||||||
|
name: Feature request (English)
|
||||||
|
about: Suggest new features
|
||||||
|
title: "[Feature]"
|
||||||
|
labels: enhancement
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Feature Description
|
||||||
|
|
||||||
|
Please briefly describe the feature you would like to add.
|
||||||
|
|
||||||
|
### Reason for Feature
|
||||||
|
|
||||||
|
Please explain why you need this feature.
|
||||||
|
|
||||||
|
### Feature Implementation
|
||||||
|
|
||||||
|
Please describe in detail how you expect this feature to be implemented.
|
||||||
62
README.md
62
README.md
|
|
@ -1 +1,61 @@
|
||||||
# caddydash
|
# CaddyDash - 现代化 Caddy Web 管理面板
|
||||||
|
|
||||||
|
CaddyDash 是一个现代化、用户友好的 Web 界面,用于管理和配置您的 Caddy 服务器。它提供了一个直观的图形界面,让您能够轻松地管理站点配置、调整全局设置,并监控 Caddy 实例的状态。
|
||||||
|
|
||||||
|
## ✨ 特性
|
||||||
|
|
||||||
|
* **直观的站点配置**: 通过表单轻松创建、编辑和删除站点配置,支持反向代理和文件服务模式。
|
||||||
|
* **全局 Caddyfile 管理**: 直接在 Web 界面中修改和保存 Caddy 的全局配置文件。
|
||||||
|
* **Caddy 实例控制**: 一键启动、停止和重载 Caddy 服务。
|
||||||
|
* **多语言支持**: 内置国际化 (i18n) 功能,支持中英文切换,未来可扩展更多语言。
|
||||||
|
* **响应式设计**: 界面适配桌面和移动设备,提供一致的用户体验。
|
||||||
|
* **主题切换**: 支持明亮与暗色主题,满足不同用户偏好。
|
||||||
|
* **用户认证**: 提供安全的登录和初始化流程,保障面板访问安全。
|
||||||
|
* **预设管理**: 支持从预设填充常用的请求头配置,提高配置效率。
|
||||||
|
|
||||||
|
## 🚀 技术栈
|
||||||
|
|
||||||
|
**前端:**
|
||||||
|
|
||||||
|
* **纯原生 HTML5/CSS3/JavaScript (ESM)**: 完全基于浏览器原生技术构建,响应式设计, 移动端友好
|
||||||
|
|
||||||
|
**后端:**
|
||||||
|
|
||||||
|
* **Go 语言**: 高性能、并发友好的后端服务
|
||||||
|
* **Touka 框架**: 基于 Go 构建的 HTTP 框架,用于处理 Web 请求
|
||||||
|
* **SQLite**: 轻量级嵌入式数据库,用于存储用户和配置数据
|
||||||
|
* **CaddyServer**: 作为核心组件
|
||||||
|
|
||||||
|
## 💡 架构概览
|
||||||
|
|
||||||
|
CaddyDash 前端采用**多页面应用 (MPA)** 架构,每个主要功能模块都对应一个独立的 HTML 页面,并由其专属的 JavaScript 入口文件驱动。
|
||||||
|
|
||||||
|
* **高度模块化**: 所有 JavaScript 代码都以 **ESM (ECMAScript Modules)** 形式组织,通过 `import/export` 机制实现代码复用和职责分离。
|
||||||
|
* **共享组件**: `js/common.js`、`js/locale.js`、`js/notifications.js`、`js/ui.js`、`js/api.js` 等模块封装了跨页面共享的功能,如页面初始化、国际化、通知、UI操作和后端 API 调用。
|
||||||
|
* **独立页面逻辑**: `js/app.js` (站点配置), `js/global.js` (全局配置), `js/settings.js` (面板设置), `js/login.js` (登录), `js/init.js` (初始化) 分别处理各自页面的特定业务逻辑。
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## 🌐 国际化 (i18n)
|
||||||
|
|
||||||
|
CaddyDash 前端支持多语言显示。
|
||||||
|
|
||||||
|
* **语言包**: 翻译文本存储在 `locales/en.json` (英文) 和 `locales/zh-CN.json` (简体中文) 文件中。
|
||||||
|
* **动态翻译**: `js/locale.js` 模块负责加载正确的语言包,并动态地将 HTML 元素中带有 `data-i18n` (内容)、`data-i18n-title` (标题属性) 和 `data-i18n-placeholder` (输入框提示) 的文本进行翻译。
|
||||||
|
* **切换语言**: 在登录页、初始化页或面板设置页,您可以通过界面上的语言切换选项来改变语言。
|
||||||
|
|
||||||
|
**如何添加新的翻译条目:**
|
||||||
|
|
||||||
|
1. 在 `locales/en.json` 和 `locales/zh-CN.json` 中添加新的键值对。请遵循现有的点分隔命名约定(例如 `pages.feature.new_text`)。
|
||||||
|
2. 在 HTML 中使用 `data-i18n="your.new.key"`、`data-i18n-title="your.new.key"` 或 `data-i18n-placeholder="your.new.key"` 属性。
|
||||||
|
3. 在 JavaScript 代码中,使用 `t('your.new.key', { replacements })` 函数来获取翻译文本。
|
||||||
|
|
||||||
|
## 🤝 贡献
|
||||||
|
|
||||||
|
我们欢迎并鼓励任何形式的贡献!如果您有任何功能建议、bug 报告或代码改进,请随时通过 Issues 或 Pull Requests 提交。
|
||||||
|
|
||||||
|
## 📜 许可证
|
||||||
|
|
||||||
|
Copyright © 2025 WJQSERVER
|
||||||
|
|
||||||
|
本项目 CaddyDash 在 **Mozilla Public License 2.0 (MPL 2.0)** 许可证下授权
|
||||||
|
|
@ -9,7 +9,7 @@ import (
|
||||||
"github.com/infinite-iroha/touka"
|
"github.com/infinite-iroha/touka"
|
||||||
)
|
)
|
||||||
|
|
||||||
func ApiGroup(v0 touka.IRouter, cdb *db.ConfigDB, cfg *config.Config) {
|
func ApiGroup(v0 touka.IRouter, cdb *db.ConfigDB, cfg *config.Config, version string) {
|
||||||
api := v0.Group("/api")
|
api := v0.Group("/api")
|
||||||
api.GET("/config/filenames", func(c *touka.Context) {
|
api.GET("/config/filenames", func(c *touka.Context) {
|
||||||
filenames, err := cdb.GetFileNames()
|
filenames, err := cdb.GetFileNames()
|
||||||
|
|
@ -20,6 +20,8 @@ func ApiGroup(v0 touka.IRouter, cdb *db.ConfigDB, cfg *config.Config) {
|
||||||
c.JSON(200, filenames)
|
c.JSON(200, filenames)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
api.GET("/info", infoHandle(version))
|
||||||
|
|
||||||
// 配置参数相关
|
// 配置参数相关
|
||||||
cfgr := api.Group("/config")
|
cfgr := api.Group("/config")
|
||||||
{
|
{
|
||||||
|
|
|
||||||
12
api/auth.go
12
api/auth.go
|
|
@ -20,6 +20,7 @@ var (
|
||||||
"/v0/api/auth/init": {},
|
"/v0/api/auth/init": {},
|
||||||
"/init.html": {},
|
"/init.html": {},
|
||||||
"/favicon.ico": {},
|
"/favicon.ico": {},
|
||||||
|
"/v0/api/info": {},
|
||||||
}
|
}
|
||||||
prefixMatchPaths = []string{ // 保持前缀匹配,因为数量少
|
prefixMatchPaths = []string{ // 保持前缀匹配,因为数量少
|
||||||
"/js/",
|
"/js/",
|
||||||
|
|
@ -38,17 +39,18 @@ var (
|
||||||
)
|
)
|
||||||
|
|
||||||
func isPassPath(requestPath string) bool {
|
func isPassPath(requestPath string) bool {
|
||||||
// 精确匹配
|
|
||||||
if _, ok := exactMatchPaths[requestPath]; ok {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// 前缀匹配
|
// 前缀匹配
|
||||||
for _, prefix := range prefixMatchPaths {
|
for _, prefix := range prefixMatchPaths {
|
||||||
if strings.HasPrefix(requestPath, prefix) {
|
if strings.HasPrefix(requestPath, prefix) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 精确匹配
|
||||||
|
if _, ok := exactMatchPaths[requestPath]; ok {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
33
api/info.go
Normal file
33
api/info.go
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"runtime/debug"
|
||||||
|
|
||||||
|
"github.com/infinite-iroha/touka"
|
||||||
|
)
|
||||||
|
|
||||||
|
type InfoApiStruct struct {
|
||||||
|
Version string `json:"version"`
|
||||||
|
License string `json:"license"`
|
||||||
|
Author []string `json:"author"`
|
||||||
|
BuildVersion string `json:"build_version"`
|
||||||
|
GoVersion string `json:"go_version"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func infoHandle(version string) touka.HandlerFunc {
|
||||||
|
return func(c *touka.Context) {
|
||||||
|
buildinfo, ok := debug.ReadBuildInfo()
|
||||||
|
if !ok {
|
||||||
|
c.JSON(500, touka.H{"error": "no build info"})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.JSON(200, InfoApiStruct{
|
||||||
|
Version: version,
|
||||||
|
License: "Mozilla Public License 2.0",
|
||||||
|
//Author: "WJQSERVER",
|
||||||
|
Author: []string{"WJQSERVER"},
|
||||||
|
BuildVersion: buildinfo.Main.Version,
|
||||||
|
GoVersion: buildinfo.GoVersion,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
4
go.mod
4
go.mod
|
|
@ -7,7 +7,7 @@ require (
|
||||||
github.com/fenthope/compress v0.0.3
|
github.com/fenthope/compress v0.0.3
|
||||||
github.com/fenthope/record v0.0.3
|
github.com/fenthope/record v0.0.3
|
||||||
github.com/fenthope/sessions v0.0.1
|
github.com/fenthope/sessions v0.0.1
|
||||||
github.com/infinite-iroha/touka v0.2.2
|
github.com/infinite-iroha/touka v0.2.8
|
||||||
github.com/klauspost/compress v1.18.0
|
github.com/klauspost/compress v1.18.0
|
||||||
golang.org/x/crypto v0.39.0
|
golang.org/x/crypto v0.39.0
|
||||||
modernc.org/sqlite v1.38.0
|
modernc.org/sqlite v1.38.0
|
||||||
|
|
@ -34,4 +34,4 @@ require (
|
||||||
modernc.org/memory v1.11.0 // indirect
|
modernc.org/memory v1.11.0 // indirect
|
||||||
)
|
)
|
||||||
|
|
||||||
replace github.com/infinite-iroha/touka => /data/github/WJQSERVER/touka
|
//replace github.com/infinite-iroha/touka => /data/github/WJQSERVER/touka
|
||||||
|
|
|
||||||
2
go.sum
2
go.sum
|
|
@ -28,6 +28,8 @@ github.com/gorilla/securecookie v1.1.2 h1:YCIWL56dvtr73r6715mJs5ZvhtnY73hBvEF8kX
|
||||||
github.com/gorilla/securecookie v1.1.2/go.mod h1:NfCASbcHqRSY+3a8tlWJwsQap2VX5pwzwo4h3eOamfo=
|
github.com/gorilla/securecookie v1.1.2/go.mod h1:NfCASbcHqRSY+3a8tlWJwsQap2VX5pwzwo4h3eOamfo=
|
||||||
github.com/gorilla/sessions v1.4.0 h1:kpIYOp/oi6MG/p5PgxApU8srsSw9tuFbt46Lt7auzqQ=
|
github.com/gorilla/sessions v1.4.0 h1:kpIYOp/oi6MG/p5PgxApU8srsSw9tuFbt46Lt7auzqQ=
|
||||||
github.com/gorilla/sessions v1.4.0/go.mod h1:FLWm50oby91+hl7p/wRxDth9bWSuk0qVL2emc7lT5ik=
|
github.com/gorilla/sessions v1.4.0/go.mod h1:FLWm50oby91+hl7p/wRxDth9bWSuk0qVL2emc7lT5ik=
|
||||||
|
github.com/infinite-iroha/touka v0.2.8 h1:PH4oR0fUjNr6t+Q3xkpqK+Q+kOFk7LN3xvy81xydu7Y=
|
||||||
|
github.com/infinite-iroha/touka v0.2.8/go.mod h1:e2LRc8FoSU8qjxSlyh3J8gGsBGKQ2VN9bQMU4sIrqnE=
|
||||||
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
|
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
|
||||||
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
|
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
|
||||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||||
|
|
|
||||||
0
licenses/about.md
Normal file
0
licenses/about.md
Normal file
3
main.go
3
main.go
|
|
@ -29,6 +29,7 @@ var (
|
||||||
cfgfile string
|
cfgfile string
|
||||||
cdb *db.ConfigDB
|
cdb *db.ConfigDB
|
||||||
sessionKey []byte
|
sessionKey []byte
|
||||||
|
version string
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
|
@ -161,7 +162,7 @@ func main() {
|
||||||
r.Use(api.SessionMiddleware(cdb))
|
r.Use(api.SessionMiddleware(cdb))
|
||||||
|
|
||||||
v0 := r.Group("/v0")
|
v0 := r.Group("/v0")
|
||||||
api.ApiGroup(v0, cdb, cfg)
|
api.ApiGroup(v0, cdb, cfg, version)
|
||||||
|
|
||||||
gob.Register(map[string]interface{}{})
|
gob.Register(map[string]interface{}{})
|
||||||
gob.Register(time.Time{})
|
gob.Register(time.Time{})
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue