13 Commits

Author SHA1 Message Date
ssongliu
15c391e763 fix: 解决概览页左右高度不一致的问题 (#1671) 2023-07-14 08:22:11 +00:00
ssongliu
3b3584714c fix: 修改部分国际化内容 (#1669) 2023-07-14 07:18:11 +00:00
zhengkunwang
61a0244cfe fix: 修改部分国际化内容 (#1670) 2023-07-14 07:08:10 +00:00
wangdan-fit2cloud
73a61933c5 Pr@dev@dan (#1668)
#### What this PR does / why we need it?

#### Summary of your change

#### Please indicate you've done the following:

- [ ] Made sure tests are passing and test coverage is added if needed.
- [ ] Made sure commit message follow the rule of [Conventional Commits specification](https://www.conventionalcommits.org/).
- [ ] Considered the docs impact and opened a new docs issue or PR with docs changes if needed.
2023-07-14 06:34:10 +00:00
zhengkunwang
72c7407b0b style: 文件列表增加操作列宽度 (#1667) 2023-07-14 06:22:10 +00:00
zhengkunwang
6538282a7b fix: 解决网站停止之后再启动运行目录错误的问题 (#1666)
Refs https://github.com/1Panel-dev/1Panel/issues/1665
2023-07-14 06:20:19 +00:00
ssongliu
87326e3292 fix: 解决监控数据异常导致溢出的问题 2023-07-14 11:55:33 +08:00
zhengkunwang
6eadb116c2 feat: 修复当网站主域名与网站目录不一致时,定时任务切割网站日志失败的问题 (#1659) 2023-07-14 03:50:10 +00:00
zhengkunwang
c9ffd2564e feat: 基本名称名称长度限制增加到 128 (#1658) 2023-07-14 03:48:11 +00:00
wangdan-fit2cloud
cd6e5f7905 fix: 优化暗色背景下禁用按钮样式 (#1663)
#### What this PR does / why we need it?

#### Summary of your change

#### Please indicate you've done the following:

- [ ] Made sure tests are passing and test coverage is added if needed.
- [ ] Made sure commit message follow the rule of [Conventional Commits specification](https://www.conventionalcommits.org/).
- [ ] Considered the docs impact and opened a new docs issue or PR with docs changes if needed.
2023-07-14 03:38:10 +00:00
Mystery0 M
b96e988f20 fix: 修复当网站主域名与网站目录不一致时,定时任务切割网站日志失败 (#1653)
* fix: 网站日志切割定时任务执行失败时打印失败原因,方便排查问题

* fix: 修复SiteDir与主域名不匹配时,切割网站日志失败
2023-07-13 22:25:58 +08:00
wzrove
30f7fa6afa fix: 优化监控页面echart资源释放 (#1651)
#### What this PR does / why we need it?

#1598 监控页面echart资源 组件卸载未释放

#### Summary of your change

优化监控页面echart资源释放

#### Please indicate you've done the following:

- [x] Made sure tests are passing and test coverage is added if needed.
- [x] Made sure commit message follow the rule of [Conventional Commits specification](https://www.conventionalcommits.org/).
- [x] Considered the docs impact and opened a new docs issue or PR with docs changes if needed.
2023-07-13 12:47:18 +00:00
ssongliu
4605b19473 fix: 网站上传备份逻辑调整 (#1649) 2023-07-13 11:51:17 +00:00
23 changed files with 129 additions and 61 deletions

View File

@@ -11,6 +11,7 @@ import (
"github.com/1Panel-dev/1Panel/backend/app/dto"
"github.com/1Panel-dev/1Panel/backend/app/model"
"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"
@@ -80,11 +81,11 @@ func handleWebsiteRecover(website *model.Website, recoverFile string, isRollback
temPathWithName := tmpPath + "/" + website.Alias
if !fileOp.Stat(tmpPath+"/website.json") || !fileOp.Stat(temPathWithName+".conf") || !fileOp.Stat(temPathWithName+".web.tar.gz") {
return errors.New("the wrong recovery package does not have .conf or .web.tar.gz files")
return buserr.WithDetail(constant.ErrBackupExist, ".conf or .web.tar.gz", nil)
}
if website.Type == constant.Deployment {
if !fileOp.Stat(temPathWithName + ".app.tar.gz") {
return errors.New("the wrong recovery package does not have .app.tar.gz files")
return buserr.WithDetail(constant.ErrBackupExist, ".app.tar.gz", nil)
}
}
var oldWebsite model.Website
@@ -95,8 +96,9 @@ func handleWebsiteRecover(website *model.Website, recoverFile string, isRollback
if err := json.Unmarshal(websiteJson, &oldWebsite); err != nil {
return fmt.Errorf("unmarshal app.json failed, err: %v", err)
}
if oldWebsite.Alias != website.Alias || oldWebsite.Type != website.Type || oldWebsite.ID != website.ID {
return errors.New("the current backup file does not match the application")
if err := checkValidOfWebsite(&oldWebsite, website); err != nil {
return err
}
isOk := false
@@ -155,6 +157,7 @@ func handleWebsiteRecover(website *model.Website, recoverFile string, isRollback
return errors.New(string(stdout))
}
oldWebsite.ID = website.ID
if err := websiteRepo.SaveWithoutCtx(&oldWebsite); err != nil {
global.LOG.Errorf("handle save website data failed, err: %v", err)
return err
@@ -212,3 +215,29 @@ func handleWebsiteBackup(website *model.Website, backupDir, fileName string) err
return nil
}
func checkValidOfWebsite(oldWebsite, website *model.Website) error {
if oldWebsite.Alias != website.Alias || oldWebsite.Type != website.Type {
return buserr.WithDetail(constant.ErrBackupMatch, fmt.Sprintf("oldName: %s, oldType: %v", oldWebsite.Alias, oldWebsite.Type), nil)
}
if oldWebsite.AppInstallID != 0 {
app, err := appInstallRepo.GetFirst(commonRepo.WithByID(website.AppInstallID))
if err != nil {
return buserr.WithDetail(constant.ErrBackupMatch, "app", nil)
}
if app.App.Type != "website" {
return buserr.WithDetail(constant.ErrBackupMatch, fmt.Sprintf("appType: %s", app.App.Type), nil)
}
}
if oldWebsite.RuntimeID != 0 {
if _, err := runtimeRepo.GetFirst(commonRepo.WithByID(website.RuntimeID)); err != nil {
return buserr.WithDetail(constant.ErrBackupMatch, "runtime", nil)
}
}
if oldWebsite.WebsiteSSLID != 0 {
if _, err := websiteSSLRepo.GetFirst(commonRepo.WithByID(website.WebsiteSSLID)); err != nil {
return buserr.WithDetail(constant.ErrBackupMatch, "ssl", nil)
}
}
return nil
}

View File

@@ -359,10 +359,10 @@ func (u *CronjobService) handleCutWebsiteLog(cronjob *model.Cronjob, startTime t
wg.Done()
return
}
websiteLogDir := path.Join(baseDir, website.PrimaryDomain, "log")
websiteLogDir := path.Join(baseDir, website.Alias, "log")
srcAccessLogPath := path.Join(websiteLogDir, "access.log")
srcErrorLogPath := path.Join(websiteLogDir, "error.log")
dstLogDir := path.Join(global.CONF.System.Backup, "log", "website", website.PrimaryDomain)
dstLogDir := path.Join(global.CONF.System.Backup, "log", "website", website.Alias)
if !fileOp.Stat(dstLogDir) {
_ = os.MkdirAll(dstLogDir, 0755)
}

View File

@@ -76,29 +76,29 @@ func loadDiskIO() {
if io2.Name == io1.Name {
var itemIO model.MonitorIO
itemIO.Name = io1.Name
if io2.ReadBytes != 0 && io1.ReadBytes != 0 {
if io2.ReadBytes != 0 && io1.ReadBytes != 0 && io2.ReadBytes > io1.ReadBytes {
itemIO.Read = uint64(float64(io2.ReadBytes-io1.ReadBytes) / 60)
}
if io2.WriteBytes != 0 && io1.WriteBytes != 0 {
if io2.WriteBytes != 0 && io1.WriteBytes != 0 && io2.WriteBytes > io1.WriteBytes {
itemIO.Write = uint64(float64(io2.WriteBytes-io1.WriteBytes) / 60)
}
if io2.ReadCount != 0 && io1.ReadCount != 0 {
if io2.ReadCount != 0 && io1.ReadCount != 0 && io2.ReadCount > io1.ReadCount {
itemIO.Count = uint64(float64(io2.ReadCount-io1.ReadCount) / 60)
}
writeCount := uint64(0)
if io2.WriteCount != 0 && io1.WriteCount != 0 {
if io2.WriteCount != 0 && io1.WriteCount != 0 && io2.WriteCount > io1.WriteCount {
writeCount = uint64(float64(io2.WriteCount-io1.WriteCount) / 60)
}
if writeCount > itemIO.Count {
itemIO.Count = writeCount
}
if io2.ReadTime != 0 && io1.ReadTime != 0 {
if io2.ReadTime != 0 && io1.ReadTime != 0 && io2.ReadTime > io1.ReadTime {
itemIO.Time = uint64(float64(io2.ReadTime-io1.ReadTime) / 60)
}
writeTime := uint64(0)
if io2.WriteTime != 0 && io1.WriteTime != 0 {
if io2.WriteTime != 0 && io1.WriteTime != 0 && io2.WriteTime > io1.WriteTime {
writeTime = uint64(float64(io2.WriteTime-io1.WriteTime) / 60)
}
if writeTime > itemIO.Time {
@@ -128,10 +128,10 @@ func loadNetIO() {
var itemNet model.MonitorNetwork
itemNet.Name = net1.Name
if net2.BytesSent != 0 && net1.BytesSent != 0 {
if net2.BytesSent != 0 && net1.BytesSent != 0 && net2.BytesSent > net1.BytesSent {
itemNet.Up = float64(net2.BytesSent-net1.BytesSent) / 1024 / 60
}
if net2.BytesRecv != 0 && net1.BytesRecv != 0 {
if net2.BytesRecv != 0 && net1.BytesRecv != 0 && net2.BytesRecv > net1.BytesRecv {
itemNet.Down = float64(net2.BytesRecv-net1.BytesRecv) / 1024 / 60
}
netList = append(netList, itemNet)
@@ -145,21 +145,13 @@ func loadNetIO() {
if net2.Name == net1.Name {
var itemNet model.MonitorNetwork
itemNet.Name = net1.Name
if net2.BytesSent != 0 && net1.BytesSent != 0 {
if net2.BytesSent != 0 && net1.BytesSent != 0 && net2.BytesSent > net1.BytesSent {
itemNet.Up = float64(net2.BytesSent-net1.BytesSent) / 1024 / 60
}
if itemNet.Up > 10485760 {
itemNet.Up = 0
global.LOG.Errorf("net2: %v, net1: %v, BytesSent: %v \n", net2.BytesSent, net1.BytesSent, float64(net2.BytesSent-net1.BytesSent)/1024/60)
}
if net2.BytesRecv != 0 && net1.BytesRecv != 0 {
if net2.BytesRecv != 0 && net1.BytesRecv != 0 && net2.BytesRecv > net1.BytesRecv {
itemNet.Down = float64(net2.BytesRecv-net1.BytesRecv) / 1024 / 60
}
if itemNet.Down > 10485760 {
itemNet.Down = 0
global.LOG.Errorf("net2: %v, net1: %v, BytesRecv: %v \n", net2.BytesRecv, net1.BytesRecv, float64(net2.BytesRecv-net1.BytesRecv)/1024/60)
}
netList = append(netList, itemNet)
break
}

View File

@@ -536,6 +536,10 @@ func opWebsite(website *model.Website, operate string) error {
if files.NewFileOp().Stat(absoluteRewritePath) {
server.UpdateDirective("include", []string{rewriteInclude})
}
rootIndex := path.Join("/www/sites", website.Alias, "index")
if website.SiteDir != "/" {
rootIndex = path.Join(rootIndex, website.SiteDir)
}
switch website.Type {
case constant.Deployment:
server.RemoveDirective("root", nil)
@@ -546,12 +550,11 @@ func opWebsite(website *model.Website, operate string) error {
proxy := fmt.Sprintf("http://127.0.0.1:%d", appInstall.HttpPort)
server.UpdateRootProxy([]string{proxy})
case constant.Static:
server.UpdateRoot(path.Join("/www/sites", website.Alias, "index"))
server.UpdateRoot(rootIndex)
server.UpdateRootLocation()
case constant.Proxy:
server.RemoveDirective("root", nil)
case constant.Runtime:
rootIndex := path.Join("/www/sites", website.Alias, "index")
server.UpdateRoot(rootIndex)
localPath := ""
if website.ProxyType == constant.RuntimeProxyUnix {

View File

@@ -68,6 +68,8 @@ var (
ErrGroupIsUsed = "ErrGroupIsUsed"
ErrUsernameIsExist = "ErrUsernameIsExist"
ErrUsernameIsNotExist = "ErrUsernameIsNotExist"
ErrBackupMatch = "ErrBackupMatch"
ErrBackupExist = "ErrBackupExist"
)
// ssl

View File

@@ -59,6 +59,8 @@ ErrDomainIsExist: "Domain is already exist"
ErrAliasIsExist: "Alias is already exist"
ErrAppDelete: 'Other Website use this App'
ErrGroupIsUsed: 'The group is in use and cannot be deleted'
ErrBackupMatch: 'the backup file does not match the current partial data of the website: {{ .detail}}"'
ErrBackupExist: 'the backup file corresponds to a portion of the original data that does not exist: {{ .detail}}"'
#ssl
ErrSSLCannotDelete: "The certificate is being used by the website and cannot be removed"

View File

@@ -59,6 +59,8 @@ ErrDomainIsExist: "域名已存在"
ErrAliasIsExist: "代號已存在"
ErrAppDelete: '其他網站使用此應用,無法刪除'
ErrGroupIsUsed: '分組正在使用中,無法刪除'
ErrBackupMatch: '該備份文件與當前網站部分數據不匹配: {{ .detail}}"'
ErrBackupExist: '該備份文件對應部分原數據不存在: {{ .detail}}"'
#ssl
ErrSSLCannotDelete: "證書正在被網站使用,無法刪除"

View File

@@ -59,6 +59,8 @@ ErrDomainIsExist: "域名已存在"
ErrAliasIsExist: "代号已存在"
ErrAppDelete: '其他网站使用此应用,无法删除'
ErrGroupIsUsed: '分组正在使用中,无法删除'
ErrBackupMatch: '该备份文件与当前网站部分数据不匹配 {{ .detail}}"'
ErrBackupExist: '该备份文件对应部分源数据不存在 {{ .detail}}"'
#ssl
ErrSSLCannotDelete: "证书正在被网站使用,无法删除"

View File

@@ -174,7 +174,7 @@ const checkLinuxName = (rule: any, value: any, callback: any) => {
if (value === '' || typeof value === 'undefined' || value == null) {
callback(new Error(i18n.global.t('commons.rule.linuxName', ['/\\:*?\'"<>|'])));
} else {
const reg = /^[^/\\\"'|<>?*]{1,30}$/;
const reg = /^[^/\\\"'|<>?*]{1,128}$/;
if (!reg.test(value) && value !== '') {
callback(new Error(i18n.global.t('commons.rule.linuxName', ['/\\:*?\'"<>|'])));
} else {
@@ -402,7 +402,7 @@ const checkParamSimple = (rule: any, value: any, callback: any) => {
if (value === '' || typeof value === 'undefined' || value == null) {
callback();
} else {
const reg = /^[a-z0-9][a-z0-9]{1,64}$/;
const reg = /^[a-z0-9][a-z0-9]{1,128}$/;
if (!reg.test(value) && value !== '') {
callback(new Error(i18n.global.t('commons.rule.paramSimple')));
} else {

View File

@@ -159,6 +159,7 @@ const message = {
complexityPassword:
'Longer than eight characters and contains at least two combinations of letters, digits, and special characters',
commonPassword: 'Please enter a password with more than 6 characters',
linuxName: 'Length 1-128, the name cannot contain symbols such as {0}',
email: 'Email format error',
number: 'Please enter the correct number',
integer: 'Please enter the correct positive integer',
@@ -180,7 +181,7 @@ const message = {
'Supports letters, numbers, underscores, hyphens and dots, cannot end with hyphen- or dot.1-127',
disableFunction: 'Only support letters and,',
leechExts: 'Only support letters, numbers and,',
paramSimple: 'Support lowercase letters and numbers, length 1-64',
paramSimple: 'Support lowercase letters and numbers, length 1-128',
},
res: {
paramError: 'The request failed, please try again later!',
@@ -355,7 +356,7 @@ const message = {
threadCacheHitHelper: 'If it is too low, increase thread_cache_size',
indexHit: 'Index hit',
indexHitHelper: 'If it is too low, increase key_buffer_size',
innodbIndexHit: 'Innodb 索引命中率',
innodbIndexHit: 'Innodb index hit rate',
innodbIndexHitHelper: 'If it is too low, increase innodb_buffer_pool_size',
cacheHit: 'Querying the Cache Hit',
cacheHitHelper: 'If it is too low, increase query_cache_size',
@@ -443,7 +444,8 @@ const message = {
localIP: 'Local IP',
},
container: {
createContainer: 'Create container',
create: 'Create container',
edit: 'Edit container',
updateContaienrHelper:
'Container editing requires rebuilding the container. Any data that has not been persisted will be lost. Do you want to continue?',
containerList: 'Container list',
@@ -649,13 +651,13 @@ const message = {
startIn: ' to start',
},
cronjob: {
cronTask: 'Task',
cronTask: 'Cronjob',
changeStatus: 'Change status',
disableMsg:
'Stopping the scheduled task will result in the task no longer automatically executing. Do you want to continue?',
enableMsg:
'Enabling the scheduled task will allow the task to automatically execute on a regular basis. Do you want to continue?',
taskType: 'Task type',
taskType: 'Cronjob type',
record: 'Records',
shell: 'Shell script',
containerCheckBox: 'In container (no need to enter the container command)',
@@ -673,7 +675,7 @@ const message = {
syncDate: 'Synchronization time ',
releaseMemory: 'Free memory',
curl: 'Access URL',
taskName: 'Task name',
taskName: 'Cronjob name',
cronSpec: 'Lifecycle',
cronSpecHelper: 'Enter the correct execution period',
cleanHelper:
@@ -710,7 +712,7 @@ const message = {
sunday: 'Sunday',
shellContent: 'Script content',
errRecord: 'Incorrect logging',
errHandle: 'Task execution failure',
errHandle: 'Cronjob execution failure',
noRecord: 'The execution did not generate any logs',
cleanData: 'Clean data',
cleanDataHelper: 'Delete the backup file generated during this task.',
@@ -1017,7 +1019,7 @@ const message = {
entranceInputHelper: 'When the security entry is set to blank, the security entry is cancelled.',
randomGenerate: 'Random',
expirationTime: 'Expiration Time',
unSetting: 'Not Set',
unSetting: 'Unset',
noneSetting:
'Set the expiration time for the panel password. After the expiration, you need to reset the password',
expirationHelper: 'If the password expiration time is [0] days, the password expiration function is disabled',
@@ -1317,7 +1319,7 @@ const message = {
startHelper:
'After enabling the site, users can access the content of the site normally, do you want to continue? ',
sitePath: 'Website Directory',
siteAlias: 'Site Path Name',
siteAlias: 'Site Alias',
primaryPath: 'Main directory',
folderTitle: 'The main directory of the website mainly contains four folders',
wafFolder: 'Firewall Rules',
@@ -1417,11 +1419,11 @@ const message = {
'The password is asymmetrically encrypted and cannot be echoed. Editing needs to reset the password',
antiLeech: 'Anti-leech',
extends: 'Extension',
browserCache: 'browser cache',
browserCache: 'Cache',
leechLog: 'Record anti-leech log',
accessDomain: 'Allowed domain names',
accessDomain: 'Allowed domains',
leechReturn: 'Response resource',
noneRef: 'Allow the source to be empty',
noneRef: 'Allow empty source',
disable: 'not enabled',
disableLeechHelper: 'Whether to disable the anti-leech',
disableLeech: 'Disable anti-leech',
@@ -1499,6 +1501,8 @@ const message = {
acmeHelper: 'Acme account is used to apply for free certificates',
},
firewall: {
create: 'Create rule',
edit: 'Edit rule',
notSupport:
'No system firewall detected (firewalld or ufw). Please refer to the official documentation for installation.',
ccDeny: 'CC Protection',
@@ -1614,7 +1618,8 @@ const message = {
laddr: 'Source address/port',
raddr: 'Destination address/port',
stopProcess: 'End',
stopProcessWarn: 'Are you sure you want to end this process (PID:{0})? This operation cannot be rolled back',
stopProcessWarn: 'Are you sure you want to end this process (PID:{0})? ',
processName: 'ProcessName',
},
};

View File

@@ -159,7 +159,7 @@ const message = {
volumeName: '支持英文數字.-和_,長度2-30',
complexityPassword: '請輸入長度大於 8 位且包含字母數字特殊字符至少兩項的密碼組合',
commonPassword: '請輸入 6 位以上長度密碼',
linuxName: '長度1-30名稱不能含有{0}等符號',
linuxName: '長度1-128名稱不能含有{0}等符號',
email: '請輸入正確的郵箱',
number: '請輸入正確的數字',
integer: '請輸入正確的正整數',
@@ -179,7 +179,7 @@ const message = {
containerName: '支持字母數字下劃線連字符和點,不能以連字符-或點.結尾,長度1-127',
disableFunction: '僅支持字母和,',
leechExts: '僅支持字母數字和,',
paramSimple: '支持小寫字母和數字,長度1-64',
paramSimple: '支持小寫字母和數字,長度 1-128',
},
res: {
paramError: '請求失敗,請稍後重試!',
@@ -1530,7 +1530,8 @@ const message = {
laddr: '源地址/端口',
raddr: '目標地址/端口',
stopProcess: '結束',
stopProcessWarn: '是否確定結束此進程 (PID:{0})此操作不可回滾',
stopProcessWarn: '是否確定結束此進程 (PID:{0})',
processName: '進程名稱',
},
};
export default {

View File

@@ -159,7 +159,7 @@ const message = {
volumeName: '支持英文数字.-和_,长度2-30',
complexityPassword: '请输入长度大于 8 位且包含字母数字特殊字符至少两项的密码组合',
commonPassword: '请输入 6 位以上长度密码',
linuxName: '长度1-30名称不能含有{0}等符号',
linuxName: '长度1-128名称不能含有{0}等符号',
email: '请输入正确的邮箱',
number: '请输入正确的数字',
integer: '请输入正确的正整数',
@@ -179,7 +179,7 @@ const message = {
containerName: '支持字母数字下划线连字符和点,不能以连字符-或点.结尾,长度1-127',
disableFunction: '仅支持字母和,',
leechExts: '仅支持字母数字和,',
paramSimple: '支持小写字母和数字,长度1-64',
paramSimple: '支持小写字母和数字,长度1-128',
},
res: {
paramError: '请求失败,请稍后重试!',
@@ -1538,7 +1538,7 @@ const message = {
laddr: '源地址/端口',
raddr: '目标地址/端口',
stopProcess: '结束',
stopProcessWarn: '是否确定结束此进程 (PID:{0})此操作不可回滚',
stopProcessWarn: '是否确定结束此进程 (PID:{0})',
processName: '进程名称',
},
};

View File

@@ -171,7 +171,7 @@ html.dark {
.mobile-header {
background-color: var(--panel-main-bg-color) !important;
border-bottom: var(--panel-border);
color: #ffffff;
color: #ffffff;
}
}
.system-label {
@@ -306,4 +306,10 @@ html.dark {
background-color: rgb(56, 59, 59);
color: var(--el-color-warning);
}
.el-dropdown-menu__item.is-disabled {
color: var(--panel-button-disabled);
}
.el-date-editor .el-range-separator {
color: var(--panel-button-disabled);
}
}

View File

@@ -21,7 +21,7 @@
:type="activeTag === item.key ? 'primary' : ''"
:plain="activeTag !== item.key"
>
{{ item.name }}
{{ language == 'zh' || language == 'tw' ? item.name : item.key }}
</el-button>
</div>
</div>
@@ -271,6 +271,7 @@ import { getAge } from '@/utils/util';
import { useRouter } from 'vue-router';
import { MsgSuccess } from '@/utils/message';
import { toFolder } from '@/global/business';
import { useI18n } from 'vue-i18n';
const data = ref<any>();
const loading = ref(false);
@@ -308,6 +309,8 @@ const router = useRouter();
const activeName = ref(i18n.global.t('app.installed'));
const mode = ref('installed');
const language = useI18n().locale.value;
const sync = () => {
syncLoading.value = true;
SyncInstalledApp()

View File

@@ -66,7 +66,7 @@
fix
:formatter="dateFormat"
/>
<fu-table-operations :buttons="buttons" :label="$t('commons.table.operate')" />
<fu-table-operations width="200px" :buttons="buttons" :label="$t('commons.table.operate')" />
</ComplexTable>
</template>
</LayoutContent>

View File

@@ -80,7 +80,7 @@
<el-table-column :label="$t('cronjob.cronSpec')" :min-width="120">
<template #default="{ row }">
<span v-if="row.specType.indexOf('N') === -1 || row.specType === 'perWeek'">
{{ $t('cronjob.' + row.specType) }}
{{ $t('cronjob.' + row.specType) }}&nbsp;
</span>
<span v-else>{{ $t('cronjob.per') }}</span>
<span v-if="row.specType === 'perMonth'">
@@ -123,7 +123,7 @@
</template>
</el-table-column>
<fu-table-operations
width="200px"
width="300px"
:buttons="buttons"
:ellipsis="10"
:label="$t('commons.table.operate')"

View File

@@ -126,7 +126,7 @@
<div v-if="chartOption === 'io'" style="margin-top: 40px" class="mobile-monitor-chart">
<v-charts
height="305px"
height="360px"
id="ioChart"
type="line"
:option="chartsOption['ioChart']"
@@ -136,7 +136,7 @@
</div>
<div v-if="chartOption === 'network'" style="margin-top: 40px" class="mobile-monitor-chart">
<v-charts
height="305px"
height="360px"
id="networkChart"
type="line"
:option="chartsOption['networkChart']"

View File

@@ -156,7 +156,7 @@
:ellipsis="3"
:buttons="buttons"
:label="$t('commons.table.operate')"
min-width="200"
min-width="300"
fixed="right"
fix
/>

View File

@@ -424,6 +424,10 @@ function initCharts(chartName: string, xDatas: any, yDatas: any, yTitle: string,
},
legend: {
data: chartName === 'loadNetworkChart' && [i18n.global.t('monitor.up'), i18n.global.t('monitor.down')],
textStyle: {
color: '#646A73',
},
icon: 'circle',
},
grid: {
left: getSideWidth(chartName == 'loadNetworkChart'),
@@ -481,6 +485,10 @@ function initLoadCharts(item: Monitor.MonitorData) {
'15 ' + i18n.global.t('commons.units.minute'),
i18n.global.t('monitor.resourceUsage'),
],
textStyle: {
color: '#646A73',
},
icon: 'circle',
},
grid: { left: '7%', right: '7%', bottom: '20%' },
xAxis: {
@@ -638,6 +646,10 @@ function initIOCharts(item: Monitor.MonitorData) {
i18n.global.t('monitor.readWriteCount'),
i18n.global.t('monitor.readWriteTime'),
],
textStyle: {
color: '#646A73',
},
icon: 'circle',
},
grid: { left: getSideWidth(true), right: getSideWidth(true), bottom: '20%' },
xAxis: {
@@ -759,12 +771,21 @@ function changeChartSize() {
echarts.getInstanceByDom(document.getElementById('loadNetworkChart') as HTMLElement)?.resize();
}
function disposeChart() {
echarts.getInstanceByDom(document.getElementById('loadLoadChart') as HTMLElement)?.dispose();
echarts.getInstanceByDom(document.getElementById('loadCPUChart') as HTMLElement)?.dispose();
echarts.getInstanceByDom(document.getElementById('loadMemoryChart') as HTMLElement)?.dispose();
echarts.getInstanceByDom(document.getElementById('loadIOChart') as HTMLElement)?.dispose();
echarts.getInstanceByDom(document.getElementById('loadNetworkChart') as HTMLElement)?.dispose();
}
onMounted(() => {
zoomStart.value = dateFormatWithoutYear(new Date(new Date().setHours(0, 0, 0, 0)));
loadNetworkOptions();
window.addEventListener('resize', changeChartSize);
});
onBeforeUnmount(() => {
disposeChart();
window.removeEventListener('resize', changeChartSize);
});
</script>

View File

@@ -54,7 +54,7 @@
<el-col :span="1"><br /></el-col>
<el-col :xs="24" :sm="20" :md="20" :lg="10" :xl="10">
<el-form :model="form" label-position="left" ref="formRef" label-width="120px">
<el-form-item :label="$t('ssh.port')" prop="port">
<el-form-item :label="$t('commons.table.port')" prop="port">
<el-input disabled v-model.number="form.port">
<template #append>
<el-button @click="onChangePort" icon="Setting">

View File

@@ -8,12 +8,12 @@
size="30%"
>
<template #header>
<DrawerHeader :header="$t('ssh.port')" :back="handleClose" />
<DrawerHeader :header="$t('commons.table.port')" :back="handleClose" />
</template>
<el-form ref="formRef" label-position="top" :model="form" @submit.prevent v-loading="loading">
<el-row type="flex" justify="center">
<el-col :span="22">
<el-form-item :label="$t('ssh.port')" prop="port" :rules="Rules.port">
<el-form-item :label="$t('commons.table.port')" prop="port" :rules="Rules.port">
<el-input clearable v-model.number="form.port" />
</el-form-item>
</el-col>
@@ -63,7 +63,7 @@ const onSave = async (formEl: FormInstance | undefined) => {
formEl.validate(async (valid) => {
if (!valid) return;
ElMessageBox.confirm(
i18n.global.t('ssh.sshChangeHelper', [i18n.global.t('ssh.port'), form.port]),
i18n.global.t('ssh.sshChangeHelper', [i18n.global.t('commons.table.port'), form.port]),
i18n.global.t('ssh.sshChange'),
{
confirmButtonText: i18n.global.t('commons.button.confirm'),

View File

@@ -7,7 +7,7 @@
:rules="rules"
ref="leechRef"
label-position="right"
label-width="120px"
label-width="180px"
class="moblie-form"
>
<el-form-item :label="$t('website.enableOrNot')">

View File

@@ -1,7 +1,7 @@
<template>
<el-row :gutter="20" v-loading="loading">
<el-col :xs="24" :sm="18" :md="8" :lg="8" :xl="8">
<el-form ref="websiteForm" label-position="right" label-width="80px" :model="form" :rules="rules">
<el-form ref="websiteForm" label-position="right" label-width="150px" :model="form" :rules="rules">
<el-form-item :label="$t('website.primaryDomain')" prop="primaryDomain">
<el-input v-model="form.primaryDomain" disabled></el-input>
</el-form-item>