fix: 修复用户管理超过 100 人列表截断
This commit is contained in:
parent
5c496e6347
commit
2474fb0a6c
@ -33,6 +33,7 @@
|
||||
- 优化图谱抽取器配置:未配置时在图谱中心展示配置入口,抽取方案收敛为 LLM,前端仅保留“更多拓展中”占位;LLM 抽取器使用固定 Prompt + 自定义 Schema,并支持模型参数与并发队列数;已配置后允许修改参数并提示重置重抽风险。修复上传并入库新文件时旧内存 metadata 覆盖数据库图谱配置的问题。
|
||||
- 新增 Milvus 图谱检索链路:Query 可召回图谱实体和三元组,结合 Chunk 命中实体构造 seed entity,读取 Neo4j 2-hop 子图后用 igraph 执行 PPR,最终以 Chunk 为产物并通过 RRF 与原 Chunk 召回融合;检索配置改为 dataclass 元数据生成,支持 `depend_on` 控制重排序和图检索参数展示。
|
||||
- 收紧用户管理部门隔离:普通管理员创建用户时固定归属本部门,用户列表、访问选项、详情、更新和删除接口均限制在本部门范围内。
|
||||
- 修复用户管理列表超过 100 人时被默认分页截断的问题:前端按 `skip/limit` 分批加载用户,并在用户卡片列表中补充分页渲染。
|
||||
- 调整 Agent 资源默认选择与运行时上下文:未显式配置工具、知识库、MCP、Skills、子智能体时默认启用当前用户可访问/可用的全部资源,显式选择后按允许列表过滤;Agent 创建前统一完成最终资源权限过滤、知识库 `kb_id` 可见范围派生和 Skill prompt/readable 依赖闭包派生,聊天运行时与文件系统预览复用同一结果。
|
||||
- 重构 Skills 权限与安装流程:Skill 增加 `source_type/share_config/enabled`,内置 Skill 作为启动同步入库的全局资源,不再保留前端安装/更新状态,支持启停但不允许删除;上传和远程添加统一为解析草稿后确认生效范围,安装 slug 优先读取 `SKILL.md` 的 `slug` 字段并保留 `name` 展示名,压缩包名称不参与 slug 校验;管理端支持编辑生效范围与启停;Agent 运行时按当前用户可访问 Skills 派生 prompt/readable 依赖闭包并限制挂载/激活,Skills prompt 改为模型请求级注入以避免污染 runtime context;主智能体恢复 `install_skill` 工具,允许当前用户安装私有 Skill 并激活当前会话,子智能体配置和运行态均禁用该工具。
|
||||
- 精简历史兼容层:移除 sandbox provisioner `local` 后端别名、ask_user_question 单问题旧协议、JWT 历史默认密钥特殊判断、内置 Skill `SKILLS.md` 文件名回退、运行事件数字 seq 兼容和前端若干旧字段回退。
|
||||
|
||||
@ -69,7 +69,7 @@
|
||||
/>
|
||||
</div>
|
||||
<div v-else class="user-cards-grid">
|
||||
<div v-for="user in filteredUsers" :key="user.id" class="user-card">
|
||||
<div v-for="user in paginatedUsers" :key="user.id" class="user-card">
|
||||
<div class="card-header">
|
||||
<div class="user-info-main">
|
||||
<div class="user-avatar">
|
||||
@ -152,6 +152,16 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="filteredUsers.length > userManagement.pageSize" class="pagination-section">
|
||||
<a-pagination
|
||||
v-model:current="userManagement.currentPage"
|
||||
v-model:page-size="userManagement.pageSize"
|
||||
:total="filteredUsers.length"
|
||||
:page-size-options="['20', '50', '100']"
|
||||
show-size-changer
|
||||
size="small"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</a-spin>
|
||||
</div>
|
||||
@ -283,6 +293,8 @@ const userManagement = reactive({
|
||||
searchKeyword: '',
|
||||
departmentFilter: '',
|
||||
roleFilter: '',
|
||||
currentPage: 1,
|
||||
pageSize: 50,
|
||||
error: null,
|
||||
modalVisible: false,
|
||||
modalTitle: '添加用户',
|
||||
@ -356,6 +368,12 @@ const filteredUsers = computed(() => {
|
||||
})
|
||||
})
|
||||
|
||||
const paginatedUsers = computed(() => {
|
||||
const pageSize = Number(userManagement.pageSize)
|
||||
const start = (userManagement.currentPage - 1) * pageSize
|
||||
return filteredUsers.value.slice(start, start + pageSize)
|
||||
})
|
||||
|
||||
// 获取部门列表
|
||||
const fetchDepartments = async () => {
|
||||
if (!userStore.isSuperAdmin) return // 普通管理员不需要获取所有部门列表
|
||||
@ -427,6 +445,23 @@ watch(
|
||||
}
|
||||
)
|
||||
|
||||
watch(
|
||||
() => [userManagement.searchKeyword, userManagement.departmentFilter, userManagement.roleFilter],
|
||||
() => {
|
||||
userManagement.currentPage = 1
|
||||
}
|
||||
)
|
||||
|
||||
watch(
|
||||
() => filteredUsers.value.length,
|
||||
(total) => {
|
||||
const maxPage = Math.max(1, Math.ceil(total / Number(userManagement.pageSize)))
|
||||
if (userManagement.currentPage > maxPage) {
|
||||
userManagement.currentPage = maxPage
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
// 格式化时间显示
|
||||
const formatTime = (timeStr) => formatDateTime(timeStr)
|
||||
|
||||
@ -946,6 +981,12 @@ onMounted(async () => {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.pagination-section {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
margin-top: 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -146,19 +146,37 @@ export const useUserStore = defineStore('user', () => {
|
||||
}
|
||||
|
||||
// 用户管理功能
|
||||
async function getUsers() {
|
||||
async function getUsers({ pageSize = 100 } = {}) {
|
||||
try {
|
||||
const response = await fetch('/api/auth/users', {
|
||||
headers: {
|
||||
...getAuthHeaders()
|
||||
}
|
||||
})
|
||||
const users = []
|
||||
let skip = 0
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error('获取用户列表失败')
|
||||
while (true) {
|
||||
const params = new URLSearchParams({
|
||||
skip: String(skip),
|
||||
limit: String(pageSize)
|
||||
})
|
||||
const response = await fetch(`/api/auth/users?${params.toString()}`, {
|
||||
headers: {
|
||||
...getAuthHeaders()
|
||||
}
|
||||
})
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error('获取用户列表失败')
|
||||
}
|
||||
|
||||
const batch = await response.json()
|
||||
users.push(...batch)
|
||||
|
||||
if (batch.length < pageSize) {
|
||||
break
|
||||
}
|
||||
|
||||
skip += pageSize
|
||||
}
|
||||
|
||||
return await response.json()
|
||||
return users
|
||||
} catch (error) {
|
||||
console.error('获取用户列表错误:', error)
|
||||
throw error
|
||||
|
||||
Loading…
Reference in New Issue
Block a user