diff --git a/frontend/src/components/doc-content.vue b/frontend/src/components/doc-content.vue
index 6ea7bb2a..b8d8f991 100644
--- a/frontend/src/components/doc-content.vue
+++ b/frontend/src/components/doc-content.vue
@@ -13,9 +13,21 @@ import { MessagePlugin, DialogPlugin } from "tdesign-vue-next";
import { sanitizeHTML, safeMarkdownToHTML, createSafeImage, isValidImageURL, hydrateProtectedFileImages, isValidURL } from '@/utils/security';
import { openMermaidFullscreen } from '@/utils/mermaidViewer';
import { useI18n } from 'vue-i18n';
+import { useAuthStore } from '@/stores/auth';
import DocumentPreview from '@/components/document-preview.vue';
const { t } = useI18n();
+const authStore = useAuthStore();
+
+// canDeleteGeneratedQuestion 对应后端 DELETE /chunks/by-id/:id/questions
+// 的 OwnedChunkKBOrAdminFromChunkID 守卫——KB 创建者或租户 Admin+
+// 才允许删除。父组件 KnowledgeBase.vue 通过 :canEditKB 把 KB 级权限
+// 传下来(包含 KB creator / Admin / 组织分享 editor 三种来源),未
+// 传时按更严格的 Admin 兜底,避免 Viewer 看到一个会 403 的入口。
+const canDeleteGeneratedQuestion = computed(() => {
+ if (props.canEditKB === true) return true;
+ return authStore.hasRole('admin');
+});
// Mermaid 初始化计数器,用于生成唯一ID
let mermaidRenderCount = 0;
@@ -48,7 +60,7 @@ mermaid.initialize({
topPadding: 50
}
});
-const props = defineProps(["visible", "details", "knowledgeType", "sourceInfo"]);
+const props = defineProps(["visible", "details", "knowledgeType", "sourceInfo", "canEditKB"]);
const emit = defineEmits(["closeDoc", "getDoc", "questionDeleted"]);
marked.use({
@@ -955,9 +967,10 @@ const handleDetailsScroll = () => {
>
{{ question.question }}
-
@@ -1458,6 +1458,12 @@ const props = defineProps<{
mode: 'create' | 'edit';
agent?: CustomAgent | null;
initialSection?: string;
+ // readOnly hides the save button so a Viewer who clicks an agent
+ // card to inspect its config doesn't see a "确定" that 403s on the
+ // backend update endpoint. Field-level disable is intentionally NOT
+ // wired here yet (the modal has 3000+ lines of form inputs); instead
+ // we just remove the only mutation surface — the footer button.
+ readOnly?: boolean;
}>();
const emit = defineEmits<{
diff --git a/frontend/src/views/agent/AgentList.vue b/frontend/src/views/agent/AgentList.vue
index 435642d7..f29c8a49 100644
--- a/frontend/src/views/agent/AgentList.vue
+++ b/frontend/src/views/agent/AgentList.vue
@@ -89,7 +89,7 @@
{{ agent.name }}