Compare commits

...
Author SHA1 Message Date
zhengkunwang223 174d60e3d6 fix: 解决网站配置文件生成错误问题 2024-06-26 15:52:00 +08:00
ssongliu 88f19b792c fix: 解决依赖升级导致的引用问题 2024-06-25 15:45:43 +08:00
ssongliu 790e9252e7 fix: 增加系统主题变化监听事件 (#5555) 2024-06-25 14:43:42 +08:00
zhengkunwang223 3d8d18db4d feat: 优化应用升级逻辑,拉取镜像失败无需回滚 2024-06-25 14:13:08 +08:00
zhengkunwang223 297e630753 feat: 优化 WAF 配置文件生成 2024-06-24 14:54:17 +08:00
ssongliu 7583196c80 fix: 解决面板主题跟随系统失效的问题 (#5547)
Refs #5527
2024-06-24 14:44:50 +08:00
zhengkunwang a06e4060a2 feat: 优化文件上传逻辑,减少临时空间占用 (#5508)
Refs https://github.com/1Panel-dev/1Panel/issues/5184
2024-06-24 14:44:40 +08:00
ssongliu 60d484bce4 fix: 解决升级导致的计划任务未执行问题 (#5483)
Refs #5414
2024-06-24 14:42:25 +08:00
ssongliu ebc6a1bd6d fix: 解决界面设置主题色不统一的问题 (#5449) 2024-06-24 14:40:42 +08:00
zhengkunwang 9bcfce14cb feat: demo 环境适配网站监控 (#5446) 2024-06-24 14:39:20 +08:00
zhengkunwang dfd84d414e fix: 解决应用安装 services 为空报系统错误的问题 (#5445) 2024-06-24 14:39:16 +08:00
zhengkunwang 1b07314c23 feat: 优化非80端口网站开启 https 端口配置 (#5443)
Refs https://github.com/1Panel-dev/1Panel/issues/5364
2024-06-24 14:39:13 +08:00
ssongliu f7e2f2dbb8 fix: 修改终端全屏按钮样式 (#5442)
Refs #5435
2024-06-24 14:38:41 +08:00
ssongliu 1a617e71bd fix: 解决浏览器切换时部分设置未同步的问题 (#5436)
Refs #5422
2024-06-24 14:38:38 +08:00
zhengkunwang 794ebfab2b fix: 解决部分情况下打开文件中文乱码的问题 (#5425)
Refs https://github.com/1Panel-dev/1Panel/issues/5374
2024-06-24 14:37:43 +08:00
zhengkunwang d33b836d3e fix: 解决升级页面 链接点击不跳转的问题 (#5413)
Refs https://github.com/1Panel-dev/1Panel/issues/5371
2024-06-24 14:37:40 +08:00
ssongliu 408997e725 fix: 解决计划任务执行周期错误的问题 (#5412)
Refs #5404
2024-06-24 14:37:13 +08:00
Frost-ZX 3ca3949b1e fix: 修正未认证设置表单初始值 (#5383) 2024-06-24 14:37:01 +08:00
ssongliu 2e05af650a fix: 解决深色模式下版本显示问题 (#5402)
Refs #5370
2024-06-24 14:36:56 +08:00
26 changed files with 181 additions and 89 deletions
+6 -1
View File
@@ -593,6 +593,10 @@ func (b *BaseApi) Size(c *gin.Context) {
}
func mergeChunks(fileName string, fileDir string, dstDir string, chunkCount int, overwrite bool) error {
defer func() {
_ = os.RemoveAll(fileDir)
}()
op := files.NewFileOp()
dstDir = strings.TrimSpace(dstDir)
mode, _ := files.GetParentMode(dstDir)
@@ -629,9 +633,10 @@ func mergeChunks(fileName string, fileDir string, dstDir string, chunkCount int,
if err != nil {
return err
}
_ = os.Remove(chunkPath)
}
return files.NewFileOp().DeleteDir(fileDir)
return nil
}
// @Tags File
+7
View File
@@ -88,6 +88,12 @@ type AppInstalledDTO struct {
Path string `json:"path"`
}
type AppDetail struct {
Website string `json:"website"`
Document string `json:"document"`
Github string `json:"github"`
}
type AppInstallDTO struct {
ID uint `json:"id"`
Name string `json:"name"`
@@ -109,6 +115,7 @@ type AppInstallDTO struct {
AppStatus string `json:"appStatus"`
DockerCompose string `json:"dockerCompose"`
CreatedAt time.Time `json:"createdAt"`
App AppDetail `json:"app"`
}
type DatabaseConn struct {
+1 -1
View File
@@ -367,7 +367,7 @@ func (a AppService) Install(ctx context.Context, req request.AppInstallCreate) (
}
value, ok := composeMap["services"]
if !ok {
if !ok || value == nil {
err = buserr.New(constant.ErrFileParse)
return
}
+45 -33
View File
@@ -14,6 +14,7 @@ import (
"regexp"
"strconv"
"strings"
"time"
"github.com/docker/docker/api/types"
@@ -449,7 +450,7 @@ func getUpgradeCompose(install model.AppInstall, detail model.AppDetail) (string
return "", err
}
value, ok := composeMap["services"]
if !ok {
if !ok || value == nil {
return "", buserr.New(constant.ErrFileParse)
}
servicesMap := value.(map[string]interface{})
@@ -511,6 +512,7 @@ func upgradeInstall(req request.AppInstallUpgrade) error {
var (
upErr error
backupFile string
preErr error
)
global.LOG.Infof(i18n.GetMsgWithName("UpgradeAppStart", install.Name, nil))
if req.Backup {
@@ -543,18 +545,27 @@ func upgradeInstall(req request.AppInstallUpgrade) error {
_ = appInstallRepo.Save(context.Background(), &existInstall)
}
}
if preErr != nil {
global.LOG.Infof(i18n.GetMsgWithName("ErrAppUpgrade", install.Name, preErr))
existInstall, _ := appInstallRepo.GetFirst(commonRepo.WithByID(req.InstallID))
if existInstall.ID > 0 {
existInstall.Status = constant.UpgradeErr
existInstall.Message = preErr.Error()
_ = appInstallRepo.Save(context.Background(), &existInstall)
}
}
}()
fileOp := files.NewFileOp()
detailDir := path.Join(constant.ResourceDir, "apps", install.App.Resource, install.App.Key, detail.Version)
if install.App.Resource == constant.AppResourceRemote {
if upErr = downloadApp(install.App, detail, &install); upErr != nil {
if preErr = downloadApp(install.App, detail, &install); preErr != nil {
return
}
if detail.DockerCompose == "" {
composeDetail, err := fileOp.GetContent(path.Join(detailDir, "docker-compose.yml"))
if err != nil {
upErr = err
preErr = err
return
}
detail.DockerCompose = string(composeDetail)
@@ -569,6 +580,32 @@ func upgradeInstall(req request.AppInstallUpgrade) error {
detailDir = path.Join(constant.ResourceDir, "apps", "local", strings.TrimPrefix(install.App.Key, "local"), detail.Version)
}
content, err := fileOp.GetContent(install.GetEnvPath())
if err != nil {
preErr = err
return
}
if req.PullImage {
projectName := strings.ToLower(install.Name)
images, err := composeV2.GetDockerComposeImages(projectName, content, []byte(detail.DockerCompose))
if err != nil {
preErr = err
return
}
for _, image := range images {
global.LOG.Infof(i18n.GetMsgWithName("PullImageStart", image, nil))
if out, err := cmd.ExecWithTimeOut("docker pull "+image, 20*time.Minute); err != nil {
if out != "" {
err = errors.New(out)
}
preErr = buserr.WithNameAndErr("ErrDockerPullImage", "", err)
return
} else {
global.LOG.Infof(i18n.GetMsgByKey("PullImageSuccess"))
}
}
}
command := exec.Command("/bin/bash", "-c", fmt.Sprintf("cp -rn %s/* %s || true", detailDir, install.GetPath()))
stdout, _ := command.CombinedOutput()
if stdout != nil {
@@ -597,36 +634,6 @@ func upgradeInstall(req request.AppInstallUpgrade) error {
install.Version = detail.Version
install.AppDetailId = req.DetailID
content, err := fileOp.GetContent(install.GetEnvPath())
if err != nil {
upErr = err
return
}
if req.PullImage {
projectName := strings.ToLower(install.Name)
images, err := composeV2.GetDockerComposeImages(projectName, content, []byte(detail.DockerCompose))
if err != nil {
upErr = err
return
}
dockerCli, err := composeV2.NewClient()
if err != nil {
upErr = err
return
}
defer dockerCli.Close()
for _, image := range images {
global.LOG.Infof(i18n.GetMsgWithName("PullImageStart", image, nil))
if err = dockerCli.PullImage(image, true); err != nil {
upErr = buserr.WithNameAndErr("ErrDockerPullImage", "", err)
return
} else {
global.LOG.Infof(i18n.GetMsgByKey("PullImageSuccess"))
}
}
}
if out, err := compose.Down(install.GetComposePath()); err != nil {
if out != "" {
upErr = errors.New(out)
@@ -1255,6 +1262,11 @@ func handleInstalled(appInstallList []model.AppInstall, updated bool, sync bool)
AppType: installed.App.Type,
Path: installed.GetPath(),
CreatedAt: installed.CreatedAt,
App: response.AppDetail{
Github: installed.App.Github,
Website: installed.App.Website,
Document: installed.App.Document,
},
}
if updated {
installDTO.DockerCompose = installed.DockerCompose
+6 -6
View File
@@ -29,7 +29,7 @@ type ICronjobService interface {
UpdateStatus(id uint, status string) error
Delete(req dto.CronjobBatchDelete) error
Download(down dto.CronjobDownload) (string, error)
StartJob(cronjob *model.Cronjob) (string, error)
StartJob(cronjob *model.Cronjob, isUpdate bool) (string, error)
CleanRecord(req dto.CronjobClean) error
LoadRecordLog(req dto.OperateByID) string
@@ -181,7 +181,7 @@ func (u *CronjobService) Create(cronjobDto dto.CronjobCreate) error {
global.LOG.Infof("create cronjob %s successful, spec: %s", cronjob.Name, cronjob.Spec)
spec := cronjob.Spec
entryIDs, err := u.StartJob(&cronjob)
entryIDs, err := u.StartJob(&cronjob, false)
if err != nil {
return err
}
@@ -193,8 +193,8 @@ func (u *CronjobService) Create(cronjobDto dto.CronjobCreate) error {
return nil
}
func (u *CronjobService) StartJob(cronjob *model.Cronjob) (string, error) {
if len(cronjob.EntryIDs) != 0 {
func (u *CronjobService) StartJob(cronjob *model.Cronjob, isUpdate bool) (string, error) {
if len(cronjob.EntryIDs) != 0 && isUpdate {
ids := strings.Split(cronjob.EntryIDs, ",")
for _, id := range ids {
idItem, _ := strconv.Atoi(id)
@@ -251,7 +251,7 @@ func (u *CronjobService) Update(id uint, req dto.CronjobUpdate) error {
cronjob.Type = cronModel.Type
spec := cronjob.Spec
if cronModel.Status == constant.StatusEnable {
newEntryIDs, err := u.StartJob(&cronjob)
newEntryIDs, err := u.StartJob(&cronjob, true)
if err != nil {
return err
}
@@ -294,7 +294,7 @@ func (u *CronjobService) UpdateStatus(id uint, status string) error {
err error
)
if status == constant.StatusEnable {
entryIDs, err = u.StartJob(&cronjob)
entryIDs, err = u.StartJob(&cronjob, false)
if err != nil {
return err
}
+12 -11
View File
@@ -10,6 +10,7 @@ import (
"path/filepath"
"strings"
"time"
"unicode/utf8"
"github.com/1Panel-dev/1Panel/backend/app/dto/request"
"github.com/1Panel-dev/1Panel/backend/app/dto/response"
@@ -236,20 +237,20 @@ func (f *FileService) GetContent(op request.FileContentReq) (response.FileInfo,
}
content := []byte(info.Content)
var decodeName string
if len(content) > 1024 {
_, decodeName, _ = charset.DetermineEncoding(content[:1024], "")
} else {
_, decodeName, _ = charset.DetermineEncoding(content, "")
content = content[:1024]
}
if decodeName == "windows-1252" {
reader := strings.NewReader(info.Content)
item := transform.NewReader(reader, simplifiedchinese.GBK.NewDecoder())
contents, err := io.ReadAll(item)
if err != nil {
return response.FileInfo{}, err
if !utf8.Valid(content) {
_, decodeName, _ := charset.DetermineEncoding(content, "")
if decodeName == "windows-1252" {
reader := strings.NewReader(info.Content)
item := transform.NewReader(reader, simplifiedchinese.GBK.NewDecoder())
contents, err := io.ReadAll(item)
if err != nil {
return response.FileInfo{}, err
}
info.Content = string(contents)
}
info.Content = string(contents)
}
return response.FileInfo{FileInfo: *info}, nil
}
+2 -2
View File
@@ -526,7 +526,7 @@ func (w WebsiteService) CreateWebsiteDomain(create request.WebsiteDomainCreate)
for _, domain := range domainModels {
wafSite.Domains = append(wafSite.Domains, domain.Domain)
if domain.Port != 80 && domain.Port != 443 {
wafSite.Host = append(wafSite.Host, domain.Domain+":"+string(rune(domain.Port)))
wafSite.Host = append(wafSite.Host, domain.Domain+":"+strconv.Itoa(domain.Port))
}
}
if len(wafSite.Host) == 0 {
@@ -619,7 +619,7 @@ func (w WebsiteService) DeleteWebsiteDomain(domainId uint) error {
oldHostArray := wafSite.Host
var newHostArray []string
for _, host := range oldHostArray {
if host == webSiteDomain.Domain+":"+string(rune(webSiteDomain.Port)) {
if host == webSiteDomain.Domain+":"+strconv.Itoa(webSiteDomain.Port) {
continue
}
newHostArray = append(newHostArray, host)
+18 -6
View File
@@ -316,9 +316,7 @@ func createWafConfig(website *model.Website, domains []model.WebsiteDomain) erro
for _, domain := range domains {
wafWebsite.Domains = append(wafWebsite.Domains, domain.Domain)
if domain.Port != 80 && domain.Port != 443 {
wafWebsite.Host = append(wafWebsite.Host, domain.Domain+":"+string(rune(domain.Port)))
}
wafWebsite.Host = append(wafWebsite.Host, domain.Domain+":"+strconv.Itoa(domain.Port))
}
websitesArray = append(websitesArray, wafWebsite)
websitesContent, err := json.Marshal(websitesArray)
@@ -563,6 +561,16 @@ func applySSL(website model.Website, websiteSSL model.WebsiteSSL, req request.We
if err != nil {
return nil
}
domains, err := websiteDomainRepo.GetBy(websiteDomainRepo.WithWebsiteId(website.ID))
if err != nil {
return nil
}
noDefaultPort := true
for _, domain := range domains {
if domain.Port == 80 {
noDefaultPort = false
}
}
config := nginxFull.SiteConfig.Config
server := config.FindServers()[0]
@@ -582,13 +590,17 @@ func applySSL(website model.Website, websiteSSL model.WebsiteSSL, req request.We
server.RemoveListenByBind(httpPortIPV6)
server.RemoveDirective("if", []string{"($scheme"})
case constant.HTTPToHTTPS:
server.UpdateListen(httpPort, website.DefaultServer)
if !noDefaultPort {
server.UpdateListen(httpPort, website.DefaultServer)
}
if website.IPV6 {
server.UpdateListen(httpPortIPV6, website.DefaultServer)
}
server.AddHTTP2HTTPS()
case constant.HTTPAlso:
server.UpdateListen(httpPort, website.DefaultServer)
if !noDefaultPort {
server.UpdateListen(httpPort, website.DefaultServer)
}
server.RemoveDirective("if", []string{"($scheme"})
if website.IPV6 {
server.UpdateListen(httpPortIPV6, website.DefaultServer)
@@ -849,7 +861,7 @@ func changeServiceName(newComposeContent, newServiceName string) (composeByte []
return
}
value, ok := composeMap["services"]
if !ok {
if !ok || value == nil {
err = buserr.New(constant.ErrFileParse)
return
}
+1 -1
View File
@@ -71,7 +71,7 @@ func Run() {
global.LOG.Errorf("start my cronjob failed, err: %v", err)
}
for i := 0; i < len(cronJobs); i++ {
entryIDs, err := service.NewICronjobService().StartJob(&cronJobs[i])
entryIDs, err := service.NewICronjobService().StartJob(&cronJobs[i], false)
if err != nil {
global.LOG.Errorf("start %s job %s failed, err: %v", cronJobs[i].Type, cronJobs[i].Name, err)
}
+5
View File
@@ -30,6 +30,11 @@ var whiteUrlList = map[string]struct{}{
"/api/v1/waf/attack/stat": {},
"/api/v1/waf/config/website": {},
"/api/v1/monitor/stat": {},
"/api/v1/monitor/visitors": {},
"/api/v1/monitor/visitors/loc": {},
"/api/v1/monitor/qps": {},
}
func DemoHandle() gin.HandlerFunc {
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

+9
View File
@@ -0,0 +1,9 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
<path d="M11.1451 18.8875L5.66228 15.7224V8.40336L3.5376 7.1759V16.9488L9.02038 20.114L11.1451 18.8875Z" />
<path d="M18.3397 15.7224L12.0005 19.3819L9.87683 20.6083L12.0005 21.8348L20.4644 16.9488L18.3397 15.7224Z" />
<path d="M12.0015 4.74388L14.1252 3.5174L12.0005 2.28995L3.5376 7.17591L5.66228 8.40337L12.0005 4.74388H12.0015Z" />
<path d="M14.9816 4.01077L12.8569 5.23723L18.3397 8.40336V15.7224L20.4634 16.9488V7.1759L14.9816 4.01077Z" />
<path d="M11.9995 1.02569L21.5576 6.54428V17.5795L11.9995 23.0971L2.44343 17.5795V6.54428L11.9995 1.02569ZM11.9995 0.72728L2.18182 6.39707V17.7366L11.9995 23.4064L21.8182 17.7366V6.39707L11.9995 0.72728Z" />
<path d="M12.3079 6.78001L12.9564 7.16695V17.105L12.3079 17.48V6.78001Z" />
<path d="M12.3078 6.78001L9.10889 8.6222V9.86954H10.2359V16.2854L12.3059 17.481L12.3078 6.78001Z" />
</svg>

After

Width:  |  Height:  |  Size: 942 B

@@ -205,6 +205,7 @@ onMounted(() => {
font-size: 14px;
}
:deep(.default-theme h2) {
color: var(--dark-gold-base-color);
margin: 13px, 0;
padding: 0;
font-size: 16px;
+4 -2
View File
@@ -8,12 +8,14 @@ export const useTheme = () => {
body.setAttribute('class', 'dark-gold');
return;
}
let itemTheme = globalStore.themeConfig.theme;
if (globalStore.themeConfig.theme === 'auto') {
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)');
globalStore.themeConfig.theme = prefersDark.matches ? 'dark' : 'light';
itemTheme = prefersDark.matches ? 'dark' : 'light';
}
const body = document.documentElement as HTMLElement;
if (globalStore.themeConfig.theme === 'dark') body.setAttribute('class', 'dark');
if (itemTheme === 'dark') body.setAttribute('class', 'dark');
else body.setAttribute('class', '');
};
+4 -2
View File
@@ -1729,7 +1729,8 @@ const message = {
takeDown: 'TakeDown',
allReadyInstalled: 'Installed',
installHelper: 'Configuring image acceleration can solve the problem of image pull failure',
upgradeHelper: 'The abnormal application needs to be synchronized to the normal state first',
upgradeHelper:
'Abnormal applications need to be synchronized to normal status first. If the upgrade fails, please check the failure reason in the log audit-system log',
installWarn:
'Currently, if the port external access is not checked, it will not be able to access through the external network IP: port. Do you want to continue?',
showIgnore: 'View ignore application',
@@ -1737,7 +1738,8 @@ const message = {
ignoreList: 'ignore list',
appHelper: 'Please view the installation instructions of some applications on the application details page',
backupApp: 'Backup application before upgrade',
backupAppHelper: 'If the upgrade fails, you can use the application backup to roll back',
backupAppHelper:
'If the upgrade fails, the backup will be automatically rolled back. Please check the failure reason in the log audit-system log',
delete: 'Delete',
openrestyDeleteHelper:
'Forcibly deleting OpenResty will delete all websites, please confirm the risk before operation',
+7 -7
View File
@@ -827,12 +827,12 @@ const message = {
perMonth: '每月',
perWeek: '每周',
perHour: '每小時',
perNDay: '每隔 N 日',
perNDay: '每 N 日',
perDay: '每天',
perNHour: '每隔 N 時',
perNMinute: '每隔 N 分鐘',
perNSecond: '每隔 N 秒',
per: '每隔',
perNHour: '每 N 時',
perNMinute: '每 N 分鐘',
perNSecond: '每 N 秒',
per: '每',
handle: '執行',
day: '日',
monday: '周一',
@@ -1610,14 +1610,14 @@ const message = {
takeDown: '已廢棄',
allReadyInstalled: '已安裝',
installHelper: '配置鏡像加速可以解決鏡像拉取失敗的問題',
upgradeHelper: '異常應用需要先同步到正常狀態',
upgradeHelper: '異常應用程式需要先同步到正常狀態,升級失敗請在日誌審計-系統日誌中查看失敗原因',
installWarn: '當前未勾選端口外部訪問,將無法通過外網IP:端口訪問,是否繼續? ',
showIgnore: '查看忽略應用',
cancelIgnore: '取消忽略',
ignoreList: '忽略列表',
appHelper: '部分應用的安裝使用說明請在應用詳情頁查看',
backupApp: '升級前備份應用',
backupAppHelper: '升級失敗可以使用應用備份回滾',
backupAppHelper: '升級失敗會使用備份自動回滾,請在日誌審計-系統日誌中查看失敗原因',
delete: '刪除',
openrestyDeleteHelper: '強制刪除 OpenResty 會刪除所有的網站,請確認風險後操作',
downloadLogHelper1: '即將下載 {0} 套用所有日誌,是否繼續? ',
+7 -7
View File
@@ -828,12 +828,12 @@ const message = {
perMonth: '每月',
perWeek: '每周',
perHour: '每小时',
perNDay: '每隔 N 日',
perNDay: '每 N 日',
perDay: '每天',
perNHour: '每隔 N 时',
perNMinute: '每隔 N 分钟',
perNSecond: '每隔 N 秒',
per: '每隔',
perNHour: '每 N 时',
perNMinute: '每 N 分钟',
perNSecond: '每 N 秒',
per: '每',
handle: '执行',
day: '日',
monday: '周一',
@@ -1610,14 +1610,14 @@ const message = {
takeDown: '已废弃',
allReadyInstalled: '已安装',
installHelper: '配置镜像加速可以解决镜像拉取失败的问题',
upgradeHelper: '异常应用需要先同步到正常状态',
upgradeHelper: '异常应用需要先同步到正常状态,升级失败请在日志审计-系统日志中查看失败原因',
installWarn: '当前未勾选端口外部访问,将无法通过外网IP:端口访问,是否继续?',
showIgnore: '查看忽略应用',
cancelIgnore: '取消忽略',
ignoreList: '忽略列表',
appHelper: '部分应用的安装使用说明请在应用详情页查看',
backupApp: '升级前备份应用',
backupAppHelper: '升级失败可以使用应用备份回滚',
backupAppHelper: '升级失败会使用备份自动回滚,请在日志审计-系统日志中查看失败原因',
delete: '删除',
openrestyDeleteHelper: '强制删除 OpenResty 会删除所有的网站,请确认风险之后操作',
downloadLogHelper1: '即将下载 {0} 应用所有日志,是否继续?',
+13
View File
@@ -23,6 +23,8 @@ import { DeviceType } from '@/enums/app';
import { getSystemAvailable } from '@/api/modules/setting';
import { useRoute, useRouter } from 'vue-router';
import { loadProductProFromDB } from '@/utils/xpack';
import { useTheme } from '@/hooks/use-theme';
const { switchTheme } = useTheme();
useResize();
const router = useRouter();
@@ -98,6 +100,17 @@ onMounted(() => {
loadStatus();
loadProductProFromDB();
const mqList = window.matchMedia('(prefers-color-scheme: dark)');
if (mqList.addEventListener) {
mqList.addEventListener('change', () => {
switchTheme();
});
} else if (mqList.addListener) {
mqList.addListener(() => {
switchTheme();
});
}
});
</script>
+4 -1
View File
@@ -43,7 +43,10 @@ const GlobalStore = defineStore({
errStatus: '',
}),
getters: {
isDarkTheme: (state) => state.themeConfig.theme === 'dark' || state.themeConfig.isGold,
isDarkTheme: (state) =>
state.themeConfig.theme === 'dark' ||
state.themeConfig.isGold ||
(state.themeConfig.theme === 'auto' && window.matchMedia('(prefers-color-scheme: dark)').matches),
isDarkGoldTheme: (state) => state.themeConfig.isGold && state.isProductPro,
},
actions: {
+1
View File
@@ -1,5 +1,6 @@
html.dark {
--el-box-shadow-light: 0px 0px 4px rgba(0, 0, 0, 0.1) !important;
--dark-gold-base-color: #5a5a5a;
--el-border-color-lighter: #1d2023;
--el-fill-color-blank: #111417;
--el-bg-color: rgba(0, 11, 21, 1);
+18 -2
View File
@@ -1,4 +1,4 @@
import { getLicenseStatus } from '@/api/modules/setting';
import { getLicenseStatus, getSettingInfo } from '@/api/modules/setting';
import { useTheme } from '@/hooks/use-theme';
import { GlobalStore } from '@/store';
const globalStore = GlobalStore();
@@ -18,7 +18,12 @@ export function initFavicon() {
const link = (document.querySelector("link[rel*='icon']") || document.createElement('link')) as HTMLLinkElement;
link.type = 'image/x-icon';
link.rel = 'shortcut icon';
link.href = favicon ? '/api/v1/images/favicon' : '/public/favicon.png';
if (globalStore.isDarkGoldTheme) {
let goldLink = new URL(`../assets/images/favicon-gold.png`, import.meta.url).href;
link.href = favicon ? '/api/v1/images/favicon' : goldLink;
} else {
link.href = favicon ? '/api/v1/images/favicon' : '/public/favicon.png';
}
document.getElementsByTagName('head')[0].appendChild(link);
}
@@ -27,12 +32,22 @@ export async function getXpackSetting() {
const module = await searchXSettingGlob?.['../xpack/api/modules/setting.ts']?.();
const res = await module?.searchXSetting();
if (!res) {
initFavicon();
resetXSetting();
return;
}
initFavicon();
return res;
}
const loadDataFromDB = async () => {
const res = await getSettingInfo();
document.title = res.data.panelName;
globalStore.entrance = res.data.securityEntrance;
globalStore.setDefaultNetwork(res.data.defaultNetwork);
globalStore.setOpenMenuTabs(res.data.menuTabs === 'enable');
};
export async function loadProductProFromDB() {
const res = await getLicenseStatus();
if (!res.data) {
@@ -48,6 +63,7 @@ export async function loadProductProFromDB() {
}
switchTheme();
initFavicon();
loadDataFromDB();
}
export async function getXpackSettingForTheme() {
@@ -53,7 +53,9 @@
</el-form-item>
<el-form-item prop="backup" v-if="operateReq.operate === 'upgrade'">
<el-checkbox v-model="operateReq.backup" :label="$t('app.backupApp')" />
<span class="input-help">{{ $t('app.backupAppHelper') }}</span>
<span class="input-help">
<el-text type="warning">{{ $t('app.backupAppHelper') }}</el-text>
</span>
</el-form-item>
<el-form-item pro="pullImage" v-if="operateReq.operate === 'upgrade'">
<el-checkbox v-model="operateReq.pullImage" :label="$t('container.forcePull')" size="large" />
+2 -4
View File
@@ -92,12 +92,10 @@ export function transObjToSpec(specType: string, week, day, hour, minute, second
case 'perWeek':
return `${minute} ${hour} * * ${week}`;
case 'perNDay':
day = Number(day) + 1 + '';
return `${minute} ${hour} */${day} * *`;
case 'perDay':
return `${minute} ${hour} * * *`;
case 'perNHour':
hour = Number(hour) + 1 + '';
return `${minute} */${hour} * * *`;
case 'perHour':
return `${minute} * * * *`;
@@ -141,13 +139,13 @@ export function transSpecToObj(spec: string) {
}
if (specs[1].indexOf('*/') !== -1) {
specItem.specType = 'perNHour';
specItem.hour = Number(specs[1].replaceAll('*/', '')) - 1;
specItem.hour = Number(specs[1].replaceAll('*/', ''));
return specItem;
}
specItem.hour = Number(specs[1]);
if (specs[2].indexOf('*/') !== -1) {
specItem.specType = 'perNDay';
specItem.day = Number(specs[2].replaceAll('*/', '')) - 1;
specItem.day = Number(specs[2].replaceAll('*/', ''));
return specItem;
}
if (specs[2] !== '*') {
@@ -448,7 +448,7 @@ onMounted(() => {
font-weight: 600;
}
.fullScreen {
background-color: #efefef;
background-color: transparent;
border: none;
position: absolute;
right: 50px;
@@ -361,6 +361,7 @@ const loadDataFromDB = async () => {
i18n.locale.value = res.data.language;
i18n.warnHtmlMessage = false;
globalStore.entrance = res.data.securityEntrance;
globalStore.setDefaultNetwork(res.data.defaultNetwork);
globalStore.setOpenMenuTabs(res.data.menuTabs === 'enable');
globalStore.updateLanguage(res.data.language);
globalStore.setThemeConfig({ ...themeConfig.value, theme: res.data.theme, panelName: res.data.panelName });
+3 -1
View File
@@ -224,6 +224,7 @@ const form = reactive({
allowIPs: '',
bindDomain: '',
noAuthSetting: '200 - ' + i18n.global.t('setting.help200'),
noAuthSettingValue: '200',
});
const unset = ref(i18n.global.t('setting.unSetting'));
@@ -246,6 +247,7 @@ const search = async () => {
form.mfaInterval = Number(res.data.mfaInterval);
form.allowIPs = res.data.allowIPs.replaceAll(',', '\n');
form.bindDomain = res.data.bindDomain;
form.noAuthSettingValue = res.data.noAuthSetting;
if (res.data.noAuthSetting !== '200') {
form.noAuthSetting = res.data.noAuthSetting + ' - ' + i18n.global.t('setting.error' + res.data.noAuthSetting);
} else {
@@ -297,7 +299,7 @@ const onChangeBind = () => {
bindRef.value.acceptParams({ ipv6: form.ipv6, bindAddress: form.bindAddress });
};
const onChangeResponse = () => {
responseRef.value.acceptParams({ noAuthSetting: form.noAuthSetting });
responseRef.value.acceptParams({ noAuthSetting: form.noAuthSettingValue });
};
const onChangeBindDomain = () => {
domainRef.value.acceptParams({ bindDomain: form.bindDomain });