jcloud/dashboard/src/components/SiteDatabaseAccessDialog.vue
2025-12-28 22:48:22 +08:00

263 lines
6.3 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<Dialog
:options="{
title: '管理数据库用户',
size: planSupportsDatabaseAccess ? '3xl' : 'xl',
}"
v-model="show"
>
<template #body-content>
<!-- 当前计划不可用推荐升级计划 -->
<div v-if="!planSupportsDatabaseAccess">
<div>
<p class="text-base">
数据库访问在当前计划中不可用<br />请升级到更高计划以使用此功能
</p>
<Button
class="mt-4 w-full"
variant="solid"
@click="showChangePlanDialog = true"
>
升级站点计划
</Button>
<ManageSitePlansDialog
:site="site"
v-model="showChangePlanDialog"
v-if="showChangePlanDialog"
/>
</div>
</div>
<!-- 当前计划可用 -->
<div v-else>
<ObjectList :options="listOptions" />
</div>
</template>
</Dialog>
<SiteDatabaseUserCredentialDialog
:name="selectedUser"
v-model="showDatabaseUserCredentialDialog"
v-if="showDatabaseUserCredentialDialog"
/>
<SiteDatabaseAddEditUserDialog
:site="site"
:key="selectedUser ? selectedUser : 'new'"
:db_user_name="selectedUser"
v-model="showDatabaseAddEditUserDialog"
v-if="showDatabaseAddEditUserDialog"
@success="this.hideSiteDatabaseAddEditUserDialog"
/>
</template>
<script>
import { defineAsyncComponent } from 'vue';
import { getCachedDocumentResource } from 'jingrow-ui';
import ClickToCopyField from './ClickToCopyField.vue';
import ObjectList from './ObjectList.vue';
import { date } from '../utils/format';
import { confirmDialog, icon } from '../utils/components';
import SiteDatabaseUserCredentialDialog from './site_database_user/SiteDatabaseUserCredentialDialog.vue';
import SiteDatabaseAddEditUserDialog from './site_database_user/SiteDatabaseAddEditUserDialog.vue';
import { toast } from 'vue-sonner';
export default {
name: 'SiteDatabaseAccessDialog',
props: ['site'],
components: {
ManageSitePlansDialog: defineAsyncComponent(
() => import('./ManageSitePlansDialog.vue'),
),
ClickToCopyField,
ObjectList,
SiteDatabaseUserCredentialDialog,
SiteDatabaseAddEditUserDialog,
},
data() {
return {
mode: 'read_only',
show: true,
showChangePlanDialog: false,
selectedUser: '',
showDatabaseUserCredentialDialog: false,
showDatabaseAddEditUserDialog: false,
};
},
watch: {
showDatabaseUserCredentialDialog(val) {
if (!val) {
this.show = true;
}
},
showDatabaseAddEditUserDialog(val) {
if (!val) {
this.show = true;
}
},
},
resources: {
deleteSiteDatabaseUser() {
return {
url: 'jcloud.api.client.run_pg_method',
onSuccess() {
toast.success('数据库用户即将被删除');
},
onError(err) {
toast.error(
err.messages.length
? err.messages.join('\n')
: '无法启动数据库用户删除',
);
},
};
},
},
computed: {
listOptions() {
return {
pagetype: 'Site Database User',
filters: {
site: this.site,
status: ['!=', 'Archived'],
},
searchField: 'label',
filterControls() {
return [
{
type: 'select',
label: '状态',
fieldname: 'status',
options: ['', 'Pending', 'Active', 'Failed'],
},
];
},
columns: [
{
label: '标签',
fieldname: 'label',
width: '150px',
},
{
label: '状态',
fieldname: 'status',
width: 0.5,
align: 'center',
type: 'Badge',
},
{
label: '数据库连接',
fieldname: 'max_connections',
width: 0.5,
align: 'center',
format: (value) => `${value} 连接` + (value > 1 ? 's' : ''),
},
{
label: '模式',
fieldname: 'mode',
width: 0.5,
align: 'center',
format: (value, row) => {
return {
read_only: '只读',
read_write: '读写',
granular: '细粒度',
}[value];
},
},
{
label: '创建时间',
fieldname: 'creation',
width: 0.5,
align: 'center',
format: (value) => date(value, 'll'),
},
],
rowActions: ({ row, listResource, documentResource }) => {
if (row.status === 'Archived' || row.status === 'Pending') {
return [];
}
return [
{
label: '查看凭证',
onClick: () => {
this.show = false;
this.selectedUser = row.name;
this.showDatabaseUserCredentialDialog = true;
},
},
{
label: '配置用户',
onClick: () => {
this.selectedUser = row.name;
this.show = false;
this.showDatabaseAddEditUserDialog = true;
},
},
{
label: '删除用户',
onClick: () => {
this.show = false;
confirmDialog({
title: '删除数据库用户',
message: `确定要删除该数据库用户吗?<br>`,
primaryAction: {
label: '删除',
variant: 'solid',
theme: 'red',
onClick: ({ hide }) => {
this.$resources.deleteSiteDatabaseUser.submit({
dt: 'Site Database User',
dn: row.name,
method: 'archive',
});
this.$resources.deleteSiteDatabaseUser.promise.then(
() => {
hide();
this.show = true;
},
);
return this.$resources.deleteSiteDatabaseUser.promise;
},
},
onSuccess: () => {
listResource.refresh();
},
});
},
},
];
},
primaryAction: () => {
return {
label: '添加用户',
variant: 'solid',
slots: {
prefix: icon('plus'),
},
onClick: () => {
this.show = false;
this.selectedUser = null;
this.showDatabaseAddEditUserDialog = true;
},
};
},
};
},
sitePlan() {
return this.$site.pg.current_plan;
},
planSupportsDatabaseAccess() {
return this.sitePlan?.database_access;
},
$site() {
return getCachedDocumentResource('Site', this.site);
},
},
methods: {
hideSiteDatabaseAddEditUserDialog() {
this.showDatabaseAddEditUserDialog = false;
},
},
};
</script>