mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2025-12-30 03:13:29 +08:00
feat: Add quick operation features to node overview page (#11476)
This commit is contained in:
parent
9a17bc74b0
commit
d25b5f4f2a
8 changed files with 108 additions and 45 deletions
|
|
@ -8,8 +8,9 @@ import { GlobalStore } from '@/store';
|
|||
const globalStore = GlobalStore();
|
||||
|
||||
// backup-agent
|
||||
export const getLocalBackupDir = () => {
|
||||
return http.get<string>(`/backups/local`);
|
||||
export const getLocalBackupDir = (node?: string) => {
|
||||
const params = node ? `?operateNode=${node}` : '';
|
||||
return http.get<string>(`/backups/local${params}`);
|
||||
};
|
||||
export const searchBackup = (params: Backup.SearchWithType) => {
|
||||
return http.post<ResPage<Backup.BackupInfo>>(`/backups/search`, params);
|
||||
|
|
@ -40,35 +41,42 @@ export const listBucket = (params: Backup.ForBucket) => {
|
|||
}
|
||||
return http.post('/backups/buckets', request, TimeoutEnum.T_40S);
|
||||
};
|
||||
export const handleBackup = (params: Backup.Backup) => {
|
||||
return http.post(`/backups/backup`, params, TimeoutEnum.T_10M);
|
||||
export const handleBackup = (params: Backup.Backup, node?: string) => {
|
||||
const query = node ? `?operateNode=${node}` : '';
|
||||
return http.post(`/backups/backup${query}`, params, TimeoutEnum.T_10M);
|
||||
};
|
||||
export const listBackupOptions = () => {
|
||||
return http.get<Array<Backup.BackupOption>>(`/backups/options`);
|
||||
};
|
||||
export const handleRecover = (params: Backup.Recover) => {
|
||||
return http.post(`/backups/recover`, params, TimeoutEnum.T_10M);
|
||||
export const handleRecover = (params: Backup.Recover, node?: string) => {
|
||||
const query = node ? `?operateNode=${node}` : '';
|
||||
return http.post(`/backups/recover${query}`, params, TimeoutEnum.T_10M);
|
||||
};
|
||||
export const handleRecoverByUpload = (params: Backup.Recover) => {
|
||||
return http.post(`/backups/recover/byupload`, params, TimeoutEnum.T_10M);
|
||||
};
|
||||
export const downloadBackupRecord = (params: Backup.RecordDownload) => {
|
||||
return http.post<string>(`/backups/record/download`, params, TimeoutEnum.T_10M);
|
||||
export const downloadBackupRecord = (params: Backup.RecordDownload, node?: string) => {
|
||||
const query = node ? `?operateNode=${node}` : '';
|
||||
return http.post<string>(`/backups/record/download${query}`, params, TimeoutEnum.T_10M);
|
||||
};
|
||||
export const deleteBackupRecord = (params: { ids: number[] }) => {
|
||||
return http.post(`/backups/record/del`, params);
|
||||
export const deleteBackupRecord = (params: { ids: number[] }, node?: string) => {
|
||||
const query = node ? `?operateNode=${node}` : '';
|
||||
return http.post(`/backups/record/del${query}`, params);
|
||||
};
|
||||
export const updateRecordDescription = (id: Number, description: String) => {
|
||||
return http.post(`/backups/record/description/update`, { id: id, description: description });
|
||||
export const updateRecordDescription = (id: Number, description: String, node?: string) => {
|
||||
const query = node ? `?operateNode=${node}` : '';
|
||||
return http.post(`/backups/record/description/update${query}`, { id: id, description: description });
|
||||
};
|
||||
export const uploadByRecover = (filePath: string, targetDir: String) => {
|
||||
return http.post(`/backups/upload`, { filePath: filePath, targetDir: targetDir });
|
||||
};
|
||||
export const searchBackupRecords = (params: Backup.SearchBackupRecord) => {
|
||||
return http.post<ResPage<Backup.RecordInfo>>(`/backups/record/search`, params, TimeoutEnum.T_5M);
|
||||
export const searchBackupRecords = (params: Backup.SearchBackupRecord, node?: string) => {
|
||||
const query = node ? `?operateNode=${node}` : '';
|
||||
return http.post<ResPage<Backup.RecordInfo>>(`/backups/record/search${query}`, params, TimeoutEnum.T_5M);
|
||||
};
|
||||
export const loadRecordSize = (param: Backup.SearchForSize) => {
|
||||
return http.post<Array<Backup.RecordFileSize>>(`/backups/record/size`, param);
|
||||
export const loadRecordSize = (param: Backup.SearchForSize, node?: string) => {
|
||||
const query = node ? `?operateNode=${node}` : '';
|
||||
return http.post<Array<Backup.RecordFileSize>>(`/backups/record/size${query}`, param);
|
||||
};
|
||||
export const searchBackupRecordsByCronjob = (params: Backup.SearchBackupRecordByCronjob) => {
|
||||
return http.post<ResPage<Backup.RecordInfo>>(`/backups/record/search/bycronjob`, params, TimeoutEnum.T_5M);
|
||||
|
|
|
|||
|
|
@ -3,8 +3,9 @@ import { ResPage, SearchWithPage } from '../interface';
|
|||
import { Cronjob } from '../interface/cronjob';
|
||||
import { TimeoutEnum } from '@/enums/http-enum';
|
||||
|
||||
export const searchCronjobPage = (params: Cronjob.Search) => {
|
||||
return http.post<ResPage<Cronjob.CronjobInfo>>(`/cronjobs/search`, params);
|
||||
export const searchCronjobPage = (params: Cronjob.Search, node?: string) => {
|
||||
const query = node ? `?operateNode=${node}` : '';
|
||||
return http.post<ResPage<Cronjob.CronjobInfo>>(`/cronjobs/search${query}`, params);
|
||||
};
|
||||
|
||||
export const loadNextHandle = (spec: string) => {
|
||||
|
|
@ -58,12 +59,14 @@ export const cleanRecords = (id: number, cleanData: boolean, cleanRemoteData: bo
|
|||
return http.post(`cronjobs/records/clean`, { cronjobID: id, cleanData: cleanData, cleanRemoteData });
|
||||
};
|
||||
|
||||
export const updateStatus = (params: Cronjob.UpdateStatus) => {
|
||||
return http.post(`cronjobs/status`, params);
|
||||
export const updateStatus = (params: Cronjob.UpdateStatus, node?: string) => {
|
||||
const query = node ? `?operateNode=${node}` : '';
|
||||
return http.post(`cronjobs/status${query}`, params);
|
||||
};
|
||||
|
||||
export const handleOnce = (id: number) => {
|
||||
return http.post(`cronjobs/handle`, { id: id });
|
||||
export const handleOnce = (id: number, node?: string) => {
|
||||
const query = node ? `?operateNode=${node}` : '';
|
||||
return http.post(`cronjobs/handle${query}`, { id: id });
|
||||
};
|
||||
|
||||
export const searchScript = (params: SearchWithPage) => {
|
||||
|
|
|
|||
|
|
@ -30,8 +30,9 @@ export const bindPostgresqlUser = (params: Database.PgBind) => {
|
|||
export const changePrivileges = (params: Database.PgChangePrivileges) => {
|
||||
return http.post(`/databases/pg/privileges`, params, TimeoutEnum.T_40S);
|
||||
};
|
||||
export const searchPostgresqlDBs = (params: Database.SearchDBWithPage) => {
|
||||
return http.post<ResPage<Database.PostgresqlDBInfo>>(`/databases/pg/search`, params);
|
||||
export const searchPostgresqlDBs = (params: Database.SearchDBWithPage, node?: string) => {
|
||||
const query = node ? `?operateNode=${node}` : '';
|
||||
return http.post<ResPage<Database.PostgresqlDBInfo>>(`/databases/pg/search${query}`, params);
|
||||
};
|
||||
export const updatePostgresqlDescription = (params: DescriptionUpdate) => {
|
||||
return http.post(`/databases/pg/description`, params);
|
||||
|
|
@ -54,8 +55,9 @@ export const deletePostgresqlDB = (params: Database.PostgresqlDBDelete) => {
|
|||
};
|
||||
|
||||
// mysql
|
||||
export const searchMysqlDBs = (params: Database.SearchDBWithPage) => {
|
||||
return http.post<ResPage<Database.MysqlDBInfo>>(`/databases/search`, params);
|
||||
export const searchMysqlDBs = (params: Database.SearchDBWithPage, node?: string) => {
|
||||
const query = node ? `?operateNode=${node}` : '';
|
||||
return http.post<ResPage<Database.MysqlDBInfo>>(`/databases/search${query}`, params);
|
||||
};
|
||||
export const addMysqlDB = (params: Database.MysqlDBCreate) => {
|
||||
let request = deepCopy(params) as Database.MysqlDBCreate;
|
||||
|
|
@ -152,8 +154,9 @@ export const getDatabase = (name: string) => {
|
|||
export const searchDatabases = (params: Database.SearchDatabasePage) => {
|
||||
return http.post<ResPage<Database.DatabaseInfo>>(`/databases/db/search`, params);
|
||||
};
|
||||
export const listDatabases = (type: string) => {
|
||||
return http.get<Array<Database.DatabaseOption>>(`/databases/db/list/${type}`);
|
||||
export const listDatabases = (type: string, node?: string) => {
|
||||
const query = node ? `?operateNode=${node}` : '';
|
||||
return http.get<Array<Database.DatabaseOption>>(`/databases/db/list/${type}${query}`);
|
||||
};
|
||||
export const listDbItems = (type: string) => {
|
||||
return http.get<Array<Database.DbItem>>(`/databases/db/item/${type}`);
|
||||
|
|
|
|||
|
|
@ -6,8 +6,9 @@ import { TimeoutEnum } from '@/enums/http-enum';
|
|||
import { deepCopy } from '@/utils/util';
|
||||
import { Base64 } from 'js-base64';
|
||||
|
||||
export const searchWebsites = (req: Website.WebSiteSearch) => {
|
||||
return http.post<ResPage<Website.WebsiteRes>>(`/websites/search`, req);
|
||||
export const searchWebsites = (req: Website.WebSiteSearch, node?: string) => {
|
||||
const params = node ? `?operateNode=${node}` : '';
|
||||
return http.post<ResPage<Website.WebsiteRes>>(`/websites/search${params}`, req);
|
||||
};
|
||||
|
||||
export const listWebsites = () => {
|
||||
|
|
@ -22,8 +23,9 @@ export const createWebsite = (req: Website.WebSiteCreateReq) => {
|
|||
return http.post<any>(`/websites`, request, TimeoutEnum.T_10M);
|
||||
};
|
||||
|
||||
export const opWebsite = (req: Website.WebSiteOp) => {
|
||||
return http.post<any>(`/websites/operate`, req);
|
||||
export const opWebsite = (req: Website.WebSiteOp, node?: string) => {
|
||||
const query = node ? `?operateNode=${node}` : '';
|
||||
return http.post<any>(`/websites/operate${query}`, req);
|
||||
};
|
||||
|
||||
export const opWebsiteLog = (req: Website.WebSiteOpLog) => {
|
||||
|
|
|
|||
|
|
@ -200,6 +200,7 @@ const secret = ref();
|
|||
const description = ref();
|
||||
const timeoutItem = ref(30);
|
||||
const timeoutUnit = ref('m');
|
||||
const node = ref();
|
||||
|
||||
const open = ref();
|
||||
const isBackup = ref();
|
||||
|
|
@ -212,9 +213,11 @@ interface DialogProps {
|
|||
detailName: string;
|
||||
status: string;
|
||||
appInstallID?: number;
|
||||
node?: string;
|
||||
}
|
||||
const acceptParams = (params: DialogProps): void => {
|
||||
type.value = params.type;
|
||||
node.value = params.node || currentNode.value;
|
||||
if (type.value === 'app') {
|
||||
appInstallID.value = params.appInstallID || 0;
|
||||
loadBackupDir();
|
||||
|
|
@ -235,7 +238,7 @@ const handleBackupClose = () => {
|
|||
};
|
||||
|
||||
const loadBackupDir = async () => {
|
||||
const res = await getLocalBackupDir();
|
||||
const res = await getLocalBackupDir(node.value);
|
||||
backupPath.value = res.data;
|
||||
};
|
||||
|
||||
|
|
@ -244,7 +247,7 @@ const goFile = async () => {
|
|||
};
|
||||
|
||||
const onChange = async (info: any) => {
|
||||
await updateRecordDescription(info.id, info.description);
|
||||
await updateRecordDescription(info.id, info.description, node.value);
|
||||
MsgSuccess(i18n.global.t('commons.msg.operationSuccess'));
|
||||
};
|
||||
|
||||
|
|
@ -257,7 +260,7 @@ const search = async () => {
|
|||
detailName: detailName.value,
|
||||
};
|
||||
loading.value = true;
|
||||
await searchBackupRecords(params)
|
||||
await searchBackupRecords(params, node.value)
|
||||
.then((res) => {
|
||||
loading.value = false;
|
||||
loadSize(params);
|
||||
|
|
@ -270,7 +273,7 @@ const search = async () => {
|
|||
};
|
||||
|
||||
const loadSize = async (params: any) => {
|
||||
await loadRecordSize(params)
|
||||
await loadRecordSize(params, node.value)
|
||||
.then((res) => {
|
||||
let stats = res.data || [];
|
||||
if (stats.length === 0) {
|
||||
|
|
@ -310,7 +313,7 @@ const backup = async () => {
|
|||
description: description.value,
|
||||
};
|
||||
loading.value = true;
|
||||
await handleBackup(params)
|
||||
await handleBackup(params, node.value)
|
||||
.then(() => {
|
||||
loading.value = false;
|
||||
openTaskLog(taskID);
|
||||
|
|
@ -335,7 +338,7 @@ const recover = async (row?: any) => {
|
|||
timeout: timeoutItem.value === -1 ? -1 : transferTimeToSecond(timeoutItem.value + timeoutUnit.value),
|
||||
};
|
||||
loading.value = true;
|
||||
await handleRecover(params)
|
||||
await handleRecover(params, node.value)
|
||||
.then(() => {
|
||||
loading.value = false;
|
||||
openTaskLog(taskID);
|
||||
|
|
@ -374,8 +377,8 @@ const onDownload = async (row: Backup.RecordInfo) => {
|
|||
fileDir: row.fileDir,
|
||||
fileName: row.fileName,
|
||||
};
|
||||
await downloadBackupRecord(params).then(async (res) => {
|
||||
downloadFile(res.data, currentNode.value);
|
||||
await downloadBackupRecord(params, node.value).then(async (res) => {
|
||||
downloadFile(res.data, node.value);
|
||||
});
|
||||
};
|
||||
|
||||
|
|
@ -399,7 +402,7 @@ const onBatchDelete = async (row: Backup.RecordInfo | null) => {
|
|||
i18n.global.t('commons.button.backup'),
|
||||
i18n.global.t('commons.button.delete'),
|
||||
]),
|
||||
params: { ids: ids },
|
||||
params: { ids: ids, node: node.value },
|
||||
});
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -2,11 +2,11 @@
|
|||
<div>
|
||||
<el-card :style="{ height: height }" class="home-card">
|
||||
<div class="header">
|
||||
<div class="header-left">
|
||||
<div class="header-left flex flex-wrap gap-3">
|
||||
<span class="header-span">{{ header }}</span>
|
||||
<slot name="header-l" />
|
||||
</div>
|
||||
<div class="header-right">
|
||||
<div class="header-right flex flex-wrap gap-3">
|
||||
<slot name="header-r" />
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -126,7 +126,7 @@ html {
|
|||
}
|
||||
|
||||
.search-button {
|
||||
width: 250px;
|
||||
width: 200px;
|
||||
}
|
||||
|
||||
.drawer-header-button {
|
||||
|
|
@ -351,3 +351,42 @@ html {
|
|||
--el-dialog-padding-primary: 0px !important;
|
||||
}
|
||||
}
|
||||
|
||||
.node-dashboard-card {
|
||||
.header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
.header-left {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
|
||||
.header-span {
|
||||
position: relative;
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
margin-left: 18px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
&::before {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
left: -13px;
|
||||
width: 4px;
|
||||
height: 14px;
|
||||
content: '';
|
||||
background: $primary-color;
|
||||
border-radius: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.header-right {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -64,6 +64,8 @@ import { reactive, ref, nextTick } from 'vue';
|
|||
import { ElForm, FormInstance } from 'element-plus';
|
||||
import { Rules } from '@/global/form-rules';
|
||||
import Terminal from '@/components/terminal/index.vue';
|
||||
import { useGlobalStore } from '@/composables/useGlobalStore';
|
||||
const { currentNode } = useGlobalStore();
|
||||
|
||||
const title = ref();
|
||||
const terminalVisible = ref(false);
|
||||
|
|
@ -74,6 +76,7 @@ const form = reactive({
|
|||
user: '',
|
||||
containerID: '',
|
||||
containerIDList: [],
|
||||
node: '',
|
||||
});
|
||||
const formRef = ref();
|
||||
const terminalRef = ref<InstanceType<typeof Terminal> | null>(null);
|
||||
|
|
@ -81,6 +84,7 @@ const terminalRef = ref<InstanceType<typeof Terminal> | null>(null);
|
|||
interface DialogProps {
|
||||
containerID: string;
|
||||
title: string;
|
||||
node?: string;
|
||||
}
|
||||
const acceptParams = async (params: DialogProps): Promise<void> => {
|
||||
terminalVisible.value = true;
|
||||
|
|
@ -90,6 +94,7 @@ const acceptParams = async (params: DialogProps): Promise<void> => {
|
|||
form.isCustom = false;
|
||||
form.user = '';
|
||||
form.command = '/bin/sh';
|
||||
form.node = params.node || currentNode.value;
|
||||
terminalOpen.value = false;
|
||||
};
|
||||
|
||||
|
|
@ -105,7 +110,7 @@ const initTerm = (formEl: FormInstance | undefined) => {
|
|||
await nextTick();
|
||||
terminalRef.value!.acceptParams({
|
||||
endpoint: '/api/v2/containers/exec',
|
||||
args: `source=container&containerid=${form.containerID}&user=${form.user}&command=${form.command}`,
|
||||
args: `source=container&containerid=${form.containerID}&user=${form.user}&command=${form.command}&node=${form.node}`,
|
||||
error: '',
|
||||
initCmd: '',
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue