|
@@ -26,12 +26,6 @@
|
|
|
</el-icon>
|
|
|
查询
|
|
|
</el-button>
|
|
|
-<!-- <el-button @click="resetQuery()">-->
|
|
|
-<!-- <el-icon>-->
|
|
|
-<!-- <ele-Refresh />-->
|
|
|
-<!-- </el-icon>-->
|
|
|
-<!-- 重置-->
|
|
|
-<!-- </el-button>-->
|
|
|
<el-button type="primary" @click="addOrEdit()" v-auth="'add'">
|
|
|
<el-icon>
|
|
|
<ele-Plus />
|
|
@@ -42,25 +36,25 @@
|
|
|
</el-form>
|
|
|
<el-table :data="tableData" style="width: 100%" v-loading="loading" row-key="id">
|
|
|
<el-table-column type="selection" width="40" align="center" />
|
|
|
- <el-table-column prop="clientId" label="客户端标识" min-width="140" show-overflow-tooltip></el-table-column>
|
|
|
- <el-table-column prop="name" label="客户端名称" min-width="140" show-overflow-tooltip></el-table-column>
|
|
|
- <el-table-column prop="remark" label="备注" show-overflow-tooltip></el-table-column>
|
|
|
- <el-table-column prop="status" label="状态" width="100" align="center">
|
|
|
+ <el-table-column prop="clientId" label="客户端标识" v-col="'clientId'" min-width="140" show-overflow-tooltip></el-table-column>
|
|
|
+ <el-table-column prop="name" label="客户端名称" v-col="'name'" min-width="140" show-overflow-tooltip></el-table-column>
|
|
|
+ <el-table-column prop="remark" label="备注" v-col="'remark'" show-overflow-tooltip></el-table-column>
|
|
|
+ <el-table-column prop="status" label="状态" v-col="'status'" width="100" align="center">
|
|
|
<template #default="scope">
|
|
|
<el-tag size="small" type="success" v-if="scope.row.status === 'Active'">激活</el-tag>
|
|
|
<el-tag size="small" type="info" v-else-if="scope.row.status === 'Inactive'">未激活</el-tag>
|
|
|
<span v-else>{{ scope.row.status }}</span>
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
-<!-- <el-table-column prop="createdAt" label="创建时间" width="160" align="center"></el-table-column>-->
|
|
|
- <el-table-column label="操作" width="300" align="center" fixed="right">
|
|
|
+ <!-- <el-table-column prop="createdAt" label="创建时间" width="160" align="center"></el-table-column>-->
|
|
|
+ <el-table-column label="操作" width="300" align="center" fixed="right" v-col="'handle'">
|
|
|
<template #default="scope">
|
|
|
<div class="flex-row">
|
|
|
<el-button size="small" text type="primary" @click="viewDetail(scope.row)" v-auth="'view'">查看</el-button>
|
|
|
<el-button size="small" text type="warning" @click="addOrEdit(scope.row)" v-auth="'edit'">编辑</el-button>
|
|
|
<el-button size="small" text type="primary" @click="manageApiAuth(scope.row)" v-auth="'edit'">API权限</el-button>
|
|
|
- <el-button size="small" text type="success" @click="resetSecret(scope.row)" v-auth="'reset_secret'">重置密钥</el-button>
|
|
|
- <el-button size="small" text type="danger" @click="deleteClient(scope.row)" v-auth="'delete'">删除</el-button>
|
|
|
+ <el-button size="small" text type="success" @click="resetSecret(scope.row)" v-auth="'reset'">重置密钥</el-button>
|
|
|
+ <el-button size="small" text type="danger" @click="deleteClient(scope.row)" v-auth="'del'">删除</el-button>
|
|
|
</div>
|
|
|
</template>
|
|
|
</el-table-column>
|
|
@@ -106,14 +100,7 @@
|
|
|
</el-dialog>
|
|
|
|
|
|
<!-- API权限管理对话框 -->
|
|
|
- <el-dialog
|
|
|
- v-model="apiAuthVisible"
|
|
|
- :title="`客户端 '${currentClient.name}' 的API权限管理`"
|
|
|
- width="1100px"
|
|
|
- append-to-body
|
|
|
- destroy-on-close
|
|
|
- class="api-permission-dialog"
|
|
|
- >
|
|
|
+ <el-dialog v-model="apiAuthVisible" :title="`客户端 '${currentClient.name}' 的API权限管理`" width="1100px" append-to-body destroy-on-close class="api-permission-dialog">
|
|
|
<client-api-relation :client-id="currentClient.clientId" @update:apiKeys="handleApiKeysUpdate" />
|
|
|
<template #footer>
|
|
|
<span class="dialog-footer">
|
|
@@ -141,9 +128,9 @@
|
|
|
</div>
|
|
|
<span v-else>-</span>
|
|
|
</el-descriptions-item>
|
|
|
- <el-descriptions-item label="IP白名单">{{ detail.ipWhitelist || '-' }}</el-descriptions-item>
|
|
|
- <el-descriptions-item label="IP黑名单">{{ detail.ipBlacklist || '-' }}</el-descriptions-item>
|
|
|
- <el-descriptions-item label="备注">{{ detail.remark || '-' }}</el-descriptions-item>
|
|
|
+ <el-descriptions-item label="IP白名单">{{ detail.ipWhitelist || "-" }}</el-descriptions-item>
|
|
|
+ <el-descriptions-item label="IP黑名单">{{ detail.ipBlacklist || "-" }}</el-descriptions-item>
|
|
|
+ <el-descriptions-item label="备注">{{ detail.remark || "-" }}</el-descriptions-item>
|
|
|
<el-descriptions-item label="创建时间">{{ detail.createdAt }}</el-descriptions-item>
|
|
|
<el-descriptions-item label="更新时间">{{ detail.updatedAt }}</el-descriptions-item>
|
|
|
</el-descriptions>
|
|
@@ -157,12 +144,7 @@
|
|
|
<!-- 密钥重置结果弹窗 -->
|
|
|
<el-dialog v-model="secretVisible" title="客户端密钥" width="600px" destroy-on-close>
|
|
|
<div class="secret-result">
|
|
|
- <el-alert
|
|
|
- title="请妥善保管以下密钥信息,它仅会显示一次!"
|
|
|
- type="warning"
|
|
|
- :closable="false"
|
|
|
- show-icon
|
|
|
- />
|
|
|
+ <el-alert title="请妥善保管以下密钥信息,它仅会显示一次!" type="warning" :closable="false" show-icon />
|
|
|
<div class="secret-info" v-if="secretResult.clientSecret">
|
|
|
<div class="secret-item">
|
|
|
<div class="secret-label">客户端密钥:</div>
|
|
@@ -212,18 +194,18 @@ const selectedApiKeys = ref<string[]>([]);
|
|
|
const apiAuthVisible = ref(false);
|
|
|
const currentClient = ref<ClientInfo>({} as ClientInfo);
|
|
|
const params = reactive({
|
|
|
- keyWord: '',
|
|
|
- status: '',
|
|
|
+ keyWord: "",
|
|
|
+ status: "",
|
|
|
dateRange: [],
|
|
|
pageNum: 1,
|
|
|
pageSize: 20,
|
|
|
- total: 0
|
|
|
+ total: 0,
|
|
|
});
|
|
|
const tableData = ref<ClientInfo[]>([]);
|
|
|
|
|
|
// 获取列表数据
|
|
|
const getList = async (pageNum?: number) => {
|
|
|
- if (typeof pageNum === 'number') {
|
|
|
+ if (typeof pageNum === "number") {
|
|
|
params.pageNum = pageNum;
|
|
|
}
|
|
|
loading.value = true;
|
|
@@ -238,7 +220,7 @@ const getList = async (pageNum?: number) => {
|
|
|
params.total = 0;
|
|
|
}
|
|
|
} catch (error) {
|
|
|
- ElMessage.error('获取客户端列表失败');
|
|
|
+ ElMessage.error("获取客户端列表失败");
|
|
|
tableData.value = [];
|
|
|
params.total = 0;
|
|
|
} finally {
|
|
@@ -248,35 +230,35 @@ const getList = async (pageNum?: number) => {
|
|
|
|
|
|
// 表单相关
|
|
|
const dialogVisible = ref(false);
|
|
|
-const formTitle = ref('');
|
|
|
+const formTitle = ref("");
|
|
|
const submitLoading = ref(false);
|
|
|
const form = reactive<ClientInfo>({
|
|
|
- clientId: '',
|
|
|
- name: '',
|
|
|
+ clientId: "",
|
|
|
+ name: "",
|
|
|
apiIds: [],
|
|
|
- status: 'Active',
|
|
|
- ipWhitelist: '',
|
|
|
- ipBlacklist: '',
|
|
|
- remark: ''
|
|
|
+ status: "Active",
|
|
|
+ ipWhitelist: "",
|
|
|
+ ipBlacklist: "",
|
|
|
+ remark: "",
|
|
|
});
|
|
|
const rules = {
|
|
|
- clientId: [{ required: false, message: '请输入客户端标识', trigger: 'blur' }],
|
|
|
- name: [{ required: true, message: '请输入客户端名称', trigger: 'blur' }],
|
|
|
- status: [{ required: true, message: '请选择状态', trigger: 'change' }]
|
|
|
+ clientId: [{ required: false, message: "请输入客户端标识", trigger: "blur" }],
|
|
|
+ name: [{ required: true, message: "请输入客户端名称", trigger: "blur" }],
|
|
|
+ status: [{ required: true, message: "请选择状态", trigger: "change" }],
|
|
|
};
|
|
|
|
|
|
// 详情弹窗
|
|
|
const detailVisible = ref(false);
|
|
|
const detail = ref<ClientInfo>({
|
|
|
- clientId: '',
|
|
|
- name: '',
|
|
|
- status: '',
|
|
|
+ clientId: "",
|
|
|
+ name: "",
|
|
|
+ status: "",
|
|
|
});
|
|
|
|
|
|
// 密钥结果弹窗
|
|
|
const secretVisible = ref(false);
|
|
|
const secretResult = ref({
|
|
|
- clientSecret: ''
|
|
|
+ clientSecret: "",
|
|
|
});
|
|
|
|
|
|
// 初始化
|
|
@@ -287,8 +269,8 @@ onMounted(() => {
|
|
|
// 重置查询表单
|
|
|
const resetQuery = () => {
|
|
|
queryRef.value?.resetFields();
|
|
|
- params.keyWord = '';
|
|
|
- params.status = '';
|
|
|
+ params.keyWord = "";
|
|
|
+ params.status = "";
|
|
|
params.dateRange = [];
|
|
|
getList(1);
|
|
|
};
|
|
@@ -297,7 +279,7 @@ const resetQuery = () => {
|
|
|
const addOrEdit = (row?: ClientInfo) => {
|
|
|
resetForm();
|
|
|
if (row && row.id) {
|
|
|
- formTitle.value = '编辑客户端';
|
|
|
+ formTitle.value = "编辑客户端";
|
|
|
// 获取详细信息
|
|
|
api.client.get(row.id).then((res: any) => {
|
|
|
if (res) {
|
|
@@ -306,7 +288,7 @@ const addOrEdit = (row?: ClientInfo) => {
|
|
|
}
|
|
|
});
|
|
|
} else {
|
|
|
- formTitle.value = '新增客户端';
|
|
|
+ formTitle.value = "新增客户端";
|
|
|
dialogVisible.value = true;
|
|
|
}
|
|
|
};
|
|
@@ -318,12 +300,12 @@ const resetForm = () => {
|
|
|
}
|
|
|
Object.assign(form, {
|
|
|
id: undefined,
|
|
|
- clientId: '',
|
|
|
- name: '',
|
|
|
- status: 'Active',
|
|
|
- ipWhitelist: '',
|
|
|
- ipBlacklist: '',
|
|
|
- remark: ''
|
|
|
+ clientId: "",
|
|
|
+ name: "",
|
|
|
+ status: "Active",
|
|
|
+ ipWhitelist: "",
|
|
|
+ ipBlacklist: "",
|
|
|
+ remark: "",
|
|
|
});
|
|
|
};
|
|
|
|
|
@@ -336,20 +318,20 @@ const submitForm = () => {
|
|
|
const apiMethod = form.id ? api.client.edit : api.client.add;
|
|
|
const res = await apiMethod(form);
|
|
|
if (res) {
|
|
|
- ElMessage.success(form.id ? '编辑成功' : '添加成功');
|
|
|
+ ElMessage.success(form.id ? "编辑成功" : "添加成功");
|
|
|
dialogVisible.value = false;
|
|
|
getList(1);
|
|
|
|
|
|
// 如果是新增,显示密钥信息
|
|
|
if (!form.id && res.clientSecret) {
|
|
|
secretResult.value = {
|
|
|
- clientSecret: res.clientSecret
|
|
|
+ clientSecret: res.clientSecret,
|
|
|
};
|
|
|
secretVisible.value = true;
|
|
|
}
|
|
|
}
|
|
|
} catch (error) {
|
|
|
- ElMessage.error(form.id ? '编辑失败' : '添加失败');
|
|
|
+ ElMessage.error(form.id ? "编辑失败" : "添加失败");
|
|
|
} finally {
|
|
|
submitLoading.value = false;
|
|
|
}
|
|
@@ -370,17 +352,17 @@ const viewDetail = (row: ClientInfo) => {
|
|
|
// 重置客户端密钥
|
|
|
const resetSecret = async (row: ClientInfo) => {
|
|
|
try {
|
|
|
- await ElMessageBox.confirm(`确定要重置客户端"${row.name}"的密钥吗?\n注意:重置后原密钥将失效!`, '提示', {
|
|
|
- confirmButtonText: '确定',
|
|
|
- cancelButtonText: '取消',
|
|
|
- type: 'warning'
|
|
|
+ await ElMessageBox.confirm(`确定要重置客户端"${row.name}"的密钥吗?\n注意:重置后原密钥将失效!`, "提示", {
|
|
|
+ confirmButtonText: "确定",
|
|
|
+ cancelButtonText: "取消",
|
|
|
+ type: "warning",
|
|
|
});
|
|
|
|
|
|
const res = await api.client.resetSecret(row.id as number);
|
|
|
if (res) {
|
|
|
- ElMessage.success('密钥重置成功');
|
|
|
+ ElMessage.success("密钥重置成功");
|
|
|
secretResult.value = {
|
|
|
- clientSecret: res.clientSecret
|
|
|
+ clientSecret: res.clientSecret,
|
|
|
};
|
|
|
secretVisible.value = true;
|
|
|
}
|
|
@@ -391,19 +373,19 @@ const resetSecret = async (row: ClientInfo) => {
|
|
|
|
|
|
// 删除客户端
|
|
|
const deleteClient = (row: ClientInfo) => {
|
|
|
- ElMessageBox.confirm(`确定要删除客户端「${row.name}」吗?`, '警告', {
|
|
|
- confirmButtonText: '确定',
|
|
|
- cancelButtonText: '取消',
|
|
|
- type: 'warning'
|
|
|
+ ElMessageBox.confirm(`确定要删除客户端「${row.name}」吗?`, "警告", {
|
|
|
+ confirmButtonText: "确定",
|
|
|
+ cancelButtonText: "取消",
|
|
|
+ type: "warning",
|
|
|
})
|
|
|
.then(async () => {
|
|
|
loading.value = true;
|
|
|
try {
|
|
|
await api.client.delete([row.id as number]);
|
|
|
- ElMessage.success('删除成功');
|
|
|
+ ElMessage.success("删除成功");
|
|
|
getList();
|
|
|
} catch (error) {
|
|
|
- ElMessage.error('删除失败');
|
|
|
+ ElMessage.error("删除失败");
|
|
|
} finally {
|
|
|
loading.value = false;
|
|
|
}
|
|
@@ -415,11 +397,14 @@ const deleteClient = (row: ClientInfo) => {
|
|
|
|
|
|
// 复制文本
|
|
|
const copyText = (text: string) => {
|
|
|
- navigator.clipboard.writeText(text).then(() => {
|
|
|
- ElMessage.success('复制成功');
|
|
|
- }).catch(() => {
|
|
|
- ElMessage.error('复制失败,请手动复制');
|
|
|
- });
|
|
|
+ navigator.clipboard
|
|
|
+ .writeText(text)
|
|
|
+ .then(() => {
|
|
|
+ ElMessage.success("复制成功");
|
|
|
+ })
|
|
|
+ .catch(() => {
|
|
|
+ ElMessage.error("复制失败,请手动复制");
|
|
|
+ });
|
|
|
};
|
|
|
|
|
|
// 处理API Keys更新
|
|
@@ -429,24 +414,24 @@ const handleApiKeysUpdate = (apiKeys: string[]) => {
|
|
|
|
|
|
// 打开API权限管理窗口
|
|
|
const manageApiAuth = (row: ClientInfo) => {
|
|
|
- currentClient.value = {...row};
|
|
|
+ currentClient.value = { ...row };
|
|
|
apiAuthVisible.value = true;
|
|
|
};
|
|
|
|
|
|
// 保存API关联
|
|
|
const saveApiRelations = async () => {
|
|
|
if (!currentClient.value.clientId) {
|
|
|
- ElMessage.warning('客户端信息不完整');
|
|
|
+ ElMessage.warning("客户端信息不完整");
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
apiSaveLoading.value = true;
|
|
|
try {
|
|
|
await api.client.save_apis(currentClient.value.clientId, selectedApiKeys.value);
|
|
|
- ElMessage.success('API权限关联保存成功');
|
|
|
+ ElMessage.success("API权限关联保存成功");
|
|
|
apiAuthVisible.value = false;
|
|
|
} catch (error) {
|
|
|
- ElMessage.error('API权限关联保存失败');
|
|
|
+ ElMessage.error("API权限关联保存失败");
|
|
|
} finally {
|
|
|
apiSaveLoading.value = false;
|
|
|
}
|
|
@@ -494,7 +479,7 @@ const saveApiRelations = async () => {
|
|
|
padding: 15px;
|
|
|
}
|
|
|
/* 深色主题下的样式 */
|
|
|
-[data-theme='dark'] .secret-info {
|
|
|
+[data-theme="dark"] .secret-info {
|
|
|
margin-top: 20px;
|
|
|
background-color: #2f3030;
|
|
|
border-radius: 4px;
|
|
@@ -523,7 +508,7 @@ const saveApiRelations = async () => {
|
|
|
margin-right: 10px;
|
|
|
}
|
|
|
/* 深色主题下的样式 */
|
|
|
-[data-theme='dark'] .secret-value {
|
|
|
+[data-theme="dark"] .secret-value {
|
|
|
flex: 1;
|
|
|
word-break: break-all;
|
|
|
font-family: monospace;
|
|
@@ -533,8 +518,6 @@ const saveApiRelations = async () => {
|
|
|
margin-right: 10px;
|
|
|
}
|
|
|
|
|
|
-
|
|
|
-
|
|
|
.client-detail-tabs {
|
|
|
margin-top: 20px;
|
|
|
}
|