|
@@ -27,6 +27,7 @@
|
|
|
<TaskListPanel
|
|
<TaskListPanel
|
|
|
:taskList="taskList"
|
|
:taskList="taskList"
|
|
|
:currentTaskId="currentTaskId"
|
|
:currentTaskId="currentTaskId"
|
|
|
|
|
+ :isAdmin="isAdmin"
|
|
|
@switch-task="switchTask"
|
|
@switch-task="switchTask"
|
|
|
@create-task="createNewTask"
|
|
@create-task="createNewTask"
|
|
|
@delete-task="handleDeleteTask"
|
|
@delete-task="handleDeleteTask"
|
|
@@ -35,6 +36,9 @@
|
|
|
@toggle-sub-agents="toggleSubAgentPanel"
|
|
@toggle-sub-agents="toggleSubAgentPanel"
|
|
|
@toggle-schedules="toggleSchedulePanel"
|
|
@toggle-schedules="toggleSchedulePanel"
|
|
|
/>
|
|
/>
|
|
|
|
|
+ <!-- [审计-第四轮 M3] 重放自我方 fix/base-agent-token(M1/M2/M3)::isAdmin 透传给左侧任务面板,
|
|
|
|
|
+ 由面板内部过滤掉「技能」「子智能体」两个管理入口(按钮渲染在 TaskListPanel 的 optionItems 里)。
|
|
|
|
|
+ 注意「定时任务」不属于全局变更,保持对所有人开放。 -->
|
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
<!-- 右侧内容区:根据 activePanel 切换显示 -->
|
|
<!-- 右侧内容区:根据 activePanel 切换显示 -->
|
|
@@ -86,6 +90,9 @@
|
|
|
<TodoListBar v-if="showTodoBar" :todos="currentTodos" />
|
|
<TodoListBar v-if="showTodoBar" :todos="currentTodos" />
|
|
|
|
|
|
|
|
<!-- 输入区域 -->
|
|
<!-- 输入区域 -->
|
|
|
|
|
+ <!-- [审计-第四轮 M3] 重放自我方 fix/base-agent-token(M1/M2/M3)::isAdmin 透传给输入区,
|
|
|
|
|
+ 由输入区隐藏「思考级别」切换控件;注意只隐藏"切换",
|
|
|
|
|
+ 思考级别的读取(getModelMsg)对所有人保持开放 -->
|
|
|
<ChatInputArea
|
|
<ChatInputArea
|
|
|
ref="chatInputRef"
|
|
ref="chatInputRef"
|
|
|
v-model="inputMessage"
|
|
v-model="inputMessage"
|
|
@@ -101,6 +108,7 @@
|
|
|
:usageRemaining="usageToday?.remaining_tokens ?? 0"
|
|
:usageRemaining="usageToday?.remaining_tokens ?? 0"
|
|
|
:usageByModel="usageToday?.by_model ?? []"
|
|
:usageByModel="usageToday?.by_model ?? []"
|
|
|
:initialThinkLevel="thinkLevel"
|
|
:initialThinkLevel="thinkLevel"
|
|
|
|
|
+ :isAdmin="isAdmin"
|
|
|
:initialEditMode="editMode"
|
|
:initialEditMode="editMode"
|
|
|
:taskList="taskList"
|
|
:taskList="taskList"
|
|
|
:currentTaskId="currentTaskId"
|
|
:currentTaskId="currentTaskId"
|
|
@@ -161,7 +169,8 @@
|
|
|
<script setup lang="ts">
|
|
<script setup lang="ts">
|
|
|
import { ref, nextTick, watch, computed, onBeforeUnmount } from 'vue';
|
|
import { ref, nextTick, watch, computed, onBeforeUnmount } from 'vue';
|
|
|
import dayjs from 'dayjs';
|
|
import dayjs from 'dayjs';
|
|
|
- import { getDetail, deleteSession, deleteMessage, StreamError } from '/@/views/ventAI/manageAssistent/api/client';
|
|
|
|
|
|
|
+ // [审计-第四轮 M3] 重放自我方 fix/base-agent-token(M1/M2/M3):引入 getMe 用于按 is_admin 隐藏管理入口
|
|
|
|
|
+ import { getDetail, deleteSession, deleteMessage, StreamError, getMe } from '/@/views/ventAI/manageAssistent/api/client';
|
|
|
import { message, Modal } from 'ant-design-vue';
|
|
import { message, Modal } from 'ant-design-vue';
|
|
|
import TaskListPanel from '/@/views/ventAI/manageAssistent/components/panels/TaskListPanel.vue';
|
|
import TaskListPanel from '/@/views/ventAI/manageAssistent/components/panels/TaskListPanel.vue';
|
|
|
import ChatHeader from '/@/views/ventAI/manageAssistent/components/chat/ChatHeader.vue';
|
|
import ChatHeader from '/@/views/ventAI/manageAssistent/components/chat/ChatHeader.vue';
|
|
@@ -469,6 +478,9 @@
|
|
|
const inputMessage = ref('');
|
|
const inputMessage = ref('');
|
|
|
const selectedSessions = ref<Array<{ id: string; name: string }>>([]);
|
|
const selectedSessions = ref<Array<{ id: string; name: string }>>([]);
|
|
|
const selectedSkill = ref<{ name: string; display_name: string } | null>(null);
|
|
const selectedSkill = ref<{ name: string; display_name: string } | null>(null);
|
|
|
|
|
+ // [审计-第四轮 M3] 重放自我方 fix/base-agent-token(M1/M2/M3):当前登录用户是否管理员(TfAgents /ventAI/api/me 的 is_admin)。
|
|
|
|
|
+ // 默认 false = 保守语义:取不到权限信息时按非管理员处理,管理入口隐藏。
|
|
|
|
|
+ const isAdmin = ref(false);
|
|
|
|
|
|
|
|
// —— 以下四组职责已下沉到 composables(额度/导出/滚动/文件),组件只做接线 ——
|
|
// —— 以下四组职责已下沉到 composables(额度/导出/滚动/文件),组件只做接线 ——
|
|
|
const { scrollToBottom, scrollToBottomThrottled } = useChatScroll(() => chatMessagesRef.value);
|
|
const { scrollToBottom, scrollToBottomThrottled } = useChatScroll(() => chatMessagesRef.value);
|
|
@@ -718,6 +730,28 @@
|
|
|
},
|
|
},
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 拉取当前登录用户的权限信息(TfAgents 的 GET /ventAI/api/me)。
|
|
|
|
|
+ *
|
|
|
|
|
+ * [审计-第四轮 M3] 重放自我方 fix/base-agent-token(M1/M2/M3)。
|
|
|
|
|
+ * 为什么需要:TfAgents 已把「技能上传/启停、子智能体增删改、思考级别切换」等全局变更端点收归管理员
|
|
|
|
|
+ * (用户已定案方案 B:后端返回 is_admin,前端隐藏入口),基座据此隐藏对应入口,避免非管理员点了才被 403。
|
|
|
|
|
+ *
|
|
|
|
|
+ * 安全语义(保守失败,历史踩坑点必须保留):任何异常(未登录 401 / 接口未上线 404 / 网络失败)
|
|
|
|
|
+ * 一律按「非管理员」处理——isAdmin 置 false,且不缓存结果(每次打开都重新拉取,管理员名单可能在
|
|
|
|
|
+ * 服务端 .env 变更)。注意这只是界面可见性,真正的拦截仍在 TfAgents 后端——前端隐藏不等于安全。
|
|
|
|
|
+ */
|
|
|
|
|
+ const fetchMe = async () => {
|
|
|
|
|
+ try {
|
|
|
|
|
+ const me = await getMe();
|
|
|
|
|
+ isAdmin.value = !!me?.is_admin;
|
|
|
|
|
+ } catch (e) {
|
|
|
|
|
+ // 取不到(未登录/接口未上线/令牌失效)→ 按非管理员处理,隐藏管理入口
|
|
|
|
|
+ isAdmin.value = false;
|
|
|
|
|
+ console.warn('获取当前用户权限失败,管理入口将隐藏:', e);
|
|
|
|
|
+ }
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
// 发送流式 AI 回答的核心:推送一条空的 AI 消息 → 建 AbortController → 调 SSE → 处理 session_id 迁移 → 异常/清理。
|
|
// 发送流式 AI 回答的核心:推送一条空的 AI 消息 → 建 AbortController → 调 SSE → 处理 session_id 迁移 → 异常/清理。
|
|
|
// 正常发送、编辑重发、重新生成都复用此函数,file 存在且带 originalFile 时走 PDF 审查流,否则走纯文本流。
|
|
// 正常发送、编辑重发、重新生成都复用此函数,file 存在且带 originalFile 时走 PDF 审查流,否则走纯文本流。
|
|
|
// Throttled version for SSE streaming (no await, uses rAF)
|
|
// Throttled version for SSE streaming (no await, uses rAF)
|
|
@@ -733,6 +767,8 @@
|
|
|
fetchModelMsg();
|
|
fetchModelMsg();
|
|
|
fetchScheduleListForDetail();
|
|
fetchScheduleListForDetail();
|
|
|
fetchTodayUsage();
|
|
fetchTodayUsage();
|
|
|
|
|
+ // [审计-第四轮 M3] 重放自我方 fix/base-agent-token(M1/M2/M3):每次打开时刷新权限(不缓存;失败置 false 见 fetchMe)
|
|
|
|
|
+ fetchMe();
|
|
|
|
|
|
|
|
// 去除重复的空白任务,只保留一个
|
|
// 去除重复的空白任务,只保留一个
|
|
|
taskList.value = taskList.value.filter((task, index) => {
|
|
taskList.value = taskList.value.filter((task, index) => {
|