mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2026-10-09 08:00:27 +00:00
Compare commits
14
Commits
v2.2.3
...
v1.10.6-lts
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1c826525e3 | ||
|
|
3f0fd48cf3 | ||
|
|
211dbfdead | ||
|
|
aafec142cc | ||
|
|
384ff57df7 | ||
|
|
01ddd203ea | ||
|
|
29aed616ac | ||
|
|
83f0df9d84 | ||
|
|
7aa16c8142 | ||
|
|
3bd505954f | ||
|
|
275c0522a3 | ||
|
|
85dec6815b | ||
|
|
5e4e9f762e | ||
|
|
7ae3722997 |
@@ -61,7 +61,7 @@ func (b *BaseApi) LoadDaemonJson(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /containers/daemonjson/update [post]
|
||||
// @x-panel-log {"bodyKeys":["key", "value"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新 docker daemon.json 配置 [key]=>[value]","formatEN":"Updated the docker daemon.json configuration [key]=>[value]"}
|
||||
// @x-panel-log {"bodyKeys":["key", "value"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新配置 [key]","formatEN":"Updated configuration [key]"}
|
||||
func (b *BaseApi) UpdateDaemonJson(c *gin.Context) {
|
||||
var req dto.SettingUpdate
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
@@ -84,7 +84,7 @@ func (b *BaseApi) UpdateDaemonJson(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /containers/logoption/update [post]
|
||||
// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新 docker daemon.json 日志配置","formatEN":"Updated the docker daemon.json log option"}
|
||||
// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新日志配置","formatEN":"Updated the log option"}
|
||||
func (b *BaseApi) UpdateLogOption(c *gin.Context) {
|
||||
var req dto.LogOption
|
||||
if err := helper.CheckBind(&req, c); err != nil {
|
||||
@@ -107,7 +107,7 @@ func (b *BaseApi) UpdateLogOption(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /containers/ipv6option/update [post]
|
||||
// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新 docker daemon.json ipv6 配置","formatEN":"Updated the docker daemon.json ipv6 option"}
|
||||
// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新 ipv6 配置","formatEN":"Updated the ipv6 option"}
|
||||
func (b *BaseApi) UpdateIpv6Option(c *gin.Context) {
|
||||
var req dto.Ipv6Option
|
||||
if err := helper.CheckBind(&req, c); err != nil {
|
||||
@@ -130,7 +130,7 @@ func (b *BaseApi) UpdateIpv6Option(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /containers/daemonjson/update/byfile [post]
|
||||
// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新 docker daemon.json 配置","formatEN":"Updated the docker daemon.json configuration"}
|
||||
// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新配置文件","formatEN":"Updated configuration file"}
|
||||
func (b *BaseApi) UpdateDaemonJsonByFile(c *gin.Context) {
|
||||
var req dto.DaemonJsonUpdateByFile
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
|
||||
@@ -6,6 +6,7 @@ type SearchCommandWithPage struct {
|
||||
Order string `json:"order"`
|
||||
GroupID uint `json:"groupID"`
|
||||
Info string `json:"info"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
type CommandOperate struct {
|
||||
|
||||
@@ -178,7 +178,7 @@ type WebsiteProxyConfig struct {
|
||||
CacheTime int `json:"cacheTime" `
|
||||
CacheUnit string `json:"cacheUnit"`
|
||||
Name string `json:"name" validate:"required"`
|
||||
Modifier string `json:"modifier" validate:"required"`
|
||||
Modifier string `json:"modifier"`
|
||||
Match string `json:"match" validate:"required"`
|
||||
ProxyPass string `json:"proxyPass" validate:"required"`
|
||||
ProxyHost string `json:"proxyHost" validate:"required"`
|
||||
|
||||
@@ -16,6 +16,7 @@ type ICommandRepo interface {
|
||||
Update(id uint, vars map[string]interface{}) error
|
||||
Delete(opts ...DBOption) error
|
||||
Get(opts ...DBOption) (model.Command, error)
|
||||
WithLikeName(name string) DBOption
|
||||
}
|
||||
|
||||
func NewICommandRepo() ICommandRepo {
|
||||
@@ -79,3 +80,12 @@ func (u *CommandRepo) Delete(opts ...DBOption) error {
|
||||
}
|
||||
return db.Delete(&model.Command{}).Error
|
||||
}
|
||||
|
||||
func (a CommandRepo) WithLikeName(name string) DBOption {
|
||||
return func(g *gorm.DB) *gorm.DB {
|
||||
if len(name) == 0 {
|
||||
return g
|
||||
}
|
||||
return g.Where("name like ? or command like ?", "%"+name+"%", "%"+name+"%")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,7 +65,7 @@ func (u *CommandService) SearchForTree() ([]dto.CommandTree, error) {
|
||||
}
|
||||
|
||||
func (u *CommandService) SearchWithPage(search dto.SearchCommandWithPage) (int64, interface{}, error) {
|
||||
total, commands, err := commandRepo.Page(search.Page, search.PageSize, commonRepo.WithLikeName(search.Info), commonRepo.WithByGroupID(search.GroupID), commonRepo.WithOrderRuleBy(search.OrderBy, search.Order))
|
||||
total, commands, err := commandRepo.Page(search.Page, search.PageSize, commandRepo.WithLikeName(search.Name), commonRepo.WithLikeName(search.Info), commonRepo.WithByGroupID(search.GroupID), commonRepo.WithOrderRuleBy(search.OrderBy, search.Order))
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@ package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
@@ -276,21 +275,6 @@ func loadClientMap(backupAccounts string) (map[string]cronjobUploadHelper, error
|
||||
if account.BackupPath != "/" {
|
||||
pathItem = strings.TrimPrefix(account.BackupPath, "/")
|
||||
}
|
||||
if target == constant.Local {
|
||||
varMap := make(map[string]interface{})
|
||||
if err := json.Unmarshal([]byte(account.Vars), &varMap); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if _, ok := varMap["dir"]; !ok {
|
||||
return nil, errors.New("load local backup dir failed")
|
||||
}
|
||||
baseDir, ok := varMap["dir"].(string)
|
||||
if ok {
|
||||
pathItem = baseDir
|
||||
} else {
|
||||
return nil, fmt.Errorf("error type dir: %T", varMap["dir"])
|
||||
}
|
||||
}
|
||||
clients[target] = cronjobUploadHelper{
|
||||
client: client,
|
||||
backupPath: pathItem,
|
||||
|
||||
@@ -288,6 +288,10 @@ func createWafConfig(website *model.Website, domains []model.WebsiteDomain) erro
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !common.CompareVersion(nginxInstall.Version, "1.21.4.3-2-0") {
|
||||
return nil
|
||||
}
|
||||
wafDataPath := path.Join(nginxInstall.GetPath(), "1pwaf", "data")
|
||||
fileOp := files.NewFileOp()
|
||||
if !fileOp.Stat(wafDataPath) {
|
||||
@@ -419,6 +423,9 @@ func delWafConfig(website model.Website, force bool) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !common.CompareVersion(nginxInstall.Version, "1.21.4.3-2-0") {
|
||||
return nil
|
||||
}
|
||||
wafDataPath := path.Join(nginxInstall.GetPath(), "1pwaf", "data")
|
||||
fileOp := files.NewFileOp()
|
||||
if !fileOp.Stat(wafDataPath) {
|
||||
|
||||
@@ -54,7 +54,7 @@ func (c localClient) Upload(src, target string) (bool, error) {
|
||||
}
|
||||
}
|
||||
|
||||
if err := common.CopyFile(src, target); err != nil {
|
||||
if err := common.CopyFile(src, targetFilePath); err != nil {
|
||||
return false, fmt.Errorf("cp file failed, err: %v", err)
|
||||
}
|
||||
return true, nil
|
||||
|
||||
@@ -314,6 +314,7 @@ func (f FileOp) DownloadFile(url, dst string) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
out, err := os.Create(dst)
|
||||
if err != nil {
|
||||
@@ -324,8 +325,6 @@ func (f FileOp) DownloadFile(url, dst string) error {
|
||||
if _, err = io.Copy(out, resp.Body); err != nil {
|
||||
return fmt.Errorf("save download file [%s] error, err %s", dst, err.Error())
|
||||
}
|
||||
out.Close()
|
||||
resp.Body.Close()
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@ package files
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"github.com/spf13/afero"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
@@ -12,6 +11,8 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/spf13/afero"
|
||||
)
|
||||
|
||||
func IsSymlink(mode os.FileMode) bool {
|
||||
@@ -144,8 +145,5 @@ func GetParentMode(path string) (os.FileMode, error) {
|
||||
}
|
||||
|
||||
func IsInvalidChar(name string) bool {
|
||||
if strings.Contains(name, "&") {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
return strings.Contains(name, "&")
|
||||
}
|
||||
|
||||
@@ -1444,8 +1444,8 @@ const docTemplate = `{
|
||||
"key",
|
||||
"value"
|
||||
],
|
||||
"formatEN": "Updated the docker daemon.json configuration [key]=\u003e[value]",
|
||||
"formatZH": "更新 docker daemon.json 配置 [key]=\u003e[value]",
|
||||
"formatEN": "Updated configuration [key]",
|
||||
"formatZH": "更新配置 [key]",
|
||||
"paramKeys": []
|
||||
}
|
||||
}
|
||||
@@ -1484,8 +1484,8 @@ const docTemplate = `{
|
||||
"x-panel-log": {
|
||||
"BeforeFunctions": [],
|
||||
"bodyKeys": [],
|
||||
"formatEN": "Updated the docker daemon.json configuration",
|
||||
"formatZH": "更新 docker daemon.json 配置",
|
||||
"formatEN": "Updated configuration file",
|
||||
"formatZH": "更新配置文件",
|
||||
"paramKeys": []
|
||||
}
|
||||
}
|
||||
@@ -2094,8 +2094,8 @@ const docTemplate = `{
|
||||
"x-panel-log": {
|
||||
"BeforeFunctions": [],
|
||||
"bodyKeys": [],
|
||||
"formatEN": "Updated the docker daemon.json ipv6 option",
|
||||
"formatZH": "更新 docker daemon.json ipv6 配置",
|
||||
"formatEN": "Updated the ipv6 option",
|
||||
"formatZH": "更新 ipv6 配置",
|
||||
"paramKeys": []
|
||||
}
|
||||
}
|
||||
@@ -2233,8 +2233,8 @@ const docTemplate = `{
|
||||
"x-panel-log": {
|
||||
"BeforeFunctions": [],
|
||||
"bodyKeys": [],
|
||||
"formatEN": "Updated the docker daemon.json log option",
|
||||
"formatZH": "更新 docker daemon.json 日志配置",
|
||||
"formatEN": "Updated the log option",
|
||||
"formatZH": "更新日志配置",
|
||||
"paramKeys": []
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1437,8 +1437,8 @@
|
||||
"key",
|
||||
"value"
|
||||
],
|
||||
"formatEN": "Updated the docker daemon.json configuration [key]=\u003e[value]",
|
||||
"formatZH": "更新 docker daemon.json 配置 [key]=\u003e[value]",
|
||||
"formatEN": "Updated configuration [key]",
|
||||
"formatZH": "更新配置 [key]",
|
||||
"paramKeys": []
|
||||
}
|
||||
}
|
||||
@@ -1477,8 +1477,8 @@
|
||||
"x-panel-log": {
|
||||
"BeforeFunctions": [],
|
||||
"bodyKeys": [],
|
||||
"formatEN": "Updated the docker daemon.json configuration",
|
||||
"formatZH": "更新 docker daemon.json 配置",
|
||||
"formatEN": "Updated configuration file",
|
||||
"formatZH": "更新配置文件",
|
||||
"paramKeys": []
|
||||
}
|
||||
}
|
||||
@@ -2087,8 +2087,8 @@
|
||||
"x-panel-log": {
|
||||
"BeforeFunctions": [],
|
||||
"bodyKeys": [],
|
||||
"formatEN": "Updated the docker daemon.json ipv6 option",
|
||||
"formatZH": "更新 docker daemon.json ipv6 配置",
|
||||
"formatEN": "Updated the ipv6 option",
|
||||
"formatZH": "更新 ipv6 配置",
|
||||
"paramKeys": []
|
||||
}
|
||||
}
|
||||
@@ -2226,8 +2226,8 @@
|
||||
"x-panel-log": {
|
||||
"BeforeFunctions": [],
|
||||
"bodyKeys": [],
|
||||
"formatEN": "Updated the docker daemon.json log option",
|
||||
"formatZH": "更新 docker daemon.json 日志配置",
|
||||
"formatEN": "Updated the log option",
|
||||
"formatZH": "更新日志配置",
|
||||
"paramKeys": []
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5938,8 +5938,8 @@ paths:
|
||||
bodyKeys:
|
||||
- key
|
||||
- value
|
||||
formatEN: Updated the docker daemon.json configuration [key]=>[value]
|
||||
formatZH: 更新 docker daemon.json 配置 [key]=>[value]
|
||||
formatEN: Updated configuration [key]
|
||||
formatZH: 更新配置 [key]
|
||||
paramKeys: []
|
||||
/containers/daemonjson/update/byfile:
|
||||
post:
|
||||
@@ -5964,8 +5964,8 @@ paths:
|
||||
x-panel-log:
|
||||
BeforeFunctions: []
|
||||
bodyKeys: []
|
||||
formatEN: Updated the docker daemon.json configuration
|
||||
formatZH: 更新 docker daemon.json 配置
|
||||
formatEN: Updated configuration file
|
||||
formatZH: 更新配置文件
|
||||
paramKeys: []
|
||||
/containers/docker/operate:
|
||||
post:
|
||||
@@ -6353,8 +6353,8 @@ paths:
|
||||
x-panel-log:
|
||||
BeforeFunctions: []
|
||||
bodyKeys: []
|
||||
formatEN: Updated the docker daemon.json ipv6 option
|
||||
formatZH: 更新 docker daemon.json ipv6 配置
|
||||
formatEN: Updated the ipv6 option
|
||||
formatZH: 更新 ipv6 配置
|
||||
paramKeys: []
|
||||
/containers/limit:
|
||||
get:
|
||||
@@ -6438,8 +6438,8 @@ paths:
|
||||
x-panel-log:
|
||||
BeforeFunctions: []
|
||||
bodyKeys: []
|
||||
formatEN: Updated the docker daemon.json log option
|
||||
formatZH: 更新 docker daemon.json 日志配置
|
||||
formatEN: Updated the log option
|
||||
formatZH: 更新日志配置
|
||||
paramKeys: []
|
||||
/containers/network:
|
||||
get:
|
||||
|
||||
@@ -24,6 +24,7 @@ export interface SearchWithPage {
|
||||
pageSize: number;
|
||||
orderBy?: string;
|
||||
order?: string;
|
||||
name?: string;
|
||||
}
|
||||
export interface CommonModel {
|
||||
id: number;
|
||||
|
||||
@@ -139,6 +139,7 @@ export namespace Setting {
|
||||
upload: string;
|
||||
}
|
||||
export interface UpgradeInfo {
|
||||
testVersion: string;
|
||||
newVersion: string;
|
||||
latestVersion: string;
|
||||
releaseNote: string;
|
||||
|
||||
+34
-1643
File diff suppressed because it is too large
Load Diff
@@ -83,7 +83,8 @@ const seriesStyle = [
|
||||
|
||||
function initChart() {
|
||||
let itemChart = echarts?.getInstanceByDom(document.getElementById(props.id) as HTMLElement);
|
||||
// 如果不存在,就进行初始化
|
||||
const optionItem = itemChart?.getOption();
|
||||
const itemSelect = optionItem?.legend;
|
||||
if (itemChart == null) {
|
||||
itemChart = echarts.init(document.getElementById(props.id) as HTMLElement);
|
||||
}
|
||||
@@ -109,10 +110,9 @@ function initChart() {
|
||||
yAxis.push({
|
||||
splitLine: {
|
||||
show: true,
|
||||
//分隔辅助线
|
||||
lineStyle: {
|
||||
type: 'dashed', //线的类型 虚线0
|
||||
opacity: theme === 'dark' ? 0.1 : 1, //透明度
|
||||
type: 'dashed',
|
||||
opacity: theme === 'dark' ? 0.1 : 1,
|
||||
},
|
||||
},
|
||||
...item,
|
||||
@@ -120,7 +120,6 @@ function initChart() {
|
||||
});
|
||||
}
|
||||
|
||||
// 把配置和数据放这里
|
||||
const option = {
|
||||
title: [
|
||||
{
|
||||
@@ -168,7 +167,7 @@ function initChart() {
|
||||
},
|
||||
},
|
||||
grid: props.option.grid || { left: '7%', right: '7%', bottom: '20%' },
|
||||
legend: {
|
||||
legend: itemSelect || {
|
||||
right: 10,
|
||||
itemWidth: 8,
|
||||
textStyle: {
|
||||
|
||||
@@ -58,6 +58,8 @@ const message = {
|
||||
fullscreen: 'Fullscreen',
|
||||
quitFullscreen: 'Quit Fullscreen',
|
||||
update: 'Edit',
|
||||
showAll: 'Show All',
|
||||
hideSome: 'Hide Some',
|
||||
},
|
||||
search: {
|
||||
timeStart: 'Time start',
|
||||
@@ -1934,6 +1936,9 @@ const message = {
|
||||
acmeAccountType: 'Account Type',
|
||||
keyType: 'Key algorithm',
|
||||
tencentCloud: 'Tencent Cloud',
|
||||
containWarn: 'The domain name contains the main domain, please re-enter',
|
||||
rewriteHelper2:
|
||||
'Applications such as WordPress installed from the app store have pseudo-static configuration by default. Repeated configuration may result in errors',
|
||||
},
|
||||
php: {
|
||||
short_open_tag: 'Short tag support',
|
||||
|
||||
@@ -58,6 +58,8 @@ const message = {
|
||||
fullscreen: '全屏',
|
||||
quitFullscreen: '退出全屏',
|
||||
update: '編輯',
|
||||
showAll: '顯示所有',
|
||||
hideSome: '隱藏部分',
|
||||
},
|
||||
search: {
|
||||
timeStart: '開始時間',
|
||||
@@ -1810,6 +1812,8 @@ const message = {
|
||||
acmeAccountType: '賬號類型',
|
||||
keyType: '密鑰演算法',
|
||||
tencentCloud: '騰訊雲',
|
||||
containWarn: '其他域名中包含主域名,请重新輸入',
|
||||
rewriteHelper2: '從應用程式商店安裝的 WordPress 等應用,預設已經配置好偽靜態,重複配置可能會報錯',
|
||||
},
|
||||
php: {
|
||||
short_open_tag: '短標簽支持',
|
||||
|
||||
@@ -58,6 +58,8 @@ const message = {
|
||||
fullscreen: '全屏',
|
||||
quitFullscreen: '退出全屏',
|
||||
update: '编辑',
|
||||
showAll: '显示所有',
|
||||
hideSome: '隐藏部分',
|
||||
},
|
||||
search: {
|
||||
timeStart: '开始时间',
|
||||
@@ -1810,6 +1812,8 @@ const message = {
|
||||
acmeAccountType: '账号类型',
|
||||
keyType: '密钥算法',
|
||||
tencentCloud: '腾讯云',
|
||||
containWarn: '其他域名中包含主域名,请重新输入',
|
||||
rewriteHelper2: '从应用商店安装的 WordPress 等应用,默认已经配置好伪静态,重复配置可能会报错',
|
||||
},
|
||||
php: {
|
||||
short_open_tag: '短标签支持',
|
||||
|
||||
@@ -518,3 +518,14 @@ export function getAction(action: string) {
|
||||
export function getLanguage() {
|
||||
return localStorage.getItem('lang') || 'zh';
|
||||
}
|
||||
|
||||
export function emptyLineFilter(str: string, spilt: string) {
|
||||
let list = str.split(spilt);
|
||||
let results = [];
|
||||
for (let i = 0; i < list.length; i++) {
|
||||
if (list[i].trim() !== '') {
|
||||
results.push(list[i]);
|
||||
}
|
||||
}
|
||||
return results.join(spilt);
|
||||
}
|
||||
|
||||
@@ -46,6 +46,7 @@ import ConfirmDialog from '@/components/confirm-dialog/index.vue';
|
||||
import { updateDaemonJson } from '@/api/modules/container';
|
||||
import DrawerHeader from '@/components/drawer-header/index.vue';
|
||||
import { FormInstance } from 'element-plus';
|
||||
import { emptyLineFilter } from '@/utils/util';
|
||||
|
||||
const emit = defineEmits<{ (e: 'search'): void }>();
|
||||
|
||||
@@ -101,7 +102,7 @@ const onSave = async (formEl: FormInstance | undefined) => {
|
||||
|
||||
const onSubmit = async () => {
|
||||
loading.value = true;
|
||||
await updateDaemonJson('Mirrors', form.mirrors.replaceAll('\n', ','))
|
||||
await updateDaemonJson('Mirrors', emptyLineFilter(form.mirrors, '\n').replaceAll('\n', ','))
|
||||
.then(() => {
|
||||
loading.value = false;
|
||||
emit('search');
|
||||
|
||||
@@ -46,6 +46,7 @@ import ConfirmDialog from '@/components/confirm-dialog/index.vue';
|
||||
import { updateDaemonJson } from '@/api/modules/container';
|
||||
import DrawerHeader from '@/components/drawer-header/index.vue';
|
||||
import { FormInstance } from 'element-plus';
|
||||
import { emptyLineFilter } from '@/utils/util';
|
||||
|
||||
const emit = defineEmits<{ (e: 'search'): void }>();
|
||||
|
||||
@@ -97,7 +98,7 @@ const onSave = async () => {
|
||||
|
||||
const onSubmit = async () => {
|
||||
loading.value = true;
|
||||
await updateDaemonJson('Registries', form.registries.replaceAll('\n', ','))
|
||||
await updateDaemonJson('Registries', emptyLineFilter(form.registries, '\n').replaceAll('\n', ','))
|
||||
.then(() => {
|
||||
loading.value = false;
|
||||
handleClose();
|
||||
|
||||
@@ -1,12 +1,7 @@
|
||||
<template>
|
||||
<el-row :gutter="10">
|
||||
<el-col :xs="12" :sm="12" :md="6" :lg="6" :xl="6" align="center">
|
||||
<el-popover
|
||||
placement="bottom"
|
||||
:width="currentInfo.cpuPercent.length < 36 ? 300 : (currentInfo.cpuPercent.length / 12) * 150"
|
||||
trigger="hover"
|
||||
v-if="chartsOption['cpu']"
|
||||
>
|
||||
<el-popover placement="bottom" :width="loadWidth()" trigger="hover" v-if="chartsOption['cpu']">
|
||||
<div>
|
||||
<el-tooltip
|
||||
effect="dark"
|
||||
@@ -14,7 +9,7 @@
|
||||
v-if="baseInfo.cpuModelName.length > 40"
|
||||
placement="top"
|
||||
>
|
||||
<el-tag>
|
||||
<el-tag class="cpuModeTag">
|
||||
{{ baseInfo.cpuModelName.substring(0, 40) + '...' }}
|
||||
</el-tag>
|
||||
</el-tooltip>
|
||||
@@ -22,14 +17,24 @@
|
||||
{{ baseInfo.cpuModelName }}
|
||||
</el-tag>
|
||||
</div>
|
||||
<el-tag class="tagClass">
|
||||
{{ $t('home.core') }} *{{ baseInfo.cpuCores }} {{ $t('home.logicCore') }} *{{
|
||||
baseInfo.cpuLogicalCores
|
||||
}}
|
||||
</el-tag>
|
||||
<el-tag class="cpuDetailTag">{{ $t('home.core') }} *{{ baseInfo.cpuCores }}</el-tag>
|
||||
<el-tag class="cpuDetailTag">{{ $t('home.logicCore') }} *{{ baseInfo.cpuLogicalCores }}</el-tag>
|
||||
<br />
|
||||
<div v-for="(item, index) of currentInfo.cpuPercent" :key="index">
|
||||
<el-tag class="tagCPUClass">CPU-{{ index }}: {{ formatNumber(item) }}%</el-tag>
|
||||
<el-tag v-if="cpuShowAll || (!cpuShowAll && index < 32)" class="tagCPUClass">
|
||||
CPU-{{ index }}: {{ formatNumber(item) }}%
|
||||
</el-tag>
|
||||
</div>
|
||||
|
||||
<div v-if="currentInfo.cpuPercent.length > 32" class="mt-1 float-right">
|
||||
<el-button v-if="!cpuShowAll" @click="cpuShowAll = true" link type="primary" size="small">
|
||||
{{ $t('commons.button.showAll') }}
|
||||
<el-icon><DArrowRight /></el-icon>
|
||||
</el-button>
|
||||
<el-button v-if="cpuShowAll" @click="cpuShowAll = false" link type="primary" size="small">
|
||||
{{ $t('commons.button.hideSome') }}
|
||||
<el-icon><DArrowLeft /></el-icon>
|
||||
</el-button>
|
||||
</div>
|
||||
<template #reference>
|
||||
<v-charts
|
||||
@@ -302,6 +307,8 @@ const currentInfo = ref<Dashboard.CurrentInfo>({
|
||||
shotTime: new Date(),
|
||||
});
|
||||
|
||||
const cpuShowAll = ref();
|
||||
|
||||
const chartsOption = ref({ cpu: null, memory: null, load: null });
|
||||
|
||||
const acceptParams = (current: Dashboard.CurrentInfo, base: Dashboard.BaseInfo, isInit: boolean): void => {
|
||||
@@ -359,6 +366,14 @@ const goGPU = () => {
|
||||
router.push({ name: 'GPU' });
|
||||
};
|
||||
|
||||
const loadWidth = () => {
|
||||
if (!cpuShowAll.value || currentInfo.value.cpuPercent.length < 32) {
|
||||
return 310;
|
||||
}
|
||||
let line = Math.floor(currentInfo.value.cpuPercent.length / 16);
|
||||
return line * 141 + 28;
|
||||
};
|
||||
|
||||
function formatNumber(val: number) {
|
||||
return Number(val.toFixed(2));
|
||||
}
|
||||
@@ -369,6 +384,18 @@ defineExpose({
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.cpuModeTag {
|
||||
justify-content: flex-start !important;
|
||||
text-align: left !important;
|
||||
width: 280px;
|
||||
}
|
||||
.cpuDetailTag {
|
||||
justify-content: flex-start !important;
|
||||
text-align: left !important;
|
||||
width: 140px;
|
||||
margin-top: 3px;
|
||||
margin-left: 1px;
|
||||
}
|
||||
.tagClass {
|
||||
margin-top: 3px;
|
||||
}
|
||||
@@ -378,8 +405,8 @@ defineExpose({
|
||||
text-align: left !important;
|
||||
float: left;
|
||||
margin-top: 3px;
|
||||
margin-left: 4px;
|
||||
width: 100px;
|
||||
margin-left: 1px;
|
||||
width: 140px;
|
||||
}
|
||||
|
||||
.buttonClass {
|
||||
|
||||
@@ -111,27 +111,24 @@ let uploadHelper = ref('');
|
||||
const em = defineEmits(['close']);
|
||||
const handleClose = () => {
|
||||
open.value = false;
|
||||
uploadRef.value!.clearFiles();
|
||||
clearFiles();
|
||||
em('close', false);
|
||||
};
|
||||
const state = reactive({
|
||||
uploadEle: null,
|
||||
});
|
||||
const uploaderFiles = ref<UploadFiles>([]);
|
||||
const isUploadFolder = ref(false);
|
||||
const hoverIndex = ref(null);
|
||||
const uploadType = ref('file');
|
||||
const tmpFiles = ref<UploadFiles>([]);
|
||||
const breakFlag = ref(false);
|
||||
|
||||
const upload = (command: string) => {
|
||||
uploadType.value = command;
|
||||
if (command == 'dir') {
|
||||
state.uploadEle.webkitdirectory = true;
|
||||
} else {
|
||||
state.uploadEle.webkitdirectory = false;
|
||||
}
|
||||
isUploadFolder.value = true;
|
||||
uploadRef.value.$el.querySelector('input').value = '';
|
||||
uploadRef.value.$el.querySelector('input').click();
|
||||
};
|
||||
|
||||
@@ -253,10 +250,11 @@ const fileOnChange = (_uploadFile: UploadFile, uploadFiles: UploadFiles) => {
|
||||
|
||||
const clearFiles = () => {
|
||||
uploadRef.value!.clearFiles();
|
||||
uploaderFiles.value = [];
|
||||
};
|
||||
|
||||
const handleExceed: UploadProps['onExceed'] = () => {
|
||||
uploadRef.value!.clearFiles();
|
||||
clearFiles();
|
||||
MsgWarning(i18n.global.t('file.uploadOverLimit'));
|
||||
};
|
||||
|
||||
@@ -339,8 +337,7 @@ const submit = async () => {
|
||||
loading.value = false;
|
||||
uploadHelper.value = '';
|
||||
if (success == files.length) {
|
||||
uploadRef.value!.clearFiles();
|
||||
uploaderFiles.value = [];
|
||||
clearFiles();
|
||||
MsgSuccess(i18n.global.t('file.uploadSuccess'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,13 +16,20 @@
|
||||
</el-button>
|
||||
</template>
|
||||
<template #search>
|
||||
<el-select v-model="group" @change="search()" clearable class="p-w-200">
|
||||
<template #prefix>{{ $t('terminal.group') }}</template>
|
||||
<el-option :label="$t('commons.table.all')" value=""></el-option>
|
||||
<div v-for="item in groupList" :key="item.name">
|
||||
<el-option :value="item.id" :label="item.name" />
|
||||
</div>
|
||||
</el-select>
|
||||
<el-row :gutter="5">
|
||||
<el-col :xs="24" :sm="20" :md="20" :lg="20" :xl="20">
|
||||
<el-select v-model="group" @change="search()" clearable class="p-w-200">
|
||||
<template #prefix>{{ $t('terminal.group') }}</template>
|
||||
<el-option :label="$t('commons.table.all')" value=""></el-option>
|
||||
<div v-for="item in groupList" :key="item.name">
|
||||
<el-option :value="item.id" :label="item.name" />
|
||||
</div>
|
||||
</el-select>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="4" :md="4" :lg="4" :xl="4">
|
||||
<TableSearch @search="search()" v-model:searchName="commandReq.name" />
|
||||
</el-col>
|
||||
</el-row>
|
||||
</template>
|
||||
<template #main>
|
||||
<ComplexTable
|
||||
@@ -160,6 +167,10 @@ let commandInfo = reactive<Command.CommandOperate>({
|
||||
command: '',
|
||||
});
|
||||
|
||||
const commandReq = reactive({
|
||||
name: '',
|
||||
});
|
||||
|
||||
const cmdVisible = ref<boolean>(false);
|
||||
|
||||
const loadGroups = async () => {
|
||||
@@ -274,6 +285,7 @@ const search = async (column?: any) => {
|
||||
info: info.value,
|
||||
orderBy: paginationConfig.orderBy,
|
||||
order: paginationConfig.order,
|
||||
name: commandReq.name,
|
||||
};
|
||||
loading.value = true;
|
||||
await getCommandPage(params)
|
||||
|
||||
@@ -105,7 +105,7 @@
|
||||
<span v-if="node.label.length <= 25">
|
||||
<a @click="onClickConn(node, data)">{{ node.label }}</a>
|
||||
</span>
|
||||
<el-tooltip v-else :content="node.label" placement="top-start">
|
||||
<el-tooltip v-else :content="node.label" placement="right">
|
||||
<span>
|
||||
<a @click="onClickConn(node, data)">
|
||||
{{ node.label.substring(0, 22) }}...
|
||||
|
||||
@@ -126,7 +126,6 @@ const proxyForm = ref<FormInstance>();
|
||||
const rules = ref({
|
||||
name: [Rules.requiredInput, Rules.appName],
|
||||
match: [Rules.requiredInput],
|
||||
modifier: [Rules.requiredInput],
|
||||
cacheTime: [Rules.requiredInput, checkNumberRange(1, 65535)],
|
||||
proxyPass: [Rules.requiredInput],
|
||||
proxyHost: [Rules.requiredInput],
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-form-item :label="$t('website.rewriteMode')">
|
||||
<el-select v-model="req.name" filterable @change="getRewriteConfig(req.name)">
|
||||
<el-select v-model="req.name" filterable @change="getRewriteConfig(req.name)" class="p-w-200">
|
||||
<el-option :label="$t('website.current')" :value="'current'"></el-option>
|
||||
<el-option
|
||||
v-for="(rewrite, index) in Rewrites"
|
||||
@@ -11,6 +11,7 @@
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-text type="warning">{{ $t('website.rewriteHelper2') }}</el-text>
|
||||
<Codemirror
|
||||
ref="codeRef"
|
||||
v-loading="loading"
|
||||
@@ -26,7 +27,7 @@
|
||||
:extensions="extensions"
|
||||
v-model="content"
|
||||
/>
|
||||
<div style="margin-top: 10px">
|
||||
<div class="mt-2">
|
||||
<el-form-item>
|
||||
<el-alert :title="$t('website.rewriteHelper')" type="info" :closable="false" />
|
||||
</el-form-item>
|
||||
|
||||
@@ -349,7 +349,7 @@ import { ElForm, FormInstance } from 'element-plus';
|
||||
import { reactive, ref } from 'vue';
|
||||
import Params from '@/views/app-store/detail/params/index.vue';
|
||||
import Check from '../check/index.vue';
|
||||
import { MsgSuccess } from '@/utils/message';
|
||||
import { MsgError, MsgSuccess } from '@/utils/message';
|
||||
import { GetGroupList } from '@/api/modules/group';
|
||||
import { Group } from '@/api/interface/group';
|
||||
import { SearchRuntimes } from '@/api/modules/runtime';
|
||||
@@ -582,6 +582,16 @@ const changeAppType = (type: string) => {
|
||||
}
|
||||
};
|
||||
|
||||
function isSubsetOfStrArray(primaryDomain: string, otherDomains: string): boolean {
|
||||
const arr: string[] = otherDomains.split('\n');
|
||||
for (const item of arr) {
|
||||
if (primaryDomain === item) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
const submit = async (formEl: FormInstance | undefined) => {
|
||||
if (!formEl) return;
|
||||
await formEl.validate((valid) => {
|
||||
@@ -589,6 +599,12 @@ const submit = async (formEl: FormInstance | undefined) => {
|
||||
return;
|
||||
}
|
||||
loading.value = true;
|
||||
const flag = isSubsetOfStrArray(website.value.primaryDomain, website.value.otherDomains);
|
||||
if (!flag) {
|
||||
MsgError(i18n.global.t('website.containWarn'));
|
||||
loading.value = false;
|
||||
return false;
|
||||
}
|
||||
PreCheck({})
|
||||
.then((res) => {
|
||||
if (res.data) {
|
||||
|
||||
@@ -111,11 +111,12 @@
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="$t('website.remark')" prop="remark" min-width="120px">
|
||||
<template #default="{ row }">
|
||||
<MsgInfo :info="row.remark" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
:label="$t('website.remark')"
|
||||
prop="remark"
|
||||
show-overflow-tooltip
|
||||
min-width="120px"
|
||||
></el-table-column>
|
||||
<el-table-column
|
||||
:label="$t('commons.table.protocol')"
|
||||
prop="protocol"
|
||||
@@ -194,7 +195,6 @@ import { dateFormatSimple } from '@/utils/util';
|
||||
import { MsgSuccess } from '@/utils/message';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { VideoPlay, VideoPause } from '@element-plus/icons-vue';
|
||||
import MsgInfo from '@/components/msg-info/index.vue';
|
||||
import { GetGroupList } from '@/api/modules/group';
|
||||
import { Group } from '@/api/interface/group';
|
||||
import { GlobalStore } from '@/store';
|
||||
|
||||
Reference in New Issue
Block a user