mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2026-10-09 16:00:29 +00:00
Compare commits
194
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
79eb0288b4 | ||
|
|
99775e1eb4 | ||
|
|
db848b41d2 | ||
|
|
b5b11dff86 | ||
|
|
9cf4bfc606 | ||
|
|
221162d44f | ||
|
|
617970a1f8 | ||
|
|
5610c73d67 | ||
|
|
51fe02661f | ||
|
|
8f491b2933 | ||
|
|
b7e16bd6d5 | ||
|
|
38ca2ddd01 | ||
|
|
402b41100b | ||
|
|
766beae4e1 | ||
|
|
05f72e9dcf | ||
|
|
23553c68ae | ||
|
|
4dd1eb7a1e | ||
|
|
db307732c6 | ||
|
|
33d4ade1d4 | ||
|
|
186075ff9a | ||
|
|
34df745d1c | ||
|
|
ec363ac157 | ||
|
|
193b0f3cd4 | ||
|
|
67c1bf2924 | ||
|
|
b1373ff77e | ||
|
|
55d0e27212 | ||
|
|
1c052b7c13 | ||
|
|
6c8d48c2dc | ||
|
|
b61dae638b | ||
|
|
872a93aa07 | ||
|
|
b1f337020c | ||
|
|
56858dd74c | ||
|
|
358415f737 | ||
|
|
5e73260103 | ||
|
|
e169f46784 | ||
|
|
39416abd47 | ||
|
|
640a0ca815 | ||
|
|
8e54cd5162 | ||
|
|
0f0099accb | ||
|
|
718ebeb203 | ||
|
|
4101bf691d | ||
|
|
a97deb3dca | ||
|
|
10203d5c0c | ||
|
|
a357d6697d | ||
|
|
555b0aa999 | ||
|
|
6dd0dbe2c3 | ||
|
|
c31bbae768 | ||
|
|
2bb0f15973 | ||
|
|
be229551e3 | ||
|
|
6283eb4c69 | ||
|
|
c329fb6599 | ||
|
|
c3685f6b74 | ||
|
|
f4f5a36475 | ||
|
|
ea1261b48e | ||
|
|
0c68f16a66 | ||
|
|
33e5c9230f | ||
|
|
96eefab36f | ||
|
|
b0b6bf458f | ||
|
|
f3d85d1309 | ||
|
|
39385ea0a0 | ||
|
|
e492c6573c | ||
|
|
10a7fb3be2 | ||
|
|
8bc7cfade3 | ||
|
|
ea044d6c32 | ||
|
|
f6ee3dc75b | ||
|
|
367a74503f | ||
|
|
53b1a7af4c | ||
|
|
078d7fbe1e | ||
|
|
c709e48ceb | ||
|
|
0741f60896 | ||
|
|
af8eef4a91 | ||
|
|
f233ef7069 | ||
|
|
1c199bd3d7 | ||
|
|
036c973fec | ||
|
|
8bb225d272 | ||
|
|
ab932ae154 | ||
|
|
89f969ec6e | ||
|
|
afa8cf22b1 | ||
|
|
67aa8471dc | ||
|
|
0617b81b3b | ||
|
|
98c535a12c | ||
|
|
ec46518936 | ||
|
|
a7b034387f | ||
|
|
7905dd00a6 | ||
|
|
74583aa1aa | ||
|
|
4be9d71edf | ||
|
|
57bfc38eb8 | ||
|
|
aaaa5980b5 | ||
|
|
4f57dfc76e | ||
|
|
2c31ffc66b | ||
|
|
b104a13b71 | ||
|
|
28633d2fef | ||
|
|
9052386c83 | ||
|
|
7bc45f2d77 | ||
|
|
2ef6ecb951 | ||
|
|
ca0dc71338 | ||
|
|
04a1ec9a9a | ||
|
|
999e5a779a | ||
|
|
99f62b7230 | ||
|
|
4dee4e1cc2 | ||
|
|
539addc656 | ||
|
|
1a35b307fa | ||
|
|
a04f4a8b96 | ||
|
|
6b88e1adf2 | ||
|
|
99bc8177d4 | ||
|
|
cf2a1372f2 | ||
|
|
42c30f324a | ||
|
|
dab83fee20 | ||
|
|
6f3c5586fc | ||
|
|
aab8df6abc | ||
|
|
b9be79b05a | ||
|
|
ec3024f2c3 | ||
|
|
070f61e229 | ||
|
|
a82a4ebfc5 | ||
|
|
87009ddb27 | ||
|
|
3650ff27b3 | ||
|
|
6c08a3114a | ||
|
|
381cb61185 | ||
|
|
8d69da7702 | ||
|
|
8922395fdc | ||
|
|
83db40e261 | ||
|
|
95ec6c62ef | ||
|
|
56fc9ea428 | ||
|
|
88c6fc050b | ||
|
|
2392f91567 | ||
|
|
5f0c740eb0 | ||
|
|
120d0dd7c6 | ||
|
|
2844f6db7f | ||
|
|
570074f92d | ||
|
|
a13047c855 | ||
|
|
ca0d24bf56 | ||
|
|
2b18251360 | ||
|
|
f7c875acda | ||
|
|
a291a50c9f | ||
|
|
5bc7bc6aac | ||
|
|
9c376300ff | ||
|
|
5187b20252 | ||
|
|
fc401ffd8f | ||
|
|
667ee5256e | ||
|
|
f8356de93c | ||
|
|
55bb997d51 | ||
|
|
7c46f54e15 | ||
|
|
6dbb6d2247 | ||
|
|
9d0ae45edc | ||
|
|
b467dfa3b2 | ||
|
|
c13387bc70 | ||
|
|
41b2523750 | ||
|
|
afe82bd4be | ||
|
|
0f296fb70b | ||
|
|
d96ccd06a3 | ||
|
|
14095affa9 | ||
|
|
ed60565bc9 | ||
|
|
8313912c4f | ||
|
|
6274015d06 | ||
|
|
d195ce9155 | ||
|
|
cd0cd8a152 | ||
|
|
1f45ed6b06 | ||
|
|
7f6ad89edf | ||
|
|
5cdea288e2 | ||
|
|
e56feaf826 | ||
|
|
1288a09647 | ||
|
|
0cdaafa1c0 | ||
|
|
0b3334253c | ||
|
|
10f72f12d2 | ||
|
|
01643b2816 | ||
|
|
56e0da4fe3 | ||
|
|
144c397bf4 | ||
|
|
e06541984f | ||
|
|
ea7e92db84 | ||
|
|
8d48640c1d | ||
|
|
cfe5cb4b6b | ||
|
|
05c4d7dd38 | ||
|
|
13c6e0df99 | ||
|
|
dafd6ba71e | ||
|
|
2751c37716 | ||
|
|
50c01762e7 | ||
|
|
a77ebd3eb6 | ||
|
|
d84f0b5597 | ||
|
|
a3cdf87ea2 | ||
|
|
8ab3c16b3d | ||
|
|
18e943fd06 | ||
|
|
3b7a067dda | ||
|
|
4636ba815b | ||
|
|
317fad2a28 | ||
|
|
0ae28a1dd9 | ||
|
|
bbfe5f1d96 | ||
|
|
b713f20b66 | ||
|
|
3eb7a5adc5 | ||
|
|
956af78749 | ||
|
|
69ad01687e | ||
|
|
e83d07e88e | ||
|
|
6683696032 | ||
|
|
3396a5ffea | ||
|
|
18a14d3b75 |
+1
-1
@@ -33,7 +33,7 @@ builds:
|
||||
- s390x
|
||||
|
||||
archives:
|
||||
- format: tar.gz
|
||||
- formats: [ 'tar.gz' ]
|
||||
name_template: "1panel-v{{ .Version }}-{{ .Os }}-{{ .Arch }}{{- if .Arm }}v{{ .Arm }}{{ end }}"
|
||||
wrap_in_directory: true
|
||||
files:
|
||||
|
||||
+1
-1
@@ -10,7 +10,7 @@ PR are always welcome, even if they only contain small fixes like typos or a few
|
||||
|
||||
Please submit a PR broken down into small changes bit by bit. A PR consisting of a lot of features and code changes may be hard to review. It is recommended to submit PRs in an incremental fashion.
|
||||
|
||||
This [development guideline](https://docs.1panel.hk/dev_manual/dev_manual/) contains information about repository structure, how to set up development environment, how to run it, and more.
|
||||
This [development guideline](https://docs.1panel.pro/dev_manual/dev_manual/) contains information about repository structure, how to set up development environment, how to run it, and more.
|
||||
|
||||
Note: If you split your pull request to small changes, please make sure any of the changes goes to master will not break anything. Otherwise, it can not be merged until this feature complete.
|
||||
|
||||
|
||||
@@ -1,22 +1,39 @@
|
||||
<p align="center"><a href="https://1panel.hk"><img src="https://resource.1panel.hk/img/1panel-logo.png" alt="1Panel" width="300" /></a></p>
|
||||
<p align="center"><b>Top-Rated Web-based Linux Server Management Tool</b></p>
|
||||
<p align="center"><a href="https://1panel.pro"><img src="https://resource.1panel.pro/img/1panel-logo.png" alt="1Panel" width="300" /></a></p>
|
||||
<p align="center"><b>Top-Rated Web-based Linux Server Management Tool</b><br>Best VPS control panel<br>新一代的 Linux 服务器运维管理面板</p>
|
||||
<p align="center">
|
||||
<a href="https://trendshift.io/repositories/2462" target="_blank"><img src="https://trendshift.io/api/badge/repositories/2462" alt="1Panel-dev%2F1Panel | Trendshift" style="width: 180px; height: auto;" /></a>
|
||||
<a href="https://www.producthunt.com/posts/1panel?embed=true&utm_source=badge-featured&utm_medium=badge&utm_souce=badge-1panel" target="_blank"><img src="https://api.producthunt.com/widgets/embed-image/v1/featured.svg?post_id=639696&theme=light" alt="1Panel - Top-Rated web-based Linux server management tool | Product Hunt" style="width: 180px; height: auto;" /></a>
|
||||
<a href="https://trendshift.io/repositories/2462" target="_blank"><img src="https://trendshift.io/api/badge/repositories/2462" alt="1Panel-dev%2F1Panel | Trendshift" style="width: 240px; height: auto;" /></a>
|
||||
</p>
|
||||
<p align="center">
|
||||
<a href="https://www.gnu.org/licenses/gpl-3.0.html"><img src="https://shields.io/github/license/1Panel-dev/1Panel?color=%231890FF" alt="License: GPL v3"></a>
|
||||
<a href="https://app.codacy.com/gh/1Panel-dev/1Panel?utm_source=github.com&utm_medium=referral&utm_content=1Panel-dev/1Panel&utm_campaign=Badge_Grade_Dashboard"><img src="https://app.codacy.com/project/badge/Grade/da67574fd82b473992781d1386b937ef" alt="Codacy"></a>
|
||||
<a href="https://discord.gg/bUpUqWqdRr" target="_blank">
|
||||
<img src="https://img.shields.io/discord/1318846410149335080?logo=discord&labelColor=%20%235462eb&logoColor=%20%23f5f5f5&color=%20%235462eb"
|
||||
alt="chat on Discord"></a>
|
||||
<a href="https://github.com/1Panel-dev/1Panel/releases"><img src="https://img.shields.io/github/v/release/1Panel-dev/1Panel" alt="GitHub release"></a>
|
||||
<a href="https://github.com/1Panel-dev/1Panel"><img src="https://img.shields.io/github/stars/1Panel-dev/1Panel?color=%231890FF&style=flat-square" alt="Stars"></a><br>
|
||||
[<a href="/README.md">English</a>] | [<a href="/docs/README.zh-Hans.md">中文(简体)</a>] | [<a href="/docs/README.zh-Hant.md">中文(繁體)</a>] | [<a href="/docs/README.ja.md">日本語</a>] | [<a href="/docs/README.pt-br.md">Português (Brasil)</a>] | [<a href="/docs/README.ko.md">한국어</a>]| [<a href="/docs/README.id.md">Bahasa Indonesia</a>]
|
||||
</p>
|
||||
<p align="center">
|
||||
<a href="/README.md"><img alt="English" src="https://img.shields.io/badge/English-d9d9d9"></a>
|
||||
<a href="/docs/README.zh-Hans.md"><img alt="中文(简体)" src="https://img.shields.io/badge/中文(简体)-d9d9d9"></a>
|
||||
<a href="/docs/README.ja.md"><img alt="日本語" src="https://img.shields.io/badge/日本語-d9d9d9"></a>
|
||||
<a href="/docs/README.pt-br.md"><img alt="Português (Brasil)" src="https://img.shields.io/badge/Português (Brasil)-d9d9d9"></a>
|
||||
<a href="/docs/README.ar.md"><img alt="العربية" src="https://img.shields.io/badge/العربية-d9d9d9"></a>
|
||||
<a href="/docs/README.de.md"><img alt="Deutsch" src="https://img.shields.io/badge/Deutsch-d9d9d9"></a>
|
||||
<a href="/docs/README.es.md"><img alt="Español" src="https://img.shields.io/badge/Español-d9d9d9"></a><br>
|
||||
<a href="/docs/README.fr.md"><img alt="français" src="https://img.shields.io/badge/français-d9d9d9"></a>
|
||||
<a href="/docs/README.ko.md"><img alt="한국어" src="https://img.shields.io/badge/한국어-d9d9d9"></a>
|
||||
<a href="/docs/README.id.md"><img alt="Bahasa Indonesia" src="https://img.shields.io/badge/Bahasa Indonesia-d9d9d9"></a>
|
||||
<a href="/docs/README.zh-Hant.md"><img alt="中文(繁體)" src="https://img.shields.io/badge/中文(繁體)-d9d9d9"></a>
|
||||
<a href="/docs/README.tr.md"><img alt="Türkçe" src="https://img.shields.io/badge/Türkçe-d9d9d9"></a>
|
||||
<a href="/docs/README.ru.md"><img alt="Русский" src="https://img.shields.io/badge/%D0%A0%D1%83%D1%81%D1%81%D0%BA%D0%B8%D0%B9-d9d9d9"></a>
|
||||
<a href="/docs/README.ms.md"><img alt="Bahasa Melayu" src="https://img.shields.io/badge/Bahasa Melayu-d9d9d9"></a>
|
||||
</p>
|
||||
|
||||
------------------------------
|
||||
|
||||
1Panel is an open-source, modern web-based control panel for Linux server management.
|
||||
|
||||
- **Efficient Management**: Through a user-friendly web graphical interface, 1Panel enables users to effortlessly manage their Linux servers. Key features include host monitoring, file management, database administration, and container management.
|
||||
- **Efficient Management**: Through a user-friendly web graphical interface, 1Panel enables users to effortlessly manage their Linux servers. Key features include host monitoring, file management, database administration, container management, LLMs management.
|
||||
- **Rapid Website Deployment**: With deep integration of the popular open-source website building software WordPress, 1Panel streamlines the process of domain binding and SSL certificate configuration, all achievable with just one click.
|
||||
- **Application Store**: 1Panel curates a wide range of high-quality open-source tools and applications, facilitating easy installation and updates for its users.
|
||||
- **Security and Reliability**: By leveraging containerization and secure application deployment practices, 1Panel minimizes vulnerability exposure. It further enhances security through integrated firewall management and log auditing capabilities.
|
||||
@@ -27,22 +44,30 @@
|
||||
Execute the script below and follow the prompts to install 1Panel:
|
||||
|
||||
```bash
|
||||
curl -sSL https://resource.1panel.hk/quick_start.sh -o quick_start.sh && bash quick_start.sh
|
||||
curl -sSL https://resource.1panel.pro/quick_start.sh -o quick_start.sh && bash quick_start.sh
|
||||
```
|
||||
|
||||
Please refer to our [documentation](https://docs.1panel.hk/quick_start/) for more details.
|
||||
Please refer to our [documentation](https://docs.1panel.pro/quick_start/) for more details.
|
||||
|
||||
中国用户请使用这个 [安装脚本](https://1panel.cn/docs/installation/online_installation/),其应用数量比国际版本更丰富。
|
||||
|
||||
## Screenshot
|
||||
|
||||

|
||||

|
||||
|
||||
## Star History
|
||||
|
||||
[](https://star-history.com/#1Panel-dev/1Panel&Date)
|
||||
|
||||
## Pro Edition
|
||||
|
||||
Compared to the OSS Edition, 1Panel Pro Edition provides users with a wealth of enhanced features and technical support services. Enhanced features include WAF enhancement, Website monitoring, Mobile APP, custom logo and theme, etc.
|
||||
|
||||
[Click to see Pro Edition details](https://1panel.pro/pricing).
|
||||
|
||||
## Security Information
|
||||
|
||||
If you discover any security issues, please contact us through: wanghe@fit2cloud.com.
|
||||
If you discover any security issues, please refer to [SECURITY.md](/SECURITY.md).
|
||||
|
||||
## License
|
||||
|
||||
|
||||
@@ -0,0 +1,257 @@
|
||||
package v1
|
||||
|
||||
import (
|
||||
"github.com/1Panel-dev/1Panel/backend/app/api/v1/helper"
|
||||
"github.com/1Panel-dev/1Panel/backend/app/dto"
|
||||
"github.com/1Panel-dev/1Panel/backend/constant"
|
||||
"github.com/1Panel-dev/1Panel/backend/utils/ai_tools/gpu"
|
||||
"github.com/1Panel-dev/1Panel/backend/utils/ai_tools/gpu/common"
|
||||
"github.com/1Panel-dev/1Panel/backend/utils/ai_tools/xpu"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// @Tags AI
|
||||
// @Summary Create Ollama model
|
||||
// @Accept json
|
||||
// @Param request body dto.OllamaModelName true "request"
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /ai/ollama/model [post]
|
||||
// @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"添加 Ollama 模型 [name]","formatEN":"add Ollama model [name]"}
|
||||
func (b *BaseApi) CreateOllamaModel(c *gin.Context) {
|
||||
var req dto.OllamaModelName
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if err := AIToolService.Create(req.Name); err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
return
|
||||
}
|
||||
helper.SuccessWithData(c, nil)
|
||||
}
|
||||
|
||||
// @Tags AI
|
||||
// @Summary Rereate Ollama model
|
||||
// @Accept json
|
||||
// @Param request body dto.OllamaModelName true "request"
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /ai/ollama/model/recreate [post]
|
||||
// @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"添加 Ollama 模型重试 [name]","formatEN":"re-add Ollama model [name]"}
|
||||
func (b *BaseApi) RecreateOllamaModel(c *gin.Context) {
|
||||
var req dto.OllamaModelName
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if err := AIToolService.Recreate(req.Name); err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
return
|
||||
}
|
||||
helper.SuccessWithData(c, nil)
|
||||
}
|
||||
|
||||
// @Tags AI
|
||||
// @Summary Close Ollama model conn
|
||||
// @Accept json
|
||||
// @Param request body dto.OllamaModelName true "request"
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /ai/ollama/model/close [post]
|
||||
// @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"关闭 Ollama 模型连接 [name]","formatEN":"close conn for Ollama model [name]"}
|
||||
func (b *BaseApi) CloseOllamaModel(c *gin.Context) {
|
||||
var req dto.OllamaModelName
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if err := AIToolService.Close(req.Name); err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
return
|
||||
}
|
||||
helper.SuccessWithData(c, nil)
|
||||
}
|
||||
|
||||
// @Tags AI
|
||||
// @Summary Sync Ollama model list
|
||||
// @Success 200 {array} dto.OllamaModelDropList
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /ai/ollama/model/sync [post]
|
||||
// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"同步 Ollama 模型列表","formatEN":"sync Ollama model list"}
|
||||
func (b *BaseApi) SyncOllamaModel(c *gin.Context) {
|
||||
list, err := AIToolService.Sync()
|
||||
if err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
return
|
||||
}
|
||||
helper.SuccessWithData(c, list)
|
||||
}
|
||||
|
||||
// @Tags AI
|
||||
// @Summary Page Ollama models
|
||||
// @Accept json
|
||||
// @Param request body dto.SearchWithPage true "request"
|
||||
// @Success 200 {object} dto.PageResult
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /ai/ollama/model/search [post]
|
||||
func (b *BaseApi) SearchOllamaModel(c *gin.Context) {
|
||||
var req dto.SearchWithPage
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
total, list, err := AIToolService.Search(req)
|
||||
if err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
return
|
||||
}
|
||||
|
||||
helper.SuccessWithData(c, dto.PageResult{
|
||||
Items: list,
|
||||
Total: total,
|
||||
})
|
||||
}
|
||||
|
||||
// @Tags AI
|
||||
// @Summary Page Ollama models
|
||||
// @Accept json
|
||||
// @Param request body dto.OllamaModelName true "request"
|
||||
// @Success 200 {string} details
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /ai/ollama/model/load [post]
|
||||
func (b *BaseApi) LoadOllamaModelDetail(c *gin.Context) {
|
||||
var req dto.OllamaModelName
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
detail, err := AIToolService.LoadDetail(req.Name)
|
||||
if err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
return
|
||||
}
|
||||
|
||||
helper.SuccessWithData(c, detail)
|
||||
}
|
||||
|
||||
// @Tags AI
|
||||
// @Summary Delete Ollama model
|
||||
// @Accept json
|
||||
// @Param request body dto.ForceDelete true "request"
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /ai/ollama/model/del [post]
|
||||
// @x-panel-log {"bodyKeys":["ids"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"ids","isList":true,"db":"ollama_models","output_column":"name","output_value":"names"}],"formatZH":"删除 Ollama 模型 [names]","formatEN":"remove Ollama model [names]"}
|
||||
func (b *BaseApi) DeleteOllamaModel(c *gin.Context) {
|
||||
var req dto.ForceDelete
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if err := AIToolService.Delete(req); err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
return
|
||||
}
|
||||
|
||||
helper.SuccessWithOutData(c)
|
||||
}
|
||||
|
||||
// @Tags AI
|
||||
// @Summary Load gpu / xpu info
|
||||
// @Accept json
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /ai/gpu/load [get]
|
||||
func (b *BaseApi) LoadGpuInfo(c *gin.Context) {
|
||||
ok, client := gpu.New()
|
||||
if ok {
|
||||
info, err := client.LoadGpuInfo()
|
||||
if err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
return
|
||||
}
|
||||
helper.SuccessWithData(c, info)
|
||||
return
|
||||
}
|
||||
xpuOK, xpuClient := xpu.New()
|
||||
if xpuOK {
|
||||
info, err := xpuClient.LoadGpuInfo()
|
||||
if err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
return
|
||||
}
|
||||
helper.SuccessWithData(c, info)
|
||||
return
|
||||
}
|
||||
helper.SuccessWithData(c, &common.GpuInfo{})
|
||||
}
|
||||
|
||||
// @Tags AI
|
||||
// @Summary Bind domain
|
||||
// @Accept json
|
||||
// @Param request body dto.OllamaBindDomain true "request"
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /ai/domain/bind [post]
|
||||
func (b *BaseApi) BindDomain(c *gin.Context) {
|
||||
var req dto.OllamaBindDomain
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
return
|
||||
}
|
||||
if err := AIToolService.BindDomain(req); err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
return
|
||||
}
|
||||
helper.SuccessWithOutData(c)
|
||||
}
|
||||
|
||||
// @Tags AI
|
||||
// @Summary Get bind domain
|
||||
// @Accept json
|
||||
// @Param request body dto.OllamaBindDomainReq true "request"
|
||||
// @Success 200 {object} dto.OllamaBindDomainRes
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /ai/domain/get [post]
|
||||
func (b *BaseApi) GetBindDomain(c *gin.Context) {
|
||||
var req dto.OllamaBindDomainReq
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
return
|
||||
}
|
||||
res, err := AIToolService.GetBindDomain(req)
|
||||
if err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
return
|
||||
}
|
||||
helper.SuccessWithData(c, res)
|
||||
}
|
||||
|
||||
// Tags AI
|
||||
// Summary Update bind domain
|
||||
// Accept json
|
||||
// Param request body dto.OllamaBindDomain true "request"
|
||||
// Success 200
|
||||
// Security ApiKeyAuth
|
||||
// Security Timestamp
|
||||
// Router /ai/domain/update [post]
|
||||
func (b *BaseApi) UpdateBindDomain(c *gin.Context) {
|
||||
var req dto.OllamaBindDomain
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
return
|
||||
}
|
||||
if err := AIToolService.UpdateBindDomain(req); err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
return
|
||||
}
|
||||
helper.SuccessWithOutData(c)
|
||||
}
|
||||
+10
-10
@@ -13,7 +13,7 @@ import (
|
||||
// @Summary List apps
|
||||
// @Accept json
|
||||
// @Param request body request.AppSearch true "request"
|
||||
// @Success 200
|
||||
// @Success 200 {object} response.AppRes
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /apps/search [post]
|
||||
@@ -22,7 +22,7 @@ func (b *BaseApi) SearchApp(c *gin.Context) {
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
return
|
||||
}
|
||||
list, err := appService.PageApp(req)
|
||||
list, err := appService.PageApp(c, req)
|
||||
if err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
return
|
||||
@@ -68,14 +68,14 @@ func (b *BaseApi) SyncApp(c *gin.Context) {
|
||||
// @Success 200 {object} response.AppDTO
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /apps/:key [get]
|
||||
// @Router /apps/{key} [get]
|
||||
func (b *BaseApi) GetApp(c *gin.Context) {
|
||||
appKey, err := helper.GetStrParamByKey(c, "key")
|
||||
if err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||
return
|
||||
}
|
||||
appDTO, err := appService.GetApp(appKey)
|
||||
appDTO, err := appService.GetApp(c, appKey)
|
||||
if err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
return
|
||||
@@ -88,11 +88,11 @@ func (b *BaseApi) GetApp(c *gin.Context) {
|
||||
// @Accept json
|
||||
// @Param appId path integer true "app id"
|
||||
// @Param version path string true "app version"
|
||||
// @Param version path string true "app type"
|
||||
// @Param type path string true "app type"
|
||||
// @Success 200 {object} response.AppDetailDTO
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /apps/detail/:appId/:version/:type [get]
|
||||
// @Router /apps/detail/{appId}/{version}/{type} [get]
|
||||
func (b *BaseApi) GetAppDetail(c *gin.Context) {
|
||||
appID, err := helper.GetIntParamByKey(c, "appId")
|
||||
if err != nil {
|
||||
@@ -112,11 +112,11 @@ func (b *BaseApi) GetAppDetail(c *gin.Context) {
|
||||
// @Tags App
|
||||
// @Summary Get app detail by id
|
||||
// @Accept json
|
||||
// @Param appId path integer true "id"
|
||||
// @Param id path integer true "id"
|
||||
// @Success 200 {object} response.AppDetailDTO
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /apps/details/:id [get]
|
||||
// @Router /apps/details/{id} [get]
|
||||
func (b *BaseApi) GetAppDetailByID(c *gin.Context) {
|
||||
appDetailID, err := helper.GetIntParamByKey(c, "id")
|
||||
if err != nil {
|
||||
@@ -173,7 +173,7 @@ func (b *BaseApi) InstallApp(c *gin.Context) {
|
||||
}
|
||||
|
||||
func (b *BaseApi) GetAppTags(c *gin.Context) {
|
||||
tags, err := appService.GetAppTags()
|
||||
tags, err := appService.GetAppTags(c)
|
||||
if err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
return
|
||||
@@ -183,7 +183,7 @@ func (b *BaseApi) GetAppTags(c *gin.Context) {
|
||||
|
||||
// @Tags App
|
||||
// @Summary Get app list update
|
||||
// @Success 200
|
||||
// @Success 200 {object} response.AppUpdateRes
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /apps/checkupdate [get]
|
||||
|
||||
@@ -13,7 +13,7 @@ import (
|
||||
// @Summary Page app installed
|
||||
// @Accept json
|
||||
// @Param request body request.AppInstalledSearch true "request"
|
||||
// @Success 200
|
||||
// @Success 200 {object} dto.PageResult
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /apps/installed/search [post]
|
||||
@@ -28,7 +28,10 @@ func (b *BaseApi) SearchAppInstalled(c *gin.Context) {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
return
|
||||
}
|
||||
helper.SuccessWithData(c, list)
|
||||
helper.SuccessWithData(c, dto.PageResult{
|
||||
Items: list,
|
||||
Total: int64(len(list)),
|
||||
})
|
||||
} else {
|
||||
total, list, err := appInstallService.Page(req)
|
||||
if err != nil {
|
||||
@@ -45,7 +48,7 @@ func (b *BaseApi) SearchAppInstalled(c *gin.Context) {
|
||||
// @Tags App
|
||||
// @Summary List app installed
|
||||
// @Accept json
|
||||
// @Success 200 array dto.AppInstallInfo
|
||||
// @Success 200 {array} dto.AppInstallInfo
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /apps/installed/list [get]
|
||||
@@ -104,10 +107,11 @@ func (b *BaseApi) LoadPort(c *gin.Context) {
|
||||
// @Summary Search app password by key
|
||||
// @Accept json
|
||||
// @Param request body dto.OperationWithNameAndType true "request"
|
||||
// @Success 200 {string} response.DatabaseConn
|
||||
// @Param key path string true "key"
|
||||
// @Success 200 {object} response.DatabaseConn
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /apps/installed/conninfo/:key [get]
|
||||
// @Router /apps/installed/conninfo/{key} [get]
|
||||
func (b *BaseApi) LoadConnInfo(c *gin.Context) {
|
||||
var req dto.OperationWithNameAndType
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
@@ -128,7 +132,7 @@ func (b *BaseApi) LoadConnInfo(c *gin.Context) {
|
||||
// @Success 200 {array} dto.AppResource
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /apps/installed/delete/check/:appInstallId [get]
|
||||
// @Router /apps/installed/delete/check/{appInstallId} [get]
|
||||
func (b *BaseApi) DeleteCheck(c *gin.Context) {
|
||||
appInstallId, err := helper.GetIntParamByKey(c, "appInstallId")
|
||||
if err != nil {
|
||||
@@ -187,7 +191,7 @@ func (b *BaseApi) OperateInstalled(c *gin.Context) {
|
||||
// @Success 200 {array} response.AppService
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /apps/services/:key [get]
|
||||
// @Router /apps/services/{key} [get]
|
||||
func (b *BaseApi) GetServices(c *gin.Context) {
|
||||
key := c.Param("key")
|
||||
services, err := appInstallService.GetServices(key)
|
||||
@@ -201,7 +205,6 @@ func (b *BaseApi) GetServices(c *gin.Context) {
|
||||
// @Tags App
|
||||
// @Summary Search app update version by install id
|
||||
// @Accept json
|
||||
// @Param appInstallId path integer true "request"
|
||||
// @Success 200 {array} dto.AppVersion
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
@@ -266,10 +269,10 @@ func (b *BaseApi) GetDefaultConfig(c *gin.Context) {
|
||||
// @Summary Search params by appInstallId
|
||||
// @Accept json
|
||||
// @Param appInstallId path string true "request"
|
||||
// @Success 200 {object} response.AppParam
|
||||
// @Success 200 {object} response.AppConfig
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /apps/installed/params/:appInstallId [get]
|
||||
// @Router /apps/installed/params/{appInstallId} [get]
|
||||
func (b *BaseApi) GetParams(c *gin.Context) {
|
||||
appInstallId, err := helper.GetIntParamByKey(c, "appInstallId")
|
||||
if err != nil {
|
||||
|
||||
@@ -8,8 +8,6 @@ import (
|
||||
"github.com/1Panel-dev/1Panel/backend/constant"
|
||||
"github.com/1Panel-dev/1Panel/backend/global"
|
||||
"github.com/1Panel-dev/1Panel/backend/utils/captcha"
|
||||
"github.com/1Panel-dev/1Panel/backend/utils/common"
|
||||
"github.com/1Panel-dev/1Panel/backend/utils/geo"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
@@ -121,7 +119,7 @@ func (b *BaseApi) GetResponsePage(c *gin.Context) {
|
||||
|
||||
// @Tags Auth
|
||||
// @Summary Check System isDemo
|
||||
// @Success 200
|
||||
// @Success 200 {boolean} isDemo
|
||||
// @Router /auth/demo [get]
|
||||
func (b *BaseApi) CheckIsDemo(c *gin.Context) {
|
||||
helper.SuccessWithData(c, global.CONF.System.IsDemo)
|
||||
@@ -129,7 +127,7 @@ func (b *BaseApi) CheckIsDemo(c *gin.Context) {
|
||||
|
||||
// @Tags Auth
|
||||
// @Summary Check System isIntl
|
||||
// @Success 200
|
||||
// @Success 200 {boolean} isIntl
|
||||
// @Router /auth/intl [get]
|
||||
func (b *BaseApi) CheckIsIntl(c *gin.Context) {
|
||||
helper.SuccessWithData(c, global.CONF.System.IsIntl)
|
||||
@@ -137,7 +135,7 @@ func (b *BaseApi) CheckIsIntl(c *gin.Context) {
|
||||
|
||||
// @Tags Auth
|
||||
// @Summary Load System Language
|
||||
// @Success 200
|
||||
// @Success 200 {string} language
|
||||
// @Router /auth/language [get]
|
||||
func (b *BaseApi) GetLanguage(c *gin.Context) {
|
||||
settingInfo, err := settingService.GetSettingInfo()
|
||||
@@ -157,11 +155,6 @@ func saveLoginLogs(c *gin.Context, err error) {
|
||||
logs.Status = constant.StatusSuccess
|
||||
}
|
||||
logs.IP = c.ClientIP()
|
||||
address, err := geo.GetIPLocation(logs.IP, common.GetLang(c))
|
||||
if err != nil {
|
||||
global.LOG.Errorf("get ip location failed: %s", err)
|
||||
}
|
||||
logs.Agent = c.GetHeader("User-Agent")
|
||||
logs.Address = address
|
||||
_ = logService.CreateLoginLog(logs)
|
||||
}
|
||||
|
||||
@@ -64,7 +64,7 @@ func (b *BaseApi) RefreshOneDriveToken(c *gin.Context) {
|
||||
// @Summary List buckets
|
||||
// @Accept json
|
||||
// @Param request body dto.ForBuckets true "request"
|
||||
// @Success 200 {array} string
|
||||
// @Success 200 {array} object
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /settings/backup/search [post]
|
||||
@@ -140,7 +140,7 @@ func (b *BaseApi) DeleteBackup(c *gin.Context) {
|
||||
// @Summary Page backup records
|
||||
// @Accept json
|
||||
// @Param request body dto.RecordSearch true "request"
|
||||
// @Success 200
|
||||
// @Success 200 {object} dto.PageResult
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /settings/backup/record/search [post]
|
||||
@@ -162,11 +162,34 @@ func (b *BaseApi) SearchBackupRecords(c *gin.Context) {
|
||||
})
|
||||
}
|
||||
|
||||
// @Tags Backup Account
|
||||
// @Summary Load backup records size
|
||||
// @Accept json
|
||||
// @Param request body dto.RecordSearch true "request"
|
||||
// @Success 200 {array} dto.BackupFile
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /settings/backup/record/size [post]
|
||||
func (b *BaseApi) LoadBackupSize(c *gin.Context) {
|
||||
var req dto.RecordSearch
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
list, err := backupService.LoadSize(req)
|
||||
if err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
return
|
||||
}
|
||||
|
||||
helper.SuccessWithData(c, list)
|
||||
}
|
||||
|
||||
// @Tags Backup Account
|
||||
// @Summary Page backup records by cronjob
|
||||
// @Accept json
|
||||
// @Param request body dto.RecordSearchByCronjob true "request"
|
||||
// @Success 200
|
||||
// @Success 200 {object} dto.PageResult
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /settings/backup/record/search/bycronjob [post]
|
||||
@@ -188,11 +211,34 @@ func (b *BaseApi) SearchBackupRecordsByCronjob(c *gin.Context) {
|
||||
})
|
||||
}
|
||||
|
||||
// @Tags Backup Account
|
||||
// @Summary Load backup records size for cronjob
|
||||
// @Accept json
|
||||
// @Param request body dto.RecordSearchByCronjob true "request"
|
||||
// @Success 200 {array} dto.BackupFile
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /settings/backup/record/size/bycronjob [post]
|
||||
func (b *BaseApi) LoadBackupSizeByCronjob(c *gin.Context) {
|
||||
var req dto.RecordSearchByCronjob
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
list, err := backupService.LoadSizeByCronjob(req)
|
||||
if err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
return
|
||||
}
|
||||
|
||||
helper.SuccessWithData(c, list)
|
||||
}
|
||||
|
||||
// @Tags Backup Account
|
||||
// @Summary Download backup record
|
||||
// @Accept json
|
||||
// @Param request body dto.DownloadRecord true "request"
|
||||
// @Success 200
|
||||
// @Success 200 {string} filePath
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /settings/backup/record/download [post]
|
||||
|
||||
@@ -120,6 +120,7 @@ func (b *BaseApi) LoadClamBaseInfo(c *gin.Context) {
|
||||
// @Summary Operate Clam
|
||||
// @Accept json
|
||||
// @Param request body dto.Operate true "request"
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /toolbox/clam/operate [post]
|
||||
@@ -142,6 +143,7 @@ func (b *BaseApi) OperateClam(c *gin.Context) {
|
||||
// @Summary Clean clam record
|
||||
// @Accept json
|
||||
// @Param request body dto.OperateByID true "request"
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /toolbox/clam/record/clean [post]
|
||||
@@ -189,7 +191,7 @@ func (b *BaseApi) SearchClamRecord(c *gin.Context) {
|
||||
// @Summary Load clam record detail
|
||||
// @Accept json
|
||||
// @Param request body dto.ClamLogReq true "request"
|
||||
// @Success 200
|
||||
// @Success 200 {string} content
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /toolbox/clam/record/log [post]
|
||||
@@ -212,7 +214,7 @@ func (b *BaseApi) LoadClamRecordLog(c *gin.Context) {
|
||||
// @Summary Load clam file
|
||||
// @Accept json
|
||||
// @Param request body dto.ClamFileReq true "request"
|
||||
// @Success 200 {object} dto.PageResult
|
||||
// @Success 200 {string} content
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /toolbox/clam/file/search [post]
|
||||
|
||||
@@ -106,7 +106,7 @@ func (b *BaseApi) SearchRedisCommand(c *gin.Context) {
|
||||
// @Tags Command
|
||||
// @Summary Tree commands
|
||||
// @Accept json
|
||||
// @Success 200 {Array} dto.CommandTree
|
||||
// @Success 200 {array} dto.CommandTree
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /hosts/command/tree [get]
|
||||
@@ -122,7 +122,7 @@ func (b *BaseApi) SearchCommandTree(c *gin.Context) {
|
||||
|
||||
// @Tags Redis Command
|
||||
// @Summary List redis commands
|
||||
// @Success 200 {Array} dto.RedisCommand
|
||||
// @Success 200 {array} dto.RedisCommand
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /hosts/command/redis [get]
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
package v1
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/backend/app/api/v1/helper"
|
||||
"github.com/1Panel-dev/1Panel/backend/app/dto"
|
||||
"github.com/1Panel-dev/1Panel/backend/constant"
|
||||
"github.com/1Panel-dev/1Panel/backend/global"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/pkg/errors"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// @Tags Container
|
||||
@@ -40,7 +41,7 @@ func (b *BaseApi) SearchContainer(c *gin.Context) {
|
||||
// @Summary List containers
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Success 200
|
||||
// @Success 200 {array} string
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /containers/list [post]
|
||||
@@ -82,7 +83,7 @@ func (b *BaseApi) SearchCompose(c *gin.Context) {
|
||||
// @Summary Test compose
|
||||
// @Accept json
|
||||
// @Param request body dto.ComposeCreate true "request"
|
||||
// @Success 200
|
||||
// @Success 200 {boolean} isOK
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /containers/compose/test [post]
|
||||
@@ -105,7 +106,7 @@ func (b *BaseApi) TestCompose(c *gin.Context) {
|
||||
// @Summary Create compose
|
||||
// @Accept json
|
||||
// @Param request body dto.ComposeCreate true "request"
|
||||
// @Success 200
|
||||
// @Success 200 {string} log
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /containers/compose [post]
|
||||
@@ -311,7 +312,7 @@ func (b *BaseApi) CleanContainerLog(c *gin.Context) {
|
||||
// @Summary Load container log
|
||||
// @Accept json
|
||||
// @Param request body dto.OperationWithNameAndType true "request"
|
||||
// @Success 200
|
||||
// @Success 200 {string} content
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /containers/load/log [post]
|
||||
@@ -390,11 +391,11 @@ func (b *BaseApi) ContainerOperation(c *gin.Context) {
|
||||
|
||||
// @Tags Container
|
||||
// @Summary Container stats
|
||||
// @Param id path integer true "container id"
|
||||
// @Param id path string true "container id"
|
||||
// @Success 200 {object} dto.ContainerStats
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /containers/stats/:id [get]
|
||||
// @Router /containers/stats/{id} [get]
|
||||
func (b *BaseApi) ContainerStats(c *gin.Context) {
|
||||
containerID, ok := c.Params.Get("id")
|
||||
if !ok {
|
||||
@@ -438,6 +439,7 @@ func (b *BaseApi) Inspect(c *gin.Context) {
|
||||
// @Param since query string false "since"
|
||||
// @Param follow query string false "follow"
|
||||
// @Param tail query string false "tail"
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /containers/search/log [post]
|
||||
@@ -464,6 +466,7 @@ func (b *BaseApi) ContainerLogs(c *gin.Context) {
|
||||
// @Summary Download Container logs
|
||||
// @Accept json
|
||||
// @Param request body dto.ContainerLog true "request"
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /containers/download/log [post]
|
||||
@@ -680,6 +683,7 @@ func (b *BaseApi) ComposeUpdate(c *gin.Context) {
|
||||
// @Param since query string false "date"
|
||||
// @Param follow query string false "follow"
|
||||
// @Param tail query string false "tail"
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /containers/compose/search/log [get]
|
||||
|
||||
@@ -92,7 +92,7 @@ func (b *BaseApi) SearchJobRecords(c *gin.Context) {
|
||||
// @Summary Load Cronjob record log
|
||||
// @Accept json
|
||||
// @Param request body dto.OperateByID true "request"
|
||||
// @Success 200
|
||||
// @Success 200 {string} content
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /cronjobs/records/log [post]
|
||||
|
||||
@@ -34,7 +34,7 @@ func (b *BaseApi) LoadDashboardOsInfo(c *gin.Context) {
|
||||
// @Success 200 {object} dto.DashboardBase
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /dashboard/base/:ioOption/:netOption [get]
|
||||
// @Router /dashboard/base/{ioOption}/{netOption} [get]
|
||||
func (b *BaseApi) LoadDashboardBaseInfo(c *gin.Context) {
|
||||
ioOption, ok := c.Params.Get("ioOption")
|
||||
if !ok {
|
||||
@@ -78,7 +78,7 @@ func (b *BaseApi) LoadDashboardCurrentInfo(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /dashboard/system/restart/:operation [post]
|
||||
// @Router /dashboard/system/restart/{operation} [post]
|
||||
func (b *BaseApi) SystemRestart(c *gin.Context) {
|
||||
operation, ok := c.Params.Get("operation")
|
||||
if !ok {
|
||||
|
||||
@@ -43,7 +43,7 @@ func (b *BaseApi) CreateDatabase(c *gin.Context) {
|
||||
// @Summary Check database
|
||||
// @Accept json
|
||||
// @Param request body dto.DatabaseCreate true "request"
|
||||
// @Success 200
|
||||
// @Success 200 {boolean} isOk
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /databases/db/check [post]
|
||||
@@ -93,10 +93,11 @@ func (b *BaseApi) SearchDatabase(c *gin.Context) {
|
||||
|
||||
// @Tags Database
|
||||
// @Summary List databases
|
||||
// @Param type path string true "type"
|
||||
// @Success 200 {array} dto.DatabaseOption
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /databases/db/list/:type [get]
|
||||
// @Router /databases/db/list/{type} [get]
|
||||
func (b *BaseApi) ListDatabase(c *gin.Context) {
|
||||
dbType, err := helper.GetStrParamByKey(c, "type")
|
||||
if err != nil {
|
||||
@@ -114,10 +115,11 @@ func (b *BaseApi) ListDatabase(c *gin.Context) {
|
||||
|
||||
// @Tags Database
|
||||
// @Summary Retrieve database list based on type
|
||||
// @Param type path string true "type"
|
||||
// @Success 200 {array} dto.DatabaseItem
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /databases/db/item/:type [get]
|
||||
// @Router /databases/db/item/{type} [get]
|
||||
func (b *BaseApi) LoadDatabaseItems(c *gin.Context) {
|
||||
dbType, err := helper.GetStrParamByKey(c, "type")
|
||||
if err != nil {
|
||||
@@ -135,10 +137,11 @@ func (b *BaseApi) LoadDatabaseItems(c *gin.Context) {
|
||||
|
||||
// @Tags Database
|
||||
// @Summary Get databases
|
||||
// @Param name path string true "name"
|
||||
// @Success 200 {object} dto.DatabaseInfo
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /databases/db/:name [get]
|
||||
// @Router /databases/db/{name} [get]
|
||||
func (b *BaseApi) GetDatabase(c *gin.Context) {
|
||||
name, err := helper.GetStrParamByKey(c, "name")
|
||||
if err != nil {
|
||||
|
||||
@@ -34,7 +34,7 @@ func (b *BaseApi) LoadDBBaseInfo(c *gin.Context) {
|
||||
// @Summary Load Database conf
|
||||
// @Accept json
|
||||
// @Param request body dto.OperationWithNameAndType true "request"
|
||||
// @Success 200
|
||||
// @Success 200 {string} content
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /databases/common/load/file [post]
|
||||
|
||||
@@ -217,6 +217,7 @@ func (b *BaseApi) ListDBName(c *gin.Context) {
|
||||
// @Summary Load mysql database from remote
|
||||
// @Accept json
|
||||
// @Param request body dto.MysqlLoadDB true "request"
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /databases/load [post]
|
||||
|
||||
@@ -168,9 +168,11 @@ func (b *BaseApi) SearchPostgresql(c *gin.Context) {
|
||||
// @Summary Load postgresql database from remote
|
||||
// @Accept json
|
||||
// @Param request body dto.PostgresqlLoadDB true "request"
|
||||
// @Param database path string true "database"
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /databases/pg/:database/load [post]
|
||||
// @Router /databases/pg/{database}/load [post]
|
||||
func (b *BaseApi) LoadPostgresqlDBFromRemote(c *gin.Context) {
|
||||
database, err := helper.GetStrParamByKey(c, "database")
|
||||
if err != nil {
|
||||
|
||||
@@ -28,7 +28,7 @@ func (b *BaseApi) LoadDeviceBaseInfo(c *gin.Context) {
|
||||
// @Tags Device
|
||||
// @Summary list time zone options
|
||||
// @Accept json
|
||||
// @Success 200 {Array} string
|
||||
// @Success 200 {array} string
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /toolbox/device/zone/options [get]
|
||||
@@ -46,7 +46,7 @@ func (b *BaseApi) LoadTimeOption(c *gin.Context) {
|
||||
// @Summary load conf
|
||||
// @Accept json
|
||||
// @Param request body dto.OperationWithName true "request"
|
||||
// @Success 200
|
||||
// @Success 200 {array} string
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /toolbox/device/conf [post]
|
||||
@@ -185,7 +185,7 @@ func (b *BaseApi) UpdateDeviceSwap(c *gin.Context) {
|
||||
// @Summary Check device DNS conf
|
||||
// @Accept json
|
||||
// @Param request body dto.SettingUpdate true "request"
|
||||
// @Success 200
|
||||
// @Success 200 {boolean} data
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /toolbox/device/check/dns [post]
|
||||
@@ -206,7 +206,7 @@ func (b *BaseApi) CheckDNS(c *gin.Context) {
|
||||
|
||||
// @Tags Device
|
||||
// @Summary Scan system
|
||||
// @Success 200
|
||||
// @Success 200 {object} dto.CleanData
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /toolbox/scan [post]
|
||||
|
||||
@@ -15,6 +15,8 @@ var (
|
||||
appService = service.NewIAppService()
|
||||
appInstallService = service.NewIAppInstalledService()
|
||||
|
||||
AIToolService = service.NewIAIToolService()
|
||||
|
||||
containerService = service.NewIContainerService()
|
||||
composeTemplateService = service.NewIComposeTemplateService()
|
||||
imageRepoService = service.NewIImageRepoService()
|
||||
|
||||
@@ -29,7 +29,7 @@ func (b *BaseApi) LoadFail2BanBaseInfo(c *gin.Context) {
|
||||
// @Summary Page fail2ban ip list
|
||||
// @Accept json
|
||||
// @Param request body dto.Fail2BanSearch true "request"
|
||||
// @Success 200 {Array} string
|
||||
// @Success 200 {array} string
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /toolbox/fail2ban/search [post]
|
||||
@@ -52,6 +52,7 @@ func (b *BaseApi) SearchFail2Ban(c *gin.Context) {
|
||||
// @Summary Operate fail2ban
|
||||
// @Accept json
|
||||
// @Param request body dto.Operate true "request"
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /toolbox/fail2ban/operate [post]
|
||||
@@ -74,6 +75,7 @@ func (b *BaseApi) OperateFail2Ban(c *gin.Context) {
|
||||
// @Summary Operate sshd of fail2ban
|
||||
// @Accept json
|
||||
// @Param request body dto.Operate true "request"
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /toolbox/fail2ban/operate/sshd [post]
|
||||
@@ -116,7 +118,7 @@ func (b *BaseApi) UpdateFail2BanConf(c *gin.Context) {
|
||||
// @Tags Fail2ban
|
||||
// @Summary Load fail2ban conf
|
||||
// @Accept json
|
||||
// @Success 200
|
||||
// @Success 200 {string} file
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /toolbox/fail2ban/load/conf [get]
|
||||
|
||||
@@ -12,7 +12,7 @@ import (
|
||||
// @Summary List favorites
|
||||
// @Accept json
|
||||
// @Param request body dto.PageInfo true "request"
|
||||
// @Success 200
|
||||
// @Success 200 {object} dto.PageResult
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /files/favorite/search [post]
|
||||
@@ -36,7 +36,7 @@ func (b *BaseApi) SearchFavorite(c *gin.Context) {
|
||||
// @Summary Create favorite
|
||||
// @Accept json
|
||||
// @Param request body request.FavoriteCreate true "request"
|
||||
// @Success 200
|
||||
// @Success 200 {object} model.Favorite
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /files/favorite [post]
|
||||
|
||||
@@ -39,19 +39,19 @@ func (b *BaseApi) ListFiles(c *gin.Context) {
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
return
|
||||
}
|
||||
files, err := fileService.GetFileList(req)
|
||||
fileList, err := fileService.GetFileList(req)
|
||||
if err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
return
|
||||
}
|
||||
helper.SuccessWithData(c, files)
|
||||
helper.SuccessWithData(c, fileList)
|
||||
}
|
||||
|
||||
// @Tags File
|
||||
// @Summary Page file
|
||||
// @Accept json
|
||||
// @Param request body request.SearchUploadWithPage true "request"
|
||||
// @Success 200 {array} response.FileInfo
|
||||
// @Success 200 {object} dto.PageResult
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /files/upload/search [post]
|
||||
@@ -290,6 +290,7 @@ func (b *BaseApi) SaveContent(c *gin.Context) {
|
||||
|
||||
// @Tags File
|
||||
// @Summary Upload file
|
||||
// @Accept multipart/form-data
|
||||
// @Param file formData file true "request"
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
@@ -400,7 +401,7 @@ func (b *BaseApi) UploadFiles(c *gin.Context) {
|
||||
// @Summary Check file exist
|
||||
// @Accept json
|
||||
// @Param request body request.FilePathCheck true "request"
|
||||
// @Success 200
|
||||
// @Success 200 {boolean} isOk
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /files/check [post]
|
||||
@@ -416,6 +417,23 @@ func (b *BaseApi) CheckFile(c *gin.Context) {
|
||||
helper.SuccessWithData(c, true)
|
||||
}
|
||||
|
||||
// @Tags File
|
||||
// @Summary Batch check file exist
|
||||
// @Accept json
|
||||
// @Param request body request.FilePathsCheck true "request"
|
||||
// @Success 200 {array} response.ExistFileInfo
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /files/batch/check [post]
|
||||
func (b *BaseApi) BatchCheckFiles(c *gin.Context) {
|
||||
var req request.FilePathsCheck
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
return
|
||||
}
|
||||
fileList := fileService.BatchCheckFiles(req)
|
||||
helper.SuccessWithData(c, fileList)
|
||||
}
|
||||
|
||||
// @Tags File
|
||||
// @Summary Change file name
|
||||
// @Accept json
|
||||
@@ -441,7 +459,7 @@ func (b *BaseApi) ChangeFileName(c *gin.Context) {
|
||||
// @Summary Wget file
|
||||
// @Accept json
|
||||
// @Param request body request.FileWget true "request"
|
||||
// @Success 200
|
||||
// @Success 200 {object} response.FileWgetRes
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /files/wget [post]
|
||||
@@ -583,7 +601,7 @@ func (b *BaseApi) DownloadChunkFiles(c *gin.Context) {
|
||||
// @Summary Load file size
|
||||
// @Accept json
|
||||
// @Param request body request.DirSizeReq true "request"
|
||||
// @Success 200
|
||||
// @Success 200 {object} response.DirSizeRes
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /files/size [post]
|
||||
@@ -662,6 +680,7 @@ func mergeChunks(fileName string, fileDir string, dstDir string, chunkCount int,
|
||||
|
||||
// @Tags File
|
||||
// @Summary Chunk upload file
|
||||
// @Accept multipart/form-data
|
||||
// @Param file formData file true "request"
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
@@ -784,7 +803,7 @@ func (b *BaseApi) Keys(c *gin.Context) {
|
||||
// @Tags File
|
||||
// @Summary Read file by Line
|
||||
// @Param request body request.FileReadByLineReq true "request"
|
||||
// @Success 200
|
||||
// @Success 200 {object} response.FileLineContent
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /files/read [post]
|
||||
|
||||
@@ -53,7 +53,7 @@ func (b *BaseApi) SearchFirewallRule(c *gin.Context) {
|
||||
// @Summary Page firewall status
|
||||
// @Accept json
|
||||
// @Param request body dto.FirewallOperation true "request"
|
||||
// @Success 200 {object} dto.PageResult
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /hosts/firewall/operate [post]
|
||||
@@ -203,7 +203,7 @@ func (b *BaseApi) UpdatePortRule(c *gin.Context) {
|
||||
}
|
||||
|
||||
// @Tags Firewall
|
||||
// @Summary Uodate address group
|
||||
// @Summary Update address group
|
||||
// @Accept json
|
||||
// @Param request body dto.AddrRuleUpdate true "request"
|
||||
// @Success 200
|
||||
|
||||
@@ -55,6 +55,7 @@ func (b *BaseApi) LoadFtpLogInfo(c *gin.Context) {
|
||||
// @Summary Operate FTP
|
||||
// @Accept json
|
||||
// @Param request body dto.Operate true "request"
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /toolbox/ftp/operate [post]
|
||||
|
||||
@@ -12,7 +12,7 @@ import (
|
||||
// @Summary Create host
|
||||
// @Accept json
|
||||
// @Param request body dto.HostOperate true "request"
|
||||
// @Success 200
|
||||
// @Success 200 {object} dto.HostInfo
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /hosts [post]
|
||||
@@ -35,7 +35,7 @@ func (b *BaseApi) CreateHost(c *gin.Context) {
|
||||
// @Summary Test host conn by info
|
||||
// @Accept json
|
||||
// @Param request body dto.HostConnTest true "request"
|
||||
// @Success 200
|
||||
// @Success 200 {boolean} connStatus
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /hosts/test/byinfo [post]
|
||||
@@ -56,7 +56,7 @@ func (b *BaseApi) TestByInfo(c *gin.Context) {
|
||||
// @Success 200 {boolean} connStatus
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /hosts/test/byid/:id [post]
|
||||
// @Router /hosts/test/byid/{id} [post]
|
||||
func (b *BaseApi) TestByID(c *gin.Context) {
|
||||
id, err := helper.GetParamID(c)
|
||||
if err != nil {
|
||||
@@ -95,7 +95,7 @@ func (b *BaseApi) HostTree(c *gin.Context) {
|
||||
// @Summary Page host
|
||||
// @Accept json
|
||||
// @Param request body dto.SearchHostWithPage true "request"
|
||||
// @Success 200 {array} dto.HostTree
|
||||
// @Success 200 {object} dto.PageResult
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /hosts/search [post]
|
||||
|
||||
@@ -11,7 +11,7 @@ import (
|
||||
// @Summary Get tool status
|
||||
// @Accept json
|
||||
// @Param request body request.HostToolReq true "request"
|
||||
// @Success 200
|
||||
// @Success 200 {object} response.HostToolRes
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /host/tool [post]
|
||||
@@ -77,7 +77,7 @@ func (b *BaseApi) OperateTool(c *gin.Context) {
|
||||
// @Summary Get tool config
|
||||
// @Accept json
|
||||
// @Param request body request.HostToolConfig true "request"
|
||||
// @Success 200
|
||||
// @Success 200 {object} response.HostToolConfig
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /host/tool/config [post]
|
||||
@@ -100,7 +100,7 @@ func (b *BaseApi) OperateToolConfig(c *gin.Context) {
|
||||
// @Summary Get tool logs
|
||||
// @Accept json
|
||||
// @Param request body request.HostToolLogReq true "request"
|
||||
// @Success 200
|
||||
// @Success 200 {string} logContent
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /host/tool/log [post]
|
||||
@@ -144,7 +144,7 @@ func (b *BaseApi) OperateProcess(c *gin.Context) {
|
||||
// @Tags Host tool
|
||||
// @Summary Get Supervisor process config
|
||||
// @Accept json
|
||||
// @Success 200
|
||||
// @Success 200 {object} response.SupervisorProcessConfig
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /host/tool/supervisor/process [get]
|
||||
@@ -161,7 +161,7 @@ func (b *BaseApi) GetProcess(c *gin.Context) {
|
||||
// @Summary Get Supervisor process config
|
||||
// @Accept json
|
||||
// @Param request body request.SupervisorProcessFileReq true "request"
|
||||
// @Success 200
|
||||
// @Success 200 {string} content
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /host/tool/supervisor/process/file [post]
|
||||
|
||||
@@ -94,7 +94,7 @@ func (b *BaseApi) ImageBuild(c *gin.Context) {
|
||||
// @Summary Pull image
|
||||
// @Accept json
|
||||
// @Param request body dto.ImagePull true "request"
|
||||
// @Success 200 {string} log
|
||||
// @Success 200 {string} logPath
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /containers/image/pull [post]
|
||||
@@ -118,7 +118,7 @@ func (b *BaseApi) ImagePull(c *gin.Context) {
|
||||
// @Summary Push image
|
||||
// @Accept json
|
||||
// @Param request body dto.ImagePush true "request"
|
||||
// @Success 200 {string} log
|
||||
// @Success 200 {string} logPath
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /containers/image/push [post]
|
||||
|
||||
@@ -21,7 +21,7 @@ func (b *BaseApi) GetLoginLogs(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
total, list, err := logService.PageLoginLog(req)
|
||||
total, list, err := logService.PageLoginLog(c, req)
|
||||
if err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
return
|
||||
@@ -63,7 +63,7 @@ func (b *BaseApi) GetOperationLogs(c *gin.Context) {
|
||||
// @Summary Clean operation logs
|
||||
// @Accept json
|
||||
// @Param request body dto.CleanLog true "request"
|
||||
// @Success 200 {object} dto.PageResult
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /logs/clean [post]
|
||||
@@ -84,7 +84,7 @@ func (b *BaseApi) CleanLogs(c *gin.Context) {
|
||||
|
||||
// @Tags Logs
|
||||
// @Summary Load system log files
|
||||
// @Success 200
|
||||
// @Success 200 {array} string
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /logs/system/files [get]
|
||||
@@ -100,7 +100,7 @@ func (b *BaseApi) GetSystemFiles(c *gin.Context) {
|
||||
|
||||
// @Tags Logs
|
||||
// @Summary Load system logs
|
||||
// @Success 200
|
||||
// @Success 200 {string} data
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /logs/system [post]
|
||||
|
||||
@@ -18,7 +18,7 @@ import (
|
||||
// @Tags Monitor
|
||||
// @Summary Load monitor datas
|
||||
// @Param request body dto.MonitorSearch true "request"
|
||||
// @Success 200
|
||||
// @Success 200 {array} dto.MonitorData
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /hosts/monitor/search [post]
|
||||
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
|
||||
// @Tags OpenResty
|
||||
// @Summary Load OpenResty conf
|
||||
// @Success 200 {object} response.FileInfo
|
||||
// @Success 200 {object} response.NginxFile
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /openresty [get]
|
||||
|
||||
@@ -12,7 +12,7 @@ import (
|
||||
// @Summary Page Extensions
|
||||
// @Accept json
|
||||
// @Param request body request.PHPExtensionsSearch true "request"
|
||||
// @Success 200 {array} response.PHPExtensionsDTO
|
||||
// @Success 200 {object} dto.PageResult
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /runtimes/php/extensions/search [post]
|
||||
@@ -27,7 +27,10 @@ func (b *BaseApi) PagePHPExtensions(c *gin.Context) {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
return
|
||||
}
|
||||
helper.SuccessWithData(c, list)
|
||||
helper.SuccessWithData(c, dto.PageResult{
|
||||
Total: int64(len(list)),
|
||||
Items: list,
|
||||
})
|
||||
} else {
|
||||
total, list, err := phpExtensionsService.Page(req)
|
||||
if err != nil {
|
||||
|
||||
@@ -12,7 +12,7 @@ import (
|
||||
// @Summary List Recycle Bin files
|
||||
// @Accept json
|
||||
// @Param request body dto.PageInfo true "request"
|
||||
// @Success 200
|
||||
// @Success 200 {object} dto.PageResult
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /files/recycle/search [post]
|
||||
@@ -72,7 +72,7 @@ func (b *BaseApi) ClearRecycleBinFile(c *gin.Context) {
|
||||
// @Tags File
|
||||
// @Summary Get Recycle Bin status
|
||||
// @Accept json
|
||||
// @Success 200
|
||||
// @Success 200 {string} content
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /files/recycle/status [get]
|
||||
|
||||
@@ -12,7 +12,7 @@ import (
|
||||
// @Summary List runtimes
|
||||
// @Accept json
|
||||
// @Param request body request.RuntimeSearch true "request"
|
||||
// @Success 200
|
||||
// @Success 200 {object} dto.PageResult
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /runtimes/search [post]
|
||||
@@ -36,7 +36,7 @@ func (b *BaseApi) SearchRuntimes(c *gin.Context) {
|
||||
// @Summary Create runtime
|
||||
// @Accept json
|
||||
// @Param request body request.RuntimeCreate true "request"
|
||||
// @Success 200
|
||||
// @Success 200 {object} model.Runtime
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /runtimes [post]
|
||||
@@ -115,10 +115,10 @@ func (b *BaseApi) UpdateRuntime(c *gin.Context) {
|
||||
// @Summary Get runtime
|
||||
// @Accept json
|
||||
// @Param id path string true "request"
|
||||
// @Success 200
|
||||
// @Success 200 {object} response.RuntimeDTO
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /runtimes/:id [get]
|
||||
// @Router /runtimes/{id} [get]
|
||||
func (b *BaseApi) GetRuntime(c *gin.Context) {
|
||||
id, err := helper.GetIntParamByKey(c, "id")
|
||||
if err != nil {
|
||||
@@ -137,7 +137,7 @@ func (b *BaseApi) GetRuntime(c *gin.Context) {
|
||||
// @Summary Get Node package scripts
|
||||
// @Accept json
|
||||
// @Param request body request.NodePackageReq true "request"
|
||||
// @Success 200
|
||||
// @Success 200 {array} response.PackageScripts
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /runtimes/node/package [post]
|
||||
@@ -180,7 +180,7 @@ func (b *BaseApi) OperateRuntime(c *gin.Context) {
|
||||
// @Summary Get Node modules
|
||||
// @Accept json
|
||||
// @Param request body request.NodeModuleReq true "request"
|
||||
// @Success 200
|
||||
// @Success 200 {array} response.NodeModule
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /runtimes/node/modules [post]
|
||||
|
||||
@@ -3,8 +3,10 @@ package v1
|
||||
import (
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
"regexp"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/backend/app/api/v1/helper"
|
||||
"github.com/1Panel-dev/1Panel/backend/app/dto"
|
||||
@@ -53,11 +55,21 @@ func (b *BaseApi) UpdateSetting(c *gin.Context) {
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
return
|
||||
}
|
||||
if req.Key == "SecurityEntrance" {
|
||||
if !checkEntrancePattern(req.Value) {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, fmt.Errorf("the format of the security entrance %s is incorrect.", req.Value))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if err := settingService.Update(req.Key, req.Value); err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
return
|
||||
}
|
||||
if req.Key == "SecurityEntrance" {
|
||||
entranceValue := base64.StdEncoding.EncodeToString([]byte(req.Value))
|
||||
c.SetCookie("SecurityEntrance", entranceValue, 0, "", "", false, true)
|
||||
}
|
||||
helper.SuccessWithData(c, nil)
|
||||
}
|
||||
|
||||
@@ -160,7 +172,7 @@ func (b *BaseApi) UpdateSSL(c *gin.Context) {
|
||||
|
||||
// @Tags System Setting
|
||||
// @Summary Load system cert info
|
||||
// @Success 200 {object} dto.SettingInfo
|
||||
// @Success 200 {object} dto.SSLInfo
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /settings/ssl/info [get]
|
||||
@@ -192,7 +204,7 @@ func (b *BaseApi) DownloadSSL(c *gin.Context) {
|
||||
// @Tags System Setting
|
||||
// @Summary Load system address
|
||||
// @Accept json
|
||||
// @Success 200
|
||||
// @Success 200 {array} string
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /settings/interface [get]
|
||||
@@ -346,7 +358,7 @@ func (b *BaseApi) MFABind(c *gin.Context) {
|
||||
// @Tags System Setting
|
||||
// @Summary Generate api key
|
||||
// @Accept json
|
||||
// @Success 200
|
||||
// @Success 200 {string} apiKey
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /settings/api/config/generate/key [post]
|
||||
@@ -391,3 +403,11 @@ func (b *BaseApi) UpdateApiConfig(c *gin.Context) {
|
||||
}
|
||||
helper.SuccessWithData(c, nil)
|
||||
}
|
||||
|
||||
func checkEntrancePattern(val string) bool {
|
||||
if len(val) == 0 {
|
||||
return true
|
||||
}
|
||||
result, _ := regexp.MatchString("^[a-zA-Z0-9]{5,116}$", val)
|
||||
return result
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ func (b *BaseApi) ImportSnapshot(c *gin.Context) {
|
||||
// @Summary Load Snapshot status
|
||||
// @Accept json
|
||||
// @Param request body dto.OperateByID true "request"
|
||||
// @Success 200
|
||||
// @Success 200 {object} dto.SnapshotStatus
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /settings/snapshot/status [post]
|
||||
@@ -124,7 +124,7 @@ func (b *BaseApi) SearchSnapshot(c *gin.Context) {
|
||||
// @Summary Load system snapshot size
|
||||
// @Accept json
|
||||
// @Param request body dto.PageSnapshot true "request"
|
||||
// @Success 200
|
||||
// @Success 200 {array} dto.SnapshotFile
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /settings/snapshot/size [post]
|
||||
|
||||
@@ -26,6 +26,7 @@ func (b *BaseApi) GetSSHInfo(c *gin.Context) {
|
||||
// @Summary Operate SSH
|
||||
// @Accept json
|
||||
// @Param request body dto.Operate true "request"
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /host/ssh/operate [post]
|
||||
@@ -113,7 +114,7 @@ func (b *BaseApi) GenerateSSH(c *gin.Context) {
|
||||
// @Summary Load host SSH secret
|
||||
// @Accept json
|
||||
// @Param request body dto.GenerateLoad true "request"
|
||||
// @Success 200
|
||||
// @Success 200 {string} data
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /host/ssh/secret [post]
|
||||
@@ -155,7 +156,7 @@ func (b *BaseApi) LoadSSHLogs(c *gin.Context) {
|
||||
|
||||
// @Tags SSH
|
||||
// @Summary Load host SSH conf
|
||||
// @Success 200
|
||||
// @Success 200 {string} data
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /host/ssh/conf [get]
|
||||
|
||||
@@ -68,12 +68,11 @@ func (b *BaseApi) WsSsh(c *gin.Context) {
|
||||
|
||||
<-quitChan
|
||||
|
||||
if wshandleError(wsConn, err) {
|
||||
return
|
||||
}
|
||||
dt := time.Now().Add(time.Second)
|
||||
_ = wsConn.WriteControl(websocket.CloseMessage, nil, dt)
|
||||
}
|
||||
|
||||
func (b *BaseApi) RedisWsSsh(c *gin.Context) {
|
||||
func (b *BaseApi) ContainerWsSSH(c *gin.Context) {
|
||||
wsConn, err := upGrader.Upgrade(c.Writer, c.Request, nil)
|
||||
if err != nil {
|
||||
global.LOG.Errorf("gin context http handler failed, err: %v", err)
|
||||
@@ -95,38 +94,30 @@ func (b *BaseApi) RedisWsSsh(c *gin.Context) {
|
||||
if wshandleError(wsConn, errors.WithMessage(err, "invalid param rows in request")) {
|
||||
return
|
||||
}
|
||||
name := c.Query("name")
|
||||
from := c.Query("from")
|
||||
commands := []string{"redis-cli"}
|
||||
database, err := databaseService.Get(name)
|
||||
if wshandleError(wsConn, errors.WithMessage(err, "no such database in db")) {
|
||||
return
|
||||
}
|
||||
if from == "local" {
|
||||
redisInfo, err := appInstallService.LoadConnInfo(dto.OperationWithNameAndType{Name: name, Type: "redis"})
|
||||
if wshandleError(wsConn, errors.WithMessage(err, "no such database in db")) {
|
||||
source := c.Query("source")
|
||||
var containerID string
|
||||
var initCmd string
|
||||
switch source {
|
||||
case "redis":
|
||||
containerID, initCmd, err = loadRedisInitCmd(c)
|
||||
case "ollama":
|
||||
containerID, initCmd, err = loadOllamaInitCmd(c)
|
||||
case "container":
|
||||
containerID, initCmd, err = loadContainerInitCmd(c)
|
||||
default:
|
||||
if wshandleError(wsConn, fmt.Errorf("not support such source %s", source)) {
|
||||
return
|
||||
}
|
||||
name = redisInfo.ContainerName
|
||||
if len(database.Password) != 0 {
|
||||
commands = []string{"redis-cli", "-a", database.Password, "--no-auth-warning"}
|
||||
}
|
||||
} else {
|
||||
itemPort := fmt.Sprintf("%v", database.Port)
|
||||
commands = []string{"redis-cli", "-h", database.Address, "-p", itemPort}
|
||||
if len(database.Password) != 0 {
|
||||
commands = []string{"redis-cli", "-h", database.Address, "-p", itemPort, "-a", database.Password, "--no-auth-warning"}
|
||||
}
|
||||
name = "1Panel-redis-cli-tools"
|
||||
}
|
||||
|
||||
pidMap := loadMapFromDockerTop(name)
|
||||
itemCmds := append([]string{"exec", "-it", name}, commands...)
|
||||
slave, err := terminal.NewCommand(itemCmds)
|
||||
if wshandleError(wsConn, err) {
|
||||
return
|
||||
}
|
||||
defer killBash(name, strings.Join(commands, " "), pidMap)
|
||||
pidMap := loadMapFromDockerTop(containerID)
|
||||
slave, err := terminal.NewCommand("clear && " + initCmd)
|
||||
if wshandleError(wsConn, err) {
|
||||
return
|
||||
}
|
||||
defer killBash(containerID, strings.ReplaceAll(initCmd, fmt.Sprintf("docker exec -it %s ", containerID), ""), pidMap)
|
||||
defer slave.Close()
|
||||
|
||||
tty, err := terminal.NewLocalWsSession(cols, rows, wsConn, slave, false)
|
||||
@@ -141,83 +132,67 @@ func (b *BaseApi) RedisWsSsh(c *gin.Context) {
|
||||
<-quitChan
|
||||
|
||||
global.LOG.Info("websocket finished")
|
||||
if wshandleError(wsConn, err) {
|
||||
return
|
||||
}
|
||||
dt := time.Now().Add(time.Second)
|
||||
_ = wsConn.WriteControl(websocket.CloseMessage, nil, dt)
|
||||
|
||||
}
|
||||
|
||||
func (b *BaseApi) ContainerWsSsh(c *gin.Context) {
|
||||
wsConn, err := upGrader.Upgrade(c.Writer, c.Request, nil)
|
||||
func loadRedisInitCmd(c *gin.Context) (string, string, error) {
|
||||
name := c.Query("name")
|
||||
from := c.Query("from")
|
||||
commands := "redis-cli"
|
||||
database, err := databaseService.Get(name)
|
||||
if err != nil {
|
||||
global.LOG.Errorf("gin context http handler failed, err: %v", err)
|
||||
return
|
||||
return "", "", fmt.Errorf("no such database in db, err: %v", err)
|
||||
}
|
||||
defer wsConn.Close()
|
||||
|
||||
if global.CONF.System.IsDemo {
|
||||
if wshandleError(wsConn, errors.New(" demo server, prohibit this operation!")) {
|
||||
return
|
||||
if from == "local" {
|
||||
redisInfo, err := appInstallService.LoadConnInfo(dto.OperationWithNameAndType{Name: name, Type: "redis"})
|
||||
if err != nil {
|
||||
return "", "", fmt.Errorf("no such app in db, err: %v", err)
|
||||
}
|
||||
name = redisInfo.ContainerName
|
||||
if len(database.Password) != 0 {
|
||||
commands = "redis-cli -a " + database.Password + " --no-auth-warning"
|
||||
}
|
||||
} else {
|
||||
commands = fmt.Sprintf("redis-cli -h %s -p %v", database.Address, database.Port)
|
||||
if len(database.Password) != 0 {
|
||||
commands = fmt.Sprintf("redis-cli -h %s -p %v -a %s --no-auth-warning", database.Address, database.Port, database.Password)
|
||||
}
|
||||
name = "1Panel-redis-cli-tools"
|
||||
}
|
||||
return name, fmt.Sprintf("docker exec -it %s %s", name, commands), nil
|
||||
}
|
||||
|
||||
func loadOllamaInitCmd(c *gin.Context) (string, string, error) {
|
||||
name := c.Query("name")
|
||||
if cmd.CheckIllegal(name) {
|
||||
return "", "", fmt.Errorf("ollama model %s contains illegal characters", name)
|
||||
}
|
||||
ollamaInfo, err := appInstallService.LoadConnInfo(dto.OperationWithNameAndType{Name: "", Type: "ollama"})
|
||||
if err != nil {
|
||||
return "", "", fmt.Errorf("no such app in db, err: %v", err)
|
||||
}
|
||||
containerName := ollamaInfo.ContainerName
|
||||
return containerName, fmt.Sprintf("docker exec -it %s ollama run %s", containerName, name), nil
|
||||
}
|
||||
|
||||
func loadContainerInitCmd(c *gin.Context) (string, string, error) {
|
||||
containerID := c.Query("containerid")
|
||||
command := c.Query("command")
|
||||
user := c.Query("user")
|
||||
if len(command) == 0 || len(containerID) == 0 {
|
||||
if wshandleError(wsConn, errors.New("error param of command or containerID")) {
|
||||
return
|
||||
}
|
||||
}
|
||||
cols, err := strconv.Atoi(c.DefaultQuery("cols", "80"))
|
||||
if wshandleError(wsConn, errors.WithMessage(err, "invalid param cols in request")) {
|
||||
return
|
||||
}
|
||||
rows, err := strconv.Atoi(c.DefaultQuery("rows", "40"))
|
||||
if wshandleError(wsConn, errors.WithMessage(err, "invalid param rows in request")) {
|
||||
return
|
||||
}
|
||||
|
||||
cmds := []string{"exec", containerID, command}
|
||||
if len(user) != 0 {
|
||||
cmds = []string{"exec", "-u", user, containerID, command}
|
||||
}
|
||||
if cmd.CheckIllegal(user, containerID, command) {
|
||||
if wshandleError(wsConn, errors.New(" The command contains illegal characters.")) {
|
||||
return
|
||||
}
|
||||
return "", "", fmt.Errorf("the command contains illegal characters. command: %s, user: %s, containerID: %s", command, user, containerID)
|
||||
}
|
||||
stdout, err := cmd.ExecWithCheck("docker", cmds...)
|
||||
if wshandleError(wsConn, errors.WithMessage(err, stdout)) {
|
||||
return
|
||||
if len(command) == 0 || len(containerID) == 0 {
|
||||
return "", "", fmt.Errorf("error param of command: %s or containerID: %s", command, containerID)
|
||||
}
|
||||
|
||||
commands := []string{"exec", "-it", containerID, command}
|
||||
command = fmt.Sprintf("docker exec -it %s %s", containerID, command)
|
||||
if len(user) != 0 {
|
||||
commands = []string{"exec", "-it", "-u", user, containerID, command}
|
||||
}
|
||||
pidMap := loadMapFromDockerTop(containerID)
|
||||
slave, err := terminal.NewCommand(commands)
|
||||
if wshandleError(wsConn, err) {
|
||||
return
|
||||
}
|
||||
defer killBash(containerID, command, pidMap)
|
||||
defer slave.Close()
|
||||
|
||||
tty, err := terminal.NewLocalWsSession(cols, rows, wsConn, slave, true)
|
||||
if wshandleError(wsConn, err) {
|
||||
return
|
||||
command = fmt.Sprintf("docker exec -it -u %s %s %s", user, containerID, command)
|
||||
}
|
||||
|
||||
quitChan := make(chan bool, 3)
|
||||
tty.Start(quitChan)
|
||||
go slave.Wait(quitChan)
|
||||
|
||||
<-quitChan
|
||||
|
||||
global.LOG.Info("websocket finished")
|
||||
if wshandleError(wsConn, err) {
|
||||
return
|
||||
}
|
||||
return containerID, command, nil
|
||||
}
|
||||
|
||||
func wshandleError(ws *websocket.Conn, err error) bool {
|
||||
|
||||
@@ -26,7 +26,7 @@ func (b *BaseApi) GetUpgradeInfo(c *gin.Context) {
|
||||
// @Summary Load release notes by version
|
||||
// @Accept json
|
||||
// @Param request body dto.Upgrade true "request"
|
||||
// @Success 200
|
||||
// @Success 200 {string} notes
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /settings/upgrade [get]
|
||||
|
||||
@@ -51,7 +51,7 @@ func (b *BaseApi) GetWebsites(c *gin.Context) {
|
||||
|
||||
// @Tags Website
|
||||
// @Summary List website names
|
||||
// @Success 200 {array} string
|
||||
// @Success 200 {array} response.WebsiteOption
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /websites/options [get]
|
||||
@@ -166,7 +166,7 @@ func (b *BaseApi) UpdateWebsite(c *gin.Context) {
|
||||
// @Success 200 {object} response.WebsiteDTO
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /websites/:id [get]
|
||||
// @Router /websites/{id} [get]
|
||||
func (b *BaseApi) GetWebsite(c *gin.Context) {
|
||||
id, err := helper.GetParamID(c)
|
||||
if err != nil {
|
||||
@@ -185,10 +185,11 @@ func (b *BaseApi) GetWebsite(c *gin.Context) {
|
||||
// @Summary Search website nginx by id
|
||||
// @Accept json
|
||||
// @Param id path integer true "request"
|
||||
// @Param type path string true "type"
|
||||
// @Success 200 {object} response.FileInfo
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /websites/:id/config/:type [get]
|
||||
// @Router /websites/{id}/config/{type} [get]
|
||||
func (b *BaseApi) GetWebsiteNginx(c *gin.Context) {
|
||||
id, err := helper.GetParamID(c)
|
||||
if err != nil {
|
||||
@@ -254,7 +255,7 @@ func (b *BaseApi) UpdateNginxConfig(c *gin.Context) {
|
||||
// @Success 200 {object} response.WebsiteHTTPS
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /websites/:id/https [get]
|
||||
// @Router /websites/{id}/https [get]
|
||||
func (b *BaseApi) GetHTTPSConfig(c *gin.Context) {
|
||||
id, err := helper.GetParamID(c)
|
||||
if err != nil {
|
||||
@@ -272,11 +273,12 @@ func (b *BaseApi) GetHTTPSConfig(c *gin.Context) {
|
||||
// @Tags Website HTTPS
|
||||
// @Summary Update https conf
|
||||
// @Accept json
|
||||
// @Param id path integer true "request"
|
||||
// @Param request body request.WebsiteHTTPSOp true "request"
|
||||
// @Success 200 {object} response.WebsiteHTTPS
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /websites/:id/https [post]
|
||||
// @Router /websites/{id}/https [post]
|
||||
// @x-panel-log {"bodyKeys":["websiteId"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"websiteId","isList":false,"db":"websites","output_column":"primary_domain","output_value":"domain"}],"formatZH":"更新网站 [domain] https 配置","formatEN":"Update website https [domain] conf"}
|
||||
func (b *BaseApi) UpdateHTTPSConfig(c *gin.Context) {
|
||||
var req request.WebsiteHTTPSOp
|
||||
@@ -386,7 +388,7 @@ func (b *BaseApi) ChangeDefaultServer(c *gin.Context) {
|
||||
// @Success 200 {object} response.PHPConfig
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /websites/php/config/:id [get]
|
||||
// @Router /websites/php/config/{id} [get]
|
||||
func (b *BaseApi) GetWebsitePHPConfig(c *gin.Context) {
|
||||
id, err := helper.GetParamID(c)
|
||||
if err != nil {
|
||||
@@ -468,7 +470,7 @@ func (b *BaseApi) ChangePHPVersion(c *gin.Context) {
|
||||
// @Summary Get rewrite conf
|
||||
// @Accept json
|
||||
// @Param request body request.NginxRewriteReq true "request"
|
||||
// @Success 200
|
||||
// @Success 200 {object} response.NginxRewriteRes
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /websites/rewrite [post]
|
||||
@@ -552,7 +554,7 @@ func (b *BaseApi) UpdateSiteDirPermission(c *gin.Context) {
|
||||
// @Summary Get proxy conf
|
||||
// @Accept json
|
||||
// @Param request body request.WebsiteProxyReq true "request"
|
||||
// @Success 200
|
||||
// @Success 200 {array} request.WebsiteProxyConfig
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /websites/proxies [post]
|
||||
@@ -569,6 +571,28 @@ func (b *BaseApi) GetProxyConfig(c *gin.Context) {
|
||||
helper.SuccessWithData(c, res)
|
||||
}
|
||||
|
||||
// @Tags Website
|
||||
// @Summary Delete proxy conf
|
||||
// @Accept json
|
||||
// @Param request body request.WebsiteProxyDel true "request"
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /websites/proxies/del [post]
|
||||
// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"websites","output_column":"primary_domain","output_value":"domain"}],"formatZH":"删除网站 [domain] 反向代理配置","formatEN":"Delete domain [domain] proxy config"}
|
||||
func (b *BaseApi) DeleteProxyConfig(c *gin.Context) {
|
||||
var req request.WebsiteProxyDel
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
return
|
||||
}
|
||||
err := websiteService.DeleteProxy(req)
|
||||
if err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
return
|
||||
}
|
||||
helper.SuccessWithOutData(c)
|
||||
}
|
||||
|
||||
// @Tags Website
|
||||
// @Summary Update proxy conf
|
||||
// @Accept json
|
||||
@@ -616,7 +640,7 @@ func (b *BaseApi) UpdateProxyConfigFile(c *gin.Context) {
|
||||
// @Summary Get AuthBasic conf
|
||||
// @Accept json
|
||||
// @Param request body request.NginxAuthReq true "request"
|
||||
// @Success 200
|
||||
// @Success 200 {object} response.NginxAuthRes
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /websites/auths [post]
|
||||
@@ -657,7 +681,7 @@ func (b *BaseApi) UpdateAuthConfig(c *gin.Context) {
|
||||
// @Summary Get AntiLeech conf
|
||||
// @Accept json
|
||||
// @Param request body request.NginxCommonReq true "request"
|
||||
// @Success 200
|
||||
// @Success 200 {object} response.NginxAntiLeechRes
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /websites/leech [post]
|
||||
@@ -720,7 +744,7 @@ func (b *BaseApi) UpdateRedirectConfig(c *gin.Context) {
|
||||
// @Summary Get redirect conf
|
||||
// @Accept json
|
||||
// @Param request body request.WebsiteProxyReq true "request"
|
||||
// @Success 200
|
||||
// @Success 200 {array} response.NginxRedirectConfig
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /websites/redirect [post]
|
||||
@@ -762,7 +786,7 @@ func (b *BaseApi) UpdateRedirectConfigFile(c *gin.Context) {
|
||||
// @Summary Get website dir
|
||||
// @Accept json
|
||||
// @Param request body request.WebsiteCommonReq true "request"
|
||||
// @Success 200
|
||||
// @Success 200 {object} response.WebsiteDirConfig
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /websites/dir [post]
|
||||
@@ -782,10 +806,11 @@ func (b *BaseApi) GetDirConfig(c *gin.Context) {
|
||||
// @Tags Website
|
||||
// @Summary Get default html
|
||||
// @Accept json
|
||||
// @Success 200 {object} response.FileInfo
|
||||
// @Param type path string true "type"
|
||||
// @Success 200 {object} response.WebsiteHtmlRes
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /websites/default/html/:type [get]
|
||||
// @Router /websites/default/html/{type} [get]
|
||||
func (b *BaseApi) GetDefaultHtml(c *gin.Context) {
|
||||
resourceType, err := helper.GetStrParamByKey(c, "type")
|
||||
if err != nil {
|
||||
|
||||
@@ -32,7 +32,7 @@ func (b *BaseApi) DeleteWebDomain(c *gin.Context) {
|
||||
// @Summary Create website domain
|
||||
// @Accept json
|
||||
// @Param request body request.WebsiteDomainCreate true "request"
|
||||
// @Success 200 {object} model.WebsiteDomain
|
||||
// @Success 200 {array} model.WebsiteDomain
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /websites/domains [post]
|
||||
@@ -57,7 +57,7 @@ func (b *BaseApi) CreateWebDomain(c *gin.Context) {
|
||||
// @Success 200 {array} model.WebsiteDomain
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /websites/domains/:websiteId [get]
|
||||
// @Router /websites/domains/{websiteId} [get]
|
||||
func (b *BaseApi) GetWebDomains(c *gin.Context) {
|
||||
websiteId, err := helper.GetIntParamByKey(c, "websiteId")
|
||||
if err != nil {
|
||||
|
||||
@@ -17,7 +17,7 @@ import (
|
||||
// @Summary Page website ssl
|
||||
// @Accept json
|
||||
// @Param request body request.WebsiteSSLSearch true "request"
|
||||
// @Success 200
|
||||
// @Success 200 {array} response.WebsiteSSLDTO
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /websites/ssl/search [post]
|
||||
@@ -135,10 +135,10 @@ func (b *BaseApi) DeleteWebsiteSSL(c *gin.Context) {
|
||||
// @Summary Search website ssl by website id
|
||||
// @Accept json
|
||||
// @Param websiteId path integer true "request"
|
||||
// @Success 200
|
||||
// @Success 200 {object} response.WebsiteSSLDTO
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /websites/ssl/website/:websiteId [get]
|
||||
// @Router /websites/ssl/website/{websiteId} [get]
|
||||
func (b *BaseApi) GetWebsiteSSLByWebsiteId(c *gin.Context) {
|
||||
websiteId, err := helper.GetIntParamByKey(c, "websiteId")
|
||||
if err != nil {
|
||||
@@ -157,10 +157,10 @@ func (b *BaseApi) GetWebsiteSSLByWebsiteId(c *gin.Context) {
|
||||
// @Summary Search website ssl by id
|
||||
// @Accept json
|
||||
// @Param id path integer true "request"
|
||||
// @Success 200
|
||||
// @Success 200 {object} response.WebsiteSSLDTO
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /websites/ssl/:id [get]
|
||||
// @Router /websites/ssl/{id} [get]
|
||||
func (b *BaseApi) GetWebsiteSSLById(c *gin.Context) {
|
||||
id, err := helper.GetParamID(c)
|
||||
if err != nil {
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
package dto
|
||||
|
||||
import "time"
|
||||
|
||||
type OllamaModelInfo struct {
|
||||
ID uint `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Size string `json:"size"`
|
||||
From string `json:"from"`
|
||||
LogFileExist bool `json:"logFileExist"`
|
||||
|
||||
Status string `json:"status"`
|
||||
Message string `json:"message"`
|
||||
CreatedAt time.Time `json:"createdAt"`
|
||||
}
|
||||
|
||||
type OllamaModelDropList struct {
|
||||
ID uint `json:"id"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
type OllamaModelName struct {
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
type OllamaBindDomain struct {
|
||||
Domain string `json:"domain" validate:"required"`
|
||||
AppInstallID uint `json:"appInstallID" validate:"required"`
|
||||
SSLID uint `json:"sslID"`
|
||||
WebsiteID uint `json:"websiteID"`
|
||||
IPList string `json:"ipList"`
|
||||
}
|
||||
|
||||
type OllamaBindDomainReq struct {
|
||||
AppInstallID uint `json:"appInstallID" validate:"required"`
|
||||
}
|
||||
|
||||
type OllamaBindDomainRes struct {
|
||||
Domain string `json:"domain"`
|
||||
SSLID uint `json:"sslID"`
|
||||
AcmeAccountID uint `json:"acmeAccountID"`
|
||||
AllowIPs []string `json:"allowIPs"`
|
||||
WebsiteID uint `json:"websiteID"`
|
||||
ConnUrl string `json:"connUrl"`
|
||||
}
|
||||
+21
-10
@@ -1,9 +1,5 @@
|
||||
package dto
|
||||
|
||||
import (
|
||||
"github.com/1Panel-dev/1Panel/backend/app/model"
|
||||
)
|
||||
|
||||
type AppDatabase struct {
|
||||
ServiceName string `json:"PANEL_DB_HOST"`
|
||||
DbName string `json:"PANEL_DB_NAME"`
|
||||
@@ -62,7 +58,7 @@ type AppDefine struct {
|
||||
}
|
||||
|
||||
type LocalAppAppDefine struct {
|
||||
AppProperty model.App `json:"additionalProperties" yaml:"additionalProperties"`
|
||||
AppProperty AppProperty `json:"additionalProperties" yaml:"additionalProperties"`
|
||||
}
|
||||
|
||||
type LocalAppParam struct {
|
||||
@@ -82,8 +78,9 @@ type AppProperty struct {
|
||||
Name string `json:"name"`
|
||||
Type string `json:"type"`
|
||||
Tags []string `json:"tags"`
|
||||
ShortDescZh string `json:"shortDescZh"`
|
||||
ShortDescEn string `json:"shortDescEn"`
|
||||
ShortDescZh string `json:"shortDescZh" yaml:"shortDescZh"`
|
||||
ShortDescEn string `json:"shortDescEn" yaml:"shortDescEn"`
|
||||
Description Locale `json:"description"`
|
||||
Key string `json:"key"`
|
||||
Required []string `json:"Required"`
|
||||
CrossVersionUpdate bool `json:"crossVersionUpdate"`
|
||||
@@ -93,6 +90,7 @@ type AppProperty struct {
|
||||
Github string `json:"github"`
|
||||
Document string `json:"document"`
|
||||
Version float64 `json:"version"`
|
||||
GpuSupport bool `json:"gpuSupport"`
|
||||
}
|
||||
|
||||
type AppConfigVersion struct {
|
||||
@@ -104,9 +102,21 @@ type AppConfigVersion struct {
|
||||
}
|
||||
|
||||
type Tag struct {
|
||||
Key string `json:"key"`
|
||||
Name string `json:"name"`
|
||||
Sort int `json:"sort"`
|
||||
Key string `json:"key"`
|
||||
Name string `json:"name"`
|
||||
Sort int `json:"sort"`
|
||||
Locales Locale `json:"locales"`
|
||||
}
|
||||
|
||||
type Locale struct {
|
||||
En string `json:"en"`
|
||||
Ja string `json:"ja"`
|
||||
Ms string `json:"ms"`
|
||||
PtBr string `json:"pt-br" yaml:"pt-br"`
|
||||
Ru string `json:"ru"`
|
||||
ZhHant string `json:"zh-hant" yaml:"zh-hant"`
|
||||
Zh string `json:"zh"`
|
||||
Ko string `json:"ko"`
|
||||
}
|
||||
|
||||
type AppForm struct {
|
||||
@@ -118,6 +128,7 @@ type AppFormFields struct {
|
||||
Type string `json:"type"`
|
||||
LabelZh string `json:"labelZh"`
|
||||
LabelEn string `json:"labelEn"`
|
||||
Label Locale `json:"label"`
|
||||
Required bool `json:"required"`
|
||||
Default interface{} `json:"default"`
|
||||
EnvKey string `json:"envKey"`
|
||||
|
||||
@@ -29,7 +29,7 @@ type Login struct {
|
||||
Captcha string `json:"captcha"`
|
||||
CaptchaID string `json:"captchaID"`
|
||||
AuthMethod string `json:"authMethod" validate:"required,oneof=jwt session"`
|
||||
Language string `json:"language" validate:"required,oneof=zh en tw"`
|
||||
Language string `json:"language" validate:"required,oneof=zh en tw ja ko ru ms 'pt-BR'"`
|
||||
}
|
||||
|
||||
type MFALogin struct {
|
||||
|
||||
@@ -21,6 +21,12 @@ type BackupInfo struct {
|
||||
Vars string `json:"vars"`
|
||||
}
|
||||
|
||||
type BackupFile struct {
|
||||
ID uint `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Size int64 `json:"size"`
|
||||
}
|
||||
|
||||
type OneDriveInfo struct {
|
||||
ClientID string `json:"client_id"`
|
||||
ClientSecret string `json:"client_secret"`
|
||||
@@ -66,7 +72,6 @@ type BackupRecords struct {
|
||||
BackupType string `json:"backupType"`
|
||||
FileDir string `json:"fileDir"`
|
||||
FileName string `json:"fileName"`
|
||||
Size int64 `json:"size"`
|
||||
}
|
||||
|
||||
type DownloadRecord struct {
|
||||
|
||||
@@ -52,3 +52,8 @@ type OperationWithNameAndType struct {
|
||||
Name string `json:"name"`
|
||||
Type string `json:"type" validate:"required"`
|
||||
}
|
||||
|
||||
type ForceDelete struct {
|
||||
IDs []uint `json:"ids"`
|
||||
ForceDelete bool `json:"forceDelete"`
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ type Fail2BanSearch struct {
|
||||
}
|
||||
|
||||
type Fail2BanUpdate struct {
|
||||
Key string `json:"key" validate:"required,oneof=port bantime findtime maxretry banaction logpath port"`
|
||||
Key string `json:"key" validate:"required,oneof=port bantime findtime maxretry banaction logpath"`
|
||||
Value string `json:"value"`
|
||||
}
|
||||
|
||||
|
||||
@@ -30,7 +30,8 @@ type PortRuleOperate struct {
|
||||
}
|
||||
|
||||
type ForwardRuleOperate struct {
|
||||
Rules []struct {
|
||||
ForceDelete bool `json:"forceDelete"`
|
||||
Rules []struct {
|
||||
Operation string `json:"operation" validate:"required,oneof=add remove"`
|
||||
Num string `json:"num"`
|
||||
Protocol string `json:"protocol" validate:"required,oneof=tcp udp tcp/udp"`
|
||||
|
||||
@@ -33,6 +33,7 @@ type AppContainerConfig struct {
|
||||
DockerCompose string `json:"dockerCompose"`
|
||||
HostMode bool `json:"hostMode"`
|
||||
PullImage bool `json:"pullImage"`
|
||||
GpuConfig bool `json:"gpuConfig"`
|
||||
}
|
||||
|
||||
type AppInstalledSearch struct {
|
||||
|
||||
@@ -79,6 +79,10 @@ type FilePathCheck struct {
|
||||
Path string `json:"path" validate:"required"`
|
||||
}
|
||||
|
||||
type FilePathsCheck struct {
|
||||
Paths []string `json:"paths" validate:"required"`
|
||||
}
|
||||
|
||||
type FileWget struct {
|
||||
Url string `json:"url" validate:"required"`
|
||||
Path string `json:"path" validate:"required"`
|
||||
|
||||
@@ -193,6 +193,11 @@ type WebsiteProxyConfig struct {
|
||||
ProxySSLName string `json:"proxySSLName"`
|
||||
}
|
||||
|
||||
type WebsiteProxyDel struct {
|
||||
ID uint `json:"id" validate:"required"`
|
||||
Name string `json:"name" validate:"required"`
|
||||
}
|
||||
|
||||
type WebsiteProxyReq struct {
|
||||
ID uint `json:"id" validate:"required"`
|
||||
}
|
||||
|
||||
@@ -10,8 +10,8 @@ import (
|
||||
)
|
||||
|
||||
type AppRes struct {
|
||||
Items []*AppDto `json:"items"`
|
||||
Total int64 `json:"total"`
|
||||
Items []*AppItem `json:"items"`
|
||||
Total int64 `json:"total"`
|
||||
}
|
||||
|
||||
type AppUpdateRes struct {
|
||||
@@ -23,29 +23,31 @@ type AppUpdateRes struct {
|
||||
|
||||
type AppDTO struct {
|
||||
model.App
|
||||
Installed bool `json:"installed"`
|
||||
Versions []string `json:"versions"`
|
||||
Tags []model.Tag `json:"tags"`
|
||||
Installed bool `json:"installed"`
|
||||
Versions []string `json:"versions"`
|
||||
Tags []TagDTO `json:"tags"`
|
||||
}
|
||||
|
||||
type AppDto struct {
|
||||
Name string `json:"name"`
|
||||
Key string `json:"key"`
|
||||
ID uint `json:"id"`
|
||||
ShortDescZh string `json:"shortDescZh"`
|
||||
ShortDescEn string `json:"shortDescEn"`
|
||||
Icon string `json:"icon"`
|
||||
Type string `json:"type"`
|
||||
Status string `json:"status"`
|
||||
Resource string `json:"resource"`
|
||||
Installed bool `json:"installed"`
|
||||
Versions []string `json:"versions"`
|
||||
Limit int `json:"limit"`
|
||||
Tags []model.Tag `json:"tags"`
|
||||
type AppItem struct {
|
||||
Name string `json:"name"`
|
||||
Key string `json:"key"`
|
||||
ID uint `json:"id"`
|
||||
Description string `json:"description"`
|
||||
Icon string `json:"icon"`
|
||||
Type string `json:"type"`
|
||||
Status string `json:"status"`
|
||||
Resource string `json:"resource"`
|
||||
Installed bool `json:"installed"`
|
||||
Versions []string `json:"versions"`
|
||||
Limit int `json:"limit"`
|
||||
Tags []TagDTO `json:"tags"`
|
||||
GpuSupport bool `json:"gpuSupport"`
|
||||
}
|
||||
|
||||
type TagDTO struct {
|
||||
model.Tag
|
||||
ID uint `json:"id"`
|
||||
Key string `json:"key"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
type AppInstalledCheck struct {
|
||||
@@ -65,10 +67,11 @@ type AppInstalledCheck struct {
|
||||
|
||||
type AppDetailDTO struct {
|
||||
model.AppDetail
|
||||
Enable bool `json:"enable"`
|
||||
Params interface{} `json:"params"`
|
||||
Image string `json:"image"`
|
||||
HostMode bool `json:"hostMode"`
|
||||
Enable bool `json:"enable"`
|
||||
Params interface{} `json:"params"`
|
||||
Image string `json:"image"`
|
||||
HostMode bool `json:"hostMode"`
|
||||
GpuSupport bool `json:"gpuSupport"`
|
||||
}
|
||||
|
||||
type IgnoredApp struct {
|
||||
@@ -89,9 +92,10 @@ type AppInstalledDTO struct {
|
||||
}
|
||||
|
||||
type AppDetail struct {
|
||||
Website string `json:"website"`
|
||||
Document string `json:"document"`
|
||||
Github string `json:"github"`
|
||||
Website string `json:"website"`
|
||||
Document string `json:"document"`
|
||||
Github string `json:"github"`
|
||||
GpuSupport bool `json:"gpuSupport"`
|
||||
}
|
||||
|
||||
type AppInstallDTO struct {
|
||||
|
||||
@@ -2,6 +2,7 @@ package response
|
||||
|
||||
import (
|
||||
"github.com/1Panel-dev/1Panel/backend/utils/files"
|
||||
"time"
|
||||
)
|
||||
|
||||
type FileInfo struct {
|
||||
@@ -46,3 +47,10 @@ type FileLineContent struct {
|
||||
type FileExist struct {
|
||||
Exist bool `json:"exist"`
|
||||
}
|
||||
|
||||
type ExistFileInfo struct {
|
||||
Name string `json:"name"`
|
||||
Path string `json:"path"`
|
||||
Size float64 `json:"size"`
|
||||
ModTime time.Time `json:"modTime"`
|
||||
}
|
||||
|
||||
@@ -70,6 +70,8 @@ type SettingInfo struct {
|
||||
ApiInterfaceStatus string `json:"apiInterfaceStatus"`
|
||||
ApiKey string `json:"apiKey"`
|
||||
IpWhiteList string `json:"ipWhiteList"`
|
||||
ApiKeyValidityTime string `json:"apiKeyValidityTime"`
|
||||
LicenseVerify string `json:"licenseVerify"`
|
||||
}
|
||||
|
||||
type SettingUpdate struct {
|
||||
@@ -240,4 +242,5 @@ type ApiInterfaceConfig struct {
|
||||
ApiInterfaceStatus string `json:"apiInterfaceStatus"`
|
||||
ApiKey string `json:"apiKey"`
|
||||
IpWhiteList string `json:"ipWhiteList"`
|
||||
ApiKeyValidityTime string `json:"apiKeyValidityTime"`
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
package model
|
||||
|
||||
type OllamaModel struct {
|
||||
BaseModel
|
||||
|
||||
Name string `json:"name"`
|
||||
Size string `json:"size"`
|
||||
From string `json:"from"`
|
||||
Status string `json:"status"`
|
||||
Message string `json:"message"`
|
||||
}
|
||||
@@ -1,7 +1,10 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/1Panel-dev/1Panel/backend/constant"
|
||||
"github.com/1Panel-dev/1Panel/backend/utils/common"
|
||||
"github.com/gin-gonic/gin"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
@@ -12,10 +15,12 @@ type App struct {
|
||||
Key string `json:"key" gorm:"type:varchar(64);not null;"`
|
||||
ShortDescZh string `json:"shortDescZh" yaml:"shortDescZh" gorm:"type:longtext;"`
|
||||
ShortDescEn string `json:"shortDescEn" yaml:"shortDescEn" gorm:"type:longtext;"`
|
||||
Description string `json:"description"`
|
||||
Icon string `json:"icon" gorm:"type:longtext;"`
|
||||
Type string `json:"type" gorm:"type:varchar(64);not null"`
|
||||
Status string `json:"status" gorm:"type:varchar(64);not null"`
|
||||
Required string `json:"required" gorm:"type:varchar(64);"`
|
||||
GpuSupport bool `json:"gpuSupport"`
|
||||
CrossVersionUpdate bool `json:"crossVersionUpdate" yaml:"crossVersionUpdate"`
|
||||
Limit int `json:"limit" gorm:"type:Integer;not null"`
|
||||
Website string `json:"website" gorm:"type:varchar(64);not null"`
|
||||
@@ -36,8 +41,20 @@ func (i *App) IsLocalApp() bool {
|
||||
}
|
||||
func (i *App) GetAppResourcePath() string {
|
||||
if i.IsLocalApp() {
|
||||
//这里要去掉本地应用的local前缀
|
||||
return filepath.Join(constant.LocalAppResourceDir, strings.TrimPrefix(i.Key, "local"))
|
||||
}
|
||||
return filepath.Join(constant.RemoteAppResourceDir, i.Key)
|
||||
}
|
||||
|
||||
func (i *App) GetDescription(ctx *gin.Context) string {
|
||||
var translations = make(map[string]string)
|
||||
_ = json.Unmarshal([]byte(i.Description), &translations)
|
||||
lang := strings.ToLower(common.GetLang(ctx))
|
||||
if desc, ok := translations[lang]; ok && desc != "" {
|
||||
return desc
|
||||
}
|
||||
if lang == "zh" {
|
||||
return i.ShortDescZh
|
||||
}
|
||||
return i.ShortDescEn
|
||||
}
|
||||
|
||||
@@ -2,7 +2,8 @@ package model
|
||||
|
||||
type Tag struct {
|
||||
BaseModel
|
||||
Key string `json:"key" gorm:"type:varchar(64);not null"`
|
||||
Name string `json:"name" gorm:"type:varchar(64);not null"`
|
||||
Sort int `json:"sort" gorm:"type:int;not null;default:1"`
|
||||
Key string `json:"key" gorm:"type:varchar(64);not null"`
|
||||
Name string `json:"name" gorm:"type:varchar(64);not null"`
|
||||
Translations string `json:"translations"`
|
||||
Sort int `json:"sort" gorm:"type:int;not null;default:1"`
|
||||
}
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
package repo
|
||||
|
||||
import (
|
||||
"github.com/1Panel-dev/1Panel/backend/app/model"
|
||||
"github.com/1Panel-dev/1Panel/backend/global"
|
||||
)
|
||||
|
||||
type AiRepo struct{}
|
||||
|
||||
type IAiRepo interface {
|
||||
Get(opts ...DBOption) (model.OllamaModel, error)
|
||||
List(opts ...DBOption) ([]model.OllamaModel, error)
|
||||
Page(limit, offset int, opts ...DBOption) (int64, []model.OllamaModel, error)
|
||||
Create(cronjob *model.OllamaModel) error
|
||||
Update(id uint, vars map[string]interface{}) error
|
||||
Delete(opts ...DBOption) error
|
||||
}
|
||||
|
||||
func NewIAiRepo() IAiRepo {
|
||||
return &AiRepo{}
|
||||
}
|
||||
|
||||
func (u *AiRepo) Get(opts ...DBOption) (model.OllamaModel, error) {
|
||||
var item model.OllamaModel
|
||||
db := global.DB
|
||||
for _, opt := range opts {
|
||||
db = opt(db)
|
||||
}
|
||||
err := db.First(&item).Error
|
||||
return item, err
|
||||
}
|
||||
|
||||
func (u *AiRepo) List(opts ...DBOption) ([]model.OllamaModel, error) {
|
||||
var list []model.OllamaModel
|
||||
db := global.DB.Model(&model.OllamaModel{})
|
||||
for _, opt := range opts {
|
||||
db = opt(db)
|
||||
}
|
||||
err := db.Find(&list).Error
|
||||
return list, err
|
||||
}
|
||||
|
||||
func (u *AiRepo) Page(page, size int, opts ...DBOption) (int64, []model.OllamaModel, error) {
|
||||
var list []model.OllamaModel
|
||||
db := global.DB.Model(&model.OllamaModel{})
|
||||
for _, opt := range opts {
|
||||
db = opt(db)
|
||||
}
|
||||
count := int64(0)
|
||||
db = db.Count(&count)
|
||||
err := db.Limit(size).Offset(size * (page - 1)).Find(&list).Error
|
||||
return count, list, err
|
||||
}
|
||||
|
||||
func (u *AiRepo) Create(item *model.OllamaModel) error {
|
||||
return global.DB.Create(item).Error
|
||||
}
|
||||
|
||||
func (u *AiRepo) Update(id uint, vars map[string]interface{}) error {
|
||||
return global.DB.Model(&model.OllamaModel{}).Where("id = ?", id).Updates(vars).Error
|
||||
}
|
||||
|
||||
func (u *AiRepo) Delete(opts ...DBOption) error {
|
||||
db := global.DB
|
||||
for _, opt := range opts {
|
||||
db = opt(db)
|
||||
}
|
||||
return db.Delete(&model.OllamaModel{}).Error
|
||||
}
|
||||
@@ -15,6 +15,7 @@ type DBOption func(*gorm.DB) *gorm.DB
|
||||
type ICommonRepo interface {
|
||||
WithByID(id uint) DBOption
|
||||
WithByName(name string) DBOption
|
||||
WithByLowerName(name string) DBOption
|
||||
WithByType(tp string) DBOption
|
||||
WithOrderBy(orderStr string) DBOption
|
||||
WithOrderRuleBy(orderBy, order string) DBOption
|
||||
@@ -45,6 +46,12 @@ func (c *CommonRepo) WithByName(name string) DBOption {
|
||||
}
|
||||
}
|
||||
|
||||
func (c *CommonRepo) WithByLowerName(name string) DBOption {
|
||||
return func(g *gorm.DB) *gorm.DB {
|
||||
return g.Where("LOWER(name) = LOWER(?)", name)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *CommonRepo) WithByDate(startTime, endTime time.Time) DBOption {
|
||||
return func(g *gorm.DB) *gorm.DB {
|
||||
return g.Where("start_time > ? AND start_time < ?", startTime, endTime)
|
||||
|
||||
@@ -16,6 +16,7 @@ type ISettingRepo interface {
|
||||
Create(key, value string) error
|
||||
Update(key, value string) error
|
||||
WithByKey(key string) DBOption
|
||||
UpdateOrCreate(key, value string) error
|
||||
|
||||
CreateMonitorBase(model model.MonitorBase) error
|
||||
BatchCreateMonitorIO(ioList []model.MonitorIO) error
|
||||
@@ -85,3 +86,7 @@ func (u *SettingRepo) DelMonitorIO(timeForDelete time.Time) error {
|
||||
func (u *SettingRepo) DelMonitorNet(timeForDelete time.Time) error {
|
||||
return global.MonitorDB.Where("created_at < ?", timeForDelete).Delete(&model.MonitorNetwork{}).Error
|
||||
}
|
||||
|
||||
func (u *SettingRepo) UpdateOrCreate(key, value string) error {
|
||||
return global.DB.Model(&model.Setting{}).Where("key = ?", key).Assign(model.Setting{Key: key, Value: value}).FirstOrCreate(&model.Setting{}).Error
|
||||
}
|
||||
|
||||
@@ -0,0 +1,415 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/backend/utils/common"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/backend/app/dto"
|
||||
"github.com/1Panel-dev/1Panel/backend/app/dto/request"
|
||||
"github.com/1Panel-dev/1Panel/backend/app/model"
|
||||
"github.com/1Panel-dev/1Panel/backend/app/repo"
|
||||
"github.com/1Panel-dev/1Panel/backend/buserr"
|
||||
"github.com/1Panel-dev/1Panel/backend/constant"
|
||||
"github.com/1Panel-dev/1Panel/backend/global"
|
||||
"github.com/1Panel-dev/1Panel/backend/utils/cmd"
|
||||
"github.com/jinzhu/copier"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type AIToolService struct{}
|
||||
|
||||
type IAIToolService interface {
|
||||
Search(search dto.SearchWithPage) (int64, []dto.OllamaModelInfo, error)
|
||||
Create(name string) error
|
||||
Close(name string) error
|
||||
Recreate(name string) error
|
||||
Delete(req dto.ForceDelete) error
|
||||
Sync() ([]dto.OllamaModelDropList, error)
|
||||
LoadDetail(name string) (string, error)
|
||||
BindDomain(req dto.OllamaBindDomain) error
|
||||
GetBindDomain(req dto.OllamaBindDomainReq) (*dto.OllamaBindDomainRes, error)
|
||||
UpdateBindDomain(req dto.OllamaBindDomain) error
|
||||
}
|
||||
|
||||
func NewIAIToolService() IAIToolService {
|
||||
return &AIToolService{}
|
||||
}
|
||||
|
||||
func (u *AIToolService) Search(req dto.SearchWithPage) (int64, []dto.OllamaModelInfo, error) {
|
||||
var options []repo.DBOption
|
||||
if len(req.Info) != 0 {
|
||||
options = append(options, commonRepo.WithLikeName(req.Info))
|
||||
}
|
||||
total, list, err := aiRepo.Page(req.Page, req.PageSize, options...)
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
var dtoLists []dto.OllamaModelInfo
|
||||
for _, itemModel := range list {
|
||||
var item dto.OllamaModelInfo
|
||||
if err := copier.Copy(&item, &itemModel); err != nil {
|
||||
return 0, nil, errors.WithMessage(constant.ErrStructTransform, err.Error())
|
||||
}
|
||||
logPath := path.Join(global.CONF.System.DataDir, "log", "AITools", itemModel.Name)
|
||||
if _, err := os.Stat(logPath); err == nil {
|
||||
item.LogFileExist = true
|
||||
}
|
||||
dtoLists = append(dtoLists, item)
|
||||
}
|
||||
return int64(total), dtoLists, err
|
||||
}
|
||||
|
||||
func (u *AIToolService) LoadDetail(name string) (string, error) {
|
||||
if cmd.CheckIllegal(name) {
|
||||
return "", buserr.New(constant.ErrCmdIllegal)
|
||||
}
|
||||
containerName, err := LoadContainerName()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
stdout, err := cmd.Execf("docker exec %s ollama show %s", containerName, name)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return stdout, err
|
||||
}
|
||||
|
||||
func (u *AIToolService) Create(name string) error {
|
||||
if cmd.CheckIllegal(name) {
|
||||
return buserr.New(constant.ErrCmdIllegal)
|
||||
}
|
||||
modelInfo, _ := aiRepo.Get(commonRepo.WithByName(name))
|
||||
if modelInfo.ID != 0 {
|
||||
return constant.ErrRecordExist
|
||||
}
|
||||
containerName, err := LoadContainerName()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
logItem := path.Join(global.CONF.System.DataDir, "log", "AITools", name)
|
||||
if _, err := os.Stat(path.Dir(logItem)); err != nil && os.IsNotExist(err) {
|
||||
if err = os.MkdirAll(path.Dir(logItem), os.ModePerm); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
info := model.OllamaModel{
|
||||
Name: name,
|
||||
From: "local",
|
||||
Status: constant.StatusWaiting,
|
||||
}
|
||||
if err := aiRepo.Create(&info); err != nil {
|
||||
return err
|
||||
}
|
||||
file, err := os.OpenFile(logItem, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
go pullOllamaModel(file, containerName, info)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *AIToolService) Close(name string) error {
|
||||
if cmd.CheckIllegal(name) {
|
||||
return buserr.New(constant.ErrCmdIllegal)
|
||||
}
|
||||
containerName, err := LoadContainerName()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
stdout, err := cmd.Execf("docker exec %s ollama stop %s", containerName, name)
|
||||
if err != nil {
|
||||
return fmt.Errorf("handle ollama stop %s failed, stdout: %s, err: %v", name, stdout, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *AIToolService) Recreate(name string) error {
|
||||
if cmd.CheckIllegal(name) {
|
||||
return buserr.New(constant.ErrCmdIllegal)
|
||||
}
|
||||
modelInfo, _ := aiRepo.Get(commonRepo.WithByName(name))
|
||||
if modelInfo.ID == 0 {
|
||||
return constant.ErrRecordNotFound
|
||||
}
|
||||
containerName, err := LoadContainerName()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := aiRepo.Update(modelInfo.ID, map[string]interface{}{"status": constant.StatusWaiting, "from": "local"}); err != nil {
|
||||
return err
|
||||
}
|
||||
logItem := path.Join(global.CONF.System.DataDir, "log", "AITools", name)
|
||||
if _, err := os.Stat(path.Dir(logItem)); err != nil && os.IsNotExist(err) {
|
||||
if err = os.MkdirAll(path.Dir(logItem), os.ModePerm); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
file, err := os.OpenFile(logItem, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
go pullOllamaModel(file, containerName, modelInfo)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *AIToolService) Delete(req dto.ForceDelete) error {
|
||||
ollamaList, _ := aiRepo.List(commonRepo.WithIdsIn(req.IDs))
|
||||
if len(ollamaList) == 0 {
|
||||
return constant.ErrRecordNotFound
|
||||
}
|
||||
containerName, err := LoadContainerName()
|
||||
if err != nil && !req.ForceDelete {
|
||||
return err
|
||||
}
|
||||
for _, item := range ollamaList {
|
||||
if item.Status != constant.StatusDeleted {
|
||||
stdout, err := cmd.Execf("docker exec %s ollama rm %s", containerName, item.Name)
|
||||
if err != nil && !req.ForceDelete {
|
||||
return fmt.Errorf("handle ollama rm %s failed, stdout: %s, err: %v", item.Name, stdout, err)
|
||||
}
|
||||
}
|
||||
_ = aiRepo.Delete(commonRepo.WithByID(item.ID))
|
||||
logItem := path.Join(global.CONF.System.DataDir, "log", "AITools", item.Name)
|
||||
_ = os.Remove(logItem)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *AIToolService) Sync() ([]dto.OllamaModelDropList, error) {
|
||||
containerName, err := LoadContainerName()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
stdout, err := cmd.Execf("docker exec %s ollama list", containerName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var list []model.OllamaModel
|
||||
lines := strings.Split(stdout, "\n")
|
||||
for _, line := range lines {
|
||||
parts := strings.Fields(line)
|
||||
if len(parts) < 5 {
|
||||
continue
|
||||
}
|
||||
if parts[0] == "NAME" {
|
||||
continue
|
||||
}
|
||||
list = append(list, model.OllamaModel{Name: parts[0], Size: parts[2] + " " + parts[3]})
|
||||
}
|
||||
listInDB, _ := aiRepo.List()
|
||||
var dropList []dto.OllamaModelDropList
|
||||
for _, itemModel := range listInDB {
|
||||
isExit := false
|
||||
for i := 0; i < len(list); i++ {
|
||||
if list[i].Name == itemModel.Name {
|
||||
_ = aiRepo.Update(itemModel.ID, map[string]interface{}{"status": constant.StatusSuccess, "message": "", "size": list[i].Size})
|
||||
list = append(list[:i], list[(i+1):]...)
|
||||
isExit = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !isExit && itemModel.Status != constant.StatusWaiting {
|
||||
_ = aiRepo.Update(itemModel.ID, map[string]interface{}{"status": constant.StatusDeleted, "message": "not exist", "size": ""})
|
||||
dropList = append(dropList, dto.OllamaModelDropList{ID: itemModel.ID, Name: itemModel.Name})
|
||||
continue
|
||||
}
|
||||
}
|
||||
for _, item := range list {
|
||||
item.Status = constant.StatusSuccess
|
||||
item.From = "remote"
|
||||
_ = aiRepo.Create(&item)
|
||||
}
|
||||
|
||||
return dropList, nil
|
||||
}
|
||||
|
||||
func (u *AIToolService) BindDomain(req dto.OllamaBindDomain) error {
|
||||
nginxInstall, _ := getAppInstallByKey(constant.AppOpenresty)
|
||||
if nginxInstall.ID == 0 {
|
||||
return buserr.New("ErrOpenrestyInstall")
|
||||
}
|
||||
var (
|
||||
ipList []string
|
||||
err error
|
||||
)
|
||||
if len(req.IPList) > 0 {
|
||||
ipList, err = common.HandleIPList(req.IPList)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if req.SSLID > 0 {
|
||||
ssl, err := websiteSSLRepo.GetFirst(commonRepo.WithByID(req.SSLID))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if ssl.Pem == "" {
|
||||
return buserr.New("ErrSSL")
|
||||
}
|
||||
}
|
||||
createWebsiteReq := request.WebsiteCreate{
|
||||
PrimaryDomain: req.Domain,
|
||||
Alias: strings.ToLower(req.Domain),
|
||||
Type: constant.Deployment,
|
||||
AppType: constant.InstalledApp,
|
||||
AppInstallID: req.AppInstallID,
|
||||
}
|
||||
websiteService := NewIWebsiteService()
|
||||
if err := websiteService.CreateWebsite(createWebsiteReq); err != nil {
|
||||
return err
|
||||
}
|
||||
website, err := websiteRepo.GetFirst(websiteRepo.WithAlias(strings.ToLower(req.Domain)))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(ipList) > 0 {
|
||||
if err = ConfigAllowIPs(ipList, website); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if req.SSLID > 0 {
|
||||
sslReq := request.WebsiteHTTPSOp{
|
||||
WebsiteID: website.ID,
|
||||
Enable: true,
|
||||
Type: "existed",
|
||||
WebsiteSSLID: req.SSLID,
|
||||
HttpConfig: "HTTPSOnly",
|
||||
}
|
||||
if _, err = websiteService.OpWebsiteHTTPS(context.Background(), sslReq); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if err = ConfigAIProxy(website); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *AIToolService) GetBindDomain(req dto.OllamaBindDomainReq) (*dto.OllamaBindDomainRes, error) {
|
||||
install, err := appInstallRepo.GetFirst(commonRepo.WithByID(req.AppInstallID))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
res := &dto.OllamaBindDomainRes{}
|
||||
website, _ := websiteRepo.GetFirst(websiteRepo.WithAppInstallId(install.ID))
|
||||
if website.ID == 0 {
|
||||
return res, nil
|
||||
}
|
||||
res.WebsiteID = website.ID
|
||||
res.Domain = website.PrimaryDomain
|
||||
if website.WebsiteSSLID > 0 {
|
||||
res.SSLID = website.WebsiteSSLID
|
||||
ssl, _ := websiteSSLRepo.GetFirst(commonRepo.WithByID(website.WebsiteSSLID))
|
||||
res.AcmeAccountID = ssl.AcmeAccountID
|
||||
}
|
||||
res.ConnUrl = fmt.Sprintf("%s://%s", strings.ToLower(website.Protocol), website.PrimaryDomain)
|
||||
res.AllowIPs = GetAllowIps(website)
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (u *AIToolService) UpdateBindDomain(req dto.OllamaBindDomain) error {
|
||||
nginxInstall, _ := getAppInstallByKey(constant.AppOpenresty)
|
||||
if nginxInstall.ID == 0 {
|
||||
return buserr.New("ErrOpenrestyInstall")
|
||||
}
|
||||
var (
|
||||
ipList []string
|
||||
err error
|
||||
)
|
||||
if len(req.IPList) > 0 {
|
||||
ipList, err = common.HandleIPList(req.IPList)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if req.SSLID > 0 {
|
||||
ssl, err := websiteSSLRepo.GetFirst(commonRepo.WithByID(req.SSLID))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if ssl.Pem == "" {
|
||||
return buserr.New("ErrSSL")
|
||||
}
|
||||
}
|
||||
websiteService := NewIWebsiteService()
|
||||
website, err := websiteRepo.GetFirst(commonRepo.WithByID(req.WebsiteID))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err = ConfigAllowIPs(ipList, website); err != nil {
|
||||
return err
|
||||
}
|
||||
if req.SSLID > 0 {
|
||||
sslReq := request.WebsiteHTTPSOp{
|
||||
WebsiteID: website.ID,
|
||||
Enable: true,
|
||||
Type: "existed",
|
||||
WebsiteSSLID: req.SSLID,
|
||||
HttpConfig: "HTTPSOnly",
|
||||
}
|
||||
if _, err = websiteService.OpWebsiteHTTPS(context.Background(), sslReq); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
if website.WebsiteSSLID > 0 && req.SSLID == 0 {
|
||||
sslReq := request.WebsiteHTTPSOp{
|
||||
WebsiteID: website.ID,
|
||||
Enable: false,
|
||||
}
|
||||
if _, err = websiteService.OpWebsiteHTTPS(context.Background(), sslReq); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func LoadContainerName() (string, error) {
|
||||
ollamaBaseInfo, err := appInstallRepo.LoadBaseInfo("ollama", "")
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("ollama service is not found, err: %v", err)
|
||||
}
|
||||
if ollamaBaseInfo.Status != constant.Running {
|
||||
return "", fmt.Errorf("container %s of ollama is not running, please check and retry!", ollamaBaseInfo.ContainerName)
|
||||
}
|
||||
return ollamaBaseInfo.ContainerName, nil
|
||||
}
|
||||
|
||||
func pullOllamaModel(file *os.File, containerName string, info model.OllamaModel) {
|
||||
defer file.Close()
|
||||
cmd := exec.Command("docker", "exec", containerName, "ollama", "pull", info.Name)
|
||||
multiWriter := io.MultiWriter(os.Stdout, file)
|
||||
cmd.Stdout = multiWriter
|
||||
cmd.Stderr = multiWriter
|
||||
_ = cmd.Run()
|
||||
itemSize, err := loadModelSize(info.Name, containerName)
|
||||
if len(itemSize) != 0 {
|
||||
_ = aiRepo.Update(info.ID, map[string]interface{}{"status": constant.StatusSuccess, "size": itemSize})
|
||||
} else {
|
||||
_ = aiRepo.Update(info.ID, map[string]interface{}{"status": constant.StatusFailed, "message": err.Error()})
|
||||
}
|
||||
_, _ = file.WriteString("ollama pull completed!")
|
||||
}
|
||||
|
||||
func loadModelSize(name string, containerName string) (string, error) {
|
||||
stdout, err := cmd.Execf("docker exec %s ollama list | grep %s", containerName, name)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
lines := strings.Split(string(stdout), "\n")
|
||||
for _, line := range lines {
|
||||
parts := strings.Fields(line)
|
||||
if len(parts) < 5 {
|
||||
continue
|
||||
}
|
||||
return parts[2] + " " + parts[3], nil
|
||||
}
|
||||
return "", fmt.Errorf("no such model %s in ollama list, std: %s", name, string(stdout))
|
||||
}
|
||||
+53
-35
@@ -5,6 +5,7 @@ import (
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/gin-gonic/gin"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
@@ -34,9 +35,9 @@ type AppService struct {
|
||||
}
|
||||
|
||||
type IAppService interface {
|
||||
PageApp(req request.AppSearch) (interface{}, error)
|
||||
GetAppTags() ([]response.TagDTO, error)
|
||||
GetApp(key string) (*response.AppDTO, error)
|
||||
PageApp(ctx *gin.Context, req request.AppSearch) (interface{}, error)
|
||||
GetAppTags(ctx *gin.Context) ([]response.TagDTO, error)
|
||||
GetApp(ctx *gin.Context, key string) (*response.AppDTO, error)
|
||||
GetAppDetail(appId uint, version, appType string) (response.AppDetailDTO, error)
|
||||
Install(ctx context.Context, req request.AppInstallCreate) (*model.AppInstall, error)
|
||||
SyncAppListFromRemote() error
|
||||
@@ -50,7 +51,7 @@ func NewIAppService() IAppService {
|
||||
return &AppService{}
|
||||
}
|
||||
|
||||
func (a AppService) PageApp(req request.AppSearch) (interface{}, error) {
|
||||
func (a AppService) PageApp(ctx *gin.Context, req request.AppSearch) (interface{}, error) {
|
||||
var opts []repo.DBOption
|
||||
opts = append(opts, appRepo.OrderByRecommend())
|
||||
if req.Name != "" {
|
||||
@@ -89,31 +90,24 @@ func (a AppService) PageApp(req request.AppSearch) (interface{}, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var appDTOs []*response.AppDto
|
||||
var appDTOs []*response.AppItem
|
||||
lang := strings.ToLower(common.GetLang(ctx))
|
||||
for _, ap := range apps {
|
||||
appDTO := &response.AppDto{
|
||||
ID: ap.ID,
|
||||
Name: ap.Name,
|
||||
Key: ap.Key,
|
||||
Type: ap.Type,
|
||||
Icon: ap.Icon,
|
||||
ShortDescZh: ap.ShortDescZh,
|
||||
ShortDescEn: ap.ShortDescEn,
|
||||
Resource: ap.Resource,
|
||||
Limit: ap.Limit,
|
||||
appDTO := &response.AppItem{
|
||||
ID: ap.ID,
|
||||
Name: ap.Name,
|
||||
Key: ap.Key,
|
||||
Type: ap.Type,
|
||||
Icon: ap.Icon,
|
||||
Resource: ap.Resource,
|
||||
Limit: ap.Limit,
|
||||
GpuSupport: ap.GpuSupport,
|
||||
}
|
||||
appDTO.Description = ap.GetDescription(ctx)
|
||||
appDTOs = append(appDTOs, appDTO)
|
||||
appTags, err := appTagRepo.GetByAppId(ap.ID)
|
||||
tags, err := getAppTags(ap.ID, lang)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
var tagIds []uint
|
||||
for _, at := range appTags {
|
||||
tagIds = append(tagIds, at.TagId)
|
||||
}
|
||||
tags, err := tagRepo.GetByIds(tagIds)
|
||||
if err != nil {
|
||||
continue
|
||||
return nil, err
|
||||
}
|
||||
appDTO.Tags = tags
|
||||
installs, _ := appInstallRepo.ListBy(appInstallRepo.WithAppId(ap.ID))
|
||||
@@ -125,18 +119,32 @@ func (a AppService) PageApp(req request.AppSearch) (interface{}, error) {
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (a AppService) GetAppTags() ([]response.TagDTO, error) {
|
||||
func (a AppService) GetAppTags(ctx *gin.Context) ([]response.TagDTO, error) {
|
||||
tags, _ := tagRepo.All()
|
||||
res := make([]response.TagDTO, 0)
|
||||
lang := strings.ToLower(common.GetLang(ctx))
|
||||
for _, tag := range tags {
|
||||
res = append(res, response.TagDTO{
|
||||
Tag: tag,
|
||||
})
|
||||
tagDTO := response.TagDTO{
|
||||
ID: tag.ID,
|
||||
Key: tag.Key,
|
||||
}
|
||||
var translations = make(map[string]string)
|
||||
_ = json.Unmarshal([]byte(tag.Translations), &translations)
|
||||
if name, ok := translations[lang]; ok && name != "" {
|
||||
tagDTO.Name = name
|
||||
} else {
|
||||
if lang == "zh" || lang == "zh-Hant" {
|
||||
tagDTO.Name = tag.Name
|
||||
} else {
|
||||
tagDTO.Name = tag.Key
|
||||
}
|
||||
}
|
||||
res = append(res, tagDTO)
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (a AppService) GetApp(key string) (*response.AppDTO, error) {
|
||||
func (a AppService) GetApp(ctx *gin.Context, key string) (*response.AppDTO, error) {
|
||||
var appDTO response.AppDTO
|
||||
if key == "postgres" {
|
||||
key = "postgresql"
|
||||
@@ -146,6 +154,7 @@ func (a AppService) GetApp(key string) (*response.AppDTO, error) {
|
||||
return nil, err
|
||||
}
|
||||
appDTO.App = app
|
||||
appDTO.App.Description = app.GetDescription(ctx)
|
||||
details, err := appDetailRepo.GetBy(appDetailRepo.WithAppId(app.ID))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -155,7 +164,12 @@ func (a AppService) GetApp(key string) (*response.AppDTO, error) {
|
||||
versionsRaw = append(versionsRaw, detail.Version)
|
||||
}
|
||||
appDTO.Versions = common.GetSortedVersions(versionsRaw)
|
||||
|
||||
tags, err := getAppTags(app.ID, strings.ToLower(common.GetLang(ctx)))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
appDTO.GpuSupport = app.GpuSupport
|
||||
appDTO.Tags = tags
|
||||
return &appDTO, nil
|
||||
}
|
||||
|
||||
@@ -252,6 +266,7 @@ func (a AppService) GetAppDetail(appID uint, version, appType string) (response.
|
||||
if err := checkLimit(app); err != nil {
|
||||
appDetailDTO.Enable = false
|
||||
}
|
||||
appDetailDTO.GpuSupport = app.GpuSupport
|
||||
return appDetailDTO, nil
|
||||
}
|
||||
func (a AppService) GetAppDetailByID(id uint) (*response.AppDetailDTO, error) {
|
||||
@@ -296,7 +311,8 @@ func (a AppService) Install(ctx context.Context, req request.AppInstallCreate) (
|
||||
err = buserr.WithDetail(constant.Err1PanelNetworkFailed, err.Error(), nil)
|
||||
return
|
||||
}
|
||||
if list, _ := appInstallRepo.ListBy(commonRepo.WithByName(req.Name)); len(list) > 0 {
|
||||
|
||||
if list, _ := appInstallRepo.ListBy(commonRepo.WithByLowerName(req.Name)); len(list) > 0 {
|
||||
err = buserr.New(constant.ErrAppNameExist)
|
||||
return
|
||||
}
|
||||
@@ -827,10 +843,11 @@ func (a AppService) SyncAppListFromRemote() (err error) {
|
||||
oldAppIds []uint
|
||||
)
|
||||
for _, t := range list.Extra.Tags {
|
||||
translations, _ := json.Marshal(t.Locales)
|
||||
tags = append(tags, &model.Tag{
|
||||
Key: t.Key,
|
||||
Name: t.Name,
|
||||
Sort: t.Sort,
|
||||
Key: t.Key,
|
||||
Translations: string(translations),
|
||||
Sort: t.Sort,
|
||||
})
|
||||
}
|
||||
oldApps, err := appRepo.GetBy(appRepo.WithResource(constant.AppResourceRemote))
|
||||
@@ -848,6 +865,7 @@ func (a AppService) SyncAppListFromRemote() (err error) {
|
||||
global.LOG.Infof("Starting synchronization of application details...")
|
||||
for _, l := range list.Apps {
|
||||
app := appsMap[l.AppProperty.Key]
|
||||
app.GpuSupport = l.AppProperty.GpuSupport
|
||||
|
||||
if l.AppProperty.Version > 0 && common.CompareVersion(strconv.FormatFloat(l.AppProperty.Version, 'f', -1, 64), setting.SystemVersion) {
|
||||
delete(appsMap, l.AppProperty.Key)
|
||||
|
||||
@@ -750,6 +750,7 @@ func (a *AppInstallService) GetParams(id uint) (*response.AppConfig, error) {
|
||||
}
|
||||
res.AppContainerConfig = config
|
||||
res.HostMode = isHostModel(install.DockerCompose)
|
||||
res.GpuConfig = isGpuConfig(install.DockerCompose)
|
||||
return &res, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -1051,6 +1051,8 @@ func getApps(oldApps []model.App, items []dto.AppDefine) map[string]model.App {
|
||||
app.Key = key
|
||||
app.ShortDescZh = config.ShortDescZh
|
||||
app.ShortDescEn = config.ShortDescEn
|
||||
description, _ := json.Marshal(config.Description)
|
||||
app.Description = string(description)
|
||||
app.Website = config.Website
|
||||
app.Document = config.Document
|
||||
app.Github = config.Github
|
||||
@@ -1150,14 +1152,31 @@ func handleLocalApp(appDir string) (app *model.App, err error) {
|
||||
err = buserr.WithMap(constant.ErrFileParseApp, map[string]interface{}{"name": "data.yml", "err": err.Error()}, err)
|
||||
return
|
||||
}
|
||||
app = &localAppDefine.AppProperty
|
||||
appDefine := localAppDefine.AppProperty
|
||||
app = &model.App{}
|
||||
app.Name = appDefine.Name
|
||||
app.TagsKey = append(appDefine.Tags, "Local")
|
||||
app.Type = appDefine.Type
|
||||
app.CrossVersionUpdate = appDefine.CrossVersionUpdate
|
||||
app.Limit = appDefine.Limit
|
||||
app.Recommend = appDefine.Recommend
|
||||
app.Website = appDefine.Website
|
||||
app.Github = appDefine.Github
|
||||
app.Document = appDefine.Document
|
||||
if appDefine.ShortDescZh != "" {
|
||||
app.ShortDescZh = appDefine.ShortDescZh
|
||||
}
|
||||
if appDefine.ShortDescEn != "" {
|
||||
app.ShortDescEn = appDefine.ShortDescEn
|
||||
}
|
||||
desc, _ := json.Marshal(appDefine.Description)
|
||||
app.Description = string(desc)
|
||||
|
||||
app.Key = "local" + appDefine.Key
|
||||
app.Resource = constant.AppResourceLocal
|
||||
app.Status = constant.AppNormal
|
||||
app.Recommend = 9999
|
||||
app.TagsKey = append(app.TagsKey, "Local")
|
||||
app.Key = "local" + app.Key
|
||||
readMePath := path.Join(appDir, "README.md")
|
||||
readMeByte, err := fileOp.GetContent(readMePath)
|
||||
readMeByte, err := fileOp.GetContent(path.Join(appDir, "README.md"))
|
||||
if err == nil {
|
||||
app.ReadMe = string(readMeByte)
|
||||
}
|
||||
@@ -1319,9 +1338,10 @@ func handleInstalled(appInstallList []model.AppInstall, updated bool, sync bool)
|
||||
Path: installed.GetPath(),
|
||||
CreatedAt: installed.CreatedAt,
|
||||
App: response.AppDetail{
|
||||
Github: installed.App.Github,
|
||||
Website: installed.App.Website,
|
||||
Document: installed.App.Document,
|
||||
Github: installed.App.Github,
|
||||
Website: installed.App.Website,
|
||||
Document: installed.App.Document,
|
||||
GpuSupport: installed.App.GpuSupport,
|
||||
},
|
||||
}
|
||||
if updated {
|
||||
@@ -1480,6 +1500,20 @@ func addDockerComposeCommonParam(composeMap map[string]interface{}, serviceName
|
||||
deploy["resources"] = resource
|
||||
serviceValue["deploy"] = deploy
|
||||
|
||||
if req.GpuConfig {
|
||||
resource["reservations"] = map[string]interface{}{
|
||||
"devices": []map[string]interface{}{
|
||||
{
|
||||
"driver": "nvidia",
|
||||
"count": "all",
|
||||
"capabilities": []string{"gpu"},
|
||||
},
|
||||
},
|
||||
}
|
||||
} else {
|
||||
delete(resource, "reservations")
|
||||
}
|
||||
|
||||
ports, ok := serviceValue["ports"].([]interface{})
|
||||
if ok {
|
||||
for i, port := range ports {
|
||||
@@ -1581,9 +1615,74 @@ func isHostModel(dockerCompose string) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func isGpuConfig(dockerCompose string) bool {
|
||||
composeMap := make(map[string]interface{})
|
||||
_ = yaml.Unmarshal([]byte(dockerCompose), &composeMap)
|
||||
services, serviceValid := composeMap["services"].(map[string]interface{})
|
||||
if !serviceValid {
|
||||
return false
|
||||
}
|
||||
for _, service := range services {
|
||||
serviceValue := service.(map[string]interface{})
|
||||
deploy := map[string]interface{}{}
|
||||
if de, ok := serviceValue["deploy"]; ok {
|
||||
deploy = de.(map[string]interface{})
|
||||
}
|
||||
resource := map[string]interface{}{}
|
||||
if res, ok := deploy["resources"]; ok {
|
||||
resource = res.(map[string]interface{})
|
||||
}
|
||||
if reservations, ok := resource["reservations"]; ok {
|
||||
reservationsMap := reservations.(map[string]interface{})
|
||||
if _, dOk := reservationsMap["devices"]; dOk {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func RequestDownloadCallBack(downloadCallBackUrl string) {
|
||||
if downloadCallBackUrl == "" {
|
||||
return
|
||||
}
|
||||
_, _, _ = httpUtil.HandleGet(downloadCallBackUrl, http.MethodGet, constant.TimeOut5s)
|
||||
}
|
||||
|
||||
func getAppTags(appID uint, lang string) ([]response.TagDTO, error) {
|
||||
appTags, err := appTagRepo.GetByAppId(appID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var tagIds []uint
|
||||
for _, at := range appTags {
|
||||
tagIds = append(tagIds, at.TagId)
|
||||
}
|
||||
tags, err := tagRepo.GetByIds(tagIds)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var res []response.TagDTO
|
||||
for _, t := range tags {
|
||||
if t.Name != "" {
|
||||
tagDTO := response.TagDTO{
|
||||
ID: t.ID,
|
||||
Key: t.Key,
|
||||
Name: t.Name,
|
||||
}
|
||||
res = append(res, tagDTO)
|
||||
} else {
|
||||
var translations = make(map[string]string)
|
||||
_ = json.Unmarshal([]byte(t.Translations), &translations)
|
||||
if name, ok := translations[lang]; ok {
|
||||
tagDTO := response.TagDTO{
|
||||
ID: t.ID,
|
||||
Key: t.Key,
|
||||
Name: name,
|
||||
}
|
||||
res = append(res, tagDTO)
|
||||
}
|
||||
}
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
+31
-19
@@ -38,16 +38,11 @@ func (u *AuthService) Login(c *gin.Context, info dto.Login, entrance string) (*d
|
||||
if err != nil {
|
||||
return nil, errors.WithMessage(constant.ErrRecordNotFound, err.Error())
|
||||
}
|
||||
passwordSetting, err := settingRepo.Get(settingRepo.WithByKey("Password"))
|
||||
if err != nil {
|
||||
return nil, errors.WithMessage(constant.ErrRecordNotFound, err.Error())
|
||||
}
|
||||
pass, err := encrypt.StringDecrypt(passwordSetting.Value)
|
||||
if err != nil {
|
||||
if nameSetting.Value != info.Name {
|
||||
return nil, constant.ErrAuth
|
||||
}
|
||||
if !hmac.Equal([]byte(info.Password), []byte(pass)) || nameSetting.Value != info.Name {
|
||||
return nil, constant.ErrAuth
|
||||
if err = checkPassword(info.Password); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
entranceSetting, err := settingRepo.Get(settingRepo.WithByKey("SecurityEntrance"))
|
||||
if err != nil {
|
||||
@@ -83,17 +78,12 @@ func (u *AuthService) MFALogin(c *gin.Context, info dto.MFALogin, entrance strin
|
||||
if err != nil {
|
||||
return nil, errors.WithMessage(constant.ErrRecordNotFound, err.Error())
|
||||
}
|
||||
passwordSetting, err := settingRepo.Get(settingRepo.WithByKey("Password"))
|
||||
if err != nil {
|
||||
return nil, errors.WithMessage(constant.ErrRecordNotFound, err.Error())
|
||||
}
|
||||
pass, err := encrypt.StringDecrypt(passwordSetting.Value)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !hmac.Equal([]byte(info.Password), []byte(pass)) || nameSetting.Value != info.Name {
|
||||
if nameSetting.Value != info.Name {
|
||||
return nil, constant.ErrAuth
|
||||
}
|
||||
if err = checkPassword(info.Password); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
entranceSetting, err := settingRepo.Get(settingRepo.WithByKey("SecurityEntrance"))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -214,8 +204,30 @@ func (u *AuthService) GetSecurityEntrance() string {
|
||||
func (u *AuthService) IsLogin(c *gin.Context) bool {
|
||||
sID, _ := c.Cookie(constant.SessionName)
|
||||
_, err := global.SESSION.Get(sID)
|
||||
return err == nil
|
||||
}
|
||||
|
||||
func checkPassword(password string) error {
|
||||
priKey, _ := settingRepo.Get(settingRepo.WithByKey("PASSWORD_PRIVATE_KEY"))
|
||||
|
||||
privateKey, err := encrypt.ParseRSAPrivateKey(priKey.Value)
|
||||
if err != nil {
|
||||
return false
|
||||
return err
|
||||
}
|
||||
return true
|
||||
loginPassword, err := encrypt.DecryptPassword(password, privateKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
passwordSetting, err := settingRepo.Get(settingRepo.WithByKey("Password"))
|
||||
if err != nil {
|
||||
return errors.WithMessage(constant.ErrRecordNotFound, err.Error())
|
||||
}
|
||||
existPassword, err := encrypt.StringDecrypt(passwordSetting.Value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !hmac.Equal([]byte(loginPassword), []byte(existPassword)) {
|
||||
return constant.ErrAuth
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
@@ -30,7 +29,9 @@ type BackupService struct{}
|
||||
type IBackupService interface {
|
||||
List() ([]dto.BackupInfo, error)
|
||||
SearchRecordsWithPage(search dto.RecordSearch) (int64, []dto.BackupRecords, error)
|
||||
LoadSize(req dto.RecordSearch) ([]dto.BackupFile, error)
|
||||
SearchRecordsByCronjobWithPage(search dto.RecordSearchByCronjob) (int64, []dto.BackupRecords, error)
|
||||
LoadSizeByCronjob(req dto.RecordSearchByCronjob) ([]dto.BackupFile, error)
|
||||
LoadOneDriveInfo() (dto.OneDriveInfo, error)
|
||||
DownloadRecord(info dto.DownloadRecord) (string, error)
|
||||
Create(backupDto dto.BackupOperate) error
|
||||
@@ -94,11 +95,29 @@ func (u *BackupService) SearchRecordsWithPage(search dto.RecordSearch) (int64, [
|
||||
return 0, nil, err
|
||||
}
|
||||
|
||||
datas, err := u.loadRecordSize(records)
|
||||
sort.Slice(datas, func(i, j int) bool {
|
||||
return datas[i].CreatedAt.After(datas[j].CreatedAt)
|
||||
})
|
||||
return total, datas, err
|
||||
var list []dto.BackupRecords
|
||||
for _, item := range records {
|
||||
var itemRecord dto.BackupRecords
|
||||
if err := copier.Copy(&itemRecord, &item); err != nil {
|
||||
continue
|
||||
}
|
||||
list = append(list, itemRecord)
|
||||
}
|
||||
return total, list, err
|
||||
}
|
||||
|
||||
func (u *BackupService) LoadSize(req dto.RecordSearch) ([]dto.BackupFile, error) {
|
||||
_, records, err := backupRepo.PageRecord(
|
||||
req.Page, req.PageSize,
|
||||
commonRepo.WithOrderBy("created_at desc"),
|
||||
commonRepo.WithByName(req.Name),
|
||||
commonRepo.WithByType(req.Type),
|
||||
backupRepo.WithByDetailName(req.DetailName),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return u.loadRecordSize(records)
|
||||
}
|
||||
|
||||
func (u *BackupService) ListAppRecords(name, detailName, fileName string) ([]model.BackupRecord, error) {
|
||||
@@ -125,11 +144,27 @@ func (u *BackupService) SearchRecordsByCronjobWithPage(search dto.RecordSearchBy
|
||||
return 0, nil, err
|
||||
}
|
||||
|
||||
datas, err := u.loadRecordSize(records)
|
||||
sort.Slice(datas, func(i, j int) bool {
|
||||
return datas[i].CreatedAt.After(datas[j].CreatedAt)
|
||||
})
|
||||
return total, datas, err
|
||||
var list []dto.BackupRecords
|
||||
for _, item := range records {
|
||||
var itemRecord dto.BackupRecords
|
||||
if err := copier.Copy(&itemRecord, &item); err != nil {
|
||||
continue
|
||||
}
|
||||
list = append(list, itemRecord)
|
||||
}
|
||||
return total, list, err
|
||||
}
|
||||
|
||||
func (u *BackupService) LoadSizeByCronjob(req dto.RecordSearchByCronjob) ([]dto.BackupFile, error) {
|
||||
_, records, err := backupRepo.PageRecord(
|
||||
req.Page, req.PageSize,
|
||||
commonRepo.WithOrderBy("created_at desc"),
|
||||
backupRepo.WithByCronID(req.CronjobID),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return u.loadRecordSize(records)
|
||||
}
|
||||
|
||||
type loadSizeHelper struct {
|
||||
@@ -482,15 +517,14 @@ func (u *BackupService) loadAccessToken(backup *model.BackupAccount) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *BackupService) loadRecordSize(records []model.BackupRecord) ([]dto.BackupRecords, error) {
|
||||
var datas []dto.BackupRecords
|
||||
func (u *BackupService) loadRecordSize(records []model.BackupRecord) ([]dto.BackupFile, error) {
|
||||
var datas []dto.BackupFile
|
||||
clientMap := make(map[string]loadSizeHelper)
|
||||
var wg sync.WaitGroup
|
||||
for i := 0; i < len(records); i++ {
|
||||
var item dto.BackupRecords
|
||||
if err := copier.Copy(&item, &records[i]); err != nil {
|
||||
return nil, errors.WithMessage(constant.ErrStructTransform, err.Error())
|
||||
}
|
||||
var item dto.BackupFile
|
||||
item.ID = records[i].ID
|
||||
item.Name = records[i].FileName
|
||||
itemPath := path.Join(records[i].FileDir, records[i].FileName)
|
||||
if _, ok := clientMap[records[i].Source]; !ok {
|
||||
backup, err := backupRepo.Get(commonRepo.WithByType(records[i].Source))
|
||||
|
||||
@@ -2,13 +2,14 @@ package service
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/1Panel-dev/1Panel/backend/constant"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/backend/constant"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/backend/buserr"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/backend/app/dto"
|
||||
@@ -169,8 +170,9 @@ func handleMysqlRecover(req dto.CommonRecover, isRollback bool) error {
|
||||
Timeout: 300,
|
||||
}); err != nil {
|
||||
global.LOG.Errorf("rollback mysql db %s from %s failed, err: %v", req.DetailName, rollbackFile, err)
|
||||
} else {
|
||||
global.LOG.Infof("rollback mysql db %s from %s successful", req.DetailName, rollbackFile)
|
||||
}
|
||||
global.LOG.Infof("rollback mysql db %s from %s successful", req.DetailName, rollbackFile)
|
||||
_ = os.RemoveAll(rollbackFile)
|
||||
} else {
|
||||
_ = os.RemoveAll(rollbackFile)
|
||||
@@ -186,6 +188,7 @@ func handleMysqlRecover(req dto.CommonRecover, isRollback bool) error {
|
||||
|
||||
Timeout: 300,
|
||||
}); err != nil {
|
||||
global.LOG.Errorf("recover mysql db %s from %s failed, err: %v", req.DetailName, req.File, err)
|
||||
return err
|
||||
}
|
||||
isOk = true
|
||||
|
||||
@@ -2,13 +2,14 @@ package service
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/1Panel-dev/1Panel/backend/constant"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/backend/constant"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/backend/buserr"
|
||||
"github.com/1Panel-dev/1Panel/backend/utils/common"
|
||||
pgclient "github.com/1Panel-dev/1Panel/backend/utils/postgresql/client"
|
||||
@@ -157,8 +158,9 @@ func handlePostgresqlRecover(req dto.CommonRecover, isRollback bool) error {
|
||||
Timeout: 300,
|
||||
}); err != nil {
|
||||
global.LOG.Errorf("rollback postgresql db %s from %s failed, err: %v", req.DetailName, rollbackFile, err)
|
||||
} else {
|
||||
global.LOG.Infof("rollback postgresql db %s from %s successful", req.DetailName, rollbackFile)
|
||||
}
|
||||
global.LOG.Infof("rollback postgresql db %s from %s successful", req.DetailName, rollbackFile)
|
||||
_ = os.RemoveAll(rollbackFile)
|
||||
} else {
|
||||
_ = os.RemoveAll(rollbackFile)
|
||||
@@ -171,6 +173,7 @@ func handlePostgresqlRecover(req dto.CommonRecover, isRollback bool) error {
|
||||
Username: dbInfo.Username,
|
||||
Timeout: 300,
|
||||
}); err != nil {
|
||||
global.LOG.Errorf("recover postgresql db %s from %s failed, err: %v", req.DetailName, req.File, err)
|
||||
return err
|
||||
}
|
||||
isOk = true
|
||||
|
||||
@@ -255,14 +255,14 @@ func (u *ContainerService) ContainerListStats() ([]dto.ContainerListStats, error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var datas []dto.ContainerListStats
|
||||
datas := make([]dto.ContainerListStats, len(list))
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(len(list))
|
||||
for i := 0; i < len(list); i++ {
|
||||
go func(item types.Container) {
|
||||
datas = append(datas, loadCpuAndMem(client, item.ID))
|
||||
go func(index int, item types.Container) {
|
||||
datas[index] = loadCpuAndMem(client, item.ID)
|
||||
wg.Done()
|
||||
}(list[i])
|
||||
}(i, list[i])
|
||||
}
|
||||
wg.Wait()
|
||||
return datas, nil
|
||||
@@ -937,15 +937,27 @@ func calculateCPUPercentUnix(stats *types.StatsJSON) float64 {
|
||||
}
|
||||
return cpuPercent
|
||||
}
|
||||
|
||||
func calculateMemPercentUnix(memStats types.MemoryStats) float64 {
|
||||
memPercent := 0.0
|
||||
memUsage := float64(memStats.Usage)
|
||||
memLimit := float64(memStats.Limit)
|
||||
memUsage := calculateMemUsageUnixNoCache(memStats)
|
||||
memLimit := memStats.Limit
|
||||
if memUsage > 0.0 && memLimit > 0.0 {
|
||||
memPercent = (memUsage / memLimit) * 100.0
|
||||
memPercent = (float64(memUsage) / float64(memLimit)) * 100.0
|
||||
}
|
||||
return memPercent
|
||||
}
|
||||
|
||||
func calculateMemUsageUnixNoCache(mem types.MemoryStats) uint64 {
|
||||
if v, isCgroup1 := mem.Stats["total_inactive_file"]; isCgroup1 && v < mem.Usage {
|
||||
return mem.Usage - v
|
||||
}
|
||||
if v := mem.Stats["inactive_file"]; v < mem.Usage {
|
||||
return mem.Usage - v
|
||||
}
|
||||
return mem.Usage
|
||||
}
|
||||
|
||||
func calculateBlockIO(blkio types.BlkioStats) (blkRead float64, blkWrite float64) {
|
||||
for _, bioEntry := range blkio.IoServiceBytesRecursive {
|
||||
switch strings.ToLower(bioEntry.Op) {
|
||||
@@ -1063,7 +1075,7 @@ func loadCpuAndMem(client *client.Client, container string) dto.ContainerListSta
|
||||
data.PercpuUsage = len(stats.CPUStats.CPUUsage.PercpuUsage)
|
||||
|
||||
data.MemoryCache = stats.MemoryStats.Stats["cache"]
|
||||
data.MemoryUsage = stats.MemoryStats.Usage
|
||||
data.MemoryUsage = calculateMemUsageUnixNoCache(stats.MemoryStats)
|
||||
data.MemoryLimit = stats.MemoryStats.Limit
|
||||
|
||||
data.MemoryPercent = calculateMemPercentUnix(stats.MemoryStats)
|
||||
@@ -1183,9 +1195,10 @@ func loadConfigInfo(isCreate bool, req dto.ContainerOperate, oldContainer *types
|
||||
for _, volume := range req.Volumes {
|
||||
if volume.Type == "volume" {
|
||||
hostConf.Mounts = append(hostConf.Mounts, mount.Mount{
|
||||
Type: mount.Type(volume.Type),
|
||||
Source: volume.SourceDir,
|
||||
Target: volume.ContainerDir,
|
||||
Type: mount.Type(volume.Type),
|
||||
Source: volume.SourceDir,
|
||||
Target: volume.ContainerDir,
|
||||
ReadOnly: volume.Mode == "ro",
|
||||
})
|
||||
config.Volumes[volume.ContainerDir] = struct{}{}
|
||||
} else {
|
||||
@@ -1262,12 +1275,12 @@ func loadContainerPortForInfo(itemPorts []types.Port) []dto.PortHelper {
|
||||
var exposedPorts []dto.PortHelper
|
||||
samePortMap := make(map[string]dto.PortHelper)
|
||||
ports := transPortToStr(itemPorts)
|
||||
var itemPort dto.PortHelper
|
||||
for _, item := range ports {
|
||||
itemStr := strings.Split(item, "->")
|
||||
if len(itemStr) < 2 {
|
||||
continue
|
||||
}
|
||||
var itemPort dto.PortHelper
|
||||
lastIndex := strings.LastIndex(itemStr[0], ":")
|
||||
if lastIndex == -1 {
|
||||
itemPort.HostPort = itemStr[0]
|
||||
|
||||
@@ -10,19 +10,19 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/backend/constant"
|
||||
"github.com/shirou/gopsutil/v3/load"
|
||||
"github.com/shirou/gopsutil/v3/mem"
|
||||
"github.com/shirou/gopsutil/v3/net"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/backend/app/dto"
|
||||
"github.com/1Panel-dev/1Panel/backend/constant"
|
||||
"github.com/1Panel-dev/1Panel/backend/global"
|
||||
"github.com/1Panel-dev/1Panel/backend/utils/ai_tools/gpu"
|
||||
"github.com/1Panel-dev/1Panel/backend/utils/ai_tools/xpu"
|
||||
"github.com/1Panel-dev/1Panel/backend/utils/cmd"
|
||||
"github.com/1Panel-dev/1Panel/backend/utils/copier"
|
||||
"github.com/1Panel-dev/1Panel/backend/utils/xpack"
|
||||
"github.com/shirou/gopsutil/v3/cpu"
|
||||
"github.com/shirou/gopsutil/v3/disk"
|
||||
"github.com/shirou/gopsutil/v3/host"
|
||||
"github.com/shirou/gopsutil/v3/load"
|
||||
"github.com/shirou/gopsutil/v3/mem"
|
||||
"github.com/shirou/gopsutil/v3/net"
|
||||
)
|
||||
|
||||
type DashboardService struct{}
|
||||
@@ -341,7 +341,17 @@ func loadDiskInfo() []dto.DiskInfo {
|
||||
}
|
||||
|
||||
func loadGPUInfo() []dto.GPUInfo {
|
||||
list := xpack.LoadGpuInfo()
|
||||
ok, client := gpu.New()
|
||||
var list []interface{}
|
||||
if ok {
|
||||
info, err := client.LoadGpuInfo()
|
||||
if err != nil || len(info.GPUs) == 0 {
|
||||
return nil
|
||||
}
|
||||
for _, item := range info.GPUs {
|
||||
list = append(list, item)
|
||||
}
|
||||
}
|
||||
if len(list) == 0 {
|
||||
return nil
|
||||
}
|
||||
@@ -359,7 +369,17 @@ func loadGPUInfo() []dto.GPUInfo {
|
||||
}
|
||||
|
||||
func loadXpuInfo() []dto.XPUInfo {
|
||||
list := xpack.LoadXpuInfo()
|
||||
var list []interface{}
|
||||
ok, xpuClient := xpu.New()
|
||||
if ok {
|
||||
xpus, err := xpuClient.LoadDashData()
|
||||
if err != nil || len(xpus) == 0 {
|
||||
return nil
|
||||
}
|
||||
for _, item := range xpus {
|
||||
list = append(list, item)
|
||||
}
|
||||
}
|
||||
if len(list) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -50,10 +50,6 @@ func (u *DBCommonService) LoadDatabaseFile(req dto.OperationWithNameAndType) (st
|
||||
filePath = path.Join(global.CONF.System.DataDir, fmt.Sprintf("apps/postgresql/%s/data/postgresql.conf", req.Name))
|
||||
case "redis-conf":
|
||||
filePath = path.Join(global.CONF.System.DataDir, fmt.Sprintf("apps/redis/%s/conf/redis.conf", req.Name))
|
||||
case "mysql-slow-logs":
|
||||
filePath = path.Join(global.CONF.System.DataDir, fmt.Sprintf("apps/mysql/%s/data/1Panel-slow.log", req.Name))
|
||||
case "mariadb-slow-logs":
|
||||
filePath = path.Join(global.CONF.System.DataDir, fmt.Sprintf("apps/mariadb/%s/db/data/1Panel-slow.log", req.Name))
|
||||
}
|
||||
if _, err := os.Stat(filePath); err != nil {
|
||||
return "", buserr.New("ErrHttpReqNotFound")
|
||||
|
||||
@@ -12,6 +12,8 @@ var (
|
||||
appInstallRepo = repo.NewIAppInstallRepo()
|
||||
appInstallResourceRepo = repo.NewIAppInstallResourceRpo()
|
||||
|
||||
aiRepo = repo.NewIAiRepo()
|
||||
|
||||
mysqlRepo = repo.NewIMysqlRepo()
|
||||
postgresqlRepo = repo.NewIPostgresqlRepo()
|
||||
databaseRepo = repo.NewIDatabaseRepo()
|
||||
|
||||
@@ -50,6 +50,7 @@ type IFileService interface {
|
||||
ChangeMode(op request.FileCreate) error
|
||||
BatchChangeModeAndOwner(op request.FileRoleReq) error
|
||||
ReadLogByLine(req request.FileReadByLineReq) (*response.FileLineContent, error)
|
||||
BatchCheckFiles(req request.FilePathsCheck) []response.ExistFileInfo
|
||||
}
|
||||
|
||||
var filteredPaths = []string{
|
||||
@@ -478,6 +479,12 @@ func (f *FileService) ReadLogByLine(req request.FileReadByLineReq) (*response.Fi
|
||||
}
|
||||
case "image-pull", "image-push", "image-build", "compose-create":
|
||||
logFilePath = path.Join(global.CONF.System.TmpDir, fmt.Sprintf("docker_logs/%s", req.Name))
|
||||
case "ollama-model":
|
||||
logFilePath = path.Join(global.CONF.System.DataDir, "log", "AITools", req.Name)
|
||||
case "mysql-slow-logs":
|
||||
logFilePath = path.Join(global.CONF.System.DataDir, fmt.Sprintf("apps/mysql/%s/data/1Panel-slow.log", req.Name))
|
||||
case "mariadb-slow-logs":
|
||||
logFilePath = path.Join(global.CONF.System.DataDir, fmt.Sprintf("apps/mariadb/%s/db/data/1Panel-slow.log", req.Name))
|
||||
}
|
||||
|
||||
lines, isEndOfFile, total, err := files.ReadFileByLine(logFilePath, req.Page, req.PageSize, req.Latest)
|
||||
@@ -501,3 +508,18 @@ func (f *FileService) ReadLogByLine(req request.FileReadByLineReq) (*response.Fi
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (f *FileService) BatchCheckFiles(req request.FilePathsCheck) []response.ExistFileInfo {
|
||||
fileList := make([]response.ExistFileInfo, 0, len(req.Paths))
|
||||
for _, filePath := range req.Paths {
|
||||
if info, err := os.Stat(filePath); err == nil {
|
||||
fileList = append(fileList, response.ExistFileInfo{
|
||||
Size: float64(info.Size()),
|
||||
Name: info.Name(),
|
||||
Path: filePath,
|
||||
ModTime: info.ModTime(),
|
||||
})
|
||||
}
|
||||
}
|
||||
return fileList
|
||||
}
|
||||
|
||||
@@ -381,6 +381,10 @@ func (u *FirewallService) OperateForwardRule(req dto.ForwardRuleOperate) error {
|
||||
TargetIP: r.TargetIP,
|
||||
TargetPort: r.TargetPort,
|
||||
}, r.Operation); err != nil {
|
||||
if req.ForceDelete {
|
||||
global.LOG.Error(err)
|
||||
continue
|
||||
}
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
+16
-11
@@ -103,23 +103,28 @@ func (f *FtpService) Sync() error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
currentData := make(map[string]model.Ftp)
|
||||
for _, item := range listsInDB {
|
||||
currentData[item.User] = item
|
||||
}
|
||||
|
||||
sameData := make(map[string]struct{})
|
||||
for _, item := range lists {
|
||||
for _, itemInDB := range listsInDB {
|
||||
if item.User == itemInDB.User {
|
||||
sameData[item.User] = struct{}{}
|
||||
if item.Path != itemInDB.Path || item.Status != itemInDB.Status {
|
||||
_ = ftpRepo.Update(itemInDB.ID, map[string]interface{}{"path": item.Path, "status": item.Status})
|
||||
if itemInDB, ok := currentData[item.User]; ok {
|
||||
sameData[item.User] = struct{}{}
|
||||
if item.Path != itemInDB.Path || item.Status != itemInDB.Status {
|
||||
if err := ftpRepo.Update(itemInDB.ID, map[string]interface{}{"path": item.Path, "status": item.Status}); err != nil {
|
||||
return err
|
||||
}
|
||||
break
|
||||
}
|
||||
} else {
|
||||
if err := ftpRepo.Create(&model.Ftp{User: item.User, Path: item.Path, Status: item.Status}); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, item := range lists {
|
||||
if _, ok := sameData[item.User]; !ok {
|
||||
_ = ftpRepo.Create(&model.Ftp{User: item.User, Path: item.Path, Status: item.Status})
|
||||
}
|
||||
}
|
||||
|
||||
for _, item := range listsInDB {
|
||||
if _, ok := sameData[item.User]; !ok {
|
||||
_ = ftpRepo.Update(item.ID, map[string]interface{}{"status": "deleted"})
|
||||
|
||||
@@ -439,6 +439,9 @@ func (u *ImageService) ImageRemove(req dto.BatchDelete) error {
|
||||
}
|
||||
return buserr.WithDetail(constant.ErrInUsed, id, nil)
|
||||
}
|
||||
if strings.Contains(err.Error(), "image has dependent") {
|
||||
return buserr.New(constant.ErrObjectBeDependent)
|
||||
}
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,9 @@ package service
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/1Panel-dev/1Panel/backend/utils/common"
|
||||
"github.com/1Panel-dev/1Panel/backend/utils/geo"
|
||||
"github.com/gin-gonic/gin"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
@@ -26,7 +29,7 @@ const logs = "https://resource.fit2cloud.com/installation-log.sh"
|
||||
type ILogService interface {
|
||||
ListSystemLogFile() ([]string, error)
|
||||
CreateLoginLog(operation model.LoginLog) error
|
||||
PageLoginLog(search dto.SearchLgLogWithPage) (int64, interface{}, error)
|
||||
PageLoginLog(c *gin.Context, search dto.SearchLgLogWithPage) (int64, interface{}, error)
|
||||
|
||||
CreateOperationLog(operation model.OperationLog) error
|
||||
PageOperationLog(search dto.SearchOpLogWithPage) (int64, interface{}, error)
|
||||
@@ -77,7 +80,7 @@ func (u *LogService) ListSystemLogFile() ([]string, error) {
|
||||
return files, nil
|
||||
}
|
||||
|
||||
func (u *LogService) PageLoginLog(req dto.SearchLgLogWithPage) (int64, interface{}, error) {
|
||||
func (u *LogService) PageLoginLog(c *gin.Context, req dto.SearchLgLogWithPage) (int64, interface{}, error) {
|
||||
total, ops, err := logRepo.PageLoginLog(
|
||||
req.Page,
|
||||
req.PageSize,
|
||||
@@ -91,6 +94,7 @@ func (u *LogService) PageLoginLog(req dto.SearchLgLogWithPage) (int64, interface
|
||||
if err := copier.Copy(&item, &op); err != nil {
|
||||
return 0, nil, errors.WithMessage(constant.ErrStructTransform, err.Error())
|
||||
}
|
||||
item.Address, _ = geo.GetIPLocation(item.IP, common.GetLang(c))
|
||||
dtoOps = append(dtoOps, item)
|
||||
}
|
||||
return total, dtoOps, err
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"encoding/json"
|
||||
@@ -42,6 +44,7 @@ type ISettingService interface {
|
||||
HandlePasswordExpired(c *gin.Context, old, new string) error
|
||||
GenerateApiKey() (string, error)
|
||||
UpdateApiConfig(req dto.ApiInterfaceConfig) error
|
||||
GenerateRSAKey() error
|
||||
}
|
||||
|
||||
func NewISettingService() ISettingService {
|
||||
@@ -510,5 +513,53 @@ func (u *SettingService) UpdateApiConfig(req dto.ApiInterfaceConfig) error {
|
||||
return err
|
||||
}
|
||||
global.CONF.System.IpWhiteList = req.IpWhiteList
|
||||
if err := settingRepo.Update("ApiKeyValidityTime", req.ApiKeyValidityTime); err != nil {
|
||||
return err
|
||||
}
|
||||
global.CONF.System.ApiKeyValidityTime = req.ApiKeyValidityTime
|
||||
return nil
|
||||
}
|
||||
|
||||
func exportPrivateKeyToPEM(privateKey *rsa.PrivateKey) string {
|
||||
privateKeyBytes := x509.MarshalPKCS1PrivateKey(privateKey)
|
||||
privateKeyPEM := pem.EncodeToMemory(&pem.Block{
|
||||
Type: "RSA PRIVATE KEY",
|
||||
Bytes: privateKeyBytes,
|
||||
})
|
||||
return string(privateKeyPEM)
|
||||
}
|
||||
|
||||
func exportPublicKeyToPEM(publicKey *rsa.PublicKey) (string, error) {
|
||||
publicKeyBytes, err := x509.MarshalPKIXPublicKey(publicKey)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
publicKeyPEM := pem.EncodeToMemory(&pem.Block{
|
||||
Type: "PUBLIC KEY",
|
||||
Bytes: publicKeyBytes,
|
||||
})
|
||||
return string(publicKeyPEM), nil
|
||||
}
|
||||
|
||||
func (u *SettingService) GenerateRSAKey() error {
|
||||
priKey, _ := settingRepo.Get(settingRepo.WithByKey("PASSWORD_PRIVATE_KEY"))
|
||||
pubKey, _ := settingRepo.Get(settingRepo.WithByKey("PASSWORD_PUBLIC_KEY"))
|
||||
if priKey.Value != "" && pubKey.Value != "" {
|
||||
return nil
|
||||
}
|
||||
privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
privateKeyPEM := exportPrivateKeyToPEM(privateKey)
|
||||
publicKeyPEM, err := exportPublicKeyToPEM(&privateKey.PublicKey)
|
||||
err = settingRepo.UpdateOrCreate("PASSWORD_PRIVATE_KEY", privateKeyPEM)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = settingRepo.UpdateOrCreate("PASSWORD_PUBLIC_KEY", publicKeyPEM)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -87,13 +87,18 @@ type IWebsiteService interface {
|
||||
LoadWebsiteDirConfig(req request.WebsiteCommonReq) (*response.WebsiteDirConfig, error)
|
||||
UpdateSiteDir(req request.WebsiteUpdateDir) error
|
||||
UpdateSitePermission(req request.WebsiteUpdateDirPermission) error
|
||||
|
||||
OperateProxy(req request.WebsiteProxyConfig) (err error)
|
||||
GetProxies(id uint) (res []request.WebsiteProxyConfig, err error)
|
||||
UpdateProxyFile(req request.NginxProxyUpdate) (err error)
|
||||
DeleteProxy(req request.WebsiteProxyDel) (err error)
|
||||
|
||||
GetAuthBasics(req request.NginxAuthReq) (res response.NginxAuthRes, err error)
|
||||
UpdateAuthBasic(req request.NginxAuthUpdate) (err error)
|
||||
|
||||
GetAntiLeech(id uint) (*response.NginxAntiLeechRes, error)
|
||||
UpdateAntiLeech(req request.NginxAntiLeechUpdate) (err error)
|
||||
|
||||
OperateRedirect(req request.NginxRedirectReq) (err error)
|
||||
GetRedirect(id uint) (res []response.NginxRedirectConfig, err error)
|
||||
UpdateRedirectFile(req request.NginxRedirectUpdate) (err error)
|
||||
@@ -1553,6 +1558,29 @@ func (w WebsiteService) UpdateSitePermission(req request.WebsiteUpdateDirPermiss
|
||||
return websiteRepo.Save(context.Background(), &website)
|
||||
}
|
||||
|
||||
func (w WebsiteService) DeleteProxy(req request.WebsiteProxyDel) (err error) {
|
||||
fileOp := files.NewFileOp()
|
||||
website, err := websiteRepo.GetFirst(commonRepo.WithByID(req.ID))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
nginxInstall, err := getAppInstallByKey(constant.AppOpenresty)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
includeDir := path.Join(nginxInstall.GetPath(), "www", "sites", website.Alias, "proxy")
|
||||
if !fileOp.Stat(includeDir) {
|
||||
_ = fileOp.CreateDir(includeDir, 0755)
|
||||
}
|
||||
fileName := fmt.Sprintf("%s.conf", req.Name)
|
||||
includePath := path.Join(includeDir, fileName)
|
||||
backName := fmt.Sprintf("%s.bak", req.Name)
|
||||
backPath := path.Join(includeDir, backName)
|
||||
_ = fileOp.DeleteFile(includePath)
|
||||
_ = fileOp.DeleteFile(backPath)
|
||||
return updateNginxConfig(constant.NginxScopeServer, nil, &website)
|
||||
}
|
||||
|
||||
func (w WebsiteService) OperateProxy(req request.WebsiteProxyConfig) (err error) {
|
||||
var (
|
||||
website model.Website
|
||||
@@ -2043,7 +2071,19 @@ func (w WebsiteService) UpdateAntiLeech(req request.NginxAntiLeechUpdate) (err e
|
||||
}
|
||||
newBlock.Directives = append(newBlock.Directives, ifDir)
|
||||
newDirective.Block = newBlock
|
||||
block.Directives = append(block.Directives, &newDirective)
|
||||
|
||||
index := -1
|
||||
for i, directive := range block.Directives {
|
||||
if directive.GetName() == "include" {
|
||||
index = i
|
||||
break
|
||||
}
|
||||
}
|
||||
if index != -1 {
|
||||
block.Directives = append(block.Directives[:index], append([]components.IDirective{&newDirective}, block.Directives[index:]...)...)
|
||||
} else {
|
||||
block.Directives = append(block.Directives, &newDirective)
|
||||
}
|
||||
}
|
||||
|
||||
if err = nginx.WriteConfig(nginxFull.SiteConfig.Config, nginx.IndentedStyle); err != nil {
|
||||
|
||||
@@ -642,9 +642,15 @@ func applySSL(website model.Website, websiteSSL model.WebsiteSSL, req request.We
|
||||
}
|
||||
if param.Name == "ssl_protocols" {
|
||||
nginxParams[i].Params = req.SSLProtocol
|
||||
if len(req.SSLProtocol) == 0 {
|
||||
nginxParams[i].Params = []string{"TLSv1.3", "TLSv1.2", "TLSv1.1", "TLSv1"}
|
||||
}
|
||||
}
|
||||
if param.Name == "ssl_ciphers" {
|
||||
nginxParams[i].Params = []string{req.Algorithm}
|
||||
if len(req.Algorithm) == 0 {
|
||||
nginxParams[i].Params = []string{"ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:!aNULL:!eNULL:!EXPORT:!DSS:!DES:!RC4:!3DES:!MD5:!PSK:!KRB5:!SRP:!CAMELLIA:!SEED"}
|
||||
}
|
||||
}
|
||||
}
|
||||
if req.Hsts {
|
||||
@@ -1106,3 +1112,55 @@ func getResourceContent(fileOp files.FileOp, resourcePath string) (string, error
|
||||
}
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func ConfigAllowIPs(ips []string, website model.Website) error {
|
||||
nginxFull, err := getNginxFull(&website)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
nginxConfig := nginxFull.SiteConfig
|
||||
config := nginxFull.SiteConfig.Config
|
||||
server := config.FindServers()[0]
|
||||
server.RemoveDirective("allow", nil)
|
||||
server.RemoveDirective("deny", nil)
|
||||
if len(ips) > 0 {
|
||||
server.UpdateAllowIPs(ips)
|
||||
}
|
||||
if err := nginx.WriteConfig(config, nginx.IndentedStyle); err != nil {
|
||||
return err
|
||||
}
|
||||
return nginxCheckAndReload(nginxConfig.OldContent, config.FilePath, nginxFull.Install.ContainerName)
|
||||
}
|
||||
|
||||
func GetAllowIps(website model.Website) []string {
|
||||
nginxFull, err := getNginxFull(&website)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
config := nginxFull.SiteConfig.Config
|
||||
server := config.FindServers()[0]
|
||||
dirs := server.GetDirectives()
|
||||
var ips []string
|
||||
for _, dir := range dirs {
|
||||
if dir.GetName() == "allow" {
|
||||
ips = append(ips, dir.GetParameters()...)
|
||||
}
|
||||
}
|
||||
return ips
|
||||
}
|
||||
|
||||
func ConfigAIProxy(website model.Website) error {
|
||||
nginxFull, err := getNginxFull(&website)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
config := nginxFull.SiteConfig.Config
|
||||
server := config.FindServers()[0]
|
||||
dirs := server.GetDirectives()
|
||||
for _, dir := range dirs {
|
||||
if dir.GetName() == "location" && dir.GetParameters()[0] == "/" {
|
||||
server.UpdateRootProxyForAi([]string{fmt.Sprintf("http://%s", website.Proxy)})
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ type System struct {
|
||||
Language string `mapstructure:"language"`
|
||||
IsDemo bool `mapstructure:"is_demo"`
|
||||
IsIntl bool `mapstructure:"is_intl"`
|
||||
LicenseVerify string `mapstructure:"license_verify"`
|
||||
AppRepo string `mapstructure:"app_repo"`
|
||||
ChangeUserInfo string `mapstructure:"change_user_info"`
|
||||
OneDriveID string `mapstructure:"one_drive_id"`
|
||||
@@ -30,4 +31,5 @@ type System struct {
|
||||
ApiInterfaceStatus string `mapstructure:"api_interface_status"`
|
||||
ApiKey string `mapstructure:"api_key"`
|
||||
IpWhiteList string `mapstructure:"ip_white_list"`
|
||||
ApiKeyValidityTime string `mapstructure:"api_key_validity_time"`
|
||||
}
|
||||
|
||||
@@ -32,6 +32,10 @@ var WebUrlMap = map[string]struct{}{
|
||||
"/apps/installed": {},
|
||||
"/apps/upgrade": {},
|
||||
|
||||
"/ai": {},
|
||||
"/ai/model": {},
|
||||
"/ai/gpu": {},
|
||||
|
||||
"/containers": {},
|
||||
"/containers/container": {},
|
||||
"/containers/image": {},
|
||||
@@ -113,11 +117,11 @@ var WebUrlMap = map[string]struct{}{
|
||||
"/xpack/monitor/rank": {},
|
||||
"/xpack/monitor/log": {},
|
||||
"/xpack/tamper": {},
|
||||
"/xpack/gpu": {},
|
||||
"/xpack/alert/dashboard": {},
|
||||
"/xpack/alert/log": {},
|
||||
"/xpack/alert/setting": {},
|
||||
"/xpack/setting": {},
|
||||
"/xpack/app": {},
|
||||
}
|
||||
|
||||
var DynamicRoutes = []string{
|
||||
|
||||
+30
-20
@@ -37,22 +37,23 @@ var (
|
||||
|
||||
// api
|
||||
var (
|
||||
ErrTypeInternalServer = "ErrInternalServer"
|
||||
ErrTypeInvalidParams = "ErrInvalidParams"
|
||||
ErrTypeNotLogin = "ErrNotLogin"
|
||||
ErrTypePasswordExpired = "ErrPasswordExpired"
|
||||
ErrNameIsExist = "ErrNameIsExist"
|
||||
ErrDemoEnvironment = "ErrDemoEnvironment"
|
||||
ErrCmdIllegal = "ErrCmdIllegal"
|
||||
ErrXpackNotFound = "ErrXpackNotFound"
|
||||
ErrXpackNotActive = "ErrXpackNotActive"
|
||||
ErrXpackLost = "ErrXpackLost"
|
||||
ErrXpackTimeout = "ErrXpackTimeout"
|
||||
ErrXpackOutOfDate = "ErrXpackOutOfDate"
|
||||
ErrApiConfigStatusInvalid = "ErrApiConfigStatusInvalid"
|
||||
ErrApiConfigKeyInvalid = "ErrApiConfigKeyInvalid"
|
||||
ErrApiConfigIPInvalid = "ErrApiConfigIPInvalid"
|
||||
ErrApiConfigDisable = "ErrApiConfigDisable"
|
||||
ErrTypeInternalServer = "ErrInternalServer"
|
||||
ErrTypeInvalidParams = "ErrInvalidParams"
|
||||
ErrTypeNotLogin = "ErrNotLogin"
|
||||
ErrTypePasswordExpired = "ErrPasswordExpired"
|
||||
ErrNameIsExist = "ErrNameIsExist"
|
||||
ErrDemoEnvironment = "ErrDemoEnvironment"
|
||||
ErrCmdIllegal = "ErrCmdIllegal"
|
||||
ErrXpackNotFound = "ErrXpackNotFound"
|
||||
ErrXpackNotActive = "ErrXpackNotActive"
|
||||
ErrXpackLost = "ErrXpackLost"
|
||||
ErrXpackTimeout = "ErrXpackTimeout"
|
||||
ErrXpackOutOfDate = "ErrXpackOutOfDate"
|
||||
ErrApiConfigStatusInvalid = "ErrApiConfigStatusInvalid"
|
||||
ErrApiConfigKeyInvalid = "ErrApiConfigKeyInvalid"
|
||||
ErrApiConfigIPInvalid = "ErrApiConfigIPInvalid"
|
||||
ErrApiConfigDisable = "ErrApiConfigDisable"
|
||||
ErrApiConfigKeyTimeInvalid = "ErrApiConfigKeyTimeInvalid"
|
||||
)
|
||||
|
||||
// app
|
||||
@@ -125,10 +126,11 @@ var (
|
||||
|
||||
// container
|
||||
var (
|
||||
ErrInUsed = "ErrInUsed"
|
||||
ErrObjectInUsed = "ErrObjectInUsed"
|
||||
ErrPortRules = "ErrPortRules"
|
||||
ErrPgImagePull = "ErrPgImagePull"
|
||||
ErrInUsed = "ErrInUsed"
|
||||
ErrObjectInUsed = "ErrObjectInUsed"
|
||||
ErrObjectBeDependent = "ErrObjectBeDependent"
|
||||
ErrPortRules = "ErrPortRules"
|
||||
ErrPgImagePull = "ErrPgImagePull"
|
||||
)
|
||||
|
||||
// runtime
|
||||
@@ -167,6 +169,7 @@ var (
|
||||
var (
|
||||
ErrLicense = "ErrLicense"
|
||||
ErrLicenseCheck = "ErrLicenseCheck"
|
||||
ErrXpackVersion = "ErrXpackVersion"
|
||||
ErrLicenseSave = "ErrLicenseSave"
|
||||
ErrLicenseSync = "ErrLicenseSync"
|
||||
)
|
||||
@@ -179,3 +182,10 @@ var (
|
||||
ErrAlertSync = "ErrAlertSync"
|
||||
ErrAlertRemote = "ErrAlertRemote"
|
||||
)
|
||||
|
||||
// mobile app
|
||||
var (
|
||||
ErrVerifyToken = "ErrVerifyToken"
|
||||
ErrInvalidToken = "ErrInvalidToken"
|
||||
ErrExpiredToken = "ErrExpiredToken"
|
||||
)
|
||||
|
||||
@@ -6,6 +6,8 @@ const (
|
||||
StatusWaiting = "Waiting"
|
||||
StatusSuccess = "Success"
|
||||
StatusFailed = "Failed"
|
||||
StatusDeleted = "Deleted"
|
||||
StatusCanceled = "Canceled"
|
||||
StatusUploading = "Uploading"
|
||||
StatusEnable = "Enable"
|
||||
StatusDisable = "Disable"
|
||||
|
||||
@@ -13,8 +13,10 @@ func NewAppStoreJob() *app {
|
||||
|
||||
func (a *app) Run() {
|
||||
global.LOG.Info("AppStore scheduled task in progress ...")
|
||||
if err := service.NewIAppService().SyncAppListFromRemote(); err != nil {
|
||||
appService := service.NewIAppService()
|
||||
if err := appService.SyncAppListFromRemote(); err != nil {
|
||||
global.LOG.Errorf("AppStore sync failed %s", err.Error())
|
||||
}
|
||||
appService.SyncAppListFromLocal()
|
||||
global.LOG.Info("AppStore scheduled task has completed")
|
||||
}
|
||||
|
||||
@@ -100,15 +100,18 @@ func Init() {
|
||||
_, _ = bundle.LoadMessageFileFS(fs, "lang/zh-Hant.yaml")
|
||||
_, _ = bundle.LoadMessageFileFS(fs, "lang/fa.yaml")
|
||||
_, _ = bundle.LoadMessageFileFS(fs, "lang/pt.yaml")
|
||||
_, _ = bundle.LoadMessageFileFS(fs, "lang/pt-BR.yaml")
|
||||
_, _ = bundle.LoadMessageFileFS(fs, "lang/ja.yaml")
|
||||
_, _ = bundle.LoadMessageFileFS(fs, "lang/ru.yaml")
|
||||
_, _ = bundle.LoadMessageFileFS(fs, "lang/ms.yaml")
|
||||
_, _ = bundle.LoadMessageFileFS(fs, "lang/ko.yaml")
|
||||
}
|
||||
|
||||
func UseI18nForCmd(lang string) {
|
||||
if lang == "" {
|
||||
lang = "en"
|
||||
}
|
||||
if lang == "pt-BR" {
|
||||
lang = "pt"
|
||||
}
|
||||
|
||||
if bundle == nil {
|
||||
Init()
|
||||
}
|
||||
|
||||
@@ -12,9 +12,10 @@ ErrApiConfigStatusInvalid: "API Interface access prohibited: {{ .detail }}"
|
||||
ErrApiConfigKeyInvalid: "API Interface key error: {{ .detail }}"
|
||||
ErrApiConfigIPInvalid: "API Interface IP is not on the whitelist: {{ .detail }}"
|
||||
ErrApiConfigDisable: "This interface prohibits the use of API Interface calls: {{ .detail }}"
|
||||
ErrApiConfigKeyTimeInvalid: "API Interface timestamp error: {{ .detail }}"
|
||||
|
||||
#common
|
||||
ErrNameIsExist: "Name is already exist"
|
||||
ErrNameIsExist: "Name already exists"
|
||||
ErrDemoEnvironment: "Demo server, prohibit this operation!"
|
||||
ErrCmdTimeout: "Command execution timed out!"
|
||||
ErrCmdIllegal: "The command contains illegal characters. Please modify and try again!"
|
||||
@@ -31,7 +32,7 @@ SystemRestart: "System restart causes task interruption"
|
||||
#app
|
||||
ErrPortInUsed: "{{ .detail }} port already in use"
|
||||
ErrAppLimit: "App exceeds install limit"
|
||||
ErrAppRequired: "{{ .detail }} app is required"
|
||||
ErrAppRequired: "The {{ .detail }} app is required"
|
||||
ErrNotInstall: "App not installed"
|
||||
ErrPortInOtherApp: "{{ .port }} port already in use by app {{ .apps }}"
|
||||
ErrDbUserNotValid: "Stock database, username and password do not match!"
|
||||
@@ -59,7 +60,7 @@ ErrContainerNotFound: '{{ .name }} container does not exist'
|
||||
ErrContainerMsg: '{{ .name }} container is abnormal, please check the log on the container page for details'
|
||||
ErrAppBackup: '{{ .name }} application backup failed err {{.err}}'
|
||||
ErrImagePull: '{{ .name }} image pull failed err {{.err}}'
|
||||
ErrVersionTooLow: 'The current 1Panel version is too low to update the app store, please upgrade the version'
|
||||
ErrVersionTooLow: 'The current 1Panel version is too low for updating the app store, please upgrade the version'
|
||||
ErrAppNameExist: 'App name is already exist'
|
||||
AppStoreIsSyncing: 'The App Store is syncing, please try again later'
|
||||
ErrGetCompose: "Failed to obtain docker-compose.yml file! {{ .detail }}"
|
||||
@@ -88,8 +89,8 @@ ErrInvalidChar: "Illegal characters are prohibited"
|
||||
ErrPathNotDelete: "The selected directory cannot be deleted"
|
||||
|
||||
#website
|
||||
ErrDomainIsExist: "Domain is already exist"
|
||||
ErrAliasIsExist: "Alias is already exist"
|
||||
ErrDomainIsExist: "The domain name already exists"
|
||||
ErrAliasIsExist: "The alias already exists"
|
||||
ErrAppDelete: 'Other Website use this App'
|
||||
ErrGroupIsUsed: "The group is in use and can't be deleted"
|
||||
ErrBackupMatch: "the backup file doesn't match the current partial data of the website: {{ .detail}}"
|
||||
@@ -145,12 +146,13 @@ ErrTypeOfRedis: "The recovery file type does not match the current persistence m
|
||||
#container
|
||||
ErrInUsed: "{{ .detail }} is in use and can't be deleted"
|
||||
ErrObjectInUsed: "This object is in use and can't be deleted"
|
||||
ErrObjectBeDependent: "This image is dependent on other images and can't be deleted"
|
||||
ErrPortRules: "The number of ports does not match, please re-enter!"
|
||||
ErrPgImagePull: "Image pull timeout. Please configure image acceleration or manually pull the postgres:16.0-alpine image and try again"
|
||||
|
||||
#runtime
|
||||
ErrDirNotFound: "The build folder does not exist! Please check file integrity!"
|
||||
ErrFileNotExist: "{{ .detail }} file does not exist! Please check source file integrity!"
|
||||
ErrDirNotFound: "The build folder does not exist! Please check the integrity of the file!"
|
||||
ErrFileNotExist: "{{ .detail }} file does not exist! Please check the integrity of the source file!"
|
||||
ErrImageBuildErr: "Image build failed"
|
||||
ErrImageExist: "Image is already exist!"
|
||||
ErrDelWithWebsite: "The operating environment has been associated with a website and cannot be deleted"
|
||||
@@ -203,6 +205,7 @@ ErrIPExist: "IP is exit"
|
||||
#license
|
||||
ErrLicense: "License format error, please check and try again!"
|
||||
ErrLicenseCheck: "License verification failed, please check and try again!"
|
||||
ErrXpackVersion: "License verification failed, this license is version-restricted and cannot be successfully imported. Please check and try again!"
|
||||
ErrLicenseSave: "Failed to save license information, error {{ .err }}, please try again!"
|
||||
ErrLicenseSync: "Failed to sync license information, no license information detected in the database!"
|
||||
ErrXpackNotFound: "This section is a professional edition feature, please import the license first in Panel Settings-License interface"
|
||||
@@ -281,3 +284,12 @@ UserInfoPassHelp: "Tip: To change the password, you can execute the command: "
|
||||
DBConnErr: "Error: Failed to initialize database connection, {{ .err }}"
|
||||
SystemVersion: "version: "
|
||||
SystemMode: "mode: "
|
||||
|
||||
#ai-tool
|
||||
ErrOpenrestyInstall: 'Please install Openresty first'
|
||||
ErrSSL: "Certificate content is empty, please check the certificate!"
|
||||
|
||||
#mobile app
|
||||
ErrVerifyToken: 'Token verification error, please reset and scan again.'
|
||||
ErrInvalidToken: 'Invalid token, please reset and scan again.'
|
||||
ErrExpiredToken: 'Token has expired, please reset and scan again.'
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
#cmd
|
||||
AppVersion: "Lotfan noskhe-ye barname ra vared konid"
|
||||
AppCommands: "Dasturat-e marbut be barname"
|
||||
AppInit: "Barname ra shoru' konid"
|
||||
AppKeyVal: "Kelid-e barname (faghat az zabane englisi poshtibani mikonad)"
|
||||
AppCreateFileErr: "Khalgh-e file {{ .name }} namovaffagh bud {{ .err }}"
|
||||
AppCreateDirErr: "Khalgh-e folder {{ .name }} namovaffagh bud {{ .err }}"
|
||||
AppMissKey: "Kelid-e barname mojood nist, az -k estefade konid"
|
||||
AppMissVersion: "Noskhe-ye barname mojood nist, az -v estefade konid"
|
||||
AppVersionExist: "Noskhe ghablan mojood ast!"
|
||||
AppCreateSuccessful: "Khalgh ba movaffaghiat anjam shod!"
|
||||
AppWriteErr: "Neveshtan file {{ .name }} namovaffagh bud {{ .err }}"
|
||||
SudoHelper: "Lotfan in eskript ra be onvane karbare root ya ba mojavez sudo ejra konid"
|
||||
ListenIPCommands: "IP goosh dadan ra taghir dahid"
|
||||
ListenIPv4: "Goosh dadan bar IPv4"
|
||||
ListenIPv6: "Goosh dadan bar IPv6"
|
||||
ListenChangeSuccessful: "Taghir movaffagh! Hala bar {{ .value }} goosh midahad"
|
||||
ResetCommands: "E'ade setadad etela'at-e system"
|
||||
ResetMFA: "Fa'al-sazi do marhale'i 1Panel ra laghv konid"
|
||||
ResetHttps: "Voroud HTTPS baraye 1Panel ra laghv konid"
|
||||
ResetEntrance: "Voroud amin 1Panel ra laghv konid"
|
||||
ResetIPs: "Mahdudiyat IP-haye mojaz 1Panel ra laghv konid"
|
||||
ResetDomain: "Sazgari domain 1Panel ra laghv konid"
|
||||
RestoreCommands: "Bargasht be khadamate 1Panel va data"
|
||||
RestoreNoSuchFile: "Hich file mojood baraye bargasht nist"
|
||||
RestoreStep1: "(1/5) Shoru' bargasht be khadamate 1Panel va data az directory {{ .name }} ..."
|
||||
RestoreStep2: "(2/5) Bargasht be binary 1Panel ba movaffaghiat anjam shod"
|
||||
RestoreStep3: "(3/5) Bargasht be script 1Panel ba movaffaghiat anjam shod"
|
||||
RestoreStep4: "(4/5) Bargasht be khadamat 1Panel ba movaffaghiat anjam shod"
|
||||
RestoreStep5: "(5/5) Bargasht be data 1Panel ba movaffaghiat anjam shod"
|
||||
RestoreSuccessful: "Bargasht ba movaffaghiat anjam shod! Khadamat dar hale restart ast, lotfan montazer bashid..."
|
||||
UpdateCommands: "Be'rooz resani etela'at-e panel"
|
||||
UpdateUser: "Be'rooz resani karbare panel"
|
||||
UpdatePassword: "Be'rooz resani ramz-e panel"
|
||||
UpdatePort: "Be'rooz resani port-e panel"
|
||||
UpdateUserNull: "Khatta: karbare panel khalist!"
|
||||
UpdateUserBlank: "Khatta: karbare panel shamel faseleh ast!"
|
||||
UpdateUserFormat: "Khatta: format-e karbare panel na dorost ast! Faghat az englisi, chine'i, adad va _, ba tool-e 3-30 poshtibani mikonad"
|
||||
UpdateUserErr: "Khatta: be'rooz resani karbare panel namovaffagh bud, {{ .err }}"
|
||||
UpdateSuccessful: "Be'rooz resani ba movaffaghiat anjam shod!"
|
||||
UpdateUserResult: "Karbare panel: {{ .name }}"
|
||||
UpdatePasswordRead: "Khatta: khatayi dar khandan etela'at-e ramz-e panel, {{ .err }}"
|
||||
UpdatePasswordNull: "Khatta: ramz-e panel khalist!"
|
||||
UpdateUPasswordBlank: "Khatta: ramz-e panel shamel faseleh ast!"
|
||||
UpdatePasswordFormat: "Khatta: ramz-e panel faghat az harf, adad, karakter-haye vizhe !@#$%*_,.? ba tool-e 8-30 poshtibani mikonad!"
|
||||
UpdatePasswordLen: "Khatta: lotfan ramzi bishtar az 6 karakter vared konid!"
|
||||
UpdatePasswordRe: "Teyid-e ramz:"
|
||||
UpdatePasswordErr: "Khatta: be'rooz resani ramz-e panel namovaffagh bud, {{ .err }}"
|
||||
UpdatePasswordSame: "Khatta: do ramz ba ham yeksan nistand, lotfan barrasi konid va dobare talash konid!"
|
||||
UpdatePasswordResult: "Ramz-e panel: {{ .name }}"
|
||||
UpdatePortFormat: "Khatta: shomareye port bayad bein 1 ta 65535 bashad!"
|
||||
UpdatePortUsed: "Khatta: shomareye port ghablan estefade shode ast, lotfan barrasi konid va dobare talash konid!"
|
||||
UpdatePortErr: "Khatta: be'rooz resani port-e panel namovaffagh bud, {{ .err }}"
|
||||
UpdatePortResult: "Port-e panel: {{ .name }}"
|
||||
UpdatePortFirewallAdd: "Ezafe kardane ghanoun-e port firewall namovaffagh bud, {{ .err }}, lotfan port {{ .name }} ra be dast az qavaneen firewall ezafe konid."
|
||||
UpdatePortFirewallDel: "Khatta: hazf-e port firewall namovaffagh bud, {{ .err }}"
|
||||
UpdatePortFirewallReload: "Reload firewall namovaffagh bud, {{ .err }}, lotfan firewall ra be dast reload konid."
|
||||
UserInfo: "Daryaft etela'at-e panel"
|
||||
UserInfoAddr: "Address-e panel: "
|
||||
UserInfoPassHelp: "Nokte: baraye taghiri ramz, mitavanid dastur zir ra anjam dahid: "
|
||||
DBConnErr: "Khatta: etesal be database namovaffagh bud, {{ .err }}"
|
||||
SystemVersion: "noskhe: "
|
||||
SystemMode: "halat: "
|
||||
@@ -0,0 +1,293 @@
|
||||
ErrInvalidParams: "リクエストパラメーターエラー: {{.Detail}}"
|
||||
ErrTokenParse: "トークン生成エラー: {{.Detail}}"
|
||||
ErrInitialPassword: "初期パスワードエラー"
|
||||
ErrInternalServer: "サービス内部エラー: {{.Detail}}"
|
||||
ErrRecordExist: "レコードはすでに存在します"
|
||||
ErrRecordNotFound: "記録が見つかりません"
|
||||
ErrStructTransform: "タイプ変換障害: {{.Detail}}"
|
||||
ErrNotLogin: "ユーザーはログインしません: {{.Detail}}"
|
||||
ErrPasswordExpired: "現在のパスワードが期限切れになっています: {{.Detail}}"
|
||||
ErrNotSupportType: "システムは現在のタイプをサポートしていません: {{.Detail}}"
|
||||
ErrApiConfigStatusInvalid: "APIインターフェイスアクセス禁止: {{.Detail}}"
|
||||
ErrApiConfigKeyInvalid: "APIインターフェイスキーエラー: {{.Detail}}"
|
||||
ErrApiConfigIPInvalid: "APIインターフェイスIPはホワイトリストにありません: {{.Detail}}"
|
||||
ErrApiConfigDisable: "このインターフェイスは、APIインターフェイスコールの使用を禁止しています: {{.Detail}}"
|
||||
|
||||
#common
|
||||
ErrNameIsExist: "名前はすでに存在しています"
|
||||
ErrDemoEnvironment: "デモサーバー、この操作を禁止します!"
|
||||
ErrCmdTimeout: "コマンド実行がタイムアウトしました!"
|
||||
ErrCmdIllegal: "コマンドには違法な文字が含まれています。変更してもう一度やり直してください!"
|
||||
ErrPortExist: '{{.port}}ポートはすでに{{.type}} [{{.name}}]によって占有されています。'
|
||||
TYPE_APP: "応用"
|
||||
TYPE_RUNTIME: "ランタイム環境"
|
||||
TYPE_DOMAIN: "ドメイン名"
|
||||
ErrTypePort: 'port {{.name}}フォーマットエラー'
|
||||
ErrTypePortRange: 'ポートレンジは1-65535の間である必要があります'
|
||||
Success: "成功"
|
||||
Failed: "失敗した"
|
||||
SystemRestart: "システムの再起動により、タスクが中断されます"
|
||||
|
||||
#app
|
||||
ErrPortInUsed: "{{.Detail}}ポートはすでに使用されています"
|
||||
ErrAppLimit: "アプリはインストール制限を超えています"
|
||||
ErrAppRequired: "{{.Detail}}アプリが必要です"
|
||||
ErrNotInstall: "アプリがインストールされていません"
|
||||
ErrPortInOtherApp: "{{.port}}ポートは既にapp {{.apps}}で使用されています"
|
||||
ErrDbUserNotValid: "ストックデータベース、ユーザー名、パスワードが一致しません!"
|
||||
ErrDockerComposeNotValid: "Docker-Composeファイル形式のエラー!"
|
||||
ErrUpdateBuWebsite: 'アプリケーションは正常に更新されましたが、Webサイト構成ファイルの変更に失敗しました。構成を確認してください!'
|
||||
Err1PanelNetworkFailed: 'デフォルトのコンテナネットワークの作成に失敗しました!{{ 。詳細 }}'
|
||||
ErrFileParse: 'アプリケーションDocker-Composeファイルの解析は失敗しました!'
|
||||
ErrInstallDirNotFound: 'インストールディレクトリは存在しません'
|
||||
AppStoreIsUpToDate: '最新の'
|
||||
LocalAppVersionNull: '{{.name}}アプリはバージョンに同期されません!アプリケーションリストに追加できませんでした'
|
||||
LocalAppVersionErr: '{{.name}}}バージョン{{.version}}の同期に失敗しました!{{.err}}'
|
||||
ErrFileNotFound: '{{.name}}ファイルは存在しません'
|
||||
ErrFileParseApp: '{{.name}} file {{.err}}を解析できなかった'
|
||||
ErrAppDirNull: 'バージョンフォルダーは存在しません'
|
||||
LocalAppErr: "app {{.name}}同期が失敗しました!{{.err}}"
|
||||
ErrContainerName: "cantablernameはすでに存在しています"
|
||||
ErrAppSystemRestart: "1パネルの再起動により、タスクが終了します"
|
||||
ErrCreateHttpClient: "http request {{.err}}の作成に失敗しました"
|
||||
ErrHttpReqTimeOut: "リクエスト{{.err}}"
|
||||
ErrHttpReqFailed: "リクエストが失敗しました{{.err}}"
|
||||
ErrHttpReqNotFound: "ファイルは存在しません"
|
||||
ErrNoSuchHost: "ネットワーク接続に失敗しました"
|
||||
ErrImagePullTimeOut: '画像プルタイムアウト'
|
||||
ErrContainerNotFound: '{{.name}}コンテナは存在しません'
|
||||
ErrContainerMsg: '{{.name}}コンテナは異常です。詳細については、コンテナページのログを確認してください'
|
||||
ErrAppBackup: '{{.name}}アプリケーションバックアップが失敗したerr {{.err}}'
|
||||
ErrImagePull: '{{.name}}画像プルFailed err {{.err}}'
|
||||
ErrVersionTooLow: '現在の1パネルバージョンが低すぎてApp Storeを更新できないので、バージョンをアップグレードしてください'
|
||||
ErrAppNameExist: 'アプリ名はすでに存在しています'
|
||||
AppStoreIsSyncing: 'App Storeが同期しています。後でもう一度やり直してください'
|
||||
ErrGetCompose: "docker-compose.ymlファイルを取得できませんでした!{{ 。詳細 }}"
|
||||
ErrAppWarn: "異常なステータス、ログを確認してください"
|
||||
ErrAppParamKey: "parameter {{.name}}フィールド例外"
|
||||
ErrAppUpgrade: "アプリケーションのアップグレードに失敗しました{{.name}} {{.err}}"
|
||||
AppRecover: "app {{.name}}ロールバック"
|
||||
PullImageStart: "画像の引っ張りを開始{{.name}}"
|
||||
PullImageSuccess: "画像が正常に引っ張られました"
|
||||
UpgradeAppStart: "アプリケーションのアップグレードを起動{{.name}}"
|
||||
UpgradeAppSuccess: "App {{.Name}}アップグレードされました"
|
||||
|
||||
#file
|
||||
ErrFileCanNotRead: "ファイルは読み取れません"
|
||||
ErrFileToLarge: "ファイルが大きすぎます"
|
||||
ErrPathNotFound: "パスは見つかりません"
|
||||
ErrMovePathFailed: "ターゲットパスには元のパスが含まれていません!"
|
||||
ErrLinkPathNotFound: "ターゲットパスは存在しません!"
|
||||
ErrFileIsExist: "ファイルまたはディレクトリはすでに存在します!"
|
||||
ErrFileUpload: "file {{.name}} {{.detail}}}のアップロードに失敗しました"
|
||||
ErrFileDownloadDir: "サポートされていないフォルダーをダウンロードします"
|
||||
ErrCmdNotFound: "{{.name}}コマンドは存在しません。最初にホストにこのコマンドをインストールしてください"
|
||||
ErrSourcePathNotFound: "ソースディレクトリは存在しません"
|
||||
ErrFavoriteExist: "このパスが収集されました"
|
||||
ErrInvalidChar: "違法なキャラクターは禁止されています"
|
||||
ErrPathNotDelete: "選択したディレクトリを削除することはできません"
|
||||
|
||||
#website
|
||||
ErrDomainIsExist: "ドメインはすでに存在しています"
|
||||
ErrAliasIsExist: "エイリアスはすでに存在しています"
|
||||
ErrAppDelete: '他のウェブサイトはこのアプリを使用します'
|
||||
ErrGroupIsUsed: "グループは使用されており、削除することはできません"
|
||||
ErrBackupMatch: "バックアップファイルは、ウェブサイトの現在の部分的なデータと一致しません: {{.Detail}}"
|
||||
ErrBackupExist: 'バックアップファイルは、存在しない元のデータの一部に対応しています。{{.Detail}}'
|
||||
ErrPHPResource: 'ローカルランタイムはスイッチングをサポートしません!'
|
||||
ErrPathPermission: 'インデックスディレクトリで1000: 1000以外のアクセス許可を持つフォルダーが検出されたため、Webサイトにアクセスするとアクセスが拒否された場合があります。上の[保存]ボタンをクリックしてください'
|
||||
ErrDomainIsUsed: "ドメインはすでにWebサイトで使用されています{{.Name}}"
|
||||
ErrDomainFormat: "{{.name}}ドメイン形式エラー"
|
||||
ErrDefaultAlias: "デフォルトは予約済みのコード名です。別のコード名を使用してください"
|
||||
ErrImageNotExist: "実行中の環境{{.name}}画像は存在しません。実行中の環境を再編集してください"
|
||||
|
||||
#ssl
|
||||
ErrSSLCannotDelete: "証明書{{.Name}}はWebサイトで使用されており、削除できません"
|
||||
ErrAccountCannotDelete: "アカウントに関連付けられた証明書を削除することはできません"
|
||||
ErrSSLApply: "証明書は引き続き正常に署名されていますが、OpenRestyリロードが失敗します。構成を確認してください!"
|
||||
ErrEmailIsExist: 'メールはすでに存在しています'
|
||||
ErrSSLKeyNotFound: '秘密キーファイルは存在しません'
|
||||
ErrSSLCertificateNotFound: '証明書ファイルは存在しません'
|
||||
ErrSSLKeyFormat: '秘密キーファイル検証エラー'
|
||||
ErrSSLCertificateFormat: '証明書ファイル形式エラー、PEM形式を使用してください'
|
||||
ErrEabKidOrEabHmacKeyCannotBlank: 'eabkidまたはeabhmackeyは空にすることはできません'
|
||||
ErrOpenrestyNotFound: 'HTTPモードでは、最初にOpenRestyをインストールする必要があります'
|
||||
ApplySSLStart: '証明書、ドメイン名[{{.domain}}]アプリケーションメソッド[{{.type}}]の申請を開始します'
|
||||
dnsAccount: "DNSオートマチック"
|
||||
dnsManual: "DNSマニュアル"
|
||||
http: "http"
|
||||
ApplySSLFailed: '[{{.domain}}]証明書のアプリケーションが失敗しました、{{.detail}}'
|
||||
ApplySSLSuccess: '[{{{.domain}}]証明書のアプリケーションが成功しました!!'
|
||||
DNSAccountName: 'dnsアカウント[{{.name}}]メーカー[{{.type}}]'
|
||||
PushDirLog: 'ディレクトリにプッシュされた証明書[{{.Path}}] {{.Status}}'
|
||||
ErrDeleteCAWithSSL: "現在の組織の下に発行された証明書があり、削除できません"
|
||||
ErrDeleteWithPanelSSL: "パネルSSL構成はこの証明書を使用しており、削除できません"
|
||||
ErrDefaultCA: "デフォルトの証明書当局は削除できません"
|
||||
ApplyWebSiteSSLLog: "{{.name}} Webサイト証明書の更新を開始します"
|
||||
ErrUpdateWebsiteSSL: "{{.name}}ウェブサイトは証明書の更新に失敗しました: {{.err}}"
|
||||
ApplyWebSiteSSLSuccess: "ウェブサイトの証明書を正常に更新します"
|
||||
ErrExecShell: "スクリプトの実行に失敗した{{.err}}"
|
||||
ExecShellStart: "スクリプトの実行を開始します"
|
||||
ExecShellSuccess: "スクリプトは正常に実行されました"
|
||||
StartUpdateSystemSSL: "システム証明書の更新を開始します"
|
||||
UpdateSystemSSLSuccess: "システム証明書を正常に更新します"
|
||||
|
||||
#mysql
|
||||
ErrUserIsExist: "現在のユーザーはすでに存在しています。新しいユーザーを入力してください"
|
||||
ErrDatabaseIsExist: "現在のデータベースはすでに存在しています。新しいデータベースを入力してください"
|
||||
ErrExecTimeOut: "SQL実行のタイミングを出して、データベースを確認してください"
|
||||
ErrRemoteExist: "リモートデータベースはすでにその名前に存在しています。それを変更して、再試行してください"
|
||||
ErrLocalExist: "ローカルデータベースはすでにその名前に存在しています。それを変更して、もう一度試してください"
|
||||
|
||||
#redis
|
||||
ErrTypeOfRedis: "回復ファイルのタイプは、現在の永続性モードと一致しません。ファイルタイプを変更して、再試行してください"
|
||||
|
||||
#container
|
||||
ErrInUsed: "{{.Detail}}が使用されており、削除できません"
|
||||
ErrObjectInUsed: "このオブジェクトは使用されており、削除することはできません"
|
||||
ErrPortRules: "ポートの数が一致しません。再入力してください!"
|
||||
ErrPgImagePull: "画像プルタイムアウト。画像の加速を構成するか、Postgres: 16.0-Alpine画像を手動で引いて、再試行してください"
|
||||
|
||||
#runtime
|
||||
ErrDirNotFound: "ビルドフォルダーは存在しません!ファイルの整合性を確認してください!"
|
||||
ErrFileNotExist: "{{.Detail}}ファイルは存在しません!ソースファイルの完全性を確認してください!"
|
||||
ErrImageBuildErr: "画像ビルドが失敗しました"
|
||||
ErrImageExist: "画像はすでに存在しています!"
|
||||
ErrDelWithWebsite: "運用環境はウェブサイトに関連付けられており、削除することはできません"
|
||||
ErrRuntimeStart: "開始に失敗しました"
|
||||
ErrPackageJsonNotFound: "package.jsonファイルは存在しません"
|
||||
ErrScriptsNotFound: "Package.jsonにスクリプト構成アイテムは見つかりませんでした"
|
||||
ErrContainerNameNotFound: "コンテナ名を取得できない場合は、.envファイルを確認してください"
|
||||
ErrNodeModulesNotFound: "node_modulesフォルダーは存在しません!実行中の環境を編集するか、実行中の環境が正常に開始するのを待ちます"
|
||||
|
||||
#setting
|
||||
ErrBackupInUsed: "バックアップアカウントは既にCronjobで使用されており、削除することはできません。"
|
||||
ErrBackupCheck: "バックアップアカウントテスト接続に失敗した{{.err}}"
|
||||
ErrOSSConn: "最新バージョンを取得できない場合は、サーバーが外部ネットワークに接続できるかどうかを確認してください。"
|
||||
ErrEntrance: "セキュリティ入り口情報エラー。チェックしてもう一度やり直してください!"
|
||||
|
||||
#tool
|
||||
ErrConfigNotFound: "構成ファイルは存在しません"
|
||||
ErrConfigParse: "構成ファイル形式エラー"
|
||||
ErrConfigIsNull: "構成ファイルは空にすることは許可されていません"
|
||||
ErrConfigDirNotFound: "実行中のディレクトリは存在しません"
|
||||
ErrConfigAlreadyExist: "同じ名前の構成ファイルが既に存在しています"
|
||||
ErrUserFindErr: "ユーザー{{.name}} {{.err}}を見つけられなかった"
|
||||
|
||||
#ssh
|
||||
ErrFirewallNone: "システムでFirewalldまたはUFWサービスは検出されませんでした。チェックしてもう一度やり直してください!"
|
||||
ErrFirewallBoth: "FirewalldサービスとUFWサービスの両方がシステムで検出されます。競合を避けるために、1つをアンインストールして再試行してください!"
|
||||
|
||||
#cronjob
|
||||
ErrBashExecute: "スクリプト実行エラー、タスク出力テキスト領域の特定の情報を確認してください。"
|
||||
ErrCutWebsiteLog: "{{.Name}} Webサイトログの切断が失敗した、エラー{{.err}}"
|
||||
CutWebsiteLogSuccess: "{{.Name}} Webサイトログカットに正常にカット、バックアップパス{{.Path}}"
|
||||
|
||||
#toolbox
|
||||
ErrNotExistUser: "現在のユーザーは存在しません。変更して再試行してください!"
|
||||
ErrBanAction: "失敗した設定では、現在の{{.name}}サービスが利用できません。チェックして再試行してください!"
|
||||
ErrClamdscanNotFound: "Clamdscanコマンドは検出されませんでした。インストールするためにドキュメントを参照してください!"
|
||||
|
||||
#waf
|
||||
ErrScope: "この構成の変更はサポートされていません"
|
||||
ErrStateChange: "状態の変更に失敗しました"
|
||||
ErrRuleExist: "ルールが存在します"
|
||||
ErrRuleNotExist: "ルールは存在しません"
|
||||
ErrParseIP: "IP形式エラー"
|
||||
ErrDefaultIP: "デフォルトは予約済みの名前です。別の名前に変更してください"
|
||||
ErrGroupInUse: "IPグループはブラック/ホワイトリストで使用され、削除できません"
|
||||
ErrGroupExist: "IPグループ名はすでに存在しています"
|
||||
ErrIPRange: "間違ったIP範囲"
|
||||
ErrIPExist: "IPは終了します"
|
||||
|
||||
#license
|
||||
ErrLicense: "ライセンス形式のエラー、チェックして再試行してください!"
|
||||
ErrLicenseCheck: "ライセンスの確認が失敗しました。チェックしてもう一度やり直してください!"
|
||||
ErrLicenseSave: "ライセンス情報の保存に失敗しました、{{.err}}、もう一度やり直してください!"
|
||||
ErrLicenseSync: "ライセンス情報の同期に失敗し、データベースでライセンス情報は検出されませんでした!"
|
||||
ErrXpackNotFound: "このセクションはプロフェッショナルエディション機能です。最初にパネルsettings-licenseインターフェイスにライセンスをインポートしてください"
|
||||
ErrXpackNotActive: "このセクションはプロフェッショナルエディション機能です。最初にパネル設定リセンスインターフェイスでライセンスステータスを同期してください"
|
||||
ErrXpackOutOfDate: "現在のライセンスの有効期限が切れています。パネル設定リセンスインターフェイスにライセンスを再輸入してください"
|
||||
ErrXpackLost: "ライセンスは、再試行の最大数に達しました。[設定] [ライセンス]ページに移動し、[同期]ボタンを手動でクリックして、プロフェッショナルバージョンの機能が適切に機能していることを確認してください。"
|
||||
ErrXpackTimeout: "リクエストタイムアウト、ネットワーク接続が不安定な場合があります。後でもう一度やり直してください!"
|
||||
|
||||
#license
|
||||
ErrAlert: "情報形式のエラーをアラートしてください。チェックして再試行してください!"
|
||||
ErrAlertPush: "アラートプッシュエラー、チェックして再試行してください!"
|
||||
ErrAlertSave: "エラーを保存してください、チェックして再試行してください!"
|
||||
ErrAlertSync: "アラート同期エラー、チェックして再試行してください!"
|
||||
ErrAlertRemote: "リモートアラートエラー、チェックして再試行してください!"
|
||||
|
||||
#cmd
|
||||
AppVersion: "アプリバージョン"
|
||||
AppCommands: "アプリ関連のコマンド"
|
||||
AppInit: "アプリを初期化します"
|
||||
AppKeyVal: "アプリキー(英語のみをサポートする)"
|
||||
AppCreateFileErr: "file {{.name}}作成に失敗した{{.err}}"
|
||||
AppCreateDirErr: "Folder {{.name}}作成に失敗した{{.err}}"
|
||||
AppMissKey: "アプリキーがありません、-kを使用して指定します"
|
||||
AppMissVersion: "アプリバージョンがありません、-vを使用して指定します"
|
||||
AppVersionExist: "バージョンはすでに存在します!"
|
||||
AppCreateSuccessful: "創造は成功しました!"
|
||||
AppWriteErr: "file {{.name}} write failed {{.err}}"
|
||||
SudoHelper: "{{.cmd}}を使用するか、ルートユーザーに切り替えてください"
|
||||
ListenIPCommands: "リスニングIPを切り替えます"
|
||||
ListenIPv4: "IPv4で聞いてください"
|
||||
ListenIPv6: "IPv6で聞く"
|
||||
ListenChangeSuccessful: "切り替え成功!{{.Value}}で聞いています"
|
||||
ResetCommands: "システム情報をリセットします"
|
||||
ResetMFA: "1パネルの2要素認証をキャンセルします"
|
||||
ResetHttps: "1Panel HTTPSログインをキャンセルします"
|
||||
ResetEntrance: "1パネルの安全な入り口をキャンセルします"
|
||||
ResetIPs: "1パネル認定IP制限をキャンセルします"
|
||||
ResetDomain: "1パネルドメインバインディングをキャンセルします"
|
||||
RestoreCommands: "ロールバック1パネルサービスとデータ"
|
||||
RestoreNoSuchFile: "ロールバックに使用できるファイルはありません"
|
||||
RestoreStep1: "(1/5){{.name}}ディレクトリからの1パネルサービスとデータの開始ロールバック..."
|
||||
RestoreStep2: "(2/5)1パネルバイナリロールバックが成功しました"
|
||||
RestoreStep3: "(3/5)1パネルスクリプトロールバック成功"
|
||||
RestoreStep4: "(4/5)1パネルサービスロールバックが成功しました"
|
||||
RestoreStep5: "(5/5)1パネルデータロールバックが成功しました"
|
||||
RestoreSuccessful: "ロールバックが成功しました!サービスを再起動します、待ってください..."
|
||||
UpdateCommands: "パネル情報を更新します"
|
||||
UpdateUser: "パネルユーザーを更新します"
|
||||
UpdatePassword: "パスワードを更新します"
|
||||
UpdatePort: "パネルポートを更新します"
|
||||
UpdateUserNull: "エラー: パネルユーザーは空です!"
|
||||
UpdateUserBlank: "エラー: パネルユーザーにはスペースが含まれています!"
|
||||
UpdateUserFormat: "エラー: 無効なパネルユーザー形式!英語、中国語、数字、_、長さ3〜30のみをサポートしています"
|
||||
UpdateUserErr: "エラー: パネルユーザーの更新に失敗しました{{.err}}"
|
||||
UpdateSuccessful: "更新成功!"
|
||||
UpdateUserResult: "パネルユーザー: {{.name}}"
|
||||
UpdatePasswordRead: "エラー: パネルパスワード情報の読み取りに失敗しました、{{.err}}"
|
||||
UpdatePasswordNull: "エラー: パネルパスワードは空です!"
|
||||
UpdateUPasswordBlank: "エラー: パスワードにはスペースが含まれています!"
|
||||
UpdatePasswordFormat: "エラー: パネルパスワードは、文字、数字、特殊文字のみをサポートします!@#$%*_、。、、長さ8-30!"
|
||||
UpdatePasswordLen: "エラー: 6文字より長くパスワードを入力してください!"
|
||||
UpdatePasswordRe: "パスワードを認証する: "
|
||||
UpdatePasswordErr: "エラー: {{.err}}のパスワードの更新に失敗しました"
|
||||
UpdatePasswordSame: "エラー: 2つのパスワードが一致しません。チェックして再試行してください!"
|
||||
UpdatePasswordResult: "パネルパスワード: {{.name}}"
|
||||
UpdatePortFormat: "エラー: 入力ポート番号は1〜65535でなければなりません!"
|
||||
UpdatePortUsed: "エラー: ポート番号はすでに使用されています。チェックして再試行してください!"
|
||||
UpdatePortErr: "エラー: パネルポートの更新に失敗しました{{.err}}"
|
||||
UpdatePortResult: "パネルポート: {{.name}}"
|
||||
UpdatePortFirewallAdd: "ファイアウォールポートルールの追加に失敗した{{.err}}、ファイアウォールルールに{{.name}}ポートを手動で追加してください。"
|
||||
UpdatePortFirewallDel: "エラー: ファイアウォールポートの削除に失敗しました、{{.err}}"
|
||||
UpdatePortFirewallReload: "ファイアウォールのリロードに失敗しました{{.err}}、ファイアウォールを手動でリロードしてください。"
|
||||
UserInfo: "パネル情報を取得します"
|
||||
UserInfoAddr: "パネルアドレス: "
|
||||
UserInfoPassHelp: "ヒント: パスワードを変更するには、コマンドを実行できます。"
|
||||
DBConnErr: "エラー: データベース接続の初期化に失敗しました、{{.err}}"
|
||||
SystemVersion: "バージョン: "
|
||||
SystemMode: "モード: "
|
||||
|
||||
#ai-tool
|
||||
ErrOpenrestyInstall: 'まず Openresty をインストールしてください'
|
||||
ErrSSL: "証明書の内容が空です。証明書を確認してください!"
|
||||
|
||||
|
||||
#mobile app
|
||||
ErrVerifyToken: 'トークンの検証エラーです。リセット後、再度QRコードをスキャンしてください。'
|
||||
ErrInvalidToken: '無効なトークンです。リセット後、再度QRコードをスキャンしてください。'
|
||||
ErrExpiredToken: 'トークンの有効期限が切れました。リセット後、再度QRコードをスキャンしてください。'
|
||||
@@ -0,0 +1,296 @@
|
||||
ErrInvalidParams: "요청 매개변수 오류: {{ .detail }}"
|
||||
ErrTokenParse: "토큰 생성 오류: {{ .detail }}"
|
||||
ErrInitialPassword: "초기 비밀번호 오류"
|
||||
ErrInternalServer: "서버 내부 오류: {{ .detail }}"
|
||||
ErrRecordExist: "기록이 이미 존재합니다"
|
||||
ErrRecordNotFound: "기록을 찾을 수 없습니다"
|
||||
ErrStructTransform: "형식 변환 실패: {{ .detail }}"
|
||||
ErrNotLogin: "사용자가 로그인되지 않았습니다: {{ .detail }}"
|
||||
ErrPasswordExpired: "현재 비밀번호가 만료되었습니다: {{ .detail }}"
|
||||
ErrNotSupportType: "시스템에서 현재 유형을 지원하지 않습니다: {{ .detail }}"
|
||||
ErrApiConfigStatusInvalid: "API 인터페이스 액세스 금지: {{ .detail }}"
|
||||
ErrApiConfigKeyInvalid: "API 인터페이스 키 오류: {{ .detail }}"
|
||||
ErrApiConfigIPInvalid: "API 인터페이스 IP가 화이트리스트에 없습니다: {{ .detail }}"
|
||||
ErrApiConfigDisable: "이 인터페이스는 API 호출을 금지합니다: {{ .detail }}"
|
||||
ErrApiConfigKeyTimeInvalid: "API 인터페이스 타임스탬프 오류: {{ .detail }}"
|
||||
|
||||
# 공통
|
||||
ErrNameIsExist: "이름이 이미 존재합니다"
|
||||
ErrDemoEnvironment: "데모 서버에서는 이 작업이 금지되어 있습니다!"
|
||||
ErrCmdTimeout: "명령어 실행 시간이 초과되었습니다!"
|
||||
ErrCmdIllegal: "명령어에 잘못된 문자가 포함되어 있습니다. 수정 후 다시 시도하세요!"
|
||||
ErrPortExist: '{{ .port }} 포트가 {{ .type }} [{{ .name }}]에 의해 이미 사용 중입니다'
|
||||
TYPE_APP: "애플리케이션"
|
||||
TYPE_RUNTIME: "실행 환경"
|
||||
TYPE_DOMAIN: "도메인 이름"
|
||||
ErrTypePort: '포트 {{ .name }} 형식 오류'
|
||||
ErrTypePortRange: '포트 범위는 1-65535 사이여야 합니다'
|
||||
Success: "성공"
|
||||
Failed: "실패"
|
||||
SystemRestart: "시스템 재시작으로 인해 작업이 중단되었습니다"
|
||||
|
||||
# 애플리케이션
|
||||
ErrPortInUsed: "{{ .detail }} 포트가 이미 사용 중입니다"
|
||||
ErrAppLimit: "앱 설치 제한을 초과했습니다"
|
||||
ErrAppRequired: "{{ .detail }} 앱이 필요합니다"
|
||||
ErrNotInstall: "앱이 설치되지 않았습니다"
|
||||
ErrPortInOtherApp: "{{ .port }} 포트가 {{ .apps }} 앱에 의해 이미 사용 중입니다"
|
||||
ErrDbUserNotValid: "데이터베이스 사용자 이름과 비밀번호가 일치하지 않습니다!"
|
||||
ErrDockerComposeNotValid: "docker-compose 파일 형식 오류!"
|
||||
ErrUpdateBuWebsite: "애플리케이션이 성공적으로 업데이트되었지만, 웹사이트 구성 파일 수정에 실패했습니다. 구성을 확인하세요!"
|
||||
Err1PanelNetworkFailed: "기본 컨테이너 네트워크 생성 실패! {{ .detail }}"
|
||||
ErrFileParse: "애플리케이션 docker-compose 파일 분석 실패!"
|
||||
ErrInstallDirNotFound: "설치 디렉터리가 존재하지 않습니다"
|
||||
AppStoreIsUpToDate: "최신 상태입니다"
|
||||
LocalAppVersionNull: "{{.name}} 앱 버전이 동기화되지 않았습니다! 애플리케이션 목록에 추가할 수 없습니다"
|
||||
LocalAppVersionErr: "{{.name}} 버전 {{.version}} 동기화 실패! {{.err}}"
|
||||
ErrFileNotFound: "{{.name}} 파일이 존재하지 않습니다"
|
||||
ErrFileParseApp: "{{.name}} 파일 분석 실패 {{.err}}"
|
||||
ErrAppDirNull: "버전 폴더가 존재하지 않습니다"
|
||||
LocalAppErr: "앱 {{.name}} 동기화 실패! {{.err}}"
|
||||
ErrContainerName: "컨테이너 이름이 이미 존재합니다"
|
||||
ErrAppSystemRestart: "1Panel 재시작으로 인해 작업이 중단되었습니다"
|
||||
ErrCreateHttpClient: "HTTP 요청 생성 실패 {{.err}}"
|
||||
ErrHttpReqTimeOut: "요청 시간이 초과되었습니다 {{.err}}"
|
||||
ErrHttpReqFailed: "요청 실패 {{.err}}"
|
||||
ErrHttpReqNotFound: "파일이 존재하지 않습니다"
|
||||
ErrNoSuchHost: "네트워크 연결 실패"
|
||||
ErrImagePullTimeOut: "이미지 가져오기 시간 초과"
|
||||
ErrContainerNotFound: "{{ .name }} 컨테이너가 존재하지 않습니다"
|
||||
ErrContainerMsg: "{{ .name }} 컨테이너가 비정상적입니다. 자세한 내용은 컨테이너 페이지의 로그를 확인하세요"
|
||||
ErrAppBackup: "{{ .name }} 애플리케이션 백업 실패 오류 {{.err}}"
|
||||
ErrImagePull: "{{ .name }} 이미지 가져오기 실패 오류 {{.err}}"
|
||||
ErrVersionTooLow: "현재 1Panel 버전이 낮아 앱 스토어를 업데이트할 수 없습니다. 버전을 업그레이드하세요"
|
||||
ErrAppNameExist: "앱 이름이 이미 존재합니다"
|
||||
AppStoreIsSyncing: "앱 스토어가 동기화 중입니다. 나중에 다시 시도하세요"
|
||||
ErrGetCompose: "docker-compose.yml 파일 가져오기 실패! {{ .detail }}"
|
||||
ErrAppWarn: "비정상 상태, 로그를 확인하세요"
|
||||
ErrAppParamKey: "매개변수 {{ .name }} 필드 예외"
|
||||
ErrAppUpgrade: "애플리케이션 {{ .name }} 업그레이드 실패 {{ .err }}"
|
||||
AppRecover: "앱 {{ .name }} 롤백 완료"
|
||||
PullImageStart: "이미지 {{ .name }} 가져오기 시작"
|
||||
PullImageSuccess: "이미지 가져오기 성공"
|
||||
UpgradeAppStart: "애플리케이션 {{ .name }} 업그레이드 시작"
|
||||
UpgradeAppSuccess: "앱 {{ .name }} 업그레이드 성공"
|
||||
|
||||
# 파일
|
||||
ErrFileCanNotRead: "파일을 읽을 수 없습니다"
|
||||
ErrFileToLarge: "파일이 너무 큽니다"
|
||||
ErrPathNotFound: "경로를 찾을 수 없습니다"
|
||||
ErrMovePathFailed: "대상 경로가 원래 경로를 포함할 수 없습니다!"
|
||||
ErrLinkPathNotFound: "대상 경로가 존재하지 않습니다!"
|
||||
ErrFileIsExist: "파일 또는 디렉터리가 이미 존재합니다!"
|
||||
ErrFileUpload: "파일 업로드 실패 {{.name}} {{.detail}}"
|
||||
ErrFileDownloadDir: "다운로드 폴더는 지원되지 않습니다"
|
||||
ErrCmdNotFound: "{{ .name }} 명령이 존재하지 않습니다. 호스트에 이 명령을 먼저 설치하세요"
|
||||
ErrSourcePathNotFound: "소스 디렉터리가 존재하지 않습니다"
|
||||
ErrFavoriteExist: "이 경로는 이미 즐겨찾기에 추가되었습니다"
|
||||
ErrInvalidChar: "잘못된 문자는 금지됩니다"
|
||||
ErrPathNotDelete: "선택한 디렉터리는 삭제할 수 없습니다"
|
||||
|
||||
# 웹사이트
|
||||
ErrDomainIsExist: "도메인 이름이 이미 존재합니다"
|
||||
ErrAliasIsExist: "별칭이 이미 존재합니다"
|
||||
ErrAppDelete: "다른 웹사이트에서 이 애플리케이션을 사용 중입니다"
|
||||
ErrGroupIsUsed: "그룹이 사용 중이므로 삭제할 수 없습니다"
|
||||
ErrBackupMatch: "백업 파일이 현재 웹사이트 데이터와 일치하지 않습니다: {{ .detail }}"
|
||||
ErrBackupExist: "백업 파일이 원본 데이터의 일부와 일치하지 않습니다: {{ .detail }}"
|
||||
ErrPHPResource: "로컬 런타임에서 전환을 지원하지 않습니다!"
|
||||
ErrPathPermission: "인덱스 디렉터리에 1000:1000 권한이 아닌 폴더가 감지되었습니다. 웹사이트 액세스 시 '접근 거부' 오류가 발생할 수 있습니다. 상단의 저장 버튼을 클릭하세요"
|
||||
ErrDomainIsUsed: "도메인이 웹사이트 {{ .name }}에서 이미 사용 중입니다"
|
||||
ErrDomainFormat: "{{ .name }} 도메인 형식 오류"
|
||||
ErrDefaultAlias: "기본은 예약된 코드 이름입니다. 다른 이름을 사용하세요"
|
||||
ErrImageNotExist: "실행 환경 {{.name}} 이미지가 존재하지 않습니다. 실행 환경을 다시 편집하세요"
|
||||
|
||||
# SSL 관련
|
||||
ErrSSLCannotDelete: "인증서 {{ .name }}은(는) 웹사이트에서 사용 중이므로 삭제할 수 없습니다."
|
||||
ErrAccountCannotDelete: "계정과 연결된 인증서는 삭제할 수 없습니다."
|
||||
ErrSSLApply: "인증서가 성공적으로 서명되었지만 Openresty 다시 로드에 실패했습니다. 구성을 확인하세요!"
|
||||
ErrEmailIsExist: "이메일이 이미 존재합니다."
|
||||
ErrSSLKeyNotFound: "개인 키 파일이 존재하지 않습니다."
|
||||
ErrSSLCertificateNotFound: "인증서 파일이 존재하지 않습니다."
|
||||
ErrSSLKeyFormat: "개인 키 파일 검증 오류"
|
||||
ErrSSLCertificateFormat: "인증서 파일 형식 오류입니다. pem 형식을 사용하세요."
|
||||
ErrEabKidOrEabHmacKeyCannotBlank: "EabKid 또는 EabHmacKey 는 비워둘 수 없습니다."
|
||||
ErrOpenrestyNotFound: "HTTP 모드는 먼저 Openresty 를 설치해야 합니다."
|
||||
ApplySSLStart: "인증서를 신청하기 시작합니다. 도메인 이름 [{{ .domain }}], 신청 방법 [{{ .type }}]"
|
||||
dnsAccount: "DNS 자동"
|
||||
dnsManual: "DNS 수동"
|
||||
http: "HTTP"
|
||||
ApplySSLFailed: "도메인 [{{ .domain }}] 인증서 신청 실패, {{ .detail }}"
|
||||
ApplySSLSuccess: "도메인 [{{ .domain }}] 인증서 신청 성공!"
|
||||
DNSAccountName: "DNS 계정 [{{ .name }}] 제조사 [{{ .type }}]"
|
||||
PushDirLog: "인증서를 디렉토리 [{{ .path }}]에 푸시했습니다. {{ .status }}"
|
||||
ErrDeleteCAWithSSL: "현재 조직에 발급된 인증서가 있으므로 삭제할 수 없습니다."
|
||||
ErrDeleteWithPanelSSL: "패널 SSL 구성이 이 인증서를 사용 중이므로 삭제할 수 없습니다."
|
||||
ErrDefaultCA: "기본 인증 기관은 삭제할 수 없습니다."
|
||||
ApplyWebSiteSSLLog: "{{ .name }} 웹사이트 인증서를 업데이트하기 시작합니다."
|
||||
ErrUpdateWebsiteSSL: "{{ .name }} 웹사이트 인증서 업데이트 실패: {{ .err }}"
|
||||
ApplyWebSiteSSLSuccess: "웹사이트 인증서 업데이트 성공"
|
||||
ErrExecShell: "스크립트 실행 실패 {{ .err }}"
|
||||
ExecShellStart: "스크립트 실행 시작"
|
||||
ExecShellSuccess: "스크립트 실행 성공"
|
||||
StartUpdateSystemSSL: "시스템 인증서 업데이트 시작"
|
||||
UpdateSystemSSLSuccess: "시스템 인증서 업데이트 성공"
|
||||
|
||||
# MySQL
|
||||
ErrUserIsExist: "현재 사용자가 이미 존재합니다. 새로운 사용자를 입력하세요."
|
||||
ErrDatabaseIsExist: "현재 데이터베이스가 이미 존재합니다. 새로운 데이터베이스를 입력하세요."
|
||||
ErrExecTimeOut: "SQL 실행이 시간 초과되었습니다. 데이터베이스를 확인하세요."
|
||||
ErrRemoteExist: "원격 데이터베이스에 동일한 이름이 이미 존재합니다. 이름을 수정한 후 다시 시도하세요."
|
||||
ErrLocalExist: "로컬 데이터베이스에 동일한 이름이 이미 존재합니다. 이름을 수정한 후 다시 시도하세요."
|
||||
|
||||
# Redis
|
||||
ErrTypeOfRedis: "복구 파일 형식이 현재 지속성 모드와 일치하지 않습니다. 파일 형식을 수정한 후 다시 시도하세요."
|
||||
|
||||
# Container
|
||||
ErrInUsed: "{{ .detail }}이(가) 사용 중이므로 삭제할 수 없습니다."
|
||||
ErrObjectInUsed: "이 객체는 사용 중이므로 삭제할 수 없습니다."
|
||||
ErrObjectBeDependent: "이 이미지는 다른 이미지에 의해 의존되고 있어 삭제할 수 없습니다."
|
||||
ErrPortRules: "포트 수가 일치하지 않습니다. 다시 입력하세요!"
|
||||
ErrPgImagePull: "이미지 가져오기 시간이 초과되었습니다. 이미지 가속 구성을 설정하거나 postgres:16.0-alpine 이미지를 수동으로 가져온 후 다시 시도하세요."
|
||||
|
||||
# Runtime
|
||||
ErrDirNotFound: "빌드 폴더가 존재하지 않습니다! 파일의 무결성을 확인하세요!"
|
||||
ErrFileNotExist: "{{ .detail }} 파일이 존재하지 않습니다! 소스 파일의 무결성을 확인하세요!"
|
||||
ErrImageBuildErr: "이미지 빌드 실패"
|
||||
ErrImageExist: "이미지가 이미 존재합니다!"
|
||||
ErrDelWithWebsite: "운영 환경이 웹사이트와 연결되어 있어 삭제할 수 없습니다."
|
||||
ErrRuntimeStart: "실행 시작 실패"
|
||||
ErrPackageJsonNotFound: "package.json 파일이 존재하지 않습니다."
|
||||
ErrScriptsNotFound: "package.json 에서 스크립트 구성 항목을 찾을 수 없습니다."
|
||||
ErrContainerNameNotFound: "컨테이너 이름을 가져올 수 없습니다. .env 파일을 확인하세요."
|
||||
ErrNodeModulesNotFound: "node_modules 폴더가 존재하지 않습니다! 실행 환경을 편집하거나 실행 환경이 성공적으로 시작되기를 기다리세요."
|
||||
|
||||
# Setting
|
||||
ErrBackupInUsed: "백업 계정이 크론 작업에 사용 중이므로 삭제할 수 없습니다."
|
||||
ErrBackupCheck: "백업 계정 연결 테스트 실패 {{ .err }}"
|
||||
ErrOSSConn: "최신 버전을 가져올 수 없습니다. 서버가 외부 네트워크에 연결할 수 있는지 확인하세요."
|
||||
ErrEntrance: "보안 입구 정보 오류. 확인 후 다시 시도하세요!"
|
||||
|
||||
# Tool
|
||||
ErrConfigNotFound: "구성 파일이 존재하지 않습니다."
|
||||
ErrConfigParse: "구성 파일 형식 오류"
|
||||
ErrConfigIsNull: "구성 파일은 비워둘 수 없습니다."
|
||||
ErrConfigDirNotFound: "실행 디렉토리가 존재하지 않습니다."
|
||||
ErrConfigAlreadyExist: "동일한 이름의 구성 파일이 이미 존재합니다."
|
||||
ErrUserFindErr: "사용자 {{ .name }} 찾기 실패 {{ .err }}"
|
||||
|
||||
# SSH
|
||||
ErrFirewallNone: "시스템에서 firewalld 또는 ufw 서비스를 감지하지 못했습니다. 확인 후 다시 시도하세요!"
|
||||
ErrFirewallBoth: "시스템에서 firewalld 와 ufw 서비스가 모두 감지되었습니다. 충돌을 방지하려면 하나를 제거한 후 다시 시도하세요!"
|
||||
|
||||
# Cronjob
|
||||
ErrBashExecute: "스크립트 실행 오류. 작업 출력 텍스트 영역에서 구체적인 정보를 확인하세요."
|
||||
ErrCutWebsiteLog: "{{ .name }} 웹사이트 로그 자르기 실패, 오류 {{ .err }}"
|
||||
CutWebsiteLogSuccess: "{{ .name }} 웹사이트 로그 자르기 성공, 백업 경로 {{ .path }}"
|
||||
|
||||
# Toolbox
|
||||
ErrNotExistUser: "현재 사용자가 존재하지 않습니다. 수정 후 다시 시도하세요!"
|
||||
ErrBanAction: "설정 실패, 현재 {{ .name }} 서비스가 사용할 수 없습니다. 확인 후 다시 시도하세요!"
|
||||
ErrClamdscanNotFound: "clamdscan 명령을 감지하지 못했습니다. 설치 문서를 참조하세요!"
|
||||
|
||||
# WAF
|
||||
ErrScope: "이 구성의 수정은 지원되지 않습니다."
|
||||
ErrStateChange: "상태 수정 실패"
|
||||
ErrRuleExist: "규칙이 이미 존재합니다."
|
||||
ErrRuleNotExist: "규칙이 존재하지 않습니다."
|
||||
ErrParseIP: "IP 형식 오류"
|
||||
ErrDefaultIP: "default 는 예약된 이름입니다. 다른 이름으로 변경하세요."
|
||||
ErrGroupInUse: "IP 그룹이 블랙/화이트 리스트에서 사용 중이며 삭제할 수 없습니다."
|
||||
ErrGroupExist: "IP 그룹 이름이 이미 존재합니다."
|
||||
ErrIPRange: "잘못된 IP 범위"
|
||||
ErrIPExist: "IP가 이미 존재합니다."
|
||||
|
||||
# License
|
||||
ErrLicense: "라이선스 형식 오류, 확인 후 다시 시도하세요!"
|
||||
ErrLicenseCheck: "라이선스 검증 실패, 확인 후 다시 시도하세요!"
|
||||
ErrXpackVersion: "라이선스 검증 실패, 이 라이선스는 버전 제한이 있어 성공적으로 가져올 수 없습니다. 확인 후 다시 시도하세요!"
|
||||
ErrLicenseSave: "라이선스 정보 저장 실패, 오류 {{ .err }}. 다시 시도하세요!"
|
||||
ErrLicenseSync: "라이선스 정보 동기화 실패, 데이터베이스에서 라이선스 정보를 감지하지 못했습니다!"
|
||||
ErrXpackNotFound: "이 섹션은 전문가 버전 기능입니다. Panel 설정 - 라이선스 인터페이스에서 먼저 라이선스를 가져오세요."
|
||||
ErrXpackNotActive: "이 섹션은 전문가 버전 기능입니다. Panel 설정 - 라이선스 인터페이스에서 먼저 라이선스 상태를 동기화하세요."
|
||||
ErrXpackOutOfDate: "현재 라이선스가 만료되었습니다. Panel 설정 - 라이선스 인터페이스에서 라이선스를 다시 가져오세요."
|
||||
ErrXpackLost: "라이선스가 최대 재시도 횟수에 도달했습니다. [설정] - [라이선스] 페이지로 이동하여 동기화 버튼을 수동으로 클릭해 전문가 버전 기능을 정상적으로 작동시키세요."
|
||||
ErrXpackTimeout: "요청 시간이 초과되었습니다. 네트워크 연결이 불안정할 수 있으니 나중에 다시 시도하세요!"
|
||||
|
||||
# Alert
|
||||
ErrAlert: "알림 정보 형식 오류, 확인 후 다시 시도하세요!"
|
||||
ErrAlertPush: "알림 전송 오류, 확인 후 다시 시도하세요!"
|
||||
ErrAlertSave: "알림 저장 오류, 확인 후 다시 시도하세요!"
|
||||
ErrAlertSync: "알림 동기화 오류, 확인 후 다시 시도하세요!"
|
||||
ErrAlertRemote: "원격 알림 오류, 확인 후 다시 시도하세요!"
|
||||
|
||||
# CMD
|
||||
AppVersion: "앱 버전"
|
||||
AppCommands: "앱 관련 명령어"
|
||||
AppInit: "앱 초기화"
|
||||
AppKeyVal: "앱 키 (영어만 지원)"
|
||||
AppCreateFileErr: "파일 {{ .name }} 생성 실패 {{ .err }}"
|
||||
AppCreateDirErr: "폴더 {{ .name }} 생성 실패 {{ .err }}"
|
||||
AppMissKey: "앱 키가 없습니다. -k 옵션으로 지정하세요."
|
||||
AppMissVersion: "앱 버전이 없습니다. -v 옵션으로 지정하세요."
|
||||
AppVersionExist: "버전이 이미 존재합니다!"
|
||||
AppCreateSuccessful: "생성 성공!"
|
||||
AppWriteErr: "파일 {{ .name }} 쓰기 실패 {{ .err }}"
|
||||
SudoHelper: "{{ .cmd }} 명령을 사용하거나 root 사용자로 전환하세요."
|
||||
ListenIPCommands: "IP 변경"
|
||||
ListenIPv4: "IPv4 에서 수신 대기"
|
||||
ListenIPv6: "IPv6 에서 수신 대기"
|
||||
ListenChangeSuccessful: "변경 성공! 현재 {{ .value }}에서 수신 대기 중입니다."
|
||||
ResetCommands: "시스템 정보 초기화"
|
||||
ResetMFA: "1Panel 이중 인증 취소"
|
||||
ResetHttps: "1Panel HTTPS 로그인 취소"
|
||||
ResetEntrance: "1Panel 보안 입구 취소"
|
||||
ResetIPs: "1Panel 허용 IP 제한 취소"
|
||||
ResetDomain: "1Panel 도메인 바인딩 취소"
|
||||
RestoreCommands: "1Panel 서비스 및 데이터 복구"
|
||||
RestoreNoSuchFile: "복구 가능한 파일이 없습니다."
|
||||
RestoreStep1: "(1/5) {{ .name }} 디렉토리에서 1Panel 서비스 및 데이터 복구 시작..."
|
||||
RestoreStep2: "(2/5) 1Panel 바이너리 복구 성공"
|
||||
RestoreStep3: "(3/5) 1Panel 스크립트 복구 성공"
|
||||
RestoreStep4: "(4/5) 1Panel 서비스 복구 성공"
|
||||
RestoreStep5: "(5/5) 1Panel 데이터 복구 성공"
|
||||
RestoreSuccessful: "복구 성공! 서비스를 다시 시작합니다. 잠시만 기다려주세요..."
|
||||
UpdateCommands: "패널 정보 업데이트"
|
||||
UpdateUser: "패널 사용자 업데이트"
|
||||
UpdatePassword: "패널 비밀번호 업데이트"
|
||||
UpdatePort: "패널 포트 업데이트"
|
||||
UpdateUserNull: "오류: 패널 사용자가 비어 있습니다!"
|
||||
UpdateUserBlank: "오류: 패널 사용자에 공백이 포함되어 있습니다!"
|
||||
UpdateUserFormat: "오류: 잘못된 패널 사용자 형식! 영어, 중국어, 숫자, _만 지원하며 길이는 3~30자입니다."
|
||||
UpdateUserErr: "오류: 패널 사용자 업데이트 실패 {{ .err }}"
|
||||
UpdateSuccessful: "업데이트 성공!"
|
||||
UpdateUserResult: "패널 사용자: {{ .name }}"
|
||||
UpdatePasswordRead: "오류: 패널 비밀번호 정보 읽기 실패 {{ .err }}"
|
||||
UpdatePasswordNull: "오류: 패널 비밀번호가 비어 있습니다!"
|
||||
UpdateUPasswordBlank: "오류: 패널 비밀번호에 공백이 포함되어 있습니다!"
|
||||
UpdatePasswordFormat: "오류: 패널 비밀번호는 문자, 숫자, 특수 문자 !@#$%*_,.?만 지원하며 길이는 8~30자입니다!"
|
||||
UpdatePasswordLen: "오류: 6자 이상의 비밀번호를 입력하세요!"
|
||||
UpdatePasswordRe: "비밀번호 확인:"
|
||||
UpdatePasswordErr: "오류: 패널 비밀번호 업데이트 실패 {{ .err }}"
|
||||
UpdatePasswordSame: "오류: 두 비밀번호가 일치하지 않습니다. 확인 후 다시 시도하세요!"
|
||||
UpdatePasswordResult: "패널 비밀번호: {{ .name }}"
|
||||
UpdatePortFormat: "오류: 입력한 포트 번호는 1~65535 사이여야 합니다!"
|
||||
UpdatePortUsed: "오류: 포트 번호가 이미 사용 중입니다. 확인 후 다시 시도하세요!"
|
||||
UpdatePortErr: "오류: 패널 포트 업데이트 실패 {{ .err }}"
|
||||
UpdatePortResult: "패널 포트: {{ .name }}"
|
||||
UpdatePortFirewallAdd: "방화벽 포트 규칙 추가 실패 {{ .err }}, 방화벽 규칙에 {{ .name }} 포트를 수동으로 추가하세요."
|
||||
UpdatePortFirewallDel: "오류: 방화벽 포트 삭제 실패 {{ .err }}"
|
||||
UpdatePortFirewallReload: "방화벽 다시 로드 실패 {{ .err }}, 방화벽을 수동으로 다시 로드하세요."
|
||||
UserInfo: "패널 정보 가져오기"
|
||||
UserInfoAddr: "패널 주소: "
|
||||
UserInfoPassHelp: "팁: 비밀번호를 변경하려면 다음 명령어를 실행할 수 있습니다: "
|
||||
DBConnErr: "오류: 데이터베이스 연결 초기화 실패 {{ .err }}"
|
||||
SystemVersion: "버전: "
|
||||
SystemMode: "모드: "
|
||||
|
||||
#ai-tool
|
||||
ErrOpenrestyInstall: '먼저 Openresty를 설치하세요'
|
||||
ErrSSL: "인증서 내용이 비어 있습니다. 인증서를 확인하세요!"
|
||||
|
||||
|
||||
#mobile app
|
||||
ErrVerifyToken: '토큰 검증 오류가 발생했습니다. 재설정 후 다시 스캔해 주세요.'
|
||||
ErrInvalidToken: '유효하지 않은 토큰입니다. 재설정 후 다시 스캔해 주세요.'
|
||||
ErrExpiredToken: '토큰이 만료되었습니다. 재설정 후 다시 스캔해 주세요.'
|
||||
@@ -0,0 +1,295 @@
|
||||
ErrInvalidParams: "Ralat parameter permintaan: {{ .detail }}"
|
||||
ErrTokenParse: "Ralat penjanaan token: {{ .detail }}"
|
||||
ErrInitialPassword: "Ralat kata laluan awal"
|
||||
ErrInternalServer: "Ralat dalaman perkhidmatan: {{ .detail }}"
|
||||
ErrRecordExist: "Rekod sudah wujud"
|
||||
ErrRecordNotFound: "Rekod tidak dijumpai"
|
||||
ErrStructTransform: "Kegagalan penukaran jenis: {{ .detail }}"
|
||||
ErrNotLogin: "Pengguna belum log masuk: {{ .detail }}"
|
||||
ErrPasswordExpired: "Kata laluan semasa telah tamat tempoh: {{ .detail }}"
|
||||
ErrNotSupportType: "Sistem tidak menyokong jenis semasa: {{ .detail }}"
|
||||
ErrApiConfigStatusInvalid: "Akses antara muka API dilarang: {{ .detail }}"
|
||||
ErrApiConfigKeyInvalid: "Ralat kunci antara muka API: {{ .detail }}"
|
||||
ErrApiConfigIPInvalid: "IP antara muka API tidak berada dalam senarai putih: {{ .detail }}"
|
||||
ErrApiConfigDisable: "Antara muka ini melarang penggunaan panggilan API: {{ .detail }}"
|
||||
ErrApiConfigKeyTimeInvalid: "Ralat cap waktu antara muka API: {{ .detail }}"
|
||||
|
||||
#common
|
||||
ErrNameIsExist: "Nama sudah wujud"
|
||||
ErrDemoEnvironment: "Pelayan demo, operasi ini dilarang!"
|
||||
ErrCmdTimeout: "Pelaksanaan arahan telah tamat masa!"
|
||||
ErrCmdIllegal: "Arahan mengandungi aksara tidak sah. Sila ubah dan cuba lagi!"
|
||||
ErrPortExist: 'Port {{ .port }} sudah digunakan oleh {{ .type }} [{{ .name }}]'
|
||||
TYPE_APP: "Aplikasi"
|
||||
TYPE_RUNTIME: "Persekitaran runtime"
|
||||
TYPE_DOMAIN: "Nama domain"
|
||||
ErrTypePort: 'Format port {{ .name }} adalah salah'
|
||||
ErrTypePortRange: 'Julat port perlu berada di antara 1-65535'
|
||||
Success: "Berjaya"
|
||||
Failed: "Gagal"
|
||||
SystemRestart: "Mulakan semula sistem menyebabkan gangguan tugas"
|
||||
|
||||
#app
|
||||
ErrPortInUsed: "Port {{ .detail }} sudah digunakan"
|
||||
ErrAppLimit: "Aplikasi melebihi had pemasangan"
|
||||
ErrAppRequired: "Aplikasi {{ .detail }} diperlukan"
|
||||
ErrNotInstall: "Aplikasi tidak dipasang"
|
||||
ErrPortInOtherApp: "Port {{ .port }} sudah digunakan oleh aplikasi {{ .apps }}"
|
||||
ErrDbUserNotValid: "Pangkalan data stok, nama pengguna dan kata laluan tidak sepadan!"
|
||||
ErrDockerComposeNotValid: "Format fail docker-compose adalah salah!"
|
||||
ErrUpdateBuWebsite: "Aplikasi berjaya dikemas kini, tetapi pengubahsuaian fail konfigurasi laman web gagal, sila semak konfigurasi!"
|
||||
Err1PanelNetworkFailed: "Penciptaan rangkaian kontena lalai gagal! {{ .detail }}"
|
||||
ErrFileParse: "Analisis fail docker-compose aplikasi gagal!"
|
||||
ErrInstallDirNotFound: "Direktori pemasangan tidak wujud"
|
||||
AppStoreIsUpToDate: "Terkini"
|
||||
LocalAppVersionNull: "Aplikasi {{.name}} tidak diselaraskan ke versi! Tidak dapat menambah ke senarai aplikasi"
|
||||
LocalAppVersionErr: "{{.name}} gagal diselaraskan ke versi {{.version}}! {{.err}}"
|
||||
ErrFileNotFound: "Fail {{.name}} tidak wujud"
|
||||
ErrFileParseApp: "Gagal menganalisis fail {{.name}} {{.err}}"
|
||||
ErrAppDirNull: "Folder versi tidak wujud"
|
||||
LocalAppErr: "Penyelarasan aplikasi {{.name}} gagal! {{.err}}"
|
||||
ErrContainerName: "Nama Kontena sudah wujud"
|
||||
ErrAppSystemRestart: "Pemulangan semula 1Panel menyebabkan tugas terhenti"
|
||||
ErrCreateHttpClient: "Gagal mencipta permintaan HTTP {{.err}}"
|
||||
ErrHttpReqTimeOut: "Permintaan tamat masa {{.err}}"
|
||||
ErrHttpReqFailed: "Permintaan gagal {{.err}}"
|
||||
ErrHttpReqNotFound: "Fail tidak wujud"
|
||||
ErrNoSuchHost: "Sambungan rangkaian gagal"
|
||||
ErrImagePullTimeOut: "Tarik imej tamat masa"
|
||||
ErrContainerNotFound: "Kontena {{ .name }} tidak wujud"
|
||||
ErrContainerMsg: "Kontena {{ .name }} bermasalah, sila semak log pada halaman kontena untuk maklumat lanjut"
|
||||
ErrAppBackup: "Sandaran aplikasi {{ .name }} gagal err {{.err}}"
|
||||
ErrImagePull: "Tarik imej {{ .name }} gagal err {{.err}}"
|
||||
ErrVersionTooLow: "Versi 1Panel semasa terlalu rendah untuk mengemas kini gedung aplikasi, sila tingkatkan versi"
|
||||
ErrAppNameExist: "Nama aplikasi sudah wujud"
|
||||
AppStoreIsSyncing: "Gedung Aplikasi sedang menyelaraskan, sila cuba lagi nanti"
|
||||
ErrGetCompose: "Gagal mendapatkan fail docker-compose.yml! {{ .detail }}"
|
||||
ErrAppWarn: "Status tidak normal, sila semak log"
|
||||
ErrAppParamKey: "Pengecualian medan parameter {{ .name }}"
|
||||
ErrAppUpgrade: "Gagal menaik taraf aplikasi {{ .name }} {{ .err }}"
|
||||
AppRecover: "Aplikasi {{ .name }} telah dikembalikan"
|
||||
PullImageStart: "Memulakan penarikan imej {{ .name }}"
|
||||
PullImageSuccess: "Imej berjaya ditarik"
|
||||
UpgradeAppStart: "Memulakan peningkatan aplikasi {{ .name }}"
|
||||
UpgradeAppSuccess: "Aplikasi {{ .name }} berjaya dinaik taraf"
|
||||
|
||||
#file
|
||||
ErrFileCanNotRead: "Fail tidak boleh dibaca"
|
||||
ErrFileToLarge: "Fail terlalu besar"
|
||||
ErrPathNotFound: "Laluan tidak dijumpai"
|
||||
ErrMovePathFailed: "Laluan sasaran tidak boleh mengandungi laluan asal!"
|
||||
ErrLinkPathNotFound: "Laluan sasaran tidak wujud!"
|
||||
ErrFileIsExist: "Fail atau direktori sudah wujud!"
|
||||
ErrFileUpload: "Gagal memuat naik fail {{.name}} {{.detail}}"
|
||||
ErrFileDownloadDir: "Muat turun folder tidak disokong"
|
||||
ErrCmdNotFound: "Arahan {{ .name }} tidak wujud, sila pasang arahan ini pada hos terlebih dahulu"
|
||||
ErrSourcePathNotFound: "Direktori sumber tidak wujud"
|
||||
ErrFavoriteExist: "Laluan ini telah dikumpulkan"
|
||||
ErrInvalidChar: "Aksara tidak sah adalah dilarang"
|
||||
ErrPathNotDelete: "Direktori yang dipilih tidak boleh dipadam"
|
||||
|
||||
#website
|
||||
ErrDomainIsExist: "Nama domain sudah wujud"
|
||||
ErrAliasIsExist: "Alias sudah wujud"
|
||||
ErrAppDelete: "Laman web lain menggunakan aplikasi ini"
|
||||
ErrGroupIsUsed: "Kumpulan sedang digunakan dan tidak boleh dipadam"
|
||||
ErrBackupMatch: "Fail sandaran tidak sepadan dengan data separa laman web semasa: {{ .detail }}"
|
||||
ErrBackupExist: "Fail sandaran berkaitan dengan sebahagian data asal yang tidak wujud: {{ .detail }}"
|
||||
ErrPHPResource: "Runtime tempatan tidak menyokong penukaran!"
|
||||
ErrPathPermission: "Folder dengan kebenaran bukan 1000:1000 dikesan dalam direktori indeks, yang mungkin menyebabkan ralat 'Access denied' semasa mengakses laman web. Sila klik butang simpan di atas"
|
||||
ErrDomainIsUsed: "Domain sudah digunakan oleh laman web {{ .name }}"
|
||||
ErrDomainFormat: "Format domain {{ .name }} adalah salah"
|
||||
ErrDefaultAlias: "default ialah nama kod terpelihara, sila gunakan nama kod lain"
|
||||
ErrImageNotExist: "Imej persekitaran runtime {{.name}} tidak wujud, sila sunting semula persekitaran runtime"
|
||||
|
||||
#ssl
|
||||
ErrSSLCannotDelete: "Sijil {{ .name }} sedang digunakan oleh laman web dan tidak boleh dihapuskan"
|
||||
ErrAccountCannotDelete: "Sijil yang dikaitkan dengan akaun tidak boleh dihapuskan"
|
||||
ErrSSLApply: "Sijil berjaya terus ditandatangani, tetapi reload OpenResty gagal, sila semak konfigurasi!"
|
||||
ErrEmailIsExist: "Emel sudah wujud"
|
||||
ErrSSLKeyNotFound: "Fail kunci peribadi tidak wujud"
|
||||
ErrSSLCertificateNotFound: "Fail sijil tidak wujud"
|
||||
ErrSSLKeyFormat: "Ralat pengesahan fail kunci peribadi"
|
||||
ErrSSLCertificateFormat: "Format fail sijil salah, sila gunakan format PEM"
|
||||
ErrEabKidOrEabHmacKeyCannotBlank: "EabKid atau EabHmacKey tidak boleh kosong"
|
||||
ErrOpenrestyNotFound: "Mod HTTP memerlukan OpenResty dipasang terlebih dahulu"
|
||||
ApplySSLStart: "Memulakan permohonan sijil, nama domain [{{ .domain }}], kaedah permohonan [{{ .type }}]"
|
||||
dnsAccount: "DNS Automatik"
|
||||
dnsManual: "DNS Manual"
|
||||
http: "HTTP"
|
||||
ApplySSLFailed: "Permohonan sijil untuk [{{ .domain }}] gagal, {{.detail}}"
|
||||
ApplySSLSuccess: "Permohonan sijil untuk [{{ .domain }}] berjaya!"
|
||||
DNSAccountName: "Akaun DNS [{{ .name }}], pengeluar [{{ .type }}]"
|
||||
PushDirLog: "Sijil dihantar ke direktori [{{ .path }}] {{ .status }}"
|
||||
ErrDeleteCAWithSSL: "Terdapat sijil yang telah dikeluarkan di bawah organisasi semasa dan tidak boleh dihapuskan"
|
||||
ErrDeleteWithPanelSSL: "Konfigurasi SSL panel menggunakan sijil ini dan tidak boleh dihapuskan"
|
||||
ErrDefaultCA: "Pihak Berkuasa Sijil lalai tidak boleh dihapuskan"
|
||||
ApplyWebSiteSSLLog: "Memulakan kemas kini sijil laman web {{ .name }}"
|
||||
ErrUpdateWebsiteSSL: "Sijil laman web {{ .name }} gagal dikemas kini: {{ .err }}"
|
||||
ApplyWebSiteSSLSuccess: "Sijil laman web berjaya dikemas kini"
|
||||
ErrExecShell: "Pelaksanaan skrip gagal {{ .err }}"
|
||||
ExecShellStart: "Memulakan pelaksanaan skrip"
|
||||
ExecShellSuccess: "Skrip berjaya dilaksanakan"
|
||||
StartUpdateSystemSSL: "Memulakan kemas kini sijil sistem"
|
||||
UpdateSystemSSLSuccess: "Sijil sistem berjaya dikemas kini"
|
||||
|
||||
#mysql
|
||||
ErrUserIsExist: "Pengguna semasa sudah wujud. Sila masukkan pengguna baharu"
|
||||
ErrDatabaseIsExist: "Pangkalan data semasa sudah wujud. Sila masukkan pangkalan data baharu"
|
||||
ErrExecTimeOut: "Pelaksanaan SQL tamat masa, sila semak pangkalan data"
|
||||
ErrRemoteExist: "Pangkalan data jauh dengan nama tersebut sudah wujud, sila ubah dan cuba lagi"
|
||||
ErrLocalExist: "Pangkalan data tempatan dengan nama tersebut sudah wujud, sila ubah dan cuba lagi"
|
||||
|
||||
#redis
|
||||
ErrTypeOfRedis: "Jenis fail pemulihan tidak sepadan dengan mod ketekalan semasa. Sila ubah jenis fail dan cuba lagi."
|
||||
|
||||
#container
|
||||
ErrInUsed: "{{ .detail }} sedang digunakan dan tidak boleh dihapuskan"
|
||||
ErrObjectInUsed: "Objek ini sedang digunakan dan tidak boleh dihapuskan"
|
||||
ErrObjectBeDependent: "Imej ini bergantung kepada imej lain dan tidak boleh dihapuskan"
|
||||
ErrPortRules: "Bilangan port tidak sepadan, sila masukkan semula!"
|
||||
ErrPgImagePull: "Tarik imej tamat masa. Sila konfigurasikan pecutan imej atau tarik imej postgres:16.0-alpine secara manual dan cuba lagi"
|
||||
|
||||
#runtime
|
||||
ErrDirNotFound: "Folder binaan tidak wujud! Sila semak integriti fail!"
|
||||
ErrFileNotExist: "Fail {{ .detail }} tidak wujud! Sila semak integriti fail sumber!"
|
||||
ErrImageBuildErr: "Binaan imej gagal"
|
||||
ErrImageExist: "Imej sudah wujud!"
|
||||
ErrDelWithWebsite: "Persekitaran operasi telah dikaitkan dengan laman web dan tidak boleh dihapuskan"
|
||||
ErrRuntimeStart: "Gagal memulakan"
|
||||
ErrPackageJsonNotFound: "Fail package.json tidak wujud"
|
||||
ErrScriptsNotFound: "Tiada item konfigurasi skrip dijumpai dalam package.json"
|
||||
ErrContainerNameNotFound: "Tidak dapat mendapatkan nama kontena, sila semak fail .env"
|
||||
ErrNodeModulesNotFound: "Folder node_modules tidak wujud! Sila sunting persekitaran operasi atau tunggu sehingga persekitaran operasi berjaya dimulakan"
|
||||
|
||||
#setting
|
||||
ErrBackupInUsed: "Akaun sandaran sedang digunakan dalam cronjob dan tidak boleh dihapuskan."
|
||||
ErrBackupCheck: "Ujian sambungan akaun sandaran gagal {{ .err }}"
|
||||
ErrOSSConn: "Tidak dapat mendapatkan versi terkini, sila semak sama ada pelayan boleh menyambung ke rangkaian luaran."
|
||||
ErrEntrance: "Ralat maklumat pintu masuk keselamatan. Sila semak dan cuba lagi!"
|
||||
|
||||
#tool
|
||||
ErrConfigNotFound: "Fail konfigurasi tidak wujud"
|
||||
ErrConfigParse: "Format fail konfigurasi salah"
|
||||
ErrConfigIsNull: "Fail konfigurasi tidak boleh kosong"
|
||||
ErrConfigDirNotFound: "Direktori operasi tidak wujud"
|
||||
ErrConfigAlreadyExist: "Fail konfigurasi dengan nama yang sama sudah wujud"
|
||||
ErrUserFindErr: "Gagal mencari pengguna {{ .name }} {{ .err }}"
|
||||
|
||||
#ssh
|
||||
ErrFirewallNone: "Tiada perkhidmatan firewalld atau ufw dikesan pada sistem. Sila semak dan cuba lagi!"
|
||||
ErrFirewallBoth: "Kedua-dua perkhidmatan firewalld dan ufw dikesan pada sistem. Untuk mengelakkan konflik, sila nyahpasang salah satu dan cuba lagi!"
|
||||
|
||||
#cronjob
|
||||
ErrBashExecute: "Ralat pelaksanaan skrip, sila semak maklumat khusus dalam kawasan teks output tugas."
|
||||
ErrCutWebsiteLog: "Pemotongan log laman web {{ .name }} gagal, ralat {{ .err }}"
|
||||
CutWebsiteLogSuccess: "Log laman web {{ .name }} berjaya dipotong, laluan sandaran {{ .path }}"
|
||||
|
||||
#toolbox
|
||||
ErrNotExistUser: "Pengguna semasa tidak wujud. Sila ubah dan cuba lagi!"
|
||||
ErrBanAction: "Tetapan gagal, perkhidmatan {{ .name }} semasa tidak tersedia, sila semak dan cuba lagi!"
|
||||
ErrClamdscanNotFound: "Perintah clamdscan tidak dikesan, sila rujuk dokumentasi untuk memasangnya!"
|
||||
|
||||
#waf
|
||||
ErrScope: "Pengubahsuaian konfigurasi ini tidak disokong"
|
||||
ErrStateChange: "Pengubahsuaian status gagal"
|
||||
ErrRuleExist: "Peraturan sudah wujud"
|
||||
ErrRuleNotExist: "Peraturan tidak wujud"
|
||||
ErrParseIP: "Format IP salah"
|
||||
ErrDefaultIP: "default adalah nama terpelihara, sila tukar kepada nama lain"
|
||||
ErrGroupInUse: "Kumpulan IP sedang digunakan oleh senarai hitam/putih dan tidak boleh dihapuskan"
|
||||
ErrGroupExist: "Nama kumpulan IP sudah wujud"
|
||||
ErrIPRange: "Julat IP salah"
|
||||
ErrIPExist: "IP sudah wujud"
|
||||
|
||||
#license
|
||||
ErrLicense: "Format lesen salah, sila semak dan cuba lagi!"
|
||||
ErrLicenseCheck: "Pengesahan lesen gagal, sila semak dan cuba lagi!"
|
||||
ErrLicenseSave: "Gagal menyimpan maklumat lesen, ralat {{ .err }}, sila cuba lagi!"
|
||||
ErrLicenseSync: "Gagal menyelaraskan maklumat lesen, tiada maklumat lesen dikesan dalam pangkalan data!"
|
||||
ErrXpackNotFound: "Bahagian ini adalah ciri edisi profesional, sila import lesen terlebih dahulu dalam Tetapan Panel - Antara Muka Lesen"
|
||||
ErrXpackNotActive: "Bahagian ini adalah ciri edisi profesional, sila selaraskan status lesen terlebih dahulu dalam Tetapan Panel - Antara Muka Lesen"
|
||||
ErrXpackOutOfDate: "Lesen semasa telah tamat tempoh, sila import semula lesen dalam Tetapan Panel - Antara Muka Lesen"
|
||||
ErrXpackLost: "Lesen telah mencapai bilangan maksimum percubaan semula. Sila pergi ke halaman [Tetapan] [Lesen] dan klik butang selaraskan secara manual untuk memastikan ciri versi profesional berfungsi dengan baik."
|
||||
ErrXpackTimeout: "Permintaan tamat masa, sambungan rangkaian mungkin tidak stabil, sila cuba lagi nanti!"
|
||||
|
||||
#license
|
||||
ErrAlert: "Format maklumat amaran salah, sila semak dan cuba lagi!"
|
||||
ErrAlertPush: "Ralat penghantaran amaran, sila semak dan cuba lagi!"
|
||||
ErrAlertSave: "Ralat penyimpanan amaran, sila semak dan cuba lagi!"
|
||||
ErrAlertSync: "Ralat penyelarasan amaran, sila semak dan cuba lagi!"
|
||||
ErrAlertRemote: "Ralat amaran jauh, sila semak dan cuba lagi!"
|
||||
|
||||
#cmd
|
||||
AppVersion: "Versi aplikasi"
|
||||
AppCommands: "Arahan berkaitan aplikasi"
|
||||
AppInit: "Inisialisasi aplikasi"
|
||||
AppKeyVal: "Kunci aplikasi (hanya menyokong bahasa Inggeris)"
|
||||
AppCreateFileErr: "Gagal mencipta fail {{ .name }} {{ .err }}"
|
||||
AppCreateDirErr: "Gagal mencipta folder {{ .name }} {{ .err }}"
|
||||
AppMissKey: "Kunci aplikasi hilang, gunakan -k untuk menetapkan"
|
||||
AppMissVersion: "Versi aplikasi hilang, gunakan -v untuk menetapkan"
|
||||
AppVersionExist: "Versi sudah wujud!"
|
||||
AppCreateSuccessful: "Ciptaan berjaya!"
|
||||
AppWriteErr: "Penulisan fail {{ .name }} gagal {{ .err }}"
|
||||
SudoHelper: "Sila gunakan {{ .cmd }} atau tukar ke pengguna root"
|
||||
ListenIPCommands: "Tukar IP mendengar"
|
||||
ListenIPv4: "Mendengar pada IPv4"
|
||||
ListenIPv6: "Mendengar pada IPv6"
|
||||
ListenChangeSuccessful: "Tukar berjaya! Kini mendengar pada {{ .value }}"
|
||||
ResetCommands: "Tetapkan semula maklumat sistem"
|
||||
ResetMFA: "Batal pengesahan dua faktor 1Panel"
|
||||
ResetHttps: "Batal log masuk HTTPS 1Panel"
|
||||
ResetEntrance: "Batal pintu masuk keselamatan 1Panel"
|
||||
ResetIPs: "Batal sekatan IP yang dibenarkan 1Panel"
|
||||
ResetDomain: "Batal pengikatan domain 1Panel"
|
||||
RestoreCommands: "Pulihkan perkhidmatan dan data 1Panel"
|
||||
RestoreNoSuchFile: "Tiada fail tersedia untuk pemulihan"
|
||||
RestoreStep1: "(1/5) Memulakan pemulihan perkhidmatan dan data 1Panel daripada direktori {{ .name }}..."
|
||||
RestoreStep2: "(2/5) Pemulihan binari 1Panel berjaya"
|
||||
RestoreStep3: "(3/5) Pemulihan skrip 1Panel berjaya"
|
||||
RestoreStep4: "(4/5) Pemulihan perkhidmatan 1Panel berjaya"
|
||||
RestoreStep5: "(5/5) Pemulihan data 1Panel berjaya"
|
||||
RestoreSuccessful: "Pemulihan berjaya! Memulakan semula perkhidmatan, sila tunggu..."
|
||||
UpdateCommands: "Kemas kini maklumat panel"
|
||||
UpdateUser: "Kemas kini pengguna panel"
|
||||
UpdatePassword: "Kemas kini kata laluan panel"
|
||||
UpdatePort: "Kemas kini port panel"
|
||||
UpdateUserNull: "Ralat: Pengguna panel kosong!"
|
||||
UpdateUserBlank: "Ralat: Pengguna panel mengandungi ruang kosong!"
|
||||
UpdateUserFormat: "Ralat: Format pengguna panel tidak sah! Hanya menyokong huruf Inggeris, Cina, nombor, dan , dengan panjang 3-30 aksara"
|
||||
UpdateUserErr: "Ralat: Gagal mengemas kini pengguna panel, {{ .err }}"
|
||||
UpdateSuccessful: "Kemas kini berjaya!"
|
||||
UpdateUserResult: "Pengguna panel: {{ .name }}"
|
||||
UpdatePasswordRead: "Ralat: Gagal membaca maklumat kata laluan panel, {{ .err }}"
|
||||
UpdatePasswordNull: "Ralat: Kata laluan panel kosong!"
|
||||
UpdateUPasswordBlank: "Ralat: Kata laluan panel mengandungi ruang kosong!"
|
||||
UpdatePasswordFormat: "Ralat: Kata laluan panel hanya menyokong huruf, nombor, dan aksara khas !@#$%*,.?, dengan panjang 8-30 aksara!"
|
||||
UpdatePasswordLen: "Ralat: Sila masukkan kata laluan lebih panjang daripada 6 aksara!"
|
||||
UpdatePasswordRe: "Sahkan kata laluan:"
|
||||
UpdatePasswordErr: "Ralat: Gagal mengemas kini kata laluan panel, {{ .err }}"
|
||||
UpdatePasswordSame: "Ralat: Kedua-dua kata laluan tidak sepadan, sila semak dan cuba lagi!"
|
||||
UpdatePasswordResult: "Kata laluan panel: {{ .name }}"
|
||||
UpdatePortFormat: "Ralat: Nombor port yang dimasukkan mesti antara 1 hingga 65535!"
|
||||
UpdatePortUsed: "Ralat: Nombor port sudah digunakan, sila semak dan cuba lagi!"
|
||||
UpdatePortErr: "Ralat: Gagal mengemas kini port panel, {{ .err }}"
|
||||
UpdatePortResult: "Port Panel: {{ .name }}"
|
||||
UpdatePortFirewallAdd: "Gagal menambah peraturan port firewall, {{ .err }}, sila tambah port {{ .name }} secara manual ke dalam peraturan firewall."
|
||||
UpdatePortFirewallDel: "Ralat: Gagal memadam port firewall, {{ .err }}"
|
||||
UpdatePortFirewallReload: "Gagal memuat semula firewall, {{ .err }}, sila muat semula firewall secara manual."
|
||||
UserInfo: "Dapatkan maklumat panel"
|
||||
UserInfoAddr: "Alamat panel: "
|
||||
UserInfoPassHelp: "Petua: Untuk menukar kata laluan, anda boleh menjalankan arahan: "
|
||||
DBConnErr: "Ralat: Gagal memulakan sambungan pangkalan data, {{ .err }}"
|
||||
SystemVersion: "Versi: "
|
||||
SystemMode: "Mod: "
|
||||
|
||||
#ai-tool
|
||||
ErrOpenrestyInstall: 'Sila pasang Openresty terlebih dahulu'
|
||||
ErrSSL: "Kandungan sijil kosong, sila periksa sijil!"
|
||||
|
||||
|
||||
#mobile app
|
||||
ErrVerifyToken: 'Ralat pengesahan token, sila tetapkan semula dan imbas semula.'
|
||||
ErrInvalidToken: 'Token tidak sah, sila tetapkan semula dan imbas semula.'
|
||||
ErrExpiredToken: 'Token telah tamat tempoh, sila tetapkan semula dan imbas semula.'
|
||||
@@ -0,0 +1,292 @@
|
||||
ErrInvalidParams: "Erro nos parâmetros da solicitação: {{ .detail }}"
|
||||
ErrTokenParse: "Erro na geração do token: {{ .detail }}"
|
||||
ErrInitialPassword: "Erro na senha inicial"
|
||||
ErrInternalServer: "Erro interno do serviço: {{ .detail }}"
|
||||
ErrRecordExist: "Registro já existente"
|
||||
ErrRecordNotFound: "Registros não encontrados"
|
||||
ErrStructTransform: "Falha na conversão de tipo: {{ .detail }}"
|
||||
ErrNotLogin: "Usuário não está logado: {{ .detail }}"
|
||||
ErrPasswordExpired: "A senha atual expirou: {{ .detail }}"
|
||||
ErrNotSupportType: "O sistema não suporta o tipo atual: {{ .detail }}"
|
||||
ErrApiConfigStatusInvalid: "Acesso à interface da API proibido: {{ .detail }}"
|
||||
ErrApiConfigKeyInvalid: "Erro na chave da interface da API: {{ .detail }}"
|
||||
ErrApiConfigIPInvalid: "O IP da interface da API não está na lista de permissões: {{ .detail }}"
|
||||
ErrApiConfigDisable: "Esta interface proíbe o uso de chamadas de API: {{ .detail }}"
|
||||
|
||||
#common
|
||||
ErrNameIsExist: "O nome já existe"
|
||||
ErrDemoEnvironment: "Servidor de demonstração, operação proibida!"
|
||||
ErrCmdTimeout: "Tempo limite de execução do comando excedido!"
|
||||
ErrCmdIllegal: "O comando contém caracteres ilegais. Por favor, modifique e tente novamente!"
|
||||
ErrPortExist: 'A porta {{ .port }} já está ocupada por {{ .type }} [{{ .name }}]'
|
||||
TYPE_APP: "Aplicação"
|
||||
TYPE_RUNTIME: "Ambiente de execução"
|
||||
TYPE_DOMAIN: "Nome de domínio"
|
||||
ErrTypePort: 'Erro no formato da porta {{ .name }}'
|
||||
ErrTypePortRange: 'O intervalo da porta deve estar entre 1-65535'
|
||||
Success: "Sucesso"
|
||||
Failed: "Falhou"
|
||||
SystemRestart: "A reinicialização do sistema causa interrupção da tarefa"
|
||||
|
||||
#app
|
||||
ErrPortInUsed: "A porta {{ .detail }} já está em uso"
|
||||
ErrAppLimit: "O limite de instalação de aplicativos foi excedido"
|
||||
ErrAppRequired: "O aplicativo {{ .detail }} é necessário"
|
||||
ErrNotInstall: "Aplicativo não instalado"
|
||||
ErrPortInOtherApp: "A porta {{ .port }} já está em uso pelo aplicativo {{ .apps }}"
|
||||
ErrDbUserNotValid: "Banco de dados padrão, nome de usuário e senha não correspondem!"
|
||||
ErrDockerComposeNotValid: "Erro no formato do arquivo docker-compose!"
|
||||
ErrUpdateBuWebsite: "O aplicativo foi atualizado com sucesso, mas a modificação do arquivo de configuração do site falhou. Verifique a configuração!"
|
||||
Err1PanelNetworkFailed: "Falha ao criar a rede padrão do container! {{ .detail }}"
|
||||
ErrFileParse: "Falha ao analisar o arquivo docker-compose do aplicativo!"
|
||||
ErrInstallDirNotFound: "O diretório de instalação não existe"
|
||||
AppStoreIsUpToDate: "Atualizado"
|
||||
LocalAppVersionNull: "O aplicativo {{.name}} não está sincronizado com a versão! Não foi possível adicionar à lista de aplicativos"
|
||||
LocalAppVersionErr: "Falha ao sincronizar a versão {{.version}} do {{.name}}! {{.err}}"
|
||||
ErrFileNotFound: "O arquivo {{.name}} não existe"
|
||||
ErrFileParseApp: "Falha ao analisar o arquivo {{.name}} {{.err}}"
|
||||
ErrAppDirNull: "O diretório da versão não existe"
|
||||
LocalAppErr: "Falha ao sincronizar o aplicativo {{.name}}! {{.err}}"
|
||||
ErrContainerName: "O nome do container já existe"
|
||||
ErrAppSystemRestart: "A reinicialização do 1Panel causa a interrupção da tarefa"
|
||||
ErrCreateHttpClient: "Falha ao criar a solicitação HTTP {{.err}}"
|
||||
ErrHttpReqTimeOut: "Tempo limite da solicitação excedido {{.err}}"
|
||||
ErrHttpReqFailed: "Falha na solicitação {{.err}}"
|
||||
ErrHttpReqNotFound: "O arquivo não existe"
|
||||
ErrNoSuchHost: "Falha na conexão de rede"
|
||||
ErrImagePullTimeOut: "Tempo limite ao puxar a imagem"
|
||||
ErrContainerNotFound: "O container {{ .name }} não existe"
|
||||
ErrContainerMsg: "O container {{ .name }} está anormal, verifique o log na página do container para mais detalhes"
|
||||
ErrAppBackup: "Falha no backup do aplicativo {{ .name }} erro {{.err}}"
|
||||
ErrImagePull: "Falha ao puxar a imagem {{ .name }} erro {{.err}}"
|
||||
ErrVersionTooLow: "A versão atual do 1Panel é muito baixa para atualizar a loja de aplicativos, por favor atualize a versão"
|
||||
ErrAppNameExist: "O nome do aplicativo já existe"
|
||||
AppStoreIsSyncing: "A loja de aplicativos está sincronizando, tente novamente mais tarde"
|
||||
ErrGetCompose: "Falha ao obter o arquivo docker-compose.yml! {{ .detail }}"
|
||||
ErrAppWarn: "Status anormal, verifique o log"
|
||||
ErrAppParamKey: "Exceção no campo do parâmetro {{ .name }}"
|
||||
ErrAppUpgrade: "Falha ao atualizar o aplicativo {{ .name }} {{ .err }}"
|
||||
AppRecover: "Aplicativo {{ .name }} revertido"
|
||||
PullImageStart: "Iniciando o download da imagem {{ .name }}"
|
||||
PullImageSuccess: "Imagem baixada com sucesso"
|
||||
UpgradeAppStart: "Iniciando a atualização do aplicativo {{ .name }}"
|
||||
UpgradeAppSuccess: "Aplicativo {{ .name }} atualizado com sucesso"
|
||||
|
||||
#file
|
||||
ErrFileCanNotRead: "Não foi possível ler o arquivo"
|
||||
ErrFileToLarge: "O arquivo é muito grande"
|
||||
ErrPathNotFound: "Caminho não encontrado"
|
||||
ErrMovePathFailed: "O caminho de destino não pode conter o caminho original!"
|
||||
ErrLinkPathNotFound: "O caminho de destino não existe!"
|
||||
ErrFileIsExist: "O arquivo ou diretório já existe!"
|
||||
ErrFileUpload: "Falha ao fazer upload do arquivo {{.name}} {{.detail}}"
|
||||
ErrFileDownloadDir: "Pasta de download não é suportada"
|
||||
ErrCmdNotFound: "O comando {{ .name }} não existe, por favor, instale este comando no host primeiro"
|
||||
ErrSourcePathNotFound: "O diretório de origem não existe"
|
||||
ErrFavoriteExist: "Este caminho já foi adicionado aos favoritos"
|
||||
ErrInvalidChar: "Caracteres ilegais são proibidos"
|
||||
ErrPathNotDelete: "O diretório selecionado não pode ser excluído"
|
||||
|
||||
#website
|
||||
ErrDomainIsExist: "O domínio já existe"
|
||||
ErrAliasIsExist: "O alias já existe"
|
||||
ErrAppDelete: "Outro site usa este aplicativo"
|
||||
ErrGroupIsUsed: "O grupo está em uso e não pode ser excluído"
|
||||
ErrBackupMatch: "O arquivo de backup não corresponde aos dados parciais atuais do site: {{ .detail }}"
|
||||
ErrBackupExist: "O arquivo de backup corresponde a uma parte dos dados originais que não existe: {{ .detail }}"
|
||||
ErrPHPResource: "O ambiente local não suporta a troca!"
|
||||
ErrPathPermission: "Foi detectada uma pasta com permissões diferentes de 1000:1000 no diretório de índice, o que pode causar um erro de acesso negado ao acessar o site. Clique no botão salvar acima"
|
||||
ErrDomainIsUsed: "O domínio já está sendo usado pelo site {{ .name }}"
|
||||
ErrDomainFormat: "O formato do domínio {{ .name }} está incorreto"
|
||||
ErrDefaultAlias: "default é um nome reservado, por favor, use outro nome"
|
||||
ErrImageNotExist: "A imagem do ambiente de execução {{.name}} não existe, por favor, reconfigure o ambiente"
|
||||
|
||||
#ssl
|
||||
ErrSSLCannotDelete: "O certificado {{ .name }} está sendo usado pelo site e não pode ser removido"
|
||||
ErrAccountCannotDelete: "O certificado associado à conta não pode ser excluído"
|
||||
ErrSSLApply: "O certificado foi assinado com sucesso, mas o recarregamento do OpenResty falhou, por favor, verifique a configuração!"
|
||||
ErrEmailIsExist: "O email já existe"
|
||||
ErrSSLKeyNotFound: "O arquivo da chave privada não existe"
|
||||
ErrSSLCertificateNotFound: "O arquivo do certificado não existe"
|
||||
ErrSSLKeyFormat: "Erro na verificação do arquivo da chave privada"
|
||||
ErrSSLCertificateFormat: "Erro no formato do arquivo do certificado, por favor, use o formato PEM"
|
||||
ErrEabKidOrEabHmacKeyCannotBlank: "EabKid ou EabHmacKey não podem estar vazios"
|
||||
ErrOpenrestyNotFound: "O modo HTTP requer a instalação prévia do OpenResty"
|
||||
ApplySSLStart: "Iniciando aplicação do certificado, domínio [{{ .domain }}], método de aplicação [{{ .type }}]"
|
||||
dnsAccount: "DNS Automático"
|
||||
dnsManual: "DNS Manual"
|
||||
http: "HTTP"
|
||||
ApplySSLFailed: "A aplicação do certificado para [{{ .domain }}] falhou, {{.detail}}"
|
||||
ApplySSLSuccess: "Certificado para [{{ .domain }}] aplicado com sucesso!"
|
||||
DNSAccountName: "Conta DNS [{{ .name }}], provedor [{{.type}}]"
|
||||
PushDirLog: "Certificado enviado para o diretório [{{ .path }}] {{ .status }}"
|
||||
ErrDeleteCAWithSSL: "Há um certificado emitido sob a organização atual, não pode ser excluído"
|
||||
ErrDeleteWithPanelSSL: "A configuração SSL do painel usa este certificado, não pode ser excluído"
|
||||
ErrDefaultCA: "A autoridade certificadora padrão não pode ser excluída"
|
||||
ApplyWebSiteSSLLog: "Iniciando atualização do certificado do site {{ .name }}"
|
||||
ErrUpdateWebsiteSSL: "Falha ao atualizar o certificado do site {{ .name }}: {{ .err }}"
|
||||
ApplyWebSiteSSLSuccess: "Certificado do site atualizado com sucesso"
|
||||
ErrExecShell: "Falha na execução do script {{ .err }}"
|
||||
ExecShellStart: "Iniciando execução do script"
|
||||
ExecShellSuccess: "Script executado com sucesso"
|
||||
StartUpdateSystemSSL: "Iniciando atualização do certificado do sistema"
|
||||
UpdateSystemSSLSuccess: "Certificado do sistema atualizado com sucesso"
|
||||
|
||||
#mysql
|
||||
ErrUserIsExist: "O usuário atual já existe. Por favor, insira um novo usuário"
|
||||
ErrDatabaseIsExist: "O banco de dados atual já existe. Por favor, insira um novo banco de dados"
|
||||
ErrExecTimeOut: "Tempo de execução SQL expirado, por favor, verifique o banco de dados"
|
||||
ErrRemoteExist: "O banco de dados remoto já existe com este nome, por favor, modifique e tente novamente"
|
||||
ErrLocalExist: "O banco de dados local já existe com este nome, por favor, modifique e tente novamente"
|
||||
|
||||
#redis
|
||||
ErrTypeOfRedis: "O tipo do arquivo de recuperação não corresponde ao modo de persistência atual. Modifique o tipo do arquivo e tente novamente"
|
||||
|
||||
#container
|
||||
ErrInUsed: "{{ .detail }} está em uso e não pode ser excluído"
|
||||
ErrObjectInUsed: "Este objeto está em uso e não pode ser excluído"
|
||||
ErrPortRules: "O número de portas não corresponde. Por favor, insira novamente!"
|
||||
ErrPgImagePull: "Tempo limite ao tentar puxar a imagem. Configure a aceleração de imagem ou puxe manualmente a imagem postgres:16.0-alpine e tente novamente"
|
||||
|
||||
#runtime
|
||||
ErrDirNotFound: "A pasta de build não existe! Por favor, verifique a integridade dos arquivos!"
|
||||
ErrFileNotExist: "O arquivo {{ .detail }} não existe! Por favor, verifique a integridade do arquivo de origem!"
|
||||
ErrImageBuildErr: "Falha ao construir a imagem"
|
||||
ErrImageExist: "A imagem já existe!"
|
||||
ErrDelWithWebsite: "O ambiente operacional está associado a um site e não pode ser excluído"
|
||||
ErrRuntimeStart: "Falha ao iniciar"
|
||||
ErrPackageJsonNotFound: "O arquivo package.json não existe"
|
||||
ErrScriptsNotFound: "Nenhum item de configuração de scripts foi encontrado no package.json"
|
||||
ErrContainerNameNotFound: "Não foi possível obter o nome do contêiner. Por favor, verifique o arquivo .env"
|
||||
ErrNodeModulesNotFound: "A pasta node_modules não existe! Edite o ambiente de execução ou aguarde até que o ambiente seja iniciado com sucesso"
|
||||
|
||||
#setting
|
||||
ErrBackupInUsed: "A conta de backup já está sendo usada em um cronjob e não pode ser excluída"
|
||||
ErrBackupCheck: "Falha ao testar a conexão com a conta de backup {{ .err }}"
|
||||
ErrOSSConn: "Não foi possível recuperar a versão mais recente. Por favor, verifique se o servidor pode se conectar à rede externa."
|
||||
ErrEntrance: "Erro nas informações da entrada de segurança. Por favor, verifique e tente novamente!"
|
||||
|
||||
#tool
|
||||
ErrConfigNotFound: "O arquivo de configuração não existe"
|
||||
ErrConfigParse: "Erro no formato do arquivo de configuração"
|
||||
ErrConfigIsNull: "O arquivo de configuração não pode estar vazio"
|
||||
ErrConfigDirNotFound: "O diretório de execução não existe"
|
||||
ErrConfigAlreadyExist: "Um arquivo de configuração com o mesmo nome já existe"
|
||||
ErrUserFindErr: "Falha ao encontrar o usuário {{ .name }} {{ .err }}"
|
||||
|
||||
#ssh
|
||||
ErrFirewallNone: "Nenhum serviço firewalld ou ufw foi detectado no sistema. Por favor, verifique e tente novamente!"
|
||||
ErrFirewallBoth: "Os serviços firewalld e ufw foram detectados no sistema. Para evitar conflitos, desinstale um deles e tente novamente!"
|
||||
|
||||
#cronjob
|
||||
ErrBashExecute: "Erro na execução do script. Por favor, verifique as informações específicas na área de saída da tarefa."
|
||||
ErrCutWebsiteLog: "Falha ao cortar os logs do site {{ .name }}, erro {{ .err }}"
|
||||
CutWebsiteLogSuccess: "Logs do site {{ .name }} cortados com sucesso, caminho do backup {{ .path }}"
|
||||
|
||||
#toolbox
|
||||
ErrNotExistUser: "O usuário atual não existe. Por favor, modifique e tente novamente!"
|
||||
ErrBanAction: "Falha na configuração. O serviço {{ .name }} atual está indisponível, por favor, verifique e tente novamente!"
|
||||
ErrClamdscanNotFound: "O comando clamdscan não foi detectado. Por favor, consulte a documentação para instalá-lo!"
|
||||
|
||||
#waf
|
||||
ErrScope: "A modificação dessa configuração não é suportada"
|
||||
ErrStateChange: "Falha ao modificar o estado"
|
||||
ErrRuleExist: "A regra já existe"
|
||||
ErrRuleNotExist: "A regra não existe"
|
||||
ErrParseIP: "Erro no formato do IP"
|
||||
ErrDefaultIP: "default é um nome reservado, por favor, escolha outro nome"
|
||||
ErrGroupInUse: "O grupo de IPs está sendo usado na lista de bloqueio/permitidos e não pode ser excluído"
|
||||
ErrGroupExist: "O nome do grupo de IPs já existe"
|
||||
ErrIPRange: "Intervalo de IP inválido"
|
||||
ErrIPExist: "O IP já existe"
|
||||
|
||||
#license
|
||||
ErrLicense: "Erro no formato da licença, por favor, verifique e tente novamente!"
|
||||
ErrLicenseCheck: "Falha na verificação da licença, por favor, verifique e tente novamente!"
|
||||
ErrLicenseSave: "Falha ao salvar as informações da licença, erro {{ .err }}, por favor, tente novamente!"
|
||||
ErrLicenseSync: "Falha ao sincronizar as informações da licença, nenhuma informação de licença detectada no banco de dados!"
|
||||
ErrXpackNotFound: "Esta seção é um recurso da edição profissional. Por favor, importe a licença primeiro na interface Configurações do Painel - Licença."
|
||||
ErrXpackNotActive: "Esta seção é um recurso da edição profissional. Por favor, sincronize o status da licença primeiro na interface Configurações do Painel - Licença."
|
||||
ErrXpackOutOfDate: "A licença atual expirou, por favor, reimporte a licença na interface Configurações do Painel - Licença."
|
||||
ErrXpackLost: "A licença atingiu o número máximo de tentativas de reexecução. Por favor, acesse as páginas [Configurações] [Licença] e clique manualmente no botão de sincronização para garantir que os recursos da versão profissional funcionem corretamente."
|
||||
ErrXpackTimeout: "Tempo limite de solicitação, a conexão de rede pode estar instável, por favor, tente novamente mais tarde!"
|
||||
|
||||
#license
|
||||
ErrAlert: "Erro no formato das informações do alerta, por favor, verifique e tente novamente!"
|
||||
ErrAlertPush: "Erro no envio do alerta, por favor, verifique e tente novamente!"
|
||||
ErrAlertSave: "Erro ao salvar o alerta, por favor, verifique e tente novamente!"
|
||||
ErrAlertSync: "Erro na sincronização do alerta, por favor, verifique e tente novamente!"
|
||||
ErrAlertRemote: "Erro de alerta remoto, por favor, verifique e tente novamente!"
|
||||
|
||||
#cmd
|
||||
AppVersion: "Versão do aplicativo"
|
||||
AppCommands: "Comandos relacionados ao aplicativo"
|
||||
AppInit: "Inicializar aplicativo"
|
||||
AppKeyVal: "Chave do aplicativo (somente suporta inglês)"
|
||||
AppCreateFileErr: "Falha ao criar o arquivo {{ .name }} {{ .err }}"
|
||||
AppCreateDirErr: "Falha ao criar a pasta {{ .name }} {{ .err }}"
|
||||
AppMissKey: "Chave do aplicativo ausente, use -k para especificar"
|
||||
AppMissVersion: "Versão do aplicativo ausente, use -v para especificar"
|
||||
AppVersionExist: "A versão já existe!"
|
||||
AppCreateSuccessful: "Criação bem-sucedida!"
|
||||
AppWriteErr: "Falha ao escrever no arquivo {{ .name }} {{ .err }}"
|
||||
SudoHelper: "Por favor, use {{ .cmd }} ou altere para o usuário root"
|
||||
ListenIPCommands: "Trocar IP de escuta"
|
||||
ListenIPv4: "Escutando em IPv4"
|
||||
ListenIPv6: "Escutando em IPv6"
|
||||
ListenChangeSuccessful: "Troca bem-sucedida! Agora escutando em {{ .value }}"
|
||||
ResetCommands: "Redefinir informações do sistema"
|
||||
ResetMFA: "Cancelar autenticação de dois fatores do 1Panel"
|
||||
ResetHttps: "Cancelar login https do 1Panel"
|
||||
ResetEntrance: "Cancelar entrada segura do 1Panel"
|
||||
ResetIPs: "Cancelar restrições de IP autorizado do 1Panel"
|
||||
ResetDomain: "Cancelar vinculação de domínio do 1Panel"
|
||||
RestoreCommands: "Restaurar serviço e dados do 1Panel"
|
||||
RestoreNoSuchFile: "Nenhum arquivo disponível para restauração"
|
||||
RestoreStep1: "(1/5) Iniciando a restauração do serviço e dados do 1Panel a partir do diretório {{ .name }}..."
|
||||
RestoreStep2: "(2/5) Restauração do binário do 1Panel bem-sucedida"
|
||||
RestoreStep3: "(3/5) Restauração dos scripts do 1Panel bem-sucedida"
|
||||
RestoreStep4: "(4/5) Restauração do serviço do 1Panel bem-sucedida"
|
||||
RestoreStep5: "(5/5) Restauração dos dados do 1Panel bem-sucedida"
|
||||
RestoreSuccessful: "Restauração bem-sucedida! Reiniciando o serviço, por favor, aguarde..."
|
||||
UpdateCommands: "Atualizar informações do painel"
|
||||
UpdateUser: "Atualizar usuário do painel"
|
||||
UpdatePassword: "Atualizar senha do painel"
|
||||
UpdatePort: "Atualizar porta do painel"
|
||||
UpdateUserNull: "Erro: usuário do painel está vazio!"
|
||||
UpdateUserBlank: "Erro: o usuário do painel contém espaços!"
|
||||
UpdateUserFormat: "Erro: Formato de usuário do painel inválido! Apenas suporta inglês, chinês, números e _, comprimento de 3-30."
|
||||
UpdateUserErr: "Erro: Falha ao atualizar o usuário do painel, {{ .err }}"
|
||||
UpdateSuccessful: "Atualização bem-sucedida!"
|
||||
UpdateUserResult: "Usuário do painel: {{ .name }}"
|
||||
UpdatePasswordRead: "Erro: Falha ao ler as informações da senha do painel, {{ .err }}"
|
||||
UpdatePasswordNull: "Erro: A senha do painel está vazia!"
|
||||
UpdateUPasswordBlank: "Erro: A senha do painel contém espaços!"
|
||||
UpdatePasswordFormat: "Erro: A senha do painel suporta apenas letras, números, caracteres especiais !@#$%*_,.?, comprimento de 8-30!"
|
||||
UpdatePasswordLen: "Erro: Por favor, insira uma senha com mais de 6 caracteres!"
|
||||
UpdatePasswordRe: "Confirmar senha:"
|
||||
UpdatePasswordErr: "Erro: Falha ao atualizar a senha do painel, {{ .err }}"
|
||||
UpdatePasswordSame: "Erro: As duas senhas não correspondem, por favor, verifique e tente novamente!"
|
||||
UpdatePasswordResult: "Senha do painel: {{ .name }}"
|
||||
UpdatePortFormat: "Erro: O número da porta deve estar entre 1 e 65535!"
|
||||
UpdatePortUsed: "Erro: O número da porta já está em uso, por favor, verifique e tente novamente!"
|
||||
UpdatePortErr: "Erro: Falha ao atualizar a porta do painel, {{ .err }}"
|
||||
UpdatePortResult: "Porta do painel: {{ .name }}"
|
||||
UpdatePortFirewallAdd: "Falha ao adicionar regra de porta ao firewall, {{ .err }}, por favor, adicione manualmente a porta {{ .name }} às regras do firewall."
|
||||
UpdatePortFirewallDel: "Erro: Falha ao excluir a porta do firewall, {{ .err }}"
|
||||
UpdatePortFirewallReload: "Falha ao recarregar o firewall, {{ .err }}, por favor, recarregue o firewall manualmente."
|
||||
UserInfo: "Obter informações do painel"
|
||||
UserInfoAddr: "Endereço do painel: "
|
||||
UserInfoPassHelp: "Dica: Para alterar a senha, você pode executar o comando: "
|
||||
DBConnErr: "Erro: Falha ao inicializar a conexão com o banco de dados, {{ .err }}"
|
||||
SystemVersion: "versão: "
|
||||
SystemMode: "modo: "
|
||||
|
||||
#ai-tool
|
||||
ErrOpenrestyInstall: 'Por favor, instale o Openresty primeiro'
|
||||
ErrSSL: "O conteúdo do certificado está vazio, por favor, verifique o certificado!"
|
||||
|
||||
#mobile app
|
||||
ErrVerifyToken: 'Erro de verificação do token, por favor, reinicie e escaneie novamente.'
|
||||
ErrInvalidToken: 'Token inválido, por favor, reinicie e escaneie novamente.'
|
||||
ErrExpiredToken: 'O token expirou, por favor, reinicie e escaneie novamente.'
|
||||
@@ -1,63 +0,0 @@
|
||||
#cmd
|
||||
AppVersion: "Versão do aplicativo"
|
||||
AppCommands: "Comandos relacionados ao aplicativo"
|
||||
AppInit: "Inicializar aplicativo"
|
||||
AppKeyVal: "Chave do aplicativo (suporta apenas inglês)"
|
||||
AppCreateFileErr: "Falha na criação do arquivo {{ .name }} {{ .err }}"
|
||||
AppCreateDirErr: "Falha na criação da pasta {{ .name }} {{ .err }}"
|
||||
AppMissKey: "Chave do aplicativo ausente, use -k para especificar"
|
||||
AppMissVersion: "Versão do aplicativo ausente, use -v para especificar"
|
||||
AppVersionExist: "Versão já existente!"
|
||||
AppCreateSuccessful: "Criação bem-sucedida!"
|
||||
AppWriteErr: "Falha na gravação do arquivo {{ .name }} {{ .err }}"
|
||||
SudoHelper: "Por favor, use {{ .cmd }} ou troque para o usuário root"
|
||||
ListenIPCommands: "Alterar IP de escuta"
|
||||
ListenIPv4: "Escutar no IPv4"
|
||||
ListenIPv6: "Escutar no IPv6"
|
||||
ListenChangeSuccessful: "Alteração bem-sucedida! Agora escutando em {{ .value }}"
|
||||
ResetCommands: "Redefinir informações do sistema"
|
||||
ResetMFA: "Cancelar autenticação de dois fatores do 1Panel"
|
||||
ResetHttps: "Cancelar login HTTPS do 1Panel"
|
||||
ResetEntrance: "Cancelar entrada segura do 1Panel"
|
||||
ResetIPs: "Cancelar restrições de IP autorizados do 1Panel"
|
||||
ResetDomain: "Cancelar vinculação de domínio do 1Panel"
|
||||
RestoreCommands: "Restaurar serviço e dados do 1Panel"
|
||||
RestoreNoSuchFile: "Nenhum arquivo disponível para restauração"
|
||||
RestoreStep1: "(1/5) Iniciando a restauração do serviço e dados do 1Panel a partir do diretório {{ .name }}..."
|
||||
RestoreStep2: "(2/5) Restauração do binário do 1Panel bem-sucedida"
|
||||
RestoreStep3: "(3/5) Restauração do script do 1Panel bem-sucedida"
|
||||
RestoreStep4: "(4/5) Restauração do serviço do 1Panel bem-sucedida"
|
||||
RestoreStep5: "(5/5) Restauração dos dados do 1Panel bem-sucedida"
|
||||
RestoreSuccessful: "Restauração bem-sucedida! Reiniciando o serviço, aguarde..."
|
||||
UpdateCommands: "Atualizar informações do painel"
|
||||
UpdateUser: "Atualizar usuário do painel"
|
||||
UpdatePassword: "Atualizar senha do painel"
|
||||
UpdatePort: "Atualizar porta do painel"
|
||||
UpdateUserNull: "Erro: usuário do painel está vazio!"
|
||||
UpdateUserBlank: "Erro: usuário do painel contém espaços!"
|
||||
UpdateUserFormat: "Erro: Formato de usuário inválido! Aceita apenas inglês, chinês, números e _, comprimento de 3-30"
|
||||
UpdateUserErr: "Erro: Falha ao atualizar usuário do painel, {{ .err }}"
|
||||
UpdateSuccessful: "Atualização bem-sucedida!"
|
||||
UpdateUserResult: "Usuário do painel: {{ .name }}"
|
||||
UpdatePasswordRead: "Erro: Falha ao ler informações da senha do painel, {{ .err }}"
|
||||
UpdatePasswordNull: "Erro: Senha do painel está vazia!"
|
||||
UpdateUPasswordBlank: "Erro: Senha do painel contém espaços!"
|
||||
UpdatePasswordFormat: "Erro: A senha do painel aceita apenas letras, números, caracteres especiais !@#$%*_,.?, comprimento de 8-30!"
|
||||
UpdatePasswordLen: "Erro: Por favor, insira uma senha com mais de 6 caracteres!"
|
||||
UpdatePasswordRe: "Confirmar senha:"
|
||||
UpdatePasswordErr: "Erro: Falha ao atualizar senha do painel, {{ .err }}"
|
||||
UpdatePasswordSame: "Erro: As duas senhas não coincidem, por favor, verifique e tente novamente!"
|
||||
UpdatePasswordResult: "Senha do painel: {{ .name }}"
|
||||
UpdatePortFormat: "Erro: O número da porta deve estar entre 1 e 65535!"
|
||||
UpdatePortUsed: "Erro: O número da porta já está em uso, por favor, verifique e tente novamente!"
|
||||
UpdatePortErr: "Erro: Falha ao atualizar a porta do painel, {{ .err }}"
|
||||
UpdatePortResult: "Porta do painel: {{ .name }}"
|
||||
UpdatePortFirewallAdd: "Falha ao adicionar regra de porta no firewall, {{ .err }}, adicione manualmente a porta {{ .name }} às regras do firewall."
|
||||
UpdatePortFirewallDel: "Erro: Falha ao excluir porta do firewall, {{ .err }}"
|
||||
UpdatePortFirewallReload: "Falha ao recarregar o firewall, {{ .err }}, recarregue o firewall manualmente."
|
||||
UserInfo: "Obter informações do painel"
|
||||
UserInfoAddr: "Endereço do painel: "
|
||||
UserInfoPassHelp: "Dica: Para alterar a senha, execute o comando: "
|
||||
DBConnErr: "Erro: Falha ao inicializar conexão com o banco de dados, {{ .err }}"
|
||||
SystemVersion: "versão: "
|
||||
SystemMode: "modo: "
|
||||
@@ -0,0 +1,295 @@
|
||||
ErrInvalidParams: "Ошибка параметра запроса: {{ .detail }}"
|
||||
ErrTokenParse: "Ошибка генерации токена: {{ .detail }}"
|
||||
ErrInitialPassword: "Ошибка исходного пароля"
|
||||
ErrInternalServer: "Внутренняя ошибка сервиса: {{ .detail }}"
|
||||
ErrRecordExist: "Запись уже существует"
|
||||
ErrRecordNotFound: "Записи не найдены"
|
||||
ErrStructTransform: "Ошибка преобразования типа: {{ .detail }}"
|
||||
ErrNotLogin: "Пользователь не вошел в систему: {{ .detail }}"
|
||||
ErrPasswordExpired: "Текущий пароль истек: {{ .detail }}"
|
||||
ErrNotSupportType: "Система не поддерживает текущий тип: {{ .detail }}"
|
||||
ErrApiConfigStatusInvalid: "Доступ к API интерфейсу запрещен: {{ .detail }}"
|
||||
ErrApiConfigKeyInvalid: "Ошибка ключа API интерфейса: {{ .detail }}"
|
||||
ErrApiConfigIPInvalid: "IP API интерфейса отсутствует в белом списке: {{ .detail }}"
|
||||
ErrApiConfigDisable: "Этот интерфейс запрещает использование вызовов API интерфейса: {{ .detail }}"
|
||||
ErrApiConfigKeyTimeInvalid: "Ошибка временной метки интерфейса API: {{ .detail }}"
|
||||
|
||||
#common
|
||||
ErrNameIsExist: "Имя уже существует"
|
||||
ErrDemoEnvironment: "Демо-сервер, операция запрещена!"
|
||||
ErrCmdTimeout: "Время выполнения команды истекло!"
|
||||
ErrCmdIllegal: "Команда содержит недопустимые символы. Пожалуйста, измените и попробуйте снова!"
|
||||
ErrPortExist: "{{ .port }} порт уже занят {{ .type }} [{{ .name }}]"
|
||||
TYPE_APP: "Приложение"
|
||||
TYPE_RUNTIME: "Среда выполнения"
|
||||
TYPE_DOMAIN: "Доменное имя"
|
||||
ErrTypePort: "Ошибка формата порта {{ .name }}"
|
||||
ErrTypePortRange: "Диапазон портов должен быть между 1-65535"
|
||||
Success: "Успех"
|
||||
Failed: "Неудача"
|
||||
SystemRestart: "Перезагрузка системы приводит к прерыванию задачи"
|
||||
|
||||
#app
|
||||
ErrPortInUsed: "Порт {{ .detail }} уже используется"
|
||||
ErrAppLimit: "Превышен лимит установки приложения"
|
||||
ErrAppRequired: "Требуется приложение {{ .detail }}"
|
||||
ErrNotInstall: "Приложение не установлено"
|
||||
ErrPortInOtherApp: "Порт {{ .port }} уже используется приложением {{ .apps }}"
|
||||
ErrDbUserNotValid: "База данных акций, имя пользователя и пароль не совпадают!"
|
||||
ErrDockerComposeNotValid: "Ошибка формата файла docker-compose!"
|
||||
ErrUpdateBuWebsite: "Приложение успешно обновлено, но изменение конфигурационного файла веб-сайта не удалось, пожалуйста, проверьте конфигурацию!"
|
||||
Err1PanelNetworkFailed: "Не удалось создать сеть контейнера по умолчанию! {{ .detail }}"
|
||||
ErrFileParse: "Не удалось разобрать файл docker-compose приложения!"
|
||||
ErrInstallDirNotFound: "Директория установки не существует"
|
||||
AppStoreIsUpToDate: "Обновлено"
|
||||
LocalAppVersionNull: "Приложение {{.name}} не синхронизировано с версией! Невозможно добавить в список приложений"
|
||||
LocalAppVersionErr: "{{.name}} не удалось синхронизировать версию {{.version}}! {{.err}}"
|
||||
ErrFileNotFound: "Файл {{.name}} не существует"
|
||||
ErrFileParseApp: "Не удалось проанализировать файл {{.name}} {{.err}}"
|
||||
ErrAppDirNull: "Папка версии не существует"
|
||||
LocalAppErr: "Синхронизация приложения {{.name}} не удалась! {{.err}}"
|
||||
ErrContainerName: "Имя контейнера уже существует"
|
||||
ErrAppSystemRestart: "Перезапуск 1Panel приводит к завершению задачи"
|
||||
ErrCreateHttpClient: "Не удалось создать HTTP-запрос {{.err}}"
|
||||
ErrHttpReqTimeOut: "Превышено время ожидания запроса {{.err}}"
|
||||
ErrHttpReqFailed: "Запрос не выполнен {{.err}}"
|
||||
ErrHttpReqNotFound: "Файл не существует"
|
||||
ErrNoSuchHost: "Сбой сетевого подключения"
|
||||
ErrImagePullTimeOut: "Тайм-аут загрузки образа"
|
||||
ErrContainerNotFound: "Контейнер {{ .name }} не существует"
|
||||
ErrContainerMsg: "Контейнер {{ .name }} работает ненормально, пожалуйста, проверьте журнал на странице контейнера для подробностей"
|
||||
ErrAppBackup: "Резервное копирование приложения {{ .name }} не удалось, ошибка {{.err}}"
|
||||
ErrImagePull: "Не удалось загрузить образ {{ .name }}, ошибка {{.err}}"
|
||||
ErrVersionTooLow: "Текущая версия 1Panel слишком стара для обновления магазина приложений, пожалуйста, обновите версию"
|
||||
ErrAppNameExist: "Имя приложения уже существует"
|
||||
AppStoreIsSyncing: "Магазин приложений синхронизируется, пожалуйста, попробуйте позже"
|
||||
ErrGetCompose: "Не удалось получить файл docker-compose.yml! {{ .detail }}"
|
||||
ErrAppWarn: "Аномальный статус, пожалуйста, проверьте журнал"
|
||||
ErrAppParamKey: "Исключение в поле параметра {{ .name }}"
|
||||
ErrAppUpgrade: "Не удалось обновить приложение {{ .name }} {{ .err }}"
|
||||
AppRecover: "Приложение {{ .name }} откатилось "
|
||||
PullImageStart: "Начало загрузки образа {{ .name }}"
|
||||
PullImageSuccess: "Образ успешно загружен"
|
||||
UpgradeAppStart: "Начало обновления приложения {{ .name }}"
|
||||
UpgradeAppSuccess: "Приложение {{ .name }} успешно обновлено"
|
||||
|
||||
#file
|
||||
ErrFileCanNotRead: "Файл недоступен для чтения"
|
||||
ErrFileToLarge: "Файл слишком большой"
|
||||
ErrPathNotFound: "Путь не найден"
|
||||
ErrMovePathFailed: "Целевой путь не может содержать исходный путь!"
|
||||
ErrLinkPathNotFound: "Целевой путь не существует!"
|
||||
ErrFileIsExist: "Файл или каталог уже существует!"
|
||||
ErrFileUpload: "Не удалось загрузить файл {{.name}} {{.detail}}"
|
||||
ErrFileDownloadDir: "Скачивание папки не поддерживается"
|
||||
ErrCmdNotFound: "Команда {{ .name}} не существует, пожалуйста, сначала установите эту команду на хосте"
|
||||
ErrSourcePathNotFound: "Исходный каталог не существует"
|
||||
ErrFavoriteExist: "Этот путь уже в избранном"
|
||||
ErrInvalidChar: "Недопустимые символы запрещены"
|
||||
ErrPathNotDelete: "Выбранный каталог не может быть удален"
|
||||
|
||||
#website
|
||||
ErrDomainIsExist: "Доменное имя уже существует"
|
||||
ErrAliasIsExist: "Псевдоним уже существует"
|
||||
ErrAppDelete: "Другой веб-сайт использует это приложение"
|
||||
ErrGroupIsUsed: "Группа используется и не может быть удалена"
|
||||
ErrBackupMatch: "файл резервной копии не соответствует текущим данным части сайта: {{ .detail}}"
|
||||
ErrBackupExist: "файл резервной копии соответствует части исходных данных, которая не существует: {{ .detail}}"
|
||||
ErrPHPResource: "Локальная среда выполнения не поддерживает переключение!"
|
||||
ErrPathPermission: "Обнаружена папка с правами доступа не 1000:1000 в каталоге индекса, что может вызвать ошибку отказа в доступе при доступе к веб-сайту. Пожалуйста, нажмите кнопку сохранения выше"
|
||||
ErrDomainIsUsed: "Домен уже используется веб-сайтом {{ .name }}"
|
||||
ErrDomainFormat: "Ошибка формата домена {{ .name }}"
|
||||
ErrDefaultAlias: "default — зарезервированное кодовое имя, пожалуйста, используйте другое кодовое имя"
|
||||
ErrImageNotExist: "Образ рабочей среды {{.name}} не существует, пожалуйста, перенастройте рабочую среду"
|
||||
|
||||
#ssl
|
||||
ErrSSLCannotDelete: "Сертификат {{ .name }} используется веб-сайтом и не может быть удален"
|
||||
ErrAccountCannotDelete: "Сертификат, связанный с учетной записью, не может быть удален"
|
||||
ErrSSLApply: "Сертификат продолжает успешно подписываться, но перезагрузка openresty не удалась, пожалуйста, проверьте конфигурацию!"
|
||||
ErrEmailIsExist: "Электронная почта уже существует"
|
||||
ErrSSLKeyNotFound: "Файл закрытого ключа не существует"
|
||||
ErrSSLCertificateNotFound: "Файл сертификата не существует"
|
||||
ErrSSLKeyFormat: "Ошибка проверки файла закрытого ключа"
|
||||
ErrSSLCertificateFormat: "Ошибка формата файла сертификата, пожалуйста, используйте формат pem"
|
||||
ErrEabKidOrEabHmacKeyCannotBlank: "EabKid или EabHmacKey не могут быть пустыми"
|
||||
ErrOpenrestyNotFound: "Режим HTTP требует предварительной установки Openresty"
|
||||
ApplySSLStart: "Начать подачу заявки на сертификат, доменное имя [{{ .domain }}] метод подачи заявки [{{ .type }}] "
|
||||
dnsAccount: "Автоматический DNS"
|
||||
dnsManual: "Ручной DNS"
|
||||
http: "HTTP"
|
||||
ApplySSLFailed: "Заявка на сертификат для [{{ .domain }}] не удалась, {{.detail}} "
|
||||
ApplySSLSuccess: "Заявка на сертификат для [{{ .domain }}] успешна! "
|
||||
DNSAccountName: "Учетная запись DNS [{{ .name }}] производитель [{{.type}}]"
|
||||
PushDirLog: "Сертификат отправлен в каталог [{{ .path }}] {{ .status }}"
|
||||
ErrDeleteCAWithSSL: "Существует выданный сертификат под текущей организацией, удаление невозможно"
|
||||
ErrDeleteWithPanelSSL: "Конфигурация SSL панели использует этот сертификат и не может быть удален"
|
||||
ErrDefaultCA: "Уполномоченный центр по умолчанию не может быть удален"
|
||||
ApplyWebSiteSSLLog: "Начать обновление сертификата веб-сайта {{ .name }}"
|
||||
ErrUpdateWebsiteSSL: "Не удалось обновить сертификат веб-сайта {{ .name }}: {{ .err }}"
|
||||
ApplyWebSiteSSLSuccess: "Сертификат веб-сайта успешно обновлен"
|
||||
ErrExecShell: "Не удалось выполнить скрипт {{ .err }}"
|
||||
ExecShellStart: "Начать выполнение скрипта"
|
||||
ExecShellSuccess: "Скрипт успешно выполнен"
|
||||
StartUpdateSystemSSL: "Начать обновление системного сертификата"
|
||||
UpdateSystemSSLSuccess: "Системный сертификат успешно обновлен"
|
||||
|
||||
#mysql
|
||||
ErrUserIsExist: "Текущий пользователь уже существует. Пожалуйста, введите нового пользователя"
|
||||
ErrDatabaseIsExist: "Текущая база данных уже существует. Пожалуйста, введите новую базу данных"
|
||||
ErrExecTimeOut: "Время выполнения SQL запроса истекло, пожалуйста, проверьте базу данных"
|
||||
ErrRemoteExist: "Удаленная база данных с таким именем уже существует, пожалуйста, измените и попробуйте снова"
|
||||
ErrLocalExist: "Локальная база данных с таким именем уже существует, пожалуйста, измените и попробуйте снова"
|
||||
|
||||
#redis
|
||||
ErrTypeOfRedis: "Тип восстановленного файла не соответствует текущему режиму сохранения. Измените тип файла и попробуйте снова"
|
||||
|
||||
#container
|
||||
ErrInUsed: "{{ .detail }} используется и не может быть удален"
|
||||
ErrObjectInUsed: "Этот объект используется и не может быть удален"
|
||||
ErrObjectBeDependent: "Этот образ зависит от других образов и не может быть удален"
|
||||
ErrPortRules: "Количество портов не совпадает, пожалуйста, введите заново!"
|
||||
ErrPgImagePull: "Тайм-аут загрузки образа. Пожалуйста, настройте ускорение загрузки образа или вручную загрузите образ postgres:16.0-alpine и попробуйте снова"
|
||||
|
||||
#runtime
|
||||
ErrDirNotFound: "Папка сборки не существует! Пожалуйста, проверьте целостность файла!"
|
||||
ErrFileNotExist: "Файл {{ .detail }} не существует! Пожалуйста, проверьте целостность исходного файла!"
|
||||
ErrImageBuildErr: "Не удалось создать образ"
|
||||
ErrImageExist: "Образ уже существует!"
|
||||
ErrDelWithWebsite: "Рабочая среда уже связана с веб-сайтом и не может быть удалена"
|
||||
ErrRuntimeStart: "Не удалось запустить"
|
||||
ErrPackageJsonNotFound: "Файл package.json не существует"
|
||||
ErrScriptsNotFound: "Конфигурационный элемент scripts не найден в package.json"
|
||||
ErrContainerNameNotFound: "Не удалось получить имя контейнера, пожалуйста, проверьте файл .env"
|
||||
ErrNodeModulesNotFound: "Папка node_modules не существует! Пожалуйста, отредактируйте среду выполнения или дождитесь успешного запуска среды выполнения"
|
||||
|
||||
#setting
|
||||
ErrBackupInUsed: "Учетная запись резервного копирования уже используется в cronjob и не может быть удалена."
|
||||
ErrBackupCheck: "Проверка подключения учетной записи резервного копирования не выполнена {{ .err}}"
|
||||
ErrOSSConn: "Не удалось получить последнюю версию, пожалуйста, проверьте возможность подключения сервера к внешней сети."
|
||||
ErrEntrance: "Информация о безопасном входе неверна. Пожалуйста, проверьте и попробуйте снова!"
|
||||
|
||||
#tool
|
||||
ErrConfigNotFound: "Конфигурационный файл не существует"
|
||||
ErrConfigParse: "Ошибка формата конфигурационного файла"
|
||||
ErrConfigIsNull: "Конфигурационный файл не может быть пустым"
|
||||
ErrConfigDirNotFound: "Каталог выполнения не существует"
|
||||
ErrConfigAlreadyExist: "Конфигурационный файл с таким именем уже существует"
|
||||
ErrUserFindErr: "Не удалось найти пользователя {{ .name }} {{ .err }}"
|
||||
|
||||
#ssh
|
||||
ErrFirewallNone: "На системе не обнаружен сервис firewalld или ufw. Пожалуйста, проверьте и попробуйте снова!"
|
||||
ErrFirewallBoth: "На системе обнаружены оба сервиса firewalld и ufw. Чтобы избежать конфликтов, удалите один и попробуйте снова!"
|
||||
|
||||
#cronjob
|
||||
ErrBashExecute: "Ошибка выполнения скрипта, пожалуйста, проверьте конкретную информацию в области вывода задачи."
|
||||
ErrCutWebsiteLog: "Не удалось разрезать лог веб-сайта {{ .name }}, ошибка {{ .err }}"
|
||||
CutWebsiteLogSuccess: "Лог веб-сайта {{ .name }} успешно разрезан, путь к резервной копии {{ .path }}"
|
||||
|
||||
#toolbox
|
||||
ErrNotExistUser: "Текущий пользователь не существует. Пожалуйста, измените и попробуйте снова!"
|
||||
ErrBanAction: "Установка не выполнена, текущий сервис {{ .name }} недоступен, пожалуйста, проверьте и попробуйте снова!"
|
||||
ErrClamdscanNotFound: "Команда clamdscan не обнаружена, пожалуйста, обратитесь к документации для установки!"
|
||||
|
||||
#waf
|
||||
ErrScope: "Изменение этой конфигурации не поддерживается"
|
||||
ErrStateChange: "Не удалось изменить состояние"
|
||||
ErrRuleExist: "Правило уже существует"
|
||||
ErrRuleNotExist: "Правило не существует"
|
||||
ErrParseIP: "Ошибка формата IP"
|
||||
ErrDefaultIP: "default — зарезервированное имя, пожалуйста, измените на другое имя"
|
||||
ErrGroupInUse: "IP-группа используется в черно/белом списке и не может быть удалена"
|
||||
ErrGroupExist: "Имя IP-группы уже существует"
|
||||
ErrIPRange: "Неверный диапазон IP"
|
||||
ErrIPExist: "IP уже существует"
|
||||
|
||||
#license
|
||||
ErrLicense: "Ошибка формата лицензии, пожалуйста, проверьте и попробуйте снова!"
|
||||
ErrLicenseCheck: "Проверка лицензии не выполнена, пожалуйста, проверьте и попробуйте снова!"
|
||||
ErrXpackVersion: "Ошибка проверки лицензии, эта лицензия ограничена по версии и не может быть успешно импортирована. Пожалуйста, проверьте и попробуйте снова!"
|
||||
ErrLicenseSave: "Не удалось сохранить информацию о лицензии, ошибка {{ .err }}, пожалуйста, попробуйте снова!"
|
||||
ErrLicenseSync: "Не удалось синхронизировать информацию о лицензии, в базе данных не обнаружена информация о лицензии!"
|
||||
ErrXpackNotFound: "Этот раздел является функцией профессионального издания, пожалуйста, сначала импортируйте лицензию в интерфейсе Настройки панели — Лицензия"
|
||||
ErrXpackNotActive: "Этот раздел является функцией профессионального издания, пожалуйста, сначала синхронизируйте статус лицензии в интерфейсе Настройки панели — Лицензия"
|
||||
ErrXpackOutOfDate: "Текущая лицензия истекла, пожалуйста, повторно импортируйте лицензию в интерфейсе Настройки панели — Лицензия"
|
||||
ErrXpackLost: "Лицензия достигла максимального числа попыток повторной попытки. Пожалуйста, перейдите на страницу [Настройки] [Лицензия] и вручную нажмите кнопку синхронизации, чтобы обеспечить корректную работу функций профессиональной версии."
|
||||
ErrXpackTimeout: "Превышено время ожидания запроса, возможно, нестабильное сетевое соединение, пожалуйста, повторите попытку позже!"
|
||||
|
||||
#license
|
||||
ErrAlert: "Ошибка формата информации об оповещении, пожалуйста, проверьте и попробуйте снова!"
|
||||
ErrAlertPush: "Ошибка отправки оповещения, пожалуйста, проверьте и попробуйте снова!"
|
||||
ErrAlertSave: "Ошибка сохранения оповещения, пожалуйста, проверьте и попробуйте снова!"
|
||||
ErrAlertSync: "Ошибка синхронизации оповещения, пожалуйста, проверьте и попробуйте снова!"
|
||||
ErrAlertRemote: "Ошибка удаленного оповещения, пожалуйста, проверьте и попробуйте снова!"
|
||||
|
||||
#cmd
|
||||
AppVersion: "Версия приложения"
|
||||
AppCommands: "Команды, связанные с приложением"
|
||||
AppInit: "Инициализировать приложение"
|
||||
AppKeyVal: "Ключ приложения (поддерживает только английский)"
|
||||
AppCreateFileErr: "Не удалось создать файл {{ .name }} {{ .err }}"
|
||||
AppCreateDirErr: "Не удалось создать папку {{ .name }} {{ .err }}"
|
||||
AppMissKey: "Отсутствует ключ приложения, используйте -k для указания"
|
||||
AppMissVersion: "Отсутствует версия приложения, используйте -v для указания"
|
||||
AppVersionExist: "Версия уже существует!"
|
||||
AppCreateSuccessful: "Создание прошло успешно!"
|
||||
AppWriteErr: "Ошибка записи файла {{ .name }} {{ .err }}"
|
||||
SudoHelper: "Пожалуйста, используйте {{ .cmd }} или переключитесь на пользователя root"
|
||||
ListenIPCommands: "Переключить IP прослушивания"
|
||||
ListenIPv4: "Прослушивать IPv4"
|
||||
ListenIPv6: "Прослушивать IPv6"
|
||||
ListenChangeSuccessful: "Переключение успешно! Теперь прослушивается {{ .value }}"
|
||||
ResetCommands: "Сбросить информацию системы"
|
||||
ResetMFA: "Отменить двухфакторную аутентификацию 1Panel"
|
||||
ResetHttps: "Отменить вход в 1Panel по https"
|
||||
ResetEntrance: "Отменить безопасный вход в 1Panel"
|
||||
ResetIPs: "Отменить авторизованные IP-ограничения 1Panel"
|
||||
ResetDomain: "Отменить привязку домена 1Panel"
|
||||
RestoreCommands: "Откатить сервис и данные 1Panel"
|
||||
RestoreNoSuchFile: "Нет доступных файлов для отката"
|
||||
RestoreStep1: "(1/5) Начало отката сервиса и данных 1Panel из каталога {{ .name }}..."
|
||||
RestoreStep2: "(2/5) Откат бинарного файла 1Panel успешен"
|
||||
RestoreStep3: "(3/5) Откат скрипта 1Panel успешен"
|
||||
RestoreStep4: "(4/5) Откат сервиса 1Panel успешен"
|
||||
RestoreStep5: "(5/5) Откат данных 1Panel успешен"
|
||||
RestoreSuccessful: "Откат успешен! Перезапуск службы, пожалуйста, подождите..."
|
||||
UpdateCommands: "Обновить информацию панели"
|
||||
UpdateUser: "Обновить пользователя панели"
|
||||
UpdatePassword: "Обновить пароль панели"
|
||||
UpdatePort: "Обновить порт панели"
|
||||
UpdateUserNull: "Ошибка: пользователь панели пуст!"
|
||||
UpdateUserBlank: "Ошибка: пользователь панели содержит пробелы!"
|
||||
UpdateUserFormat: "Ошибка: неверный формат пользователя панели! Поддерживаются только английский, китайский, цифры и , длина 3-30"
|
||||
UpdateUserErr: "Ошибка: не удалось обновить пользователя панели, {{ .err }}"
|
||||
UpdateSuccessful: "Обновление успешно!"
|
||||
UpdateUserResult: "Пользователь панели: {{ .name }}"
|
||||
UpdatePasswordRead: "Ошибка: не удалось прочитать информацию о пароле панели, {{ .err }}"
|
||||
UpdatePasswordNull: "Ошибка: пароль панели пуст!"
|
||||
UpdateUPasswordBlank: "Ошибка: пароль панели содержит пробелы!"
|
||||
UpdatePasswordFormat: "Ошибка: пароль панели поддерживает только буквы, цифры, специальные символы !@#$%* ,., длина 8-30!"
|
||||
UpdatePasswordLen: "Ошибка: Пожалуйста, введите пароль длиной более 6 символов!"
|
||||
UpdatePasswordRe: "Подтвердите пароль:"
|
||||
UpdatePasswordErr: "Ошибка: не удалось обновить пароль панели, {{ .err }}"
|
||||
UpdatePasswordSame: "Ошибка: два пароля не совпадают, пожалуйста, проверьте и попробуйте снова!"
|
||||
UpdatePasswordResult: "Пароль панели: {{ .name }}"
|
||||
UpdatePortFormat: "Ошибка: введенный номер порта должен быть между 1 и 65535!"
|
||||
UpdatePortUsed: "Ошибка: номер порта уже используется, пожалуйста, проверьте и попробуйте снова!"
|
||||
UpdatePortErr: "Ошибка: не удалось обновить порт панели, {{ .err }}"
|
||||
UpdatePortResult: "Порт панели: {{ .name }}"
|
||||
UpdatePortFirewallAdd: "Не удалось добавить правило порта брандмауэра, {{ .err }}, пожалуйста, вручную добавьте порт {{ .name }} в правила брандмауэра."
|
||||
UpdatePortFirewallDel: "Ошибка: не удалось удалить порт брандмауэра, {{ .err }}"
|
||||
UpdatePortFirewallReload: "Не удалось перезагрузить брандмауэр, {{ .err }}, пожалуйста, вручную перезагрузите брандмауэр."
|
||||
UserInfo: "Получить информацию панели"
|
||||
UserInfoAddr: "Адрес панели: "
|
||||
UserInfoPassHelp: "Подсказка: чтобы изменить пароль, вы можете выполнить команду: "
|
||||
DBConnErr: "Ошибка: не удалось инициализировать подключение к базе данных, {{ .err }}"
|
||||
SystemVersion: "версия: "
|
||||
SystemMode: "режим: "
|
||||
|
||||
#ai-tool
|
||||
ErrOpenrestyInstall: "Пожалуйста, установите Openresty сначала"
|
||||
ErrSSL: "Содержимое сертификата пустое, пожалуйста, проверьте сертификат!"
|
||||
|
||||
#mobile app
|
||||
ErrVerifyToken: 'шибка проверки токена, пожалуйста, сбросьте и отсканируйте снова.'
|
||||
ErrInvalidToken: 'Неверный токен, пожалуйста, сбросьте и отсканируйте снова.'
|
||||
ErrExpiredToken: 'Токен истек, пожалуйста, сбросьте и отсканируйте снова.'
|
||||
+136
-124
@@ -6,18 +6,19 @@ ErrRecordExist: "記錄已存在"
|
||||
ErrRecordNotFound: "記錄未找到"
|
||||
ErrStructTransform: "類型轉換失敗: {{ .detail }}"
|
||||
ErrNotLogin: "用戶未登入: {{ .detail }}"
|
||||
ErrPasswordExpired: "當前密碼已過期: {{ .detail }}"
|
||||
ErrNotSupportType: "系統暫不支持當前類型: {{ .detail }}"
|
||||
ErrApiConfigStatusInvalid: "API 接口禁止訪問: {{ .detail }}"
|
||||
ErrApiConfigKeyInvalid: "API 接口密钥錯誤: {{ .detail }}"
|
||||
ErrApiConfigIPInvalid: "调用 API 接口 IP 不在白名单: {{ .detail }}"
|
||||
ErrApiConfigDisable: "此接口禁止使用 API 接口調用: {{ .detail }}"
|
||||
ErrPasswordExpired: "目前密碼已過期: {{ .detail }}"
|
||||
ErrNotSupportType: "系統暫不支援目前類型: {{ .detail }}"
|
||||
ErrApiConfigStatusInvalid: "API 介面禁止瀏覽: {{ .detail }}"
|
||||
ErrApiConfigKeyInvalid: "API 介面金鑰錯誤: {{ .detail }}"
|
||||
ErrApiConfigIPInvalid: "呼叫 API 介面 IP 不在白名單: {{ .detail }}"
|
||||
ErrApiConfigDisable: "此介面禁止使用 API 介面呼叫: {{ .detail }}"
|
||||
ErrApiConfigKeyTimeInvalid: "API 介面時間戳記錯誤: {{ .detail }}"
|
||||
|
||||
#common
|
||||
ErrNameIsExist: "名稱已存在"
|
||||
ErrDemoEnvironment: "演示伺服器,禁止此操作!"
|
||||
ErrCmdTimeout: "指令執行超時!"
|
||||
ErrCmdIllegal: "執行命令中存在不合法字符,請修改後重試!"
|
||||
ErrCmdIllegal: "執行指令中存在不合法字元,請修改後重試!"
|
||||
ErrPortExist: '{{ .port }} 埠已被 {{ .type }} [{{ .name }}] 佔用'
|
||||
TYPE_APP: "應用"
|
||||
TYPE_RUNTIME: "運作環境"
|
||||
@@ -30,99 +31,99 @@ SystemRestart: "系統重啟導致任務中斷"
|
||||
ErrInvalidChar: "禁止使用非法字元"
|
||||
|
||||
#app
|
||||
ErrPortInUsed: "{{ .detail }} 端口已被佔用!"
|
||||
ErrPortInUsed: "{{ .detail }} 埠已被佔用!"
|
||||
ErrAppLimit: "應用超出安裝數量限制"
|
||||
ErrAppRequired: "請先安裝 {{ .detail }} 應用"
|
||||
ErrNotInstall: "應用未安裝"
|
||||
ErrPortInOtherApp: "{{ .port }} 端口已被應用 {{ .apps }} 佔用!"
|
||||
ErrPortInOtherApp: "{{ .port }} 埠已被應用 {{ .apps }} 佔用!"
|
||||
ErrDbUserNotValid: "儲存資料庫,用戶名密碼不匹配!"
|
||||
ErrDockerComposeNotValid: "docker-compose 文件格式錯誤"
|
||||
ErrDockerComposeNotValid: "docker-compose 檔案格式錯誤"
|
||||
ErrUpdateBuWebsite: '應用更新成功,但是網站配置文件修改失敗,請檢查配置!'
|
||||
Err1PanelNetworkFailed: '默認容器網絡創建失敗!{{ .detail }}'
|
||||
ErrFileParse: '應用 docker-compose 文件解析失敗!'
|
||||
Err1PanelNetworkFailed: '預設容器網路建立失敗!{{ .detail }}'
|
||||
ErrFileParse: '應用 docker-compose 檔案解析失敗!'
|
||||
ErrInstallDirNotFound: '安裝目錄不存在'
|
||||
AppStoreIsUpToDate: '應用商店已經是最新版本'
|
||||
LocalAppVersionNull: '{{.name}} 應用未同步到版本!無法添加到應用列表'
|
||||
LocalAppVersionErr: '{{.name}} 同步版本 {{.version}} 失敗!{{.err}}'
|
||||
ErrFileNotFound: '{{.name}} 文件不存在'
|
||||
ErrFileParseApp: '{{.name}} 文件解析失敗 {{.err}}'
|
||||
LocalAppVersionNull: '{{ .name }} 應用未同步到版本!無法新增到應用列表'
|
||||
LocalAppVersionErr: '{{ .name }} 同步版本 {{ .version }} 失敗!{{ .err }}'
|
||||
ErrFileNotFound: '{{ .name }} 檔案不存在'
|
||||
ErrFileParseApp: '{{ .name }} 檔案解析失敗 {{ .err }}'
|
||||
ErrAppDirNull: '版本資料夾不存在'
|
||||
LocalAppErr: "應用 {{.name}} 同步失敗!{{.err}}"
|
||||
LocalAppErr: "應用 {{ .name }} 同步失敗!{{ .err }}"
|
||||
ErrContainerName: "容器名稱已存在"
|
||||
ErrAppSystemRestart: "1Panel 重啟導致任務中斷"
|
||||
ErrCreateHttpClient: "創建HTTP請求失敗 {{.err}}"
|
||||
ErrHttpReqTimeOut: "請求超時 {{.err}}"
|
||||
ErrHttpReqFailed: "請求失敗 {{.err}}"
|
||||
ErrHttpReqNotFound: "文件不存在"
|
||||
ErrNoSuchHost: "網路連接失敗"
|
||||
ErrCreateHttpClient: "建立HTTP請求失敗 {{ .err }}"
|
||||
ErrHttpReqTimeOut: "請求超時 {{ .err }}"
|
||||
ErrHttpReqFailed: "請求失敗 {{ .err }}"
|
||||
ErrHttpReqNotFound: "檔案不存在"
|
||||
ErrNoSuchHost: "網路連線失敗"
|
||||
ErrImagePullTimeOut: "鏡像拉取超時"
|
||||
ErrContainerNotFound: '{{ .name }} 容器不存在'
|
||||
ErrContainerMsg: '{{ .name }} 容器異常,具體請在容器頁面查看日誌'
|
||||
ErrAppBackup: '{{ .name }} 應用備份失敗 err {{.err}}'
|
||||
ErrImagePull: '{{ .name }} 鏡像拉取失敗 err {{.err}}'
|
||||
ErrVersionTooLow: '當前 1Panel 版本過低,無法更新應用商店,請升級版本之後操作'
|
||||
ErrAppBackup: '{{ .name }} 應用備份失敗 err {{ .err }}'
|
||||
ErrImagePull: '{{ .name }} 鏡像拉取失敗 err {{ .err }}'
|
||||
ErrVersionTooLow: '目前 1Panel 版本過低,無法更新應用商店,請升級版本之後操作'
|
||||
ErrAppNameExist: '應用名稱已存在'
|
||||
AppStoreIsSyncing: '應用程式商店正在同步中,請稍後再試'
|
||||
ErrGetCompose: "docker-compose.yml 檔案取得失敗!{{ .detail }}"
|
||||
ErrAppWarn: "狀態異常,請查看日誌"
|
||||
ErrAppParamKey: "參數 {{ .name }} 欄位異常"
|
||||
ErrAppUpgrade: "應用程式 {{ .name }} 升級失敗 {{ .err }}"
|
||||
AppRecover: "應用程式 {{ .name }} 回滾 "
|
||||
AppRecover: "應用程式 {{ .name }} 轉返 "
|
||||
PullImageStart: "開始拉取鏡像 {{ .name }}"
|
||||
PullImageSuccess: "鏡像拉取成功"
|
||||
UpgradeAppStart: "開始升級應用程式 {{ .name }}"
|
||||
UpgradeAppSuccess: "應用程式 {{ .name }} 升級成功"
|
||||
|
||||
#file
|
||||
ErrFileCanNotRead: "此文件不支持預覽"
|
||||
ErrFileToLarge: "文件超過10M,無法打開"
|
||||
ErrFileCanNotRead: "此檔案不支援預覽"
|
||||
ErrFileToLarge: "檔案超過10M,無法打開"
|
||||
ErrPathNotFound: "目錄不存在"
|
||||
ErrMovePathFailed: "目標路徑不能包含原路徑!"
|
||||
ErrLinkPathNotFound: "目標路徑不存在!"
|
||||
ErrFileIsExist: "文件或文件夾已存在!"
|
||||
ErrFileUpload: "{{ .name }} 上傳文件失敗 {{ .detail}}"
|
||||
ErrFileDownloadDir: "不支持下載文件夾"
|
||||
ErrCmdNotFound: "{{ .name}} 命令不存在,請先在宿主機安裝此命令"
|
||||
ErrFileIsExist: "檔案或資料夾已存在!"
|
||||
ErrFileUpload: "{{ .name }} 上傳檔案失敗 {{ .detail }}"
|
||||
ErrFileDownloadDir: "不支援下載資料夾"
|
||||
ErrCmdNotFound: "{{ .name}} 指令不存在,請先在宿主機安裝此指令"
|
||||
ErrSourcePathNotFound: "源目錄不存在"
|
||||
ErrFavoriteExist: "已收藏此路徑"
|
||||
ErrPathNotDelete: "所選目錄不可删除"
|
||||
ErrPathNotDelete: "所選目錄不可刪除"
|
||||
|
||||
#website
|
||||
ErrDomainIsExist: "域名已存在"
|
||||
ErrAliasIsExist: "代號已存在"
|
||||
ErrAppDelete: '其他網站使用此應用,無法刪除'
|
||||
ErrAppDelete: '其他網站使用此應用,無法刪除'
|
||||
ErrGroupIsUsed: '分組正在使用中,無法刪除'
|
||||
ErrBackupMatch: '該備份文件與當前網站部分數據不匹配: {{ .detail}}'
|
||||
ErrBackupExist: '該備份文件對應部分原數據不存在: {{ .detail}}'
|
||||
ErrPHPResource: '本地運行環境不支持切換!'
|
||||
ErrPathPermission: 'index 目錄下偵測到非 1000:1000 權限資料夾,可能導致網站存取 Access denied 錯誤,請點擊上方儲存按鈕'
|
||||
ErrBackupMatch: '該備份檔案與目前網站部分資料不匹配: {{ .detail }}'
|
||||
ErrBackupExist: '該備份檔案對應部分原資料不存在: {{ .detail }}'
|
||||
ErrPHPResource: '本機執行環境不支援切換!'
|
||||
ErrPathPermission: 'index 目錄下偵測到非 1000:1000 權限資料夾,可能導致網站存取 Access denied 錯誤,請點選上方儲存按鈕'
|
||||
ErrDomainIsUsed: "域名已被網站【{{ .name }}】使用"
|
||||
ErrDomainFormat: "{{ .name }} 域名格式不正確"
|
||||
ErrDefaultAlias: "default 為保留代號,請使用其他代號"
|
||||
ErrImageNotExist: "執行環境 {{.name}} 鏡像不存在,請重新編輯執行環境"
|
||||
ErrImageNotExist: "執行環境 {{ .name }} 鏡像不存在,請重新編輯執行環境"
|
||||
|
||||
#ssl
|
||||
ErrSSLCannotDelete: "{{ .name }} 證書正在被網站使用,無法刪除"
|
||||
ErrAccountCannotDelete: "帳號關聯證書,無法刪除"
|
||||
ErrSSLApply: "證書續簽成功,openresty reload失敗,請檢查配置!"
|
||||
ErrEmailIsExist: '郵箱已存在'
|
||||
ErrSSLKeyNotFound: '私鑰文件不存在'
|
||||
ErrSSLCertificateNotFound: '證書文件不存在'
|
||||
ErrSSLKeyFormat: '私鑰文件校驗錯誤'
|
||||
ErrSSLCertificateFormat: '證書文件格式錯誤,請使用 pem 格式'
|
||||
ErrEmailIsExist: '信箱已存在'
|
||||
ErrSSLKeyNotFound: '私鑰檔案不存在'
|
||||
ErrSSLCertificateNotFound: '證書檔案不存在'
|
||||
ErrSSLKeyFormat: '私鑰檔案校驗錯誤'
|
||||
ErrSSLCertificateFormat: '證書檔案格式錯誤,請使用 pem 格式'
|
||||
ErrEabKidOrEabHmacKeyCannotBlank: 'EabKid 或 EabHmacKey 不能為空'
|
||||
ErrOpenrestyNotFound: 'Http 模式需要先安裝 Openresty'
|
||||
ApplySSLStart: '開始申請憑證,網域 [{{ .domain }}] 申請方式 [{{ .type }}] '
|
||||
ApplySSLStart: '開始申請憑證,網域 [{{ .domain }}] 申請方式 [{{ .type }}] '
|
||||
dnsAccount: "DNS 自動"
|
||||
dnsManual: "DNS 手排"
|
||||
http: "HTTP"
|
||||
ApplySSLFailed: '申請 [{{ .domain }}] 憑證失敗, {{.detail}} '
|
||||
ApplySSLFailed: '申請 [{{ .domain }}] 憑證失敗, {{ .detail }} '
|
||||
ApplySSLSuccess: '申請 [{{ .domain }}] 憑證成功! ! '
|
||||
DNSAccountName: 'DNS 帳號 [{{ .name }}] 廠商 [{{.type}}]'
|
||||
DNSAccountName: 'DNS 帳號 [{{ .name }}] 廠商 [{{ .type }}]'
|
||||
PushDirLog: '憑證推送到目錄 [{{ .path }}] {{ .status }}'
|
||||
ErrDeleteCAWithSSL: "目前機構下存在已簽發證書,無法刪除"
|
||||
ErrDeleteWithPanelSSL: "面板 SSL 配置使用此證書,無法刪除"
|
||||
ErrDefaultCA: "默認機構不能刪除"
|
||||
ErrDefaultCA: "預設機構不能刪除"
|
||||
ApplyWebSiteSSLLog: "開始更新 {{ .name }} 網站憑證"
|
||||
ErrUpdateWebsiteSSL: "{{ .name }} 網站更新憑證失敗: {{ .err }}"
|
||||
ApplyWebSiteSSLSuccess: "更新網站憑證成功"
|
||||
@@ -133,59 +134,60 @@ StartUpdateSystemSSL: "開始更新系統證書"
|
||||
UpdateSystemSSLSuccess: "更新系統證書成功"
|
||||
|
||||
#mysql
|
||||
ErrUserIsExist: "當前用戶已存在,請重新輸入"
|
||||
ErrDatabaseIsExist: "當前資料庫已存在,請重新輸入"
|
||||
ErrExecTimeOut: "SQL 執行超時,請檢查數據庫"
|
||||
ErrRemoteExist: "遠程數據庫已存在該名稱,請修改後重試"
|
||||
ErrLocalExist: "本地數據庫已存在該名稱,請修改後重試"
|
||||
ErrUserIsExist: "目前用戶已存在,請重新輸入"
|
||||
ErrDatabaseIsExist: "目前資料庫已存在,請重新輸入"
|
||||
ErrExecTimeOut: "SQL 執行超時,請檢查資料庫"
|
||||
ErrRemoteExist: "遠端資料庫已存在該名稱,請修改後重試"
|
||||
ErrLocalExist: "本機資料庫已存在該名稱,請修改後重試"
|
||||
|
||||
#redis
|
||||
ErrTypeOfRedis: "恢復文件類型與當前持久化方式不符,請修改後重試"
|
||||
ErrTypeOfRedis: "復原檔案類型與目前持久化方式不匹配,請修改後重試"
|
||||
|
||||
#container
|
||||
ErrInUsed: "{{ .detail }} 正被使用,無法刪除"
|
||||
ErrObjectInUsed: "該對象正被使用,無法刪除"
|
||||
ErrPortRules: "端口數目不匹配,請重新輸入!"
|
||||
ErrObjectInUsed: "該物件正被使用,無法刪除"
|
||||
ErrObjectBeDependent: "該鏡像依賴於其他鏡像,無法刪除"
|
||||
ErrPortRules: "埠數目不匹配,請重新輸入!"
|
||||
ErrPgImagePull: "鏡像拉取超時,請配置鏡像加速或手動拉取 postgres:16.0-alpine 鏡像後重試"
|
||||
|
||||
#runtime
|
||||
ErrDirNotFound: "build 文件夾不存在!請檢查文件完整性!"
|
||||
ErrFileNotExist: "{{ .detail }} 文件不存在!請檢查源文件完整性!"
|
||||
ErrDirNotFound: "build 資料夾不存在!請檢查檔案完整性!"
|
||||
ErrFileNotExist: "{{ .detail }} 檔案不存在!請檢查源文件完整性!"
|
||||
ErrImageBuildErr: "鏡像 build 失敗"
|
||||
ErrImageExist: "鏡像已存在!"
|
||||
ErrDelWithWebsite: "運行環境已經關聯網站,無法刪除"
|
||||
ErrDelWithWebsite: "執行環境已經關聯網站,無法刪除"
|
||||
ErrRuntimeStart: "啟動失敗"
|
||||
ErrPackageJsonNotFound: "package.json 文件不存在"
|
||||
ErrPackageJsonNotFound: "package.json 檔案不存在"
|
||||
ErrScriptsNotFound: "沒有在 package.json 中找到 scripts 配置項"
|
||||
ErrContainerNameNotFound: "無法取得容器名稱,請檢查 .env 文件"
|
||||
ErrNodeModulesNotFound: "node_modules 文件夾不存在!請編輯運行環境或者等待運行環境啟動成功"
|
||||
ErrContainerNameNotFound: "無法取得容器名稱,請檢查 .env 檔案"
|
||||
ErrNodeModulesNotFound: "node_modules 資料夾不存在!請編輯執行環境或者等待執行環境啟動成功"
|
||||
|
||||
#setting
|
||||
ErrBackupInUsed: "該備份帳號已在計劃任務中使用,無法刪除"
|
||||
ErrBackupCheck: "備份帳號測試連接失敗 {{ .err}}"
|
||||
ErrOSSConn: "無法獲取最新版本,請確認伺服器是否能夠連接外部網路。"
|
||||
ErrEntrance: "安全入口信息錯誤,請檢查後重試!"
|
||||
ErrBackupCheck: "備份帳號測試連線失敗 {{ .err }}"
|
||||
ErrOSSConn: "無法取得最新版本,請確認伺服器是否能夠連接外部網路。"
|
||||
ErrEntrance: "安全入口資訊錯誤,請檢查後重試!"
|
||||
|
||||
#tool
|
||||
ErrConfigNotFound: "配置文件不存在"
|
||||
ErrConfigParse: "配置文件格式有誤"
|
||||
ErrConfigIsNull: "配置文件不允許為空"
|
||||
ErrConfigDirNotFound: "運行目錄不存在"
|
||||
ErrConfigDirNotFound: "執行目錄不存在"
|
||||
ErrConfigAlreadyExist: "已存在同名配置文件"
|
||||
ErrUserFindErr: "用戶 {{ .name }} 查找失敗 {{ .err }}"
|
||||
ErrUserFindErr: "用戶 {{ .name }} 尋找失敗 {{ .err }}"
|
||||
|
||||
#ssh
|
||||
ErrFirewallNone: "未檢測到系統 firewalld 或 ufw 服務,請檢查後重試!"
|
||||
ErrFirewallBoth: "檢測到系統同時存在 firewalld 或 ufw 服務,為避免衝突,請卸載後重試!"
|
||||
ErrFirewallBoth: "檢測到系統同時存在 firewalld 或 ufw 服務,為避免衝突,請移除後重試!"
|
||||
|
||||
#cronjob
|
||||
ErrBashExecute: "腳本執行錯誤,請在任務輸出文本域中查看具體信息。"
|
||||
ErrBashExecute: "腳本執行錯誤,請在任務輸出文字區域中查看具體資訊。"
|
||||
ErrCutWebsiteLog: "{{ .name }} 網站日誌切割失敗,錯誤 {{ .err }}"
|
||||
CutWebsiteLogSuccess: "{{ .name }} 網站日誌切割成功,備份路徑 {{ .path }}"
|
||||
|
||||
#toolbox
|
||||
ErrNotExistUser: "當前使用者不存在,請修改後重試!"
|
||||
ErrBanAction: "設置失敗,當前 {{ .name }} 服務不可用,請檢查後重試!"
|
||||
ErrNotExistUser: "目前使用者不存在,請修改後重試!"
|
||||
ErrBanAction: "設定失敗,目前 {{ .name }} 服務不可用,請檢查後重試!"
|
||||
ErrClamdscanNotFound: "未偵測到 clamdscan 指令,請參考文件安裝!"
|
||||
|
||||
#waf
|
||||
@@ -203,81 +205,91 @@ ErrIPExist: "IP 已存在"
|
||||
#license
|
||||
ErrLicense: "許可證格式錯誤,請檢查後重試!"
|
||||
ErrLicenseCheck: "許可證校驗失敗,請檢查後重試!"
|
||||
ErrLicenseSave: "許可證信息保存失敗,錯誤 {{ .err }}, 請重試!"
|
||||
ErrLicenseSync: "許可證信息同步失敗,資料庫中未檢測到許可證信息!"
|
||||
ErrXpackNotFound: "該部分為專業版功能,請先在 面板設置-許可證 界面導入許可證"
|
||||
ErrXpackNotActive: "該部分為專業版功能,請先在 面板設置-許可證 界面同步許可證狀態"
|
||||
ErrXpackOutOfDate: "當前許可證已過期,請重新在 面板設置-許可證 界面導入許可證"
|
||||
ErrXpackLost: "許可證已達到最大重試次數,請進入【面板設定】【許可證】頁面手動點擊同步按鈕,以確保專業版功能正常使用"
|
||||
ErrXpackTimeout: "請求超時,網絡連接可能不穩定,請稍後再試!"
|
||||
ErrXpackVersion: "許可證校驗失敗,該許可證受版本限制,無法成功匯入,請檢查後重試!"
|
||||
ErrLicenseSave: "許可證資訊儲存失敗,錯誤 {{ .err }}, 請重試!"
|
||||
ErrLicenseSync: "許可證資訊同步失敗,資料庫中未檢測到許可證資訊!"
|
||||
ErrXpackNotFound: "該部分為專業版功能,請先在 面板設定-許可證 介面匯入許可證"
|
||||
ErrXpackNotActive: "該部分為專業版功能,請先在 面板設定-許可證 介面同步許可證狀態"
|
||||
ErrXpackOutOfDate: "目前許可證已過期,請重新在 面板設定-許可證 介面匯入許可證"
|
||||
ErrXpackLost: "許可證已達到最大重試次數,請進入【面板設定】【許可證】頁面手動點選同步按鈕,以確保專業版功能正常使用"
|
||||
ErrXpackTimeout: "請求超時,網路連線可能不穩定,請稍後再試!"
|
||||
|
||||
#license
|
||||
ErrAlert: "告警資訊格式錯誤,請檢查後重試!"
|
||||
ErrAlertPush: "告警資訊推送錯誤,請檢查後重試!"
|
||||
ErrAlertSave: "告警資訊保存錯誤,請檢查後重試!"
|
||||
ErrAlertSave: "告警資訊儲存錯誤,請檢查後重試!"
|
||||
ErrAlertSync: "告警資訊同步錯誤,請檢查後重試!"
|
||||
ErrAlertRemote: "告警資訊遠端錯誤,請檢查後重試!"
|
||||
|
||||
#cmd
|
||||
AppVersion: "應用版本"
|
||||
AppCommands: "應用相關命令"
|
||||
AppCommands: "應用相關指令"
|
||||
AppInit: "初始化應用"
|
||||
AppKeyVal: "應用的 key(僅支持英文)"
|
||||
AppCreateFileErr: "文件 {{ .name }} 創建失敗 {{ .err }}"
|
||||
AppCreateDirErr: "資料夾 {{ .name }} 創建失敗 {{ .err }}"
|
||||
AppKeyVal: "應用的 key(僅支援英文)"
|
||||
AppCreateFileErr: "檔案 {{ .name }} 建立失敗 {{ .err }}"
|
||||
AppCreateDirErr: "資料夾 {{ .name }} 建立失敗 {{ .err }}"
|
||||
AppMissKey: "應用的 key 缺失,使用 -k 指定"
|
||||
AppMissVersion: "應用版本缺失,使用 -v 指定"
|
||||
AppVersionExist: "版本已存在!"
|
||||
AppCreateSuccessful: "創建成功!"
|
||||
AppWriteErr: "文件 {{ .name }} 寫入失敗 {{ .err }}"
|
||||
AppCreateSuccessful: "建立成功!"
|
||||
AppWriteErr: "檔案 {{ .name }} 寫入失敗 {{ .err }}"
|
||||
SudoHelper: "請使用 {{ .cmd }} 或者切換到 root 用戶"
|
||||
ListenIPCommands: "切換監聽 IP"
|
||||
ListenIPv4: "監聽 IPv4"
|
||||
ListenIPv6: "監聽 IPv6"
|
||||
ListenChangeSuccessful: "切換成功!已切換至監聽 {{ .value }}"
|
||||
ResetCommands: "重置系統信息"
|
||||
ResetCommands: "重設系統資訊"
|
||||
ResetMFA: "取消 1Panel 兩步驗證"
|
||||
ResetHttps: "取消 1Panel https 方式登錄"
|
||||
ResetHttps: "取消 1Panel https 方式登入"
|
||||
ResetEntrance: "取消 1Panel 安全入口"
|
||||
ResetIPs: "取消 1Panel 授權 IP 限制"
|
||||
ResetDomain: "取消 1Panel 訪問域名綁定"
|
||||
RestoreCommands: "回滾 1Panel 服務及數據"
|
||||
RestoreNoSuchFile: "暫無可回滾文件"
|
||||
RestoreStep1: "(1/5)開始從 {{ .name }} 目錄回滾 1Panel 服務及數據... "
|
||||
RestoreStep2: "(2/5)1Panel 二進制回滾成功"
|
||||
RestoreStep3: "(3/5)1Panel 腳本回滾成功"
|
||||
RestoreStep4: "(4/5)1Panel 服務回滾成功"
|
||||
RestoreStep5: "(5/5)1Panel 數據回滾成功"
|
||||
RestoreSuccessful: "回滾成功!正在重啟服務,請稍候..."
|
||||
UpdateCommands: "修改面板信息"
|
||||
ResetDomain: "取消 1Panel 瀏覽域名綁定"
|
||||
RestoreCommands: "轉返 1Panel 服務及資料"
|
||||
RestoreNoSuchFile: "暫無可轉返文件"
|
||||
RestoreStep1: "(1/5)開始從 {{ .name }} 目錄轉返 1Panel 服務及資料... "
|
||||
RestoreStep2: "(2/5)1Panel 二進制轉返成功"
|
||||
RestoreStep3: "(3/5)1Panel 腳本轉返成功"
|
||||
RestoreStep4: "(4/5)1Panel 服務轉返成功"
|
||||
RestoreStep5: "(5/5)1Panel 資料轉返成功"
|
||||
RestoreSuccessful: "轉返成功!正在重啟服務,請稍候..."
|
||||
UpdateCommands: "修改面板資訊"
|
||||
UpdateUser: "修改面板用戶"
|
||||
UpdatePassword: "修改面板密碼"
|
||||
UpdatePort: "修改面板端口"
|
||||
UpdateUserNull: "錯誤:輸入面板用戶為空!"
|
||||
UpdateUserBlank: "錯誤:輸入面板用戶中包含空格字符!"
|
||||
UpdateUserFormat: "錯誤:輸入面板用戶錯誤!僅支持英文、中文、數字和_,長度3-30"
|
||||
UpdateUserErr: "錯誤:面板用戶修改失敗,{{ .err }}"
|
||||
UpdatePort: "修改面板埠"
|
||||
UpdateUserNull: "錯誤: 輸入面板用戶為空!"
|
||||
UpdateUserBlank: "錯誤: 輸入面板用戶中包含空格字元!"
|
||||
UpdateUserFormat: "錯誤: 輸入面板用戶錯誤!僅支援英文、中文、數字和_,長度3-30"
|
||||
UpdateUserErr: "錯誤: 面板用戶修改失敗,{{ .err }}"
|
||||
UpdateSuccessful: "修改成功!"
|
||||
UpdateUserResult: "面板用戶:{{ .name }}"
|
||||
UpdatePasswordRead: "錯誤:面板密碼信息讀取錯誤,{{ .err }}"
|
||||
UpdatePasswordNull: "錯誤:輸入面板密碼為空!"
|
||||
UpdateUPasswordBlank: "錯誤:輸入面板密碼中包含空格字符!"
|
||||
UpdatePasswordFormat: "錯誤:面板密碼僅支持字母、數字、特殊字符(!@#$%*_,.?),長度 8-30 位!"
|
||||
UpdatePasswordLen: "錯誤:請輸入 6 位以上密碼!"
|
||||
UpdatePasswordRe: "確認密碼:"
|
||||
UpdatePasswordErr: "錯誤:面板密碼修改失敗,{{ .err }}"
|
||||
UpdatePasswordSame: "錯誤:兩次密碼不匹配,請檢查後重試!"
|
||||
UpdatePasswordResult: "面板密碼:{{ .name }}"
|
||||
UpdatePortFormat: "錯誤:輸入的端口號必須在 1 到 65535 之間!"
|
||||
UpdatePortUsed: "錯誤:該端口號正被佔用,請檢查後重試!"
|
||||
UpdatePortErr: "錯誤:面板端口修改失敗,{{ .err }}"
|
||||
UpdatePortResult: "面板端口:{{ .name }}"
|
||||
UpdatePortFirewallAdd: "添加防火牆端口規則失敗,{{ .err }},請您手動將 {{ .name }} 端口添加至防火牆規則中。"
|
||||
UpdatePortFirewallDel: "錯誤:防火牆端口刪除失敗,{{ .err }}"
|
||||
UpdateUserResult: "面板用戶: {{ .name }}"
|
||||
UpdatePasswordRead: "錯誤: 面板密碼資訊讀取錯誤,{{ .err }}"
|
||||
UpdatePasswordNull: "錯誤: 輸入面板密碼為空!"
|
||||
UpdateUPasswordBlank: "錯誤: 輸入面板密碼中包含空格字元!"
|
||||
UpdatePasswordFormat: "錯誤: 面板密碼僅支援字母、數字、特殊字元(!@#$%*_,.?),長度 8-30 位!"
|
||||
UpdatePasswordLen: "錯誤: 請輸入 6 位以上密碼!"
|
||||
UpdatePasswordRe: "確認密碼: "
|
||||
UpdatePasswordErr: "錯誤: 面板密碼修改失敗,{{ .err }}"
|
||||
UpdatePasswordSame: "錯誤: 兩次密碼不匹配,請檢查後重試!"
|
||||
UpdatePasswordResult: "面板密碼: {{ .name }}"
|
||||
UpdatePortFormat: "錯誤: 輸入的埠號必須在 1 到 65535 之間!"
|
||||
UpdatePortUsed: "錯誤: 該埠號正被佔用,請檢查後重試!"
|
||||
UpdatePortErr: "錯誤: 面板埠修改失敗,{{ .err }}"
|
||||
UpdatePortResult: "面板埠: {{ .name }}"
|
||||
UpdatePortFirewallAdd: "新增防火牆埠規則失敗,{{ .err }},請您手動將 {{ .name }} 埠新增至防火牆規則中。"
|
||||
UpdatePortFirewallDel: "錯誤: 防火牆埠刪除失敗,{{ .err }}"
|
||||
UpdatePortFirewallReload: "防火牆重載失敗,{{ .err }},請您手動重載防火牆。"
|
||||
UserInfo: "獲取面板信息"
|
||||
UserInfoAddr: "面板地址:"
|
||||
UserInfoPassHelp: "提示:修改密碼可執行命令:"
|
||||
DBConnErr: "錯誤:初始化資料庫連接失敗,{{ .err }}"
|
||||
SystemVersion: "版本:"
|
||||
SystemMode: "模式:"
|
||||
UserInfo: "取得面板資訊"
|
||||
UserInfoAddr: "面板地址: "
|
||||
UserInfoPassHelp: "提示: 修改密碼可執行指令: "
|
||||
DBConnErr: "錯誤: 初始化資料庫連線失敗,{{ .err }}"
|
||||
SystemVersion: "版本: "
|
||||
SystemMode: "模式: "
|
||||
|
||||
#ai-tool
|
||||
ErrOpenrestyInstall: "請先安裝 Openresty"
|
||||
ErrSSL: "證書內容為空,請檢查證書!"
|
||||
|
||||
#mobile app
|
||||
ErrVerifyToken: '令牌驗證錯誤,請重置後再次掃碼'
|
||||
ErrInvalidToken: '無效的令牌,請重置後再次掃碼'
|
||||
ErrExpiredToken: '令牌過期,請重置後再次掃碼'
|
||||
|
||||
+56
-44
@@ -12,6 +12,7 @@ ErrApiConfigStatusInvalid: "API 接口禁止访问: {{ .detail }}"
|
||||
ErrApiConfigKeyInvalid: "API 接口密钥错误: {{ .detail }}"
|
||||
ErrApiConfigIPInvalid: "调用 API 接口 IP 不在白名单: {{ .detail }}"
|
||||
ErrApiConfigDisable: "此接口禁止使用 API 接口调用: {{ .detail }}"
|
||||
ErrApiConfigKeyTimeInvalid: "API 接口时间戳错误: {{ .detail }}"
|
||||
|
||||
#common
|
||||
ErrNameIsExist: "名称已存在"
|
||||
@@ -41,24 +42,24 @@ Err1PanelNetworkFailed: '默认容器网络创建失败!{{ .detail }}'
|
||||
ErrFileParse: '应用 docker-compose 文件解析失败!'
|
||||
ErrInstallDirNotFound: '安装目录不存在'
|
||||
AppStoreIsUpToDate: '应用商店已经是最新版本'
|
||||
LocalAppVersionNull: '{{.name}} 应用未同步到版本!无法添加到应用列表'
|
||||
LocalAppVersionErr: '{{.name}} 同步版本 {{.version}} 失败!{{.err}}'
|
||||
ErrFileNotFound: '{{.name}} 文件不存在'
|
||||
ErrFileParseApp: '{{.name}} 文件解析失败 {{.err}}'
|
||||
LocalAppVersionNull: '{{ .name }} 应用未同步到版本!无法添加到应用列表'
|
||||
LocalAppVersionErr: '{{ .name }} 同步版本 {{ .version }} 失败!{{ .err }}'
|
||||
ErrFileNotFound: '{{ .name }} 文件不存在'
|
||||
ErrFileParseApp: '{{ .name }} 文件解析失败 {{ .err }}'
|
||||
ErrAppDirNull: '版本文件夹不存在'
|
||||
LocalAppErr: "应用 {{.name}} 同步失败!{{.err}}"
|
||||
LocalAppErr: "应用 {{ .name }} 同步失败!{{ .err }}"
|
||||
ErrContainerName: "容器名称已存在"
|
||||
ErrAppSystemRestart: "1Panel 重启导致任务终止"
|
||||
ErrCreateHttpClient: "创建HTTP请求失败 {{.err}}"
|
||||
ErrHttpReqTimeOut: "请求超时 {{.err}}"
|
||||
ErrHttpReqFailed: "请求失败 {{.err}}"
|
||||
ErrCreateHttpClient: "创建HTTP请求失败 {{ .err }}"
|
||||
ErrHttpReqTimeOut: "请求超时 {{ .err }}"
|
||||
ErrHttpReqFailed: "请求失败 {{ .err }}"
|
||||
ErrHttpReqNotFound: "文件不存在"
|
||||
ErrNoSuchHost: "网络连接失败"
|
||||
ErrImagePullTimeOut: '镜像拉取超时'
|
||||
ErrContainerNotFound: '{{ .name }} 容器不存在'
|
||||
ErrContainerMsg: '{{ .name }} 容器异常,具体请在容器页面查看日志'
|
||||
ErrAppBackup: '{{ .name }} 应用备份失败 err {{.err}}'
|
||||
ErrImagePull: '镜像拉取失败 {{.err}}'
|
||||
ErrAppBackup: '{{ .name }} 应用备份失败 err {{ .err }}'
|
||||
ErrImagePull: '镜像拉取失败 {{ .err }}'
|
||||
ErrVersionTooLow: '当前 1Panel 版本过低,无法更新应用商店,请升级版本之后操作'
|
||||
ErrAppNameExist: '应用名称已存在'
|
||||
AppStoreIsSyncing: '应用商店正在同步中,请稍后再试'
|
||||
@@ -74,12 +75,12 @@ UpgradeAppSuccess: "应用 {{ .name }} 升级成功"
|
||||
|
||||
#file
|
||||
ErrFileCanNotRead: "此文件不支持预览"
|
||||
ErrFileToLarge: "文件超过10M,无法打开"
|
||||
ErrFileToLarge: "文件超过10M,无法打开"
|
||||
ErrPathNotFound: "目录不存在"
|
||||
ErrMovePathFailed: "目标路径不能包含原路径!"
|
||||
ErrLinkPathNotFound: "目标路径不存在!"
|
||||
ErrFileIsExist: "文件或文件夹已存在!"
|
||||
ErrFileUpload: "{{ .name }} 上传文件失败 {{ .detail}}"
|
||||
ErrFileUpload: "{{ .name }} 上传文件失败 {{ .detail }}"
|
||||
ErrFileDownloadDir: "不支持下载文件夹"
|
||||
ErrCmdNotFound: "{{ .name}} 命令不存在,请先在宿主机安装此命令"
|
||||
ErrSourcePathNotFound: "源目录不存在"
|
||||
@@ -90,16 +91,16 @@ ErrPathNotDelete: "所选目录不可删除"
|
||||
#website
|
||||
ErrDomainIsExist: "域名已存在"
|
||||
ErrAliasIsExist: "代号已存在"
|
||||
ErrAppDelete: '其他网站使用此应用,无法删除'
|
||||
ErrAppDelete: '其他网站使用此应用,无法删除'
|
||||
ErrGroupIsUsed: '分组正在使用中,无法删除'
|
||||
ErrBackupMatch: '该备份文件与当前网站部分数据不匹配 {{ .detail}}'
|
||||
ErrBackupExist: '该备份文件对应部分源数据不存在 {{ .detail}}'
|
||||
ErrBackupMatch: '该备份文件与当前网站部分数据不匹配 {{ .detail }}'
|
||||
ErrBackupExist: '该备份文件对应部分源数据不存在 {{ .detail }}'
|
||||
ErrPHPResource: '本地运行环境不支持切换!'
|
||||
ErrPathPermission: 'index 目录下检测到非 1000:1000 权限文件夹,可能导致网站访问 Access denied 错误,请点击上方保存按钮'
|
||||
ErrDomainIsUsed: "域名已被网站【{{ .name }}】使用"
|
||||
ErrDomainFormat: "{{ .name }} 域名格式不正确"
|
||||
ErrDefaultAlias: "default 为保留代号,请使用其他代号"
|
||||
ErrImageNotExist: "运行环境 {{.name}} 镜像不存在,请重新编辑运行环境"
|
||||
ErrImageNotExist: "运行环境 {{ .name }} 镜像不存在,请重新编辑运行环境"
|
||||
|
||||
#ssl
|
||||
ErrSSLCannotDelete: "{{ .name }} 证书正在被网站使用,无法删除"
|
||||
@@ -112,13 +113,13 @@ ErrSSLKeyFormat: '私钥文件校验失败'
|
||||
ErrSSLCertificateFormat: '证书文件格式错误,请使用 pem 格式'
|
||||
ErrEabKidOrEabHmacKeyCannotBlank: 'EabKid 或 EabHmacKey 不能为空'
|
||||
ErrOpenrestyNotFound: 'Http 模式需要首先安装 Openresty'
|
||||
ApplySSLStart: '开始申请证书,域名 [{{ .domain }}] 申请方式 [{{ .type }}] '
|
||||
ApplySSLStart: '开始申请证书,域名 [{{ .domain }}] 申请方式 [{{ .type }}] '
|
||||
dnsAccount: "DNS 自动"
|
||||
dnsManual: "DNS 手动"
|
||||
http: "HTTP"
|
||||
ApplySSLFailed: '申请 [{{ .domain }}] 证书失败, {{.detail}} '
|
||||
ApplySSLFailed: '申请 [{{ .domain }}] 证书失败, {{ .detail }} '
|
||||
ApplySSLSuccess: '申请 [{{ .domain }}] 证书成功!!'
|
||||
DNSAccountName: 'DNS 账号 [{{ .name }}] 厂商 [{{.type}}]'
|
||||
DNSAccountName: 'DNS 账号 [{{ .name }}] 厂商 [{{ .type }}]'
|
||||
PushDirLog: '证书推送到目录 [{{ .path }}] {{ .status }}'
|
||||
ErrDeleteCAWithSSL: "当前机构下存在已签发证书,无法删除"
|
||||
ErrDeleteWithPanelSSL: "面板 SSL 配置使用此证书,无法删除"
|
||||
@@ -145,6 +146,7 @@ ErrTypeOfRedis: "恢复文件类型与当前持久化方式不符,请修改后
|
||||
#container
|
||||
ErrInUsed: "{{ .detail }} 正被使用,无法删除"
|
||||
ErrObjectInUsed: "该对象正被使用,无法删除"
|
||||
ErrObjectBeDependent: "该镜像依赖于其他镜像,无法删除"
|
||||
ErrPortRules: "端口数目不匹配,请重新输入!"
|
||||
ErrPgImagePull: "镜像拉取超时,请配置镜像加速或手动拉取 postgres:16.0-alpine 镜像后重试"
|
||||
|
||||
@@ -162,7 +164,7 @@ ErrNodeModulesNotFound: "node_modules 文件夹不存在!请编辑运行环境
|
||||
|
||||
#setting
|
||||
ErrBackupInUsed: "该备份账号已在计划任务中使用,无法删除"
|
||||
ErrBackupCheck: "备份账号测试连接失败 {{ .err}}"
|
||||
ErrBackupCheck: "备份账号测试连接失败 {{ .err }}"
|
||||
ErrOSSConn: "无法获取最新版本,请确认服务器是否能够连接外部网络。"
|
||||
ErrEntrance: "安全入口信息错误,请检查后重试!"
|
||||
|
||||
@@ -203,6 +205,7 @@ ErrIPExist: "IP 已存在"
|
||||
#license
|
||||
ErrLicense: "许可证格式错误,请检查后重试!"
|
||||
ErrLicenseCheck: "许可证校验失败,请检查后重试!"
|
||||
ErrXpackVersion: "许可证校验失败,该许可证受版本限制,无法成功导入,请检查后重试!"
|
||||
ErrLicenseSave: "许可证信息保存失败,错误 {{ .err }},请重试!"
|
||||
ErrLicenseSync: "许可证信息同步失败,数据库中未检测到许可证信息!"
|
||||
ErrXpackNotFound: "该部分为专业版功能,请先在 面板设置-许可证 界面导入许可证"
|
||||
@@ -253,31 +256,40 @@ UpdateCommands: "修改面板信息"
|
||||
UpdateUser: "修改面板用户"
|
||||
UpdatePassword: "修改面板密码"
|
||||
UpdatePort: "修改面板端口"
|
||||
UpdateUserNull: "错误:输入面板用户为空!"
|
||||
UpdateUserBlank: "错误:输入面板用户中包含空格字符!"
|
||||
UpdateUserFormat: "错误:输入面板用户错误!仅支持英文、中文、数字和_,长度3-30"
|
||||
UpdateUserErr: "错误:面板用户修改失败,{{ .err }}"
|
||||
UpdateUserNull: "错误: 输入面板用户为空!"
|
||||
UpdateUserBlank: "错误: 输入面板用户中包含空格字符!"
|
||||
UpdateUserFormat: "错误: 输入面板用户错误!仅支持英文、中文、数字和_,长度3-30"
|
||||
UpdateUserErr: "错误: 面板用户修改失败,{{ .err }}"
|
||||
UpdateSuccessful: "修改成功!"
|
||||
UpdateUserResult: "面板用户:{{ .name }}"
|
||||
UpdatePasswordRead: "错误:面板密码信息读取错误,{{ .err }}"
|
||||
UpdatePasswordNull: "错误:输入面板密码为空!"
|
||||
UpdateUPasswordBlank: "错误:输入面板密码中包含空格字符!"
|
||||
UpdatePasswordFormat: "错误:面板密码仅支持字母、数字、特殊字符(!@#$%*_,.?),长度 8-30 位!"
|
||||
UpdatePasswordLen: "错误:请输入 6 位以上密码!"
|
||||
UpdatePasswordRe: "确认密码:"
|
||||
UpdatePasswordErr: "错误:面板密码修改失败,{{ .err }}"
|
||||
UpdatePasswordSame: "错误:两次密码不匹配,请检查后重试!"
|
||||
UpdatePasswordResult: "面板密码:{{ .name }}"
|
||||
UpdatePortFormat: "错误:输入的端口号必须在 1 到 65535 之间!"
|
||||
UpdatePortUsed: "错误:该端口号正被占用,请检查后重试!"
|
||||
UpdatePortErr: "错误:面板端口修改失败,{{ .err }}"
|
||||
UpdatePortResult: "面板端口:{{ .name }}"
|
||||
UpdateUserResult: "面板用户: {{ .name }}"
|
||||
UpdatePasswordRead: "错误: 面板密码信息读取错误,{{ .err }}"
|
||||
UpdatePasswordNull: "错误: 输入面板密码为空!"
|
||||
UpdateUPasswordBlank: "错误: 输入面板密码中包含空格字符!"
|
||||
UpdatePasswordFormat: "错误: 面板密码仅支持字母、数字、特殊字符(!@#$%*_,.?),长度 8-30 位!"
|
||||
UpdatePasswordLen: "错误: 请输入 6 位以上密码!"
|
||||
UpdatePasswordRe: "确认密码: "
|
||||
UpdatePasswordErr: "错误: 面板密码修改失败,{{ .err }}"
|
||||
UpdatePasswordSame: "错误: 两次密码不匹配,请检查后重试!"
|
||||
UpdatePasswordResult: "面板密码: {{ .name }}"
|
||||
UpdatePortFormat: "错误: 输入的端口号必须在 1 到 65535 之间!"
|
||||
UpdatePortUsed: "错误: 该端口号正被占用,请检查后重试!"
|
||||
UpdatePortErr: "错误: 面板端口修改失败,{{ .err }}"
|
||||
UpdatePortResult: "面板端口: {{ .name }}"
|
||||
UpdatePortFirewallAdd: "添加防火墙端口规则失败,{{ .err }},请您手动将 {{ .name }} 端口添加至防火墙规则中。"
|
||||
UpdatePortFirewallDel: "错误:防火墙端口删除失败,{{ .err }}"
|
||||
UpdatePortFirewallDel: "错误: 防火墙端口删除失败,{{ .err }}"
|
||||
UpdatePortFirewallReload: "防火墙重载失败,{{ .err }},请您手动重载防火墙。"
|
||||
UserInfo: "获取面板信息"
|
||||
UserInfoAddr: "面板地址:"
|
||||
UserInfoPassHelp: "提示:修改密码可执行命令:"
|
||||
DBConnErr: "错误:初始化数据库连接失败,{{ .err }}"
|
||||
SystemVersion: "版本:"
|
||||
SystemMode: "模式:"
|
||||
UserInfoAddr: "面板地址: "
|
||||
UserInfoPassHelp: "提示: 修改密码可执行命令: "
|
||||
DBConnErr: "错误: 初始化数据库连接失败,{{ .err }}"
|
||||
SystemVersion: "版本: "
|
||||
SystemMode: "模式: "
|
||||
|
||||
#ai-tool
|
||||
ErrOpenrestyInstall: '请先安装 Openresty'
|
||||
ErrSSL: "证书内容为空,请检查证书!"
|
||||
|
||||
#mobile app
|
||||
ErrVerifyToken: '令牌验证错误,请重置后再次扫码'
|
||||
ErrInvalidToken: '无效的令牌,请重置后再次扫码'
|
||||
ErrExpiredToken: '令牌过期,请重置后再次扫码'
|
||||
|
||||
@@ -35,7 +35,9 @@ func Init() {
|
||||
_ = docker.CreateDefaultDockerNetwork()
|
||||
|
||||
if f, err := firewall.NewFirewallClient(); err == nil {
|
||||
_ = f.EnableForward()
|
||||
if err = f.EnableForward(); err != nil {
|
||||
global.LOG.Errorf("init port forward failed, err: %v", err)
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ func Init() {
|
||||
go syncInstalledApp()
|
||||
go syncRuntime()
|
||||
go syncSSL()
|
||||
generateKey()
|
||||
}
|
||||
|
||||
func syncApp() {
|
||||
@@ -38,3 +39,9 @@ func syncSSL() {
|
||||
global.LOG.Errorf("sync ssl status error : %s", err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func generateKey() {
|
||||
if err := service.NewISettingService().GenerateRSAKey(); err != nil {
|
||||
global.LOG.Errorf("generate rsa key error : %s", err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,11 +77,26 @@ func Init() {
|
||||
global.LOG.Errorf("load service ip white list from setting failed, err: %v", err)
|
||||
}
|
||||
global.CONF.System.IpWhiteList = ipWhiteListSetting.Value
|
||||
apiKeyValidityTimeSetting, err := settingRepo.Get(settingRepo.WithByKey("ApiKeyValidityTime"))
|
||||
if err != nil {
|
||||
global.LOG.Errorf("load service api key validity time from setting failed, err: %v", err)
|
||||
}
|
||||
global.CONF.System.ApiKeyValidityTime = apiKeyValidityTimeSetting.Value
|
||||
}
|
||||
|
||||
if global.CONF.System.LicenseVerify == "" {
|
||||
licenseVerify, err := settingRepo.Get(settingRepo.WithByKey("LicenseVerify"))
|
||||
if err != nil {
|
||||
global.LOG.Errorf("load service license verify from setting failed, err: %v", err)
|
||||
}
|
||||
global.CONF.System.LicenseVerify = licenseVerify.Value
|
||||
}
|
||||
handleLicenseVerify(global.CONF.System.LicenseVerify, settingRepo)
|
||||
|
||||
handleUserInfo(global.CONF.System.ChangeUserInfo, settingRepo)
|
||||
|
||||
handleCronjobStatus()
|
||||
handleOllamaModelStatus()
|
||||
handleSnapStatus()
|
||||
loadLocalDir()
|
||||
initDir()
|
||||
@@ -145,6 +160,11 @@ func handleSnapStatus() {
|
||||
}
|
||||
}
|
||||
|
||||
func handleOllamaModelStatus() {
|
||||
message := "the task was interrupted due to the restart of the 1panel service"
|
||||
_ = global.DB.Model(&model.OllamaModel{}).Where("status = ?", constant.StatusWaiting).Updates(map[string]interface{}{"status": constant.StatusCanceled, "message": message}).Error
|
||||
}
|
||||
|
||||
func handleCronjobStatus() {
|
||||
var jobRecords []model.JobRecords
|
||||
_ = global.DB.Where("status = ?", constant.StatusWaiting).Find(&jobRecords).Error
|
||||
@@ -196,6 +216,12 @@ func loadLocalDir() {
|
||||
global.LOG.Errorf("error type dir: %T", varMap["dir"])
|
||||
}
|
||||
|
||||
func handleLicenseVerify(licenseVerify string, settingRepo repo.ISettingRepo) {
|
||||
if err := settingRepo.Update("LicenseVerify", licenseVerify); err != nil {
|
||||
global.LOG.Fatalf("init license verify before start failed, err: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func handleUserInfo(tags string, settingRepo repo.ISettingRepo) {
|
||||
if len(tags) == 0 {
|
||||
return
|
||||
|
||||
@@ -98,6 +98,14 @@ func Init() {
|
||||
|
||||
migrations.AddAutoRestart,
|
||||
migrations.AddApiInterfaceConfig,
|
||||
migrations.AddApiKeyValidityTime,
|
||||
|
||||
migrations.UpdateAppTag,
|
||||
migrations.UpdateApp,
|
||||
migrations.AddOllamaModel,
|
||||
migrations.AddAppMenu,
|
||||
migrations.AddAppPanelName,
|
||||
migrations.AddLicenseVerify,
|
||||
})
|
||||
if err := m.Migrate(); err != nil {
|
||||
global.LOG.Error(err)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user