feat : 事件目标UI

This commit is contained in:
马登山
2025-06-19 16:42:44 +08:00
parent 01bee126de
commit 62e868af21
17 changed files with 531 additions and 173 deletions
+142
View File
@@ -0,0 +1,142 @@
<template>
<div>
<page-header>
<template #title>
<h1 class="text-2xl font-bold">{{ t("Event Destinations") }}</h1>
</template>
</page-header>
<page-content class="flex flex-col gap-4">
<div class="flex items-center justify-between">
<div class="flex items-center justify-between">
<n-input v-model:value="searchTerm" :placeholder="t('Search')">
<template #prefix>
<Icon name="ri:search-2-line" />
</template>
</n-input>
</div>
<div class="flex items-center gap-4">
<n-button @click="() => addForm()">
<Icon name="ri:add-line" class="mr-2" />
<span>{{ t("Add Event Destination") }}</span>
</n-button>
<n-button @click="async () => refresh()">
<Icon name="ri:refresh-line" class="mr-2" />
<span>{{ t("Refresh") }}</span>
</n-button>
</div>
</div>
<n-data-table
class="border dark:border-neutral-700 rounded overflow-hidden"
:columns="columns"
:data="filteredData"
:pagination="false"
:bordered="false" />
</page-content>
<events-target-new ref="newFormRef"></events-target-new>
</div>
</template>
<script setup lang="ts">
import { Icon } from "#components";
import { NButton, NSpace, type DataTableColumns, NPopconfirm } from "naive-ui";
import { useI18n } from "vue-i18n";
const message = useMessage();
const { t } = useI18n();
const searchTerm = ref("");
interface RowData {
type: string;
}
const columns: DataTableColumns<RowData> = [
{
title: t("Status"),
key: "bucket",
width: 180,
},
{
title: t("Service"),
key: "endpoint",
},
{
title: t("Actions"),
key: "actions",
align: "center",
width: 140,
render: (row: RowData) => {
return h(
NSpace,
{
justify: "center",
},
{
default: () => [
h(
NPopconfirm,
{ onPositiveClick: () => deleteItem(row) },
{
default: () => t("Confirm Delete"),
trigger: () =>
h(
NButton,
{ size: "small", secondary: true },
{
default: () => "",
icon: () => h(Icon, { name: "ri:delete-bin-5-line" }),
}
),
}
),
],
}
);
},
},
];
const { data, refresh } = await useAsyncData(
"tier",
async () => {
// const response = await usetier.listTiers();
// return response;
return [];
},
{ default: () => [] }
);
const filteredData = computed(() => {
if (!searchTerm.value) {
return data.value;
}
const term = searchTerm.value.toLowerCase();
return data.value.filter(
(tier: any) =>
tier.name.toLowerCase().includes(term) ||
tier.endpoint.toLowerCase().includes(term) ||
tier.bucket.toLowerCase().includes(term)
);
});
const deleteItem = async (row: RowData) => {
// usetier
// .removeTiers(config.name)
// .then(() => {
// message.success(t("Delete Success"));
// refresh();
// })
// .catch((error) => {
// message.error(t("Delete Failed"));
// });
};
const newFormRef = ref();
const addForm = async () => {
newFormRef.value.open();
};
</script>
<style lang="scss" scoped></style>
+77 -67
View File
@@ -2,7 +2,7 @@
<div>
<page-header>
<template #title>
<h1 class="text-2xl font-bold">{{ t('Tiers') }}</h1>
<h1 class="text-2xl font-bold">{{ t("Tiers") }}</h1>
</template>
</page-header>
<page-content class="flex flex-col gap-4">
@@ -18,30 +18,38 @@
<div class="flex items-center gap-4">
<n-button @click="() => addForm()">
<Icon name="ri:add-line" class="mr-2" />
<span>{{ t('Add Tier') }}</span>
<span>{{ t("Add Tier") }}</span>
</n-button>
<n-button @click="async () => refresh()">
<Icon name="ri:refresh-line" class="mr-2" />
<span>{{ t('Refresh') }}</span>
<span>{{ t("Refresh") }}</span>
</n-button>
</div>
</div>
<n-data-table class="border dark:border-neutral-700 rounded overflow-hidden" :columns="columns" :data="filteredData" :pagination="false" :bordered="false" />
<tiers-new-form ref='newFormRef' @search="refresh"></tiers-new-form>
<tiers-change-key v-model:visible="changeKeyVisible" v-model:name="editName" ref='infoRef' @search="refresh"></tiers-change-key>
<n-data-table
class="border dark:border-neutral-700 rounded overflow-hidden"
:columns="columns"
:data="filteredData"
:pagination="false"
:bordered="false" />
<tiers-new-form ref="newFormRef" @search="refresh"></tiers-new-form>
<tiers-change-key
v-model:visible="changeKeyVisible"
v-model:name="editName"
ref="infoRef"
@search="refresh"></tiers-change-key>
</page-content>
</div>
</template>
<script lang="ts" setup>
import { Icon } from '#components'
import dayjs from 'dayjs'
import { NButton, NSpace, type DataTableColumns ,NPopconfirm} from 'naive-ui'
import { useI18n } from 'vue-i18n'
const usetier = useTiers()
import { Icon } from "#components";
import { NButton, NSpace, type DataTableColumns, NPopconfirm } from "naive-ui";
import { useI18n } from "vue-i18n";
const usetier = useTiers();
const { t } = useI18n()
const searchTerm = ref('');
const { t } = useI18n();
const searchTerm = ref("");
interface S3Config {
name: string;
@@ -59,84 +67,84 @@ interface S3Config {
interface RowData {
type: string;
rustfs?: S3Config;
minio?: S3Config;
rustfs?: S3Config;
minio?: S3Config;
s3?: S3Config;
}
const getConfig = (row: RowData): S3Config | undefined =>{
const getConfig = (row: RowData): S3Config | undefined => {
switch (row.type) {
case 'rustfs':
case "rustfs":
return row.rustfs;
case 'minio':
case "minio":
return row.minio;
case 's3':
case "s3":
return row.s3;
}
}
};
const columns: DataTableColumns<RowData> = [
{
title: t('Tier Type'),
key: 'type',
title: t("Tier Type"),
key: "type",
render: (row) => row.type,
},
{
title: t('Name'),
key: 'name',
title: t("Name"),
key: "name",
render: (row) => getConfig(row)?.name,
},
{
title: t('Endpoint'),
key: 'endpoint',
title: t("Endpoint"),
key: "endpoint",
render: (row) => getConfig(row)?.endpoint,
},
{
title: t('Bucket'),
key: 'bucket',
title: t("Bucket"),
key: "bucket",
render: (row) => getConfig(row)?.bucket,
},
{
title: t('Region'),
key: 'region',
{
title: t("Region"),
key: "region",
render: (row) => getConfig(row)?.region,
},
{
title: t('Storage Class'),
key: 'storageclass',
title: t("Storage Class"),
key: "storageclass",
render: (row) => {
// 只有 s3 类型才有 storageclass
if (row.type === 's3') {
if (row.type === "s3") {
return row.s3?.storageclass;
}
return '-';
return "-";
},
},
{
title: t('Usage'),
key: 'usage',
title: t("Usage"),
key: "usage",
render: (row) => getConfig(row)?.usage,
},
{
title: t('Objects'),
key: 'objects',
title: t("Objects"),
key: "objects",
render: (row) => getConfig(row)?.objects,
},
{
title: t('Version'),
key: 'versions',
title: t("Version"),
key: "versions",
render: (row) => getConfig(row)?.versions,
},
{
title: t('Actions'),
key: 'actions',
align: 'center',
title: t("Actions"),
key: "actions",
align: "center",
width: 140,
render: (row: RowData) => {
return h(
NSpace,
{
justify: 'center',
justify: "center",
},
{
default: () => [
@@ -144,7 +152,7 @@ const columns: DataTableColumns<RowData> = [
NPopconfirm,
{ onPositiveClick: () => deleteItem(row) },
{
default: () => t('Confirm Delete'),
default: () => t("Confirm Delete"),
trigger: () =>
h(
NButton,
@@ -159,16 +167,15 @@ const columns: DataTableColumns<RowData> = [
h(
NButton,
{
size: 'small',
size: "small",
secondary: true,
onClick: (e) => handleRowClick(row,e),
onClick: (e) => handleRowClick(row, e),
},
{
default: () => '',
icon: () => h(Icon, { name: 'ri:edit-2-line' }),
default: () => "",
icon: () => h(Icon, { name: "ri:edit-2-line" }),
}
),
],
}
);
@@ -177,10 +184,10 @@ const columns: DataTableColumns<RowData> = [
];
const { data, refresh } = await useAsyncData(
'tier',
"tier",
async () => {
const response = await usetier.listTiers();
return response
return response;
},
{ default: () => [] }
);
@@ -191,17 +198,18 @@ const filteredData = computed(() => {
}
const term = searchTerm.value.toLowerCase();
return data.value.filter((tier:any) =>
tier.name.toLowerCase().includes(term) ||
tier.endpoint.toLowerCase().includes(term) ||
tier.bucket.toLowerCase().includes(term)
return data.value.filter(
(tier: any) =>
tier.name.toLowerCase().includes(term) ||
tier.endpoint.toLowerCase().includes(term) ||
tier.bucket.toLowerCase().includes(term)
);
});
const infoRef = ref();
const changeKeyVisible = ref(false);
const editName = ref();
const handleRowClick = (row: RowData,e: Event) => {
const handleRowClick = (row: RowData, e: Event) => {
e.stopPropagation();
changeKeyVisible.value = true;
editName.value = getConfig(row)?.name;
@@ -209,19 +217,21 @@ const handleRowClick = (row: RowData,e: Event) => {
const message = useMessage();
const deleteItem = async (row: RowData) => {
const config = getConfig(row) || {name:''};
if(!config.name ) return;
usetier.removeTiers(config.name ).then(()=>{
message.success(t('Delete Success'))
refresh();
}).catch((error)=>{
message.error(t('Delete Failed'))
})
const config = getConfig(row) || { name: "" };
if (!config.name) return;
usetier
.removeTiers(config.name)
.then(() => {
message.success(t("Delete Success"));
refresh();
})
.catch((error) => {
message.error(t("Delete Failed"));
});
};
const newFormRef = ref();
const addForm = async () => {
newFormRef.value.open();
};
</script>