Browse Source

[Mod 0000] AI助手技能和子智能体面板增加非admin禁止修改

wangkeyi 5 ngày trước cách đây
mục cha
commit
cb15ad1e27

+ 8 - 18
src/views/ventAI/manageAssistent/components/AiAssistantModal.vue

@@ -21,13 +21,7 @@
     <div class="collapse-btn" @click="togglePanel">
       <div :class="['collapse-icon', { collapsed: panelCollapsed }]"></div>
     </div>
-    <div
-      class="ai-container"
-      @dragenter="onDragEnter"
-      @dragover="onDragOver"
-      @dragleave="onDragLeave"
-      @drop="onDrop"
-    >
+    <div class="ai-container" @dragenter="onDragEnter" @dragover="onDragOver" @dragleave="onDragLeave" @drop="onDrop">
       <!-- 拖拽经过时的「可放置」提示。pointer-events: none 不能去掉:遮罩一旦能命中,
            它自己会连续触发 dragenter/dragleave,反馈会持续闪断 -->
       <div v-if="isDragOver" class="drop-overlay">
@@ -38,7 +32,6 @@
         <TaskListPanel
           :taskList="taskList"
           :currentTaskId="currentTaskId"
-          :isAdmin="isAdmin"
           @switch-task="switchTask"
           @create-task="createNewTask"
           @delete-task="handleDeleteTask"
@@ -47,9 +40,8 @@
           @toggle-sub-agents="toggleSubAgentPanel"
           @toggle-schedules="toggleSchedulePanel"
         />
-        <!-- [审计-第四轮 M3] 重放自我方 fix/base-agent-token(M1/M2/M3)::isAdmin 透传给左侧任务面板,
-             由面板内部过滤掉「技能」「子智能体」两个管理入口(按钮渲染在 TaskListPanel 的 optionItems 里)。
-             注意「定时任务」不属于全局变更,保持对所有人开放。 -->
+        <!-- 「技能」「子智能体」两个入口对所有角色都显示:角色差异收敛在面板内部
+             (非管理员只读:隐藏创建/编辑/删除、禁用启停开关),而不是把入口整个藏掉。 -->
       </div>
 
       <!-- 右侧内容区:根据 activePanel 切换显示 -->
@@ -156,14 +148,14 @@
         </Transition>
       </template>
 
-      <!-- 技能面板 -->
+      <!-- 技能面板:非管理员只读(面板内部按 isAdmin 隐藏/禁用写操作) -->
       <div v-if="activePanel === 'skill'" class="right-panel full">
-        <SkillPanel @close="activePanel = 'chat'" />
+        <SkillPanel :is-admin="isAdmin" @close="activePanel = 'chat'" />
       </div>
 
-      <!-- 子智能体面板 -->
+      <!-- 子智能体面板:非管理员只读 -->
       <div v-if="activePanel === 'sub-agents'" class="right-panel full">
-        <SubAgentPanel @close="activePanel = 'chat'" />
+        <SubAgentPanel :is-admin="isAdmin" @close="activePanel = 'chat'" />
       </div>
 
       <!-- 定时任务面板 -->
@@ -609,9 +601,7 @@
     syncTodoBarFromMessages();
 
     // 切换任务时检测是否为定时任务会话:自动打开/关闭定时任务详情标签
