feat: 收口知识库分享链路

- 新增 shareKey 单参数 URL 分享页与失效页

- 新增知识库分享后端鉴权、审计与迁移脚本

- 在访问令牌中增加知识库分享授权入口
This commit is contained in:
2026-04-13 14:44:31 +08:00
parent 8cfe5400fe
commit 31a755a8bc
57 changed files with 5158 additions and 143 deletions

View File

@@ -6,7 +6,6 @@ import { onMounted, ref } from 'vue';
import { EasyFlowFormModal } from '@easyflow/common-ui';
import {
ElAlert,
ElCheckbox,
ElCheckboxGroup,
ElDatePicker,
@@ -33,6 +32,7 @@ interface Entity {
deptId: number | string;
expiredAt: Date | null | string;
permissionIds: (number | string)[]; // 绑定值:权限 ID 数组
knowledgeShareEnabled: boolean;
id?: number; // 编辑时的主键
}
@@ -50,6 +50,7 @@ const entity = ref<Entity>({
deptId: '',
expiredAt: null,
permissionIds: [],
knowledgeShareEnabled: false,
});
// 加载状态
const btnLoading = ref(false);
@@ -74,18 +75,30 @@ const rules = ref({
],
});
function openDialog(row: Partial<Entity> = {}) {
async function openDialog(row: Partial<Entity> = {}) {
saveForm.value?.resetFields();
entity.value = {
apiKey: '',
status: '',
deptId: '',
expiredAt: null,
permissionIds: [],
...row,
};
isAdd.value = !row.id;
dialogVisible.value = true;
if (!row.id) {
entity.value = createDefaultEntity(row);
dialogVisible.value = true;
return;
}
btnLoading.value = true;
try {
const res = await api.get('/api/v1/sysApiKey/detail', {
params: { id: row.id },
});
if (res.errorCode !== 0) {
ElMessage.error(res.message || $t('message.getDataError'));
return;
}
entity.value = createDefaultEntity(res.data || row);
dialogVisible.value = true;
} catch {
ElMessage.error($t('message.getDataError'));
} finally {
btnLoading.value = false;
}
}
// 获取资源权限列表
@@ -104,6 +117,33 @@ function getResourcePermissionList() {
});
}
function createDefaultEntity(row: Partial<Entity> = {}): Entity {
const permissionIds = row.permissionIds || [];
const knowledgeShareEnabled = Boolean(row.knowledgeShareEnabled);
return {
apiKey: '',
status: '',
deptId: '',
expiredAt: null,
...row,
permissionIds,
knowledgeShareEnabled,
};
}
function renderPermissionLabel(item: ResourcePermission) {
if (item.requestInterface === '/public-api/bot/chat') {
return '聊天助手调用';
}
if (
item.requestInterface === '/v1/chat/completions' ||
item.requestInterface === '/public-api/openai/v1/chat/completions'
) {
return '统一模型调用';
}
return item.title;
}
// 保存表单
function save() {
saveForm.value?.validate((valid) => {
@@ -142,6 +182,7 @@ function closeDialog() {
deptId: '',
expiredAt: null,
permissionIds: [],
knowledgeShareEnabled: false,
};
isAdd.value = true;
dialogVisible.value = false;
@@ -200,23 +241,27 @@ defineExpose({
:label="$t('sysApiKey.permissions')"
class="permission-form-item"
>
<ElAlert type="info">
接口信息请运行tech.easyflow.publicapi.SyncApis main
方法同步到数据库
</ElAlert>
<ElCheckboxGroup
v-model="entity.permissionIds"
class="permission-checkbox-group"
>
<div class="permission-section">
<ElCheckboxGroup
v-model="entity.permissionIds"
class="permission-checkbox-group"
>
<ElCheckbox
v-for="item in resourcePermissionList"
:key="item.id"
:value="item.id"
class="permission-checkbox"
>
{{ renderPermissionLabel(item) }}
</ElCheckbox>
</ElCheckboxGroup>
<ElCheckbox
v-for="item in resourcePermissionList"
:key="item.id"
:value="item.id"
v-model="entity.knowledgeShareEnabled"
class="permission-checkbox"
>
{{ item.requestInterface }} - {{ item.title }}
{{ $t('sysApiKey.knowledgeSharePermission') }}
</ElCheckbox>
</ElCheckboxGroup>
</div>
</ElFormItem>
</ElForm>
</EasyFlowFormModal>
@@ -230,15 +275,27 @@ defineExpose({
}
.permission-form-item .el-form-item__content {
display: block;
}
.permission-section {
display: flex;
flex-wrap: wrap;
flex-direction: column;
gap: 16px;
width: 100%;
}
.permission-checkbox-group {
display: flex;
flex-direction: column;
gap: 16px;
align-items: flex-start;
}
.permission-checkbox {
display: flex;
align-items: flex-start;
margin: 4px 0;
margin: 0;
}
.form-container::-webkit-scrollbar {