308 lines
7.8 KiB
Vue
308 lines
7.8 KiB
Vue
<template>
|
|
<div class="flex items-center justify-between gap-1">
|
|
<div>
|
|
<h3 class="text-base font-medium">{{ props.actionLabel }}</h3>
|
|
<p class="mt-1 text-p-base text-gray-600">{{ props.description }}</p>
|
|
</div>
|
|
<Button
|
|
v-if="site?.pg"
|
|
class="whitespace-nowrap"
|
|
@click="getSiteActionHandler(props.actionLabel)"
|
|
>
|
|
<p
|
|
:class="
|
|
group === 'Dangerous Actions' ? 'text-red-600' : 'text-gray-800'
|
|
"
|
|
>
|
|
{{ props.buttonLabel }}
|
|
</p>
|
|
</Button>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { getCachedDocumentResource } from 'jingrow-ui';
|
|
import { defineAsyncComponent, h } from 'vue';
|
|
import { toast } from 'vue-sonner';
|
|
import { confirmDialog, renderDialog } from '../utils/components';
|
|
import { getToastErrorMessage } from '../utils/toast';
|
|
import router from '../router';
|
|
import { isLastSite } from '../data/team';
|
|
|
|
const props = defineProps({
|
|
siteName: { type: String, required: true },
|
|
actionLabel: { type: String, required: true },
|
|
method: { type: String, required: true },
|
|
description: { type: String, required: true },
|
|
buttonLabel: { type: String, required: true },
|
|
group: { type: String, required: false }
|
|
});
|
|
|
|
const site = getCachedDocumentResource('Site', props.siteName);
|
|
|
|
function getSiteActionHandler(action) {
|
|
const actionDialogs = {
|
|
'使用文件恢复': defineAsyncComponent(() =>
|
|
import('./SiteDatabaseRestoreDialog.vue')
|
|
),
|
|
'从指定站点恢复': defineAsyncComponent(() =>
|
|
import('./site/SiteDatabaseRestoreFromURLDialog.vue')
|
|
),
|
|
'管理数据库用户': defineAsyncComponent(() =>
|
|
import('./SiteDatabaseAccessDialog.vue')
|
|
),
|
|
'版本升级': defineAsyncComponent(() =>
|
|
import('./site/SiteVersionUpgradeDialog.vue')
|
|
),
|
|
'更改工作台组': defineAsyncComponent(() =>
|
|
import('./site/SiteChangeGroupDialog.vue')
|
|
),
|
|
'更改区域': defineAsyncComponent(() =>
|
|
import('./site/SiteChangeRegionDialog.vue')
|
|
),
|
|
'更改服务器': defineAsyncComponent(() =>
|
|
import('./site/SiteChangeServerDialog.vue')
|
|
)
|
|
};
|
|
if (actionDialogs[action]) {
|
|
const dialog = h(actionDialogs[action], { site: site.pg.name });
|
|
renderDialog(dialog);
|
|
return;
|
|
}
|
|
|
|
const actionHandlers = {
|
|
'激活站点': onActivateSite,
|
|
'停用站点': onDeactivateSite,
|
|
'删除站点': onDropSite,
|
|
'更新数据库': onMigrateSite,
|
|
'计划备份': onScheduleBackup,
|
|
'转移站点': onTransferSite,
|
|
'重置站点': onSiteReset,
|
|
'清除缓存': onClearCache
|
|
};
|
|
if (actionHandlers[action]) {
|
|
actionHandlers[action].call(this);
|
|
}
|
|
}
|
|
|
|
function onDeactivateSite() {
|
|
return confirmDialog({
|
|
title: '停用站点',
|
|
message: `
|
|
您确定要停用此站点吗?<br><br>
|
|
<div class="text-bg-base bg-gray-100 p-2 rounded-md">
|
|
站点将进入<strong>停用</strong>状态。它将无法访问,后台作业也不会运行。
|
|
<br><br>
|
|
<div class="text-red-600">您仍将为此付费。</div>
|
|
</div>
|
|
`,
|
|
primaryAction: {
|
|
label: '停用',
|
|
variant: 'solid',
|
|
theme: 'red',
|
|
onClick({ hide }) {
|
|
toast.success('停用请求已提交');
|
|
hide();
|
|
site.deactivate.submit();
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
function onActivateSite() {
|
|
return confirmDialog({
|
|
title: '激活站点',
|
|
message: `
|
|
您确定要激活此站点吗?
|
|
<br><br>
|
|
<strong>注意:仅在站点损坏且无法访问时作为最后手段使用</strong>
|
|
`,
|
|
primaryAction: {
|
|
label: '激活',
|
|
variant: 'solid',
|
|
onClick({ hide }) {
|
|
toast.success('激活请求已提交');
|
|
hide();
|
|
site.activate.submit();
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
function onDropSite() {
|
|
return confirmDialog({
|
|
title: '删除站点',
|
|
message: `
|
|
您确定要删除您的站点吗?站点将被归档,
|
|
其所有文件和异地备份将被删除。此操作无法撤销。
|
|
`,
|
|
fields: [
|
|
{
|
|
label: '请输入站点名称以确认。',
|
|
fieldname: 'confirmSiteName'
|
|
},
|
|
{
|
|
label: '强制删除站点',
|
|
fieldname: 'force',
|
|
type: 'checkbox'
|
|
}
|
|
],
|
|
primaryAction: {
|
|
label: '删除站点',
|
|
variant: 'solid',
|
|
theme: 'red',
|
|
onClick: async ({ hide, values }) => {
|
|
if (
|
|
![site.pg.name, site.pg.host_name].includes(values.confirmSiteName)
|
|
) {
|
|
throw new Error('站点名称不匹配。');
|
|
}
|
|
|
|
const val = await isLastSite(site.pg.team);
|
|
const FeedbackDialog = defineAsyncComponent(() =>
|
|
import('./ChurnFeedbackDialog.vue')
|
|
);
|
|
|
|
toast.success('删除请求已提交');
|
|
hide();
|
|
site.archive.submit({ force: values.force });
|
|
setTimeout(() => {
|
|
if (val) {
|
|
renderDialog(
|
|
h(FeedbackDialog, {
|
|
team: site.pg.team,
|
|
onUpdated() {
|
|
router.replace({ name: 'Site List' });
|
|
}
|
|
})
|
|
);
|
|
} else {
|
|
router.replace({ name: 'Site List' });
|
|
}
|
|
}, 1000);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
function onMigrateSite() {
|
|
return confirmDialog({
|
|
title: '更新数据库',
|
|
message: `将在您的站点上执行更新数据库命令。您确定要运行此命令吗?我们建议您在继续之前进行数据库备份。
|
|
`,
|
|
fields: [
|
|
{
|
|
label: '如果更新期间补丁失败则跳过(不推荐)',
|
|
fieldname: 'skipFailingPatches',
|
|
type: 'checkbox'
|
|
},
|
|
{
|
|
label: '请输入站点名称以确认。',
|
|
fieldname: 'confirmSiteName'
|
|
}
|
|
],
|
|
primaryAction: {
|
|
label: '更新',
|
|
variant: 'solid',
|
|
theme: 'red',
|
|
onClick: ({ hide, values }) => {
|
|
if (values.confirmSiteName !== site.pg.name) {
|
|
throw new Error('站点名称不匹配');
|
|
}
|
|
toast.success('更新请求已提交');
|
|
hide();
|
|
site.migrate.submit({ skip_failing_patches: values.skipFailingPatches });
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
function onSiteReset() {
|
|
return confirmDialog({
|
|
title: '重置站点',
|
|
message: `
|
|
您的站点中的所有数据都将丢失。您确定要重置数据库吗?
|
|
`,
|
|
fields: [
|
|
{
|
|
label: '请输入站点名称以确认。',
|
|
fieldname: 'confirmSiteName'
|
|
}
|
|
],
|
|
primaryAction: {
|
|
label: '重置',
|
|
variant: 'solid',
|
|
theme: 'red',
|
|
onClick: ({ hide, values }) => {
|
|
if (values.confirmSiteName !== site.pg.name) {
|
|
throw new Error('站点名称不匹配。');
|
|
}
|
|
toast.success('重置请求已提交');
|
|
hide();
|
|
site.reinstall.submit();
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
function onScheduleBackup() {
|
|
return confirmDialog({
|
|
title: '计划备份',
|
|
message:
|
|
'您确定要计划备份吗?这将创建一个现场备份。',
|
|
onSuccess({ hide }) {
|
|
toast.success('备份请求已提交');
|
|
hide();
|
|
site.backup.submit({ with_files: true });
|
|
setTimeout(() => {
|
|
router.push({
|
|
name: 'Site Jobs',
|
|
params: { name: site.name }
|
|
});
|
|
}, 1000);
|
|
}
|
|
});
|
|
}
|
|
|
|
function onTransferSite() {
|
|
return confirmDialog({
|
|
title: '转移站点所有权',
|
|
fields: [
|
|
{
|
|
label: '输入要转移站点所有权的团队的电子邮件地址',
|
|
fieldname: 'email'
|
|
},
|
|
{
|
|
label: '转移原因',
|
|
fieldname: 'reason',
|
|
type: 'textarea'
|
|
}
|
|
],
|
|
primaryAction: {
|
|
label: '转移',
|
|
variant: 'solid',
|
|
onClick: ({ hide, values }) => {
|
|
toast.success(`转移请求已提交至 ${values.email}`);
|
|
hide();
|
|
site.sendTransferRequest.submit({ team_mail_id: values.email, reason: values.reason || '' });
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
function onClearCache() {
|
|
return confirmDialog({
|
|
title: '清除缓存',
|
|
message: `将在您的站点上执行清除缓存的命令。您确定要执行吗?`,
|
|
primaryAction: {
|
|
label: '清除缓存',
|
|
variant: 'solid',
|
|
onClick: ({ hide }) => {
|
|
toast.success('清除缓存请求已提交');
|
|
hide();
|
|
site.clearSiteCache.submit();
|
|
}
|
|
}
|
|
});
|
|
}
|
|
</script> |