-    const scheduleItem = newTask.sessionId
-      ? scheduleListForDetail.value.find((s) => s.feedback_session_id === newTask.sessionId)
-      : undefined;
+    const scheduleItem = newTask.sessionId ? scheduleListForDetail.value.find((s) => s.feedback_session_id === newTask.sessionId) : undefined;
     const panelState = getPanelState(newTask);
     const existingScheduleTab = panelState.tabs.find((t) => t.type === 'schedule');
     if (scheduleItem) {

+ 15 - 2
src/views/ventAI/manageAssistent/components/panels/SkillPanel.vue

@@ -3,7 +3,10 @@
     <div class="skill-panel-header">
       <div class="skill-panel-header-left">
         <span class="skill-panel-title">技能</span>
-        <span class="skill-panel-desc">管理模型技能,启用后可在聊天里通过$skill-name使用</span>
+        <span class="skill-panel-desc">
+          管理模型技能,启用后可在聊天里通过$skill-name使用
+          <template v-if="!props.isAdmin">(只读:仅管理员可修改)</template>
+        </span>
       </div>
       <div class="skill-panel-close" @click="emit('close')">
         <div class="close-icon"></div>
@@ -28,7 +31,9 @@
             <div class="skill-item-icon"></div>
             <span class="skill-name">{{ skill.display_name }}</span>
           </div>
-          <a-switch :checked="skill.enabled" size="small" class="skill-switch" @change="handleToggleSkill(skill)" />
+          <!-- 启用/禁用开关同时承担「当前是否启用」的状态展示,因此非管理员保留但禁用,
+               而不是隐藏——隐藏会让人看不到哪些技能是启用状态 -->
+          <a-switch :checked="skill.enabled" :disabled="!props.isAdmin" size="small" class="skill-switch" @change="handleToggleSkill(skill)" />
         </div>
         <div class="skill-desc">{{ skill.description }}</div>
         <div v-if="skill.agents && skill.agents.length > 0" class="skill-agents">
@@ -62,6 +67,14 @@
   import { message } from 'ant-design-vue';
   import type { Skill } from '/@/views/ventAI/manageAssistent/types/index';
 
+  /**
+   * 是否管理员:决定本面板是「可管理」还是「只读」。
+   *
+   * 可选并默认 false —— 值缺失时按非管理员处理(保守方向:宁可少给编辑入口)。
+   * 注意这只是界面可见性,真正的权限拦截仍在 TfAgents 后端,前端隐藏不等于安全。
+   */
+  const props = withDefaults(defineProps<{ isAdmin?: boolean }>(), { isAdmin: false });
+
   const emit = defineEmits<{ (e: 'close'): void }>();
 
   const skills = ref<Skill[]>([]);

+ 21 - 5
src/views/ventAI/manageAssistent/components/panels/SubAgentPanel.vue

@@ -3,7 +3,10 @@
     <div class="sub-agent-panel-header">
       <div class="sub-agent-panel-header-left">
         <span class="sub-agent-panel-title">子智能体</span>
-        <span class="sub-agent-panel-desc">管理模型子智能体,启用后可在聊天里使用</span>
+        <span class="sub-agent-panel-desc">
+          管理模型子智能体,启用后可在聊天里使用
+          <template v-if="!props.isAdmin">(只读:仅管理员可修改)</template>
+        </span>
       </div>
       <div class="sub-agent-panel-close" @click="emit('close')">
         <div class="close-icon"></div>
@@ -20,7 +23,8 @@
     <div class="sub-agent-summary">
       <span class="sub-agent-summary-label">子智能体</span>
       <span class="sub-agent-summary-count">{{ filteredAgents.length }}项</span>
-      <a-button type="primary" class="sub-agent-create-btn" @click="handleCreate">
+      <!-- 创建属写操作:非管理员不显示 -->
+      <a-button v-if="props.isAdmin" type="primary" class="sub-agent-create-btn" @click="handleCreate">
         <template #icon><PlusOutlined /></template>
         创建
       </a-button>
@@ -33,9 +37,13 @@
             <span class="sub-agent-name">{{ agent.name }}</span>
           </div>
           <div class="sub-agent-actions">
-            <a-switch :checked="agent.enabled" size="small" class="sub-agent-switch" @change="handleToggle(agent)" />
-            <div class="action-btn edit-btn" @click.stop="handleEdit(agent)" title="编辑"></div>
-            <div class="action-btn delete-btn" @click.stop="handleDelete(agent)" title="删除"></div>
+            <!-- 启用/禁用开关兼具「当前是否启用」的状态展示,非管理员保留但禁用;
+                 编辑/删除是纯写操作,直接不显示 -->
+            <a-switch :checked="agent.enabled" :disabled="!props.isAdmin" size="small" class="sub-agent-switch" @change="handleToggle(agent)" />
+            <template v-if="props.isAdmin">
+              <div class="action-btn edit-btn" @click.stop="handleEdit(agent)" title="编辑"></div>
+              <div class="action-btn delete-btn" @click.stop="handleDelete(agent)" title="删除"></div>
+            </template>
           </div>
         </div>
         <div class="sub-agent-desc">{{ agent.description }}</div>
@@ -91,6 +99,14 @@
   import CreateSubAgentModal from '/@/views/ventAI/manageAssistent/components/modals/CreateSubAgentModal.vue';
   import type { SubAgent } from '/@/views/ventAI/manageAssistent/types/index';
 
+  /**
+   * 是否管理员:决定本面板是「可管理」还是「只读」。
+   *
+   * 可选并默认 false —— 值缺失时按非管理员处理(保守方向:宁可少给编辑入口)。
+   * 注意这只是界面可见性,真正的权限拦截仍在 TfAgents 后端,前端隐藏不等于安全。
+   */
+  const props = withDefaults(defineProps<{ isAdmin?: boolean }>(), { isAdmin: false });
+
   const emit = defineEmits<{ (e: 'close'): void }>();
 
   const agents = ref<SubAgent[]>([]);

+ 12 - 18
src/views/ventAI/manageAssistent/components/panels/TaskListPanel.vue

@@ -60,9 +60,6 @@
   const props = defineProps<{
     taskList: Task[];
     currentTaskId: string;
-    // [审计-第四轮 M3] 重放自我方 fix/base-agent-token(M1/M2/M3):是否管理员(由 AiAssistantModal 透传 TfAgents 的 is_admin)。
-    // 为可选属性并默认 false:既兼容其它潜在调用方,也保证「值缺失 = 按非管理员处理」的保守语义。
-    isAdmin?: boolean;
   }>();
 
   const emit = defineEmits<{
@@ -101,21 +98,18 @@
     emit('pin-task', task);
   };
 
-  // [审计-第四轮 M3] 重放自我方 fix/base-agent-token(M1/M2/M3):顶部操作区的入口列表。
-  // 原行为:普通 const 数组,恒含「技能」「子智能体」,任何角色都能点进管理面板。
-  // 现行为:改为 computed 并按 isAdmin 过滤 —— 非管理员看不到这两个「全局变更」入口,
-  //         「新建任务 / 定时任务」对所有角色保持开放(定时任务属于个人功能,不在 TfAgents 的收敛范围内)。
-  // 为什么:用 computed(而非普通数组)是为了让 isAdmin 异步返回后能自动重算,无需刷新。
-  const optionItems = computed(() => {
-    const items = [
-      { type: 'add' as OptionType, label: '新建任务' },
-      // { type: 'search' as OptionType, label: '搜索' },
-      { type: 'skill' as OptionType, label: '技能' },
-      { type: 'sub-agents' as OptionType, label: '子智能体' },
-      { type: 'schedules' as OptionType, label: '定时任务' },
-    ];
-    return props.isAdmin ? items : items.filter((item) => item.type !== 'skill' && item.type !== 'sub-agents');
-  });
+  // 顶部操作区的入口列表:四个入口对所有角色都显示。
+  //
+  // 这里曾按 isAdmin 过滤掉「技能」「子智能体」两个入口(第四轮审计 M3),现改为入口一律可见:
+  // 非管理员进去后面板只读(隐藏创建/编辑/删除、禁用启停开关),而不是连看都看不到。
+  // 因此本组件不再需要 isAdmin —— 角色差异全部收敛在面板内部。
+  const optionItems = [
+    { type: 'add' as OptionType, label: '新建任务' },
+    // { type: 'search' as OptionType, label: '搜索' },
+    { type: 'skill' as OptionType, label: '技能' },
+    { type: 'sub-agents' as OptionType, label: '子智能体' },
+    { type: 'schedules' as OptionType, label: '定时任务' },
+  ];
 
   const formatRelativeTime = (dateStr?: string) => {
     if (!dateStr) return '刚刚';