mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2026-10-10 08:00:32 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
47dda4ac9f | ||
|
|
b1d40960c4 | ||
|
|
5222caecf9 | ||
|
|
bc8d4cbb0f | ||
|
|
0bb31f6caf | ||
|
|
03c8e4d3cb | ||
|
|
68ad653545 | ||
|
|
fd5b34d644 | ||
|
|
000096bc26 | ||
|
|
02023102d3 | ||
|
|
95bc3d9855 | ||
|
|
f9fb16198b |
@@ -49,4 +49,4 @@ jobs:
|
||||
access-key-secret: ${{ secrets.OSS_ACCESS_KEY_SECRET }}
|
||||
ossutil-version: '1.7.14'
|
||||
- name: Upload Assets to OSS
|
||||
- run: ossutil cp -r dist/ oss://resource-fit2cloud-com/1panel/package/stable/${{ github.ref_name }}/release/ --include "*.tar.gz" --include "checksums.txt" --only-current-dir
|
||||
run: ossutil cp -r dist/ oss://resource-fit2cloud-com/1panel/package/stable/${{ github.ref_name }}/release/ --include "*.tar.gz" --include "checksums.txt" --only-current-dir
|
||||
@@ -6,7 +6,7 @@ type CronjobCreate struct {
|
||||
Name string `json:"name" validate:"required"`
|
||||
Type string `json:"type" validate:"required"`
|
||||
SpecType string `json:"specType" validate:"required"`
|
||||
Week int `json:"week" validate:"number,max=7,min=1"`
|
||||
Week int `json:"week" validate:"number,max=6,min=0"`
|
||||
Day int `json:"day" validate:"number"`
|
||||
Hour int `json:"hour" validate:"number"`
|
||||
Minute int `json:"minute" validate:"number"`
|
||||
@@ -27,7 +27,7 @@ type CronjobUpdate struct {
|
||||
ID uint `json:"id" validate:"required"`
|
||||
Name string `json:"name" validate:"required"`
|
||||
SpecType string `json:"specType" validate:"required"`
|
||||
Week int `json:"week" validate:"number,max=7,min=1"`
|
||||
Week int `json:"week" validate:"number,max=6,min=0"`
|
||||
Day int `json:"day" validate:"number"`
|
||||
Hour int `json:"hour" validate:"number"`
|
||||
Minute int `json:"minute" validate:"number"`
|
||||
|
||||
@@ -19,6 +19,7 @@ type IAppInstallResourceRpo interface {
|
||||
GetFirst(opts ...DBOption) (model.AppInstallResource, error)
|
||||
Create(ctx context.Context, resource *model.AppInstallResource) error
|
||||
DeleteBy(ctx context.Context, opts ...DBOption) error
|
||||
BatchUpdateBy(maps map[string]interface{}, opts ...DBOption) error
|
||||
}
|
||||
|
||||
func NewIAppInstallResourceRpo() IAppInstallResourceRpo {
|
||||
@@ -71,3 +72,11 @@ func (a AppInstallResourceRpo) Create(ctx context.Context, resource *model.AppIn
|
||||
func (a AppInstallResourceRpo) DeleteBy(ctx context.Context, opts ...DBOption) error {
|
||||
return getTx(ctx, opts...).Delete(&model.AppInstallResource{}).Error
|
||||
}
|
||||
|
||||
func (a *AppInstallResourceRpo) BatchUpdateBy(maps map[string]interface{}, opts ...DBOption) error {
|
||||
db := getDb(opts...).Model(&model.AppInstallResource{})
|
||||
if len(opts) == 0 {
|
||||
db = db.Where("1=1")
|
||||
}
|
||||
return db.Updates(&maps).Error
|
||||
}
|
||||
|
||||
@@ -148,7 +148,7 @@ func handleAppRecover(install *model.AppInstall, recoverFile string, isRollback
|
||||
if err := json.Unmarshal(appjson, &oldInstall); err != nil {
|
||||
return fmt.Errorf("unmarshal app.json failed, err: %v", err)
|
||||
}
|
||||
if oldInstall.App.Key != install.App.Key || oldInstall.Name != install.Name || oldInstall.Version != install.Version || oldInstall.ID != install.ID {
|
||||
if oldInstall.App.Key != install.App.Key || oldInstall.Name != install.Name {
|
||||
return errors.New("the current backup file does not match the application")
|
||||
}
|
||||
|
||||
@@ -172,6 +172,7 @@ func handleAppRecover(install *model.AppInstall, recoverFile string, isRollback
|
||||
}()
|
||||
}
|
||||
|
||||
newEnvFile := ""
|
||||
resource, _ := appInstallResourceRepo.GetFirst(appInstallResourceRepo.WithAppInstallId(install.ID))
|
||||
if resource.ID != 0 && install.App.Key != "mysql" {
|
||||
mysqlInfo, err := appInstallRepo.LoadBaseInfo(resource.Key, "")
|
||||
@@ -182,7 +183,22 @@ func handleAppRecover(install *model.AppInstall, recoverFile string, isRollback
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := handleMysqlRecover(mysqlInfo, tmpPath, db.Name, fmt.Sprintf("%s.sql.gz", install.Name), true); err != nil {
|
||||
|
||||
newDB, envMap, err := reCreateDB(db.ID, oldInstall.Env)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
oldHost := fmt.Sprintf("\"PANEL_DB_HOST\":\"%v\"", envMap["PANEL_DB_HOST"].(string))
|
||||
newHost := fmt.Sprintf("\"PANEL_DB_HOST\":\"%v\"", mysqlInfo.ServiceName)
|
||||
oldInstall.Env = strings.ReplaceAll(oldInstall.Env, oldHost, newHost)
|
||||
envMap["PANEL_DB_HOST"] = mysqlInfo.ServiceName
|
||||
newEnvFile, err = coverEnvJsonToStr(oldInstall.Env)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_ = appInstallResourceRepo.BatchUpdateBy(map[string]interface{}{"resource_id": newDB.ID}, commonRepo.WithByID(resource.ID))
|
||||
|
||||
if err := handleMysqlRecover(mysqlInfo, tmpPath, newDB.Name, fmt.Sprintf("%s.sql.gz", install.Name), true); err != nil {
|
||||
global.LOG.Errorf("handle recover from sql.gz failed, err: %v", err)
|
||||
return err
|
||||
}
|
||||
@@ -193,11 +209,50 @@ func handleAppRecover(install *model.AppInstall, recoverFile string, isRollback
|
||||
return err
|
||||
}
|
||||
|
||||
oldInstall.Status = constant.Running
|
||||
if err := appInstallRepo.Save(context.Background(), install); err != nil {
|
||||
if len(newEnvFile) != 0 {
|
||||
envPath := fmt.Sprintf("%s/%s/%s/.env", constant.AppInstallDir, install.App.Key, install.Name)
|
||||
file, err := os.OpenFile(envPath, os.O_WRONLY|os.O_TRUNC, 0640)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
_, _ = file.WriteString(newEnvFile)
|
||||
}
|
||||
|
||||
oldInstall.ID = install.ID
|
||||
oldInstall.Status = constant.StatusRunning
|
||||
oldInstall.AppId = install.AppId
|
||||
oldInstall.AppDetailId = install.AppDetailId
|
||||
if err := appInstallRepo.Save(context.Background(), &oldInstall); err != nil {
|
||||
global.LOG.Errorf("save db app install failed, err: %v", err)
|
||||
return err
|
||||
}
|
||||
isOk = true
|
||||
return nil
|
||||
}
|
||||
|
||||
func reCreateDB(dbID uint, oldEnv string) (*model.DatabaseMysql, map[string]interface{}, error) {
|
||||
mysqlService := NewIMysqlService()
|
||||
ctx := context.Background()
|
||||
_ = mysqlService.Delete(ctx, dto.MysqlDBDelete{ID: dbID, DeleteBackup: true, ForceDelete: true})
|
||||
|
||||
envMap := make(map[string]interface{})
|
||||
if err := json.Unmarshal([]byte(oldEnv), &envMap); err != nil {
|
||||
return nil, envMap, err
|
||||
}
|
||||
oldName, _ := envMap["PANEL_DB_NAME"].(string)
|
||||
oldUser, _ := envMap["PANEL_DB_USER"].(string)
|
||||
oldPassword, _ := envMap["PANEL_DB_USER_PASSWORD"].(string)
|
||||
createDB, err := mysqlService.Create(context.Background(), dto.MysqlDBCreate{
|
||||
Name: oldName,
|
||||
Format: "utf8mb4",
|
||||
Username: oldUser,
|
||||
Password: oldPassword,
|
||||
Permission: "%",
|
||||
})
|
||||
if err != nil {
|
||||
return nil, envMap, err
|
||||
}
|
||||
|
||||
return createDB, envMap, nil
|
||||
}
|
||||
|
||||
@@ -14,7 +14,6 @@ import (
|
||||
|
||||
"github.com/1Panel-dev/1Panel/backend/app/dto"
|
||||
"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"
|
||||
@@ -100,7 +99,7 @@ func (u *MysqlService) Create(ctx context.Context, req dto.MysqlDBCreate) (*mode
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
if err := u.createUser(app, req); err != nil {
|
||||
if err := u.createUser(app.ContainerName, app.Password, app.Version, req); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -291,7 +290,7 @@ func (u *MysqlService) ChangeAccess(info dto.ChangeDBInfo) error {
|
||||
}
|
||||
}
|
||||
|
||||
if err := u.createUser(app, dto.MysqlDBCreate{
|
||||
if err := u.createUser(app.ContainerName, app.Password, app.Version, dto.MysqlDBCreate{
|
||||
Username: mysql.Username,
|
||||
Name: mysql.Name,
|
||||
Permission: info.Value,
|
||||
@@ -470,7 +469,7 @@ func (u *MysqlService) LoadStatus() (*dto.MysqlStatus, error) {
|
||||
return &info, nil
|
||||
}
|
||||
|
||||
func (u *MysqlService) createUser(app *repo.RootInfo, req dto.MysqlDBCreate) error {
|
||||
func (u *MysqlService) createUser(container, password, version string, req dto.MysqlDBCreate) error {
|
||||
var userlist []string
|
||||
if strings.Contains(req.Permission, ",") {
|
||||
ips := strings.Split(req.Permission, ",")
|
||||
@@ -484,32 +483,35 @@ func (u *MysqlService) createUser(app *repo.RootInfo, req dto.MysqlDBCreate) err
|
||||
}
|
||||
|
||||
for _, user := range userlist {
|
||||
if err := excSQL(app.ContainerName, app.Password, fmt.Sprintf("create user %s identified by '%s';", user, req.Password)); err != nil {
|
||||
handleCreateError(req.Name, userlist, app)
|
||||
if err := excSQL(container, password, fmt.Sprintf("create user %s identified by '%s';", user, req.Password)); err != nil {
|
||||
if strings.Contains(err.Error(), "ERROR 1396") {
|
||||
handleCreateError(container, password, req.Name, userlist, false)
|
||||
return buserr.New(constant.ErrUserIsExist)
|
||||
}
|
||||
handleCreateError(container, password, req.Name, userlist, true)
|
||||
return err
|
||||
}
|
||||
grantStr := fmt.Sprintf("grant all privileges on `%s`.* to %s", req.Name, user)
|
||||
if req.Name == "*" {
|
||||
grantStr = fmt.Sprintf("grant all privileges on *.* to %s", user)
|
||||
}
|
||||
if strings.HasPrefix(app.Version, "5.7") {
|
||||
if strings.HasPrefix(version, "5.7") {
|
||||
grantStr = fmt.Sprintf("%s identified by '%s' with grant option;", grantStr, req.Password)
|
||||
}
|
||||
if err := excSQL(app.ContainerName, app.Password, grantStr); err != nil {
|
||||
handleCreateError(req.Name, userlist, app)
|
||||
if err := excSQL(container, password, grantStr); err != nil {
|
||||
handleCreateError(container, password, req.Name, userlist, true)
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func handleCreateError(dbName string, userlist []string, app *repo.RootInfo) {
|
||||
_ = excSQL(app.ContainerName, app.Password, fmt.Sprintf("drop database `%s`", dbName))
|
||||
for _, user := range userlist {
|
||||
if err := excSQL(app.ContainerName, app.Password, fmt.Sprintf("drop user if exists %s", user)); err != nil {
|
||||
global.LOG.Errorf("drop user failed, err: %v", err)
|
||||
func handleCreateError(contaienr, password, dbName string, userlist []string, dropUser bool) {
|
||||
_ = excSQL(contaienr, password, fmt.Sprintf("drop database `%s`", dbName))
|
||||
if dropUser {
|
||||
for _, user := range userlist {
|
||||
if err := excSQL(contaienr, password, fmt.Sprintf("drop user if exists %s", user)); err != nil {
|
||||
global.LOG.Errorf("drop user failed, err: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -248,7 +248,7 @@ func (u *SSHService) LoadLog(req dto.SearchSSHLog) (*dto.SSHLog, error) {
|
||||
data.Logs = append(data.Logs, dataItem...)
|
||||
}
|
||||
}
|
||||
commandItem := fmt.Sprintf("cat %s | grep Accepted %s", fileList[i], command)
|
||||
commandItem := fmt.Sprintf("cat %s | grep -a Accepted %s", fileList[i], command)
|
||||
dataItem := loadSuccessDatas(commandItem)
|
||||
data.TotalCount += len(dataItem)
|
||||
if req.Status != constant.StatusFailed {
|
||||
|
||||
@@ -9,6 +9,9 @@
|
||||
<el-divider v-if="slots.buttons" direction="vertical" />
|
||||
<slot v-if="slots.buttons" name="buttons"></slot>
|
||||
</template>
|
||||
<template #extra>
|
||||
<slot v-if="slots.extra" name="extra"></slot>
|
||||
</template>
|
||||
</el-page-header>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -280,7 +280,16 @@ const buttons = [
|
||||
{
|
||||
label: i18n.global.t('commons.button.recover'),
|
||||
click: (row: File.File) => {
|
||||
onRecover(row);
|
||||
if (type.value !== 'app') {
|
||||
onRecover(row);
|
||||
} else {
|
||||
ElMessageBox.confirm(i18n.global.t('app.restoreWarn'), i18n.global.t('commons.button.recover'), {
|
||||
confirmButtonText: i18n.global.t('commons.button.confirm'),
|
||||
cancelButtonText: i18n.global.t('commons.button.cancel'),
|
||||
}).then(async () => {
|
||||
onRecover(row);
|
||||
});
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
|
||||
@@ -97,6 +97,7 @@ const message = {
|
||||
updateSuccess: 'Update Success',
|
||||
uploadSuccess: 'Update Success',
|
||||
operate: 'Operate',
|
||||
operateConfirm: 'If you are sure about the operation, please input it manually',
|
||||
inputOrSelect: 'Please select or enter',
|
||||
backupSuccess: 'Backup Success',
|
||||
unSupportType: 'Current file type is not supported!',
|
||||
@@ -553,6 +554,7 @@ const message = {
|
||||
cache: 'Cache',
|
||||
|
||||
volume: 'Volume',
|
||||
volumeDir: 'Volume dir',
|
||||
volumeName: 'Name',
|
||||
nfsEnable: 'Enable NFS storage',
|
||||
nfsAddress: 'Address',
|
||||
@@ -632,8 +634,10 @@ const message = {
|
||||
cronjob: {
|
||||
cronTask: 'Task',
|
||||
changeStatus: 'Change status',
|
||||
disableMsg: 'The cronjob cannot continue to run after it is stopped. Do you want to stop it?',
|
||||
enableMsg: 'The cronjob has been stopped. Enable now?',
|
||||
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',
|
||||
record: 'Records',
|
||||
shell: 'Shell script',
|
||||
@@ -1139,7 +1143,7 @@ const message = {
|
||||
backupdate: 'Backup time',
|
||||
restore: 'Restore',
|
||||
restoreWarn:
|
||||
'The restore operation will restart the application and replace the data. This operation cannot be rolled back. Do you want to continue?',
|
||||
'The recovery operation will delete the current data of this application and perform a restart. This action is irreversible. Do you wish to continue?',
|
||||
update: 'update',
|
||||
upgrade: 'upgrade',
|
||||
versionSelect: 'Please select a version',
|
||||
|
||||
@@ -564,6 +564,7 @@ const message = {
|
||||
gateway: '网关',
|
||||
|
||||
volume: '存储卷',
|
||||
volumeDir: '存储卷目录',
|
||||
nfsEnable: '启用 NFS 存储',
|
||||
nfsAddress: '地址',
|
||||
nfsAddressHelper: '支持输入 ip 或者域名',
|
||||
@@ -633,8 +634,8 @@ const message = {
|
||||
cronjob: {
|
||||
cronTask: '计划任务',
|
||||
changeStatus: '状态修改',
|
||||
disableMsg: '计划任务停止后将无法继续运行,是否停止?',
|
||||
enableMsg: '该计划任务已停止,是否启用?',
|
||||
disableMsg: '停止计划任务会导致该任务不再自动执行。是否继续?',
|
||||
enableMsg: '启用计划任务会让该任务定期自动执行。是否继续?',
|
||||
taskType: '任务类型',
|
||||
record: '报告',
|
||||
shell: 'Shell 脚本',
|
||||
@@ -1109,7 +1110,7 @@ const message = {
|
||||
backupPath: '文件路径',
|
||||
backupdate: '备份时间',
|
||||
restore: '恢复',
|
||||
restoreWarn: '恢复操作会重启应用,并替换数据,此操作不可回滚,是否继续?',
|
||||
restoreWarn: '恢复操作将删除该应用当前数据并重启。此操作不可回滚,是否继续?',
|
||||
update: '更新',
|
||||
upgrade: '升级',
|
||||
versionSelect: '请选择版本',
|
||||
|
||||
@@ -1,8 +1,17 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-drawer v-model="logVisiable" :destroy-on-close="true" :close-on-click-modal="false" size="50%">
|
||||
<el-drawer
|
||||
v-model="logVisiable"
|
||||
:destroy-on-close="true"
|
||||
:close-on-click-modal="false"
|
||||
:size="globalStore.isFullScreen ? '100%' : '50%'"
|
||||
>
|
||||
<template #header>
|
||||
<DrawerHeader :header="$t('commons.button.log')" :resource="logSearch.container" :back="handleClose" />
|
||||
<DrawerHeader :header="$t('commons.button.log')" :resource="logSearch.container" :back="handleClose">
|
||||
<template #extra>
|
||||
<el-button @click="toggleFullscreen" class="fullScreen" icon="FullScreen" plain></el-button>
|
||||
</template>
|
||||
</DrawerHeader>
|
||||
</template>
|
||||
<div>
|
||||
<el-select @change="searchLogs" style="width: 30%; float: left" v-model="logSearch.mode">
|
||||
@@ -47,13 +56,15 @@
|
||||
import { cleanContainerLog, logContainer } from '@/api/modules/container';
|
||||
import i18n from '@/lang';
|
||||
import { dateFormatForName } from '@/utils/util';
|
||||
import { nextTick, onBeforeUnmount, reactive, ref, shallowRef } from 'vue';
|
||||
import { nextTick, onBeforeUnmount, reactive, ref, shallowRef, watch } from 'vue';
|
||||
import { Codemirror } from 'vue-codemirror';
|
||||
import { javascript } from '@codemirror/lang-javascript';
|
||||
import { oneDark } from '@codemirror/theme-one-dark';
|
||||
import DrawerHeader from '@/components/drawer-header/index.vue';
|
||||
import { ElMessageBox } from 'element-plus';
|
||||
import { MsgSuccess } from '@/utils/message';
|
||||
import screenfull from 'screenfull';
|
||||
import { GlobalStore } from '@/store';
|
||||
|
||||
const extensions = [javascript(), oneDark];
|
||||
|
||||
@@ -64,6 +75,7 @@ const view = shallowRef();
|
||||
const handleReady = (payload) => {
|
||||
view.value = payload.view;
|
||||
};
|
||||
const globalStore = GlobalStore();
|
||||
|
||||
const logSearch = reactive({
|
||||
isWatch: false,
|
||||
@@ -93,12 +105,22 @@ const timeOptions = ref([
|
||||
},
|
||||
]);
|
||||
|
||||
function toggleFullscreen() {
|
||||
if (screenfull.isEnabled) {
|
||||
screenfull.toggle();
|
||||
}
|
||||
}
|
||||
screenfull.on('change', () => {
|
||||
globalStore.isFullScreen = screenfull.isFullscreen;
|
||||
});
|
||||
const handleClose = async () => {
|
||||
logVisiable.value = false;
|
||||
clearInterval(Number(timer));
|
||||
timer = null;
|
||||
};
|
||||
|
||||
watch(logVisiable, (val) => {
|
||||
if (screenfull.isEnabled && !val) screenfull.exit();
|
||||
});
|
||||
const searchLogs = async () => {
|
||||
const res = await logContainer(logSearch);
|
||||
logInfo.value = res.data || '';
|
||||
@@ -166,4 +188,7 @@ defineExpose({
|
||||
.margin-button {
|
||||
margin-left: 20px;
|
||||
}
|
||||
.fullScreen {
|
||||
border: none;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -49,6 +49,15 @@
|
||||
<Tooltip @click="onInspect(row.name)" :text="row.name" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="$t('container.volumeDir')" min-width="50">
|
||||
<template #default="{ row }">
|
||||
<el-button type="primary" link @click="toFolder(row.mountpoint)">
|
||||
<el-icon>
|
||||
<FolderOpened />
|
||||
</el-icon>
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
:label="$t('container.mountpoint')"
|
||||
show-overflow-tooltip
|
||||
@@ -124,7 +133,9 @@ const loadStatus = async () => {
|
||||
const goSetting = async () => {
|
||||
router.push({ name: 'ContainerSetting' });
|
||||
};
|
||||
|
||||
const toFolder = (folder: string) => {
|
||||
router.push({ path: '/hosts/files', query: { path: folder } });
|
||||
};
|
||||
const dialogCreateRef = ref<DialogExpose>();
|
||||
|
||||
interface DialogExpose {
|
||||
|
||||
@@ -15,6 +15,12 @@
|
||||
<el-button type="primary" @click="onOpenDialog('create')">
|
||||
{{ $t('commons.button.create') }}{{ $t('cronjob.cronTask') }}
|
||||
</el-button>
|
||||
<el-button plain :disabled="selects.length === 0" @click="onBatchChangeStatus('enable')">
|
||||
{{ $t('commons.button.enable') }}
|
||||
</el-button>
|
||||
<el-button plain :disabled="selects.length === 0" @click="onBatchChangeStatus('disable')">
|
||||
{{ $t('commons.button.disable') }}
|
||||
</el-button>
|
||||
<el-button plain :disabled="selects.length === 0" @click="onDelete(null)">
|
||||
{{ $t('commons.button.delete') }}
|
||||
</el-button>
|
||||
@@ -320,6 +326,20 @@ const onChangeStatus = async (id: number, status: string) => {
|
||||
});
|
||||
};
|
||||
|
||||
const onBatchChangeStatus = async (status: string) => {
|
||||
ElMessageBox.confirm(i18n.global.t('cronjob.' + status + 'Msg'), i18n.global.t('cronjob.changeStatus'), {
|
||||
confirmButtonText: i18n.global.t('commons.button.confirm'),
|
||||
cancelButtonText: i18n.global.t('commons.button.cancel'),
|
||||
}).then(async () => {
|
||||
let itemStatus = status === 'enable' ? 'Enable' : 'Disable';
|
||||
for (const item of selects.value) {
|
||||
await updateStatus({ id: item.id, status: itemStatus });
|
||||
}
|
||||
MsgSuccess(i18n.global.t('commons.msg.operationSuccess'));
|
||||
search();
|
||||
});
|
||||
};
|
||||
|
||||
const onHandle = async (row: Cronjob.CronjobInfo) => {
|
||||
loading.value = true;
|
||||
await handleOnce(row.id)
|
||||
|
||||
@@ -330,7 +330,7 @@ const weekOptions = [
|
||||
{ label: i18n.global.t('cronjob.thursday'), value: 4 },
|
||||
{ label: i18n.global.t('cronjob.friday'), value: 5 },
|
||||
{ label: i18n.global.t('cronjob.saturday'), value: 6 },
|
||||
{ label: i18n.global.t('cronjob.sunday'), value: 7 },
|
||||
{ label: i18n.global.t('cronjob.sunday'), value: 0 },
|
||||
];
|
||||
const rules = reactive({
|
||||
name: [Rules.requiredInput],
|
||||
@@ -456,7 +456,9 @@ function checkScript() {
|
||||
case 'perMonth':
|
||||
return row.day > 0 && row.day < 32 && row.hour >= 0 && row.hour < 24 && row.minute >= 0 && row.minute < 60;
|
||||
case 'perWeek':
|
||||
return row.week > 0 && row.week < 8 && row.hour >= 0 && row.hour < 24 && row.minute >= 0 && row.minute < 60;
|
||||
return (
|
||||
row.week >= 0 && row.week < 7 && row.hour >= 0 && row.hour < 24 && row.minute >= 0 && row.minute < 60
|
||||
);
|
||||
case 'perDay':
|
||||
return row.hour >= 0 && row.hour < 24 && row.minute >= 0 && row.minute < 60;
|
||||
case 'perHour':
|
||||
|
||||
Reference in New Issue
Block a user