feat:ak

This commit is contained in:
cxymds
2025-03-03 15:20:09 +08:00
parent 98410d7168
commit e9bfe7f1a8
3 changed files with 108 additions and 137 deletions
+41 -36
View File
@@ -1,65 +1,67 @@
<script setup lang="ts">
import { ref } from 'vue';
const message = useMessage();
const emit = defineEmits<Emits>();
const { getServiceAccount, updateServiceAccount } = useAccessKeys();
import { ref } from "vue"
const message = useMessage()
const emit = defineEmits<Emits>()
const { getServiceAccount, updateServiceAccount } = useAccessKeys()
const visible = ref(false);
const visible = ref(false)
const defaultFormModal = {
accesskey: '',
secretkey: '',
name: '',
description: '',
accesskey: "",
secretkey: "",
name: "",
description: "",
expiry: null,
policy: '',
status: 'on',
};
const formModel = ref({ ...defaultFormModal });
policy: "",
status: "on",
}
const formModel = ref({ ...defaultFormModal })
const accessKey = ref<string>('');
const accessKey = ref<string>("")
async function openDialog(row: any) {
accessKey.value = row.accessKey;
accessKey.value = row.accessKey
try {
const res = await getServiceAccount(row.accessKey);
formModel.value = res;
formModel.value.accesskey = row.accessKey;
formModel.value.expiry = res.expiration;
formModel.value.status = res.accountStatus;
visible.value = true;
const res = await getServiceAccount(row.accessKey)
formModel.value = res
formModel.value.accesskey = row.accessKey
formModel.value.expiry = res.expiration
formModel.value.status = res.accountStatus
visible.value = true
} catch (error) {
message.error('获取数据失败');
message.error("获取数据失败")
}
}
defineExpose({ openDialog });
defineExpose({ openDialog })
interface Emits {
(e: 'search'): void;
(e: "search"): void
}
function closeModal() {
visible.value = false;
visible.value = false
}
function dateDisabled(ts: number) {
const date = new Date(ts);
return date < new Date();
const date = new Date(ts)
return date < new Date()
}
async function submitForm() {
try {
const res = await updateServiceAccount(accessKey.value, {
...formModel.value,
policy: formModel.value.policy || '{}',
expiry: new Date(formModel.value.expiry || '').toISOString(),
});
message.success('修改成功');
closeModal();
emit('search');
newPolicy: formModel.value.policy || "{}", // 可选,新策略
newStatus: formModel.value.status, // 可选,新状态
newName: formModel.value.name, // 可选,新名称
newDescription: formModel.value.description, // 可选,新描述
newExpiration: new Date(formModel.value.expiry || "").toISOString(), // 可选,新过期时间
})
message.success("修改成功")
closeModal()
emit("search")
} catch (error) {
message.error('修改失败');
message.error("修改失败")
}
}
</script>
@@ -78,7 +80,10 @@ async function submitForm() {
<n-card>
<n-form label-placement="left" :model="formModel" label-align="right" :label-width="90">
<n-grid :cols="24" :x-gap="18">
<n-form-item-grid-item :span="24" label="Access Key" path="policy">
<n-form-item-grid-item :span="24" label="Access Key" path="accesskey">
<n-input v-model:value="formModel.accesskey" disabled />
</n-form-item-grid-item>
<n-form-item-grid-item :span="24" label="策略" path="policy">
<json-editor v-model="formModel.policy" />
</n-form-item-grid-item>
<!-- TODO: 时间格式有问题 -->
+7 -12
View File
@@ -1,13 +1,13 @@
import { name } from './../node_modules/@jsep-plugin/regex/types/tsd.d'
import { name } from "./../node_modules/@jsep-plugin/regex/types/tsd.d"
export const useAccessKeys = () => {
const { $api } = useNuxtApp()
const listUserServiceAccounts = async (params: object) => {
return await $api.get('/list-service-accounts', { params })
return await $api.get("/list-service-accounts", { params })
}
const createServiceAccount = async (data: any) => {
return await $api.put('/add-service-accounts', data)
return await $api.put("/add-service-accounts", data)
}
// const deleteMultipleServiceAccounts = async (data: any) => {
@@ -15,20 +15,15 @@ export const useAccessKeys = () => {
// }
const getServiceAccount = async (name: string) => {
return await $api.get(
`/info-service-account?accessKey=${encodeURIComponent(name)}`
)
return await $api.get(`/info-service-account?accessKey=${encodeURIComponent(name)}`)
}
const updateServiceAccount = async (name: string, data: any) => {
return await $api.post(`/update-service-account`, data)
return await $api.post(`/update-service-account?accessKey=${encodeURIComponent(name)}`, data)
}
const deleteServiceAccount = async (name: string) => {
return await $api.delete(
`/delete-service-accounts?accessKey==${encodeURIComponent(name)}`,
{}
)
return await $api.delete(`/delete-service-accounts?accessKey=${encodeURIComponent(name)}`, {})
}
const createServiceAccountCreds = async (data: any) => {
@@ -41,7 +36,7 @@ export const useAccessKeys = () => {
deleteServiceAccount,
createServiceAccountCreds,
updateServiceAccount,
getServiceAccount
getServiceAccount,
// deleteMultipleServiceAccounts
}
}
+60 -89
View File
@@ -6,10 +6,7 @@
</template>
<template #actions>
<NFlex>
<NButton
:disabled="!checkedKeys.length"
secondary
@click="deleteByList">
<NButton :disabled="!checkedKeys.length" secondary @click="deleteByList">
<template #icon>
<Icon name="ri:delete-bin-5-line"></Icon>
</template>
@@ -32,12 +29,7 @@
</page-header>
<page-content>
<n-form
class="mb-4"
ref="formRef"
:model="searchForm"
label-placement="left"
:show-feedback="false">
<n-form class="mb-4" ref="formRef" :model="searchForm" label-placement="left" :show-feedback="false">
<n-flex justify="space-between">
<n-form-item label="" path="name">
<n-input placeholder="搜索访问秘钥" @input="filterName" />
@@ -58,33 +50,17 @@
:row-key="rowKey"
@update:checked-row-keys="handleCheck" />
</page-content>
<NewItem
ref="newItemRef"
v-model:visible="newItemVisible"
@search="getDataList"
@notice="noticeDialog" />
<NewItem ref="newItemRef" v-model:visible="newItemVisible" @search="getDataList" @notice="noticeDialog" />
<EditItem ref="editItemRef" @search="getDataList" />
<ChangePassword
ref="changePasswordModalRef"
v-model:visible="changePasswordVisible"
@search="getDataList" />
<users-user-notice
ref="noticeRef"
@search="getDataList"></users-user-notice>
<ChangePassword ref="changePasswordModalRef" v-model:visible="changePasswordVisible" @search="getDataList" />
<users-user-notice ref="noticeRef" @search="getDataList"></users-user-notice>
</div>
</template>
<script lang="ts" setup>
import {
type DataTableColumns,
type DataTableInst,
type DataTableRowKey,
NButton,
NPopconfirm,
NSpace
} from 'naive-ui'
import { Icon } from '#components'
import { ChangePassword, EditItem, NewItem } from '~/components/access-keys'
import { type DataTableColumns, type DataTableInst, type DataTableRowKey, NButton, NPopconfirm, NSpace } from "naive-ui"
import { Icon } from "#components"
import { ChangePassword, EditItem, NewItem } from "~/components/access-keys"
const { $api } = useNuxtApp()
const dialog = useDialog()
@@ -92,7 +68,7 @@ const message = useMessage()
const { listUserServiceAccounts, deleteServiceAccount } = useAccessKeys()
const searchForm = reactive({
name: ''
name: "",
})
interface RowData {
accessKey: string
@@ -105,85 +81,85 @@ interface RowData {
const columns: DataTableColumns<RowData> = [
{
type: 'selection'
type: "selection",
},
{
title: 'Access Key',
align: 'center',
key: 'accessKey',
title: "Access Key",
align: "center",
key: "accessKey",
filter(value, row) {
return !!row.accessKey.includes(value.toString())
}
},
},
{
title: '有效期',
align: 'center',
key: 'expiration'
title: "有效期",
align: "center",
key: "expiration",
},
{
title: '状态',
align: 'center',
key: 'accountStatus',
title: "状态",
align: "center",
key: "accountStatus",
render: (row: any) => {
return row.accountStatus === 'on' ? '可用' : '禁用'
}
return row.accountStatus === "on" ? "可用" : "禁用"
},
},
{
title: '名称',
align: 'center',
key: 'name'
title: "名称",
align: "center",
key: "name",
},
{
title: '描述',
align: 'center',
key: 'description'
title: "描述",
align: "center",
key: "description",
},
{
title: '操作',
key: 'actions',
align: 'center',
title: "操作",
key: "actions",
align: "center",
width: 180,
render: (row: any) => {
return h(
NSpace,
{
justify: 'center'
justify: "center",
},
{
default: () => [
h(
NButton,
{
size: 'small',
size: "small",
secondary: true,
onClick: () => openEditItem(row)
onClick: () => openEditItem(row),
},
{
default: () => '',
icon: () => h(Icon, { name: 'ri:edit-2-line' })
default: () => "",
icon: () => h(Icon, { name: "ri:edit-2-line" }),
}
),
h(
NPopconfirm,
{ onPositiveClick: () => deleteItem(row) },
{
default: () => '确认删除',
default: () => "确认删除",
trigger: () =>
h(
NButton,
{ size: 'small', secondary: true },
{ size: "small", secondary: true },
{
default: () => '',
icon: () => h(Icon, { name: 'ri:delete-bin-5-line' })
default: () => "",
icon: () => h(Icon, { name: "ri:delete-bin-5-line" }),
}
)
),
}
)
]
),
],
}
)
}
}
},
},
]
// 搜索过滤
@@ -191,7 +167,7 @@ const tableRef = ref<DataTableInst>()
function filterName(value: string) {
tableRef.value &&
tableRef.value.filter({
accessKey: [value]
accessKey: [value],
})
}
const listData = ref<any[]>([])
@@ -203,14 +179,9 @@ onMounted(() => {
const getDataList = async () => {
try {
const res = await listUserServiceAccounts({})
listData.value =
res.accounts.map((item: string) => {
return {
name: item
}
}) || []
listData.value = res.accounts || []
} catch (error) {
message.error('获取数据失败')
message.error("获取数据失败")
}
}
@@ -252,10 +223,10 @@ async function deleteItem(row: any) {
try {
const res = deleteServiceAccount(row.accessKey)
message.success('删除成功')
message.success("删除成功")
getDataList()
} catch (error) {
message.error('删除失败')
message.error("删除失败")
}
}
@@ -271,25 +242,25 @@ function handleCheck(keys: DataTableRowKey[]) {
}
function deleteByList() {
dialog.error({
title: '警告',
content: '你确定要删除所有选中的秘钥吗?',
positiveText: '确定',
negativeText: '取消',
title: "警告",
content: "你确定要删除所有选中的秘钥吗?",
positiveText: "确定",
negativeText: "取消",
onPositiveClick: async () => {
if (!checkedKeys.value.length) {
message.error('请至少选择一项')
message.error("请至少选择一项")
return
}
try {
const res = await $api.delete('/service-accounts/delete-multi', {
body: checkedKeys.value
const res = await $api.delete("/service-accounts/delete-multi", {
body: checkedKeys.value,
})
message.success('删除成功')
message.success("删除成功")
getDataList()
} catch (error) {
message.error('删除失败')
message.error("删除失败")
}
}
},
})
}
</script>