Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { get, put } from '../core/request'
import type { ParamsPage, ResponsePage } from '../core/types'
import { get, put } from '../../core/request'
import type { ParamsPage, ResponsePage } from '../../core/types'
import type {
ApplicationDetail,
ApplicationFormPayload,
Expand Down
27 changes: 27 additions & 0 deletions ui/src/api/admin/workspace/knowledge/knowledge.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { del, get } from '../../core/request'
import type { ParamsPage, ResponsePage } from '../../core/types'
import type { KnowledgeItem, RequestParams } from '@/api/types'
import { getWorkspaceId } from '@/utils/workspace-context'

const getPrefix = () => {
const workspaceId = getWorkspaceId()
return `/workspace/${workspaceId}/knowledge`
}

/** 获取工作空间知识库分页列表。 */
const getKnowledgePage = (page: ParamsPage, query?: RequestParams) => {
return get<ResponsePage<KnowledgeItem>>(
`${getPrefix()}/${page.currentPage}/${page.pageSize}`,
query,
)
}

/** 删除工作空间知识库。 */
const deleteKnowledge = (knowledgeId: string) => {
return del<boolean>(`${getPrefix()}/${knowledgeId}`)
}

export default {
deleteKnowledge,
getKnowledgePage,
}
16 changes: 14 additions & 2 deletions ui/src/api/admin/workspace/shared.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { get } from '../core/request'
import type { ParamsPage, ResponsePage } from '../core/types'
import type { RequestParams, ModelItem, ToolItem } from '@/api/types'
import type { KnowledgeItem, RequestParams, ModelItem, ToolItem } from '@/api/types'
import { getWorkspaceId } from '@/utils/workspace-context'

const getPrefix = () => {
Expand All @@ -15,10 +15,22 @@ const getModelList = (query?: RequestParams) => {

/** 获取工作空间共享的工具列表。 */
const getToolPage = (page: ParamsPage, query?: RequestParams) => {
return get<ResponsePage<ToolItem>>(`${getPrefix()}/tool/${page.currentPage}/${page.pageSize}`, query)
return get<ResponsePage<ToolItem>>(
`${getPrefix()}/tool/${page.currentPage}/${page.pageSize}`,
query,
)
}

/** 获取工作空间共享的知识库列表。 */
const getKnowledgePage = (page: ParamsPage, query?: RequestParams) => {
return get<ResponsePage<KnowledgeItem>>(
`${getPrefix()}/knowledge/${page.currentPage}/${page.pageSize}`,
query,
)
}

export default {
getKnowledgePage,
getModelList,
getToolPage,
}
1 change: 1 addition & 0 deletions ui/src/api/enums/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ export * from './system-role'
export * from './model'
export * from './resource-authorization'
export * from './tool'
export * from './knowledge'
9 changes: 9 additions & 0 deletions ui/src/api/enums/knowledge.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/** 后端知识库类型。 */
// TODO v3不再用数字表示 待修改
export const KNOWLEDGE_TYPE = {
BASE: 0,
WEB: 1,
LARK: 2,
YUQUE: 3,
WORKFLOW: 4,
} as const
1 change: 1 addition & 0 deletions ui/src/api/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,4 @@ export type * from './model'
export type * from './resource-authorization'
export type * from './folder'
export type * from './tool'
export type * from './knowledge'
27 changes: 27 additions & 0 deletions ui/src/api/types/knowledge.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/** Workspace 知识库列表和知识库卡片共用的业务类型。 */

import { KNOWLEDGE_TYPE } from '@/api/enums'

export type KnowledgeType = (typeof KNOWLEDGE_TYPE)[keyof typeof KNOWLEDGE_TYPE]

export interface KnowledgeItem {
application_mapping_count?: number
char_length?: number | null
create_time?: string
desc?: string | null
document_count?: number | null
embedding_model_id?: string | null
file_count_limit?: number
file_size_limit?: number
folder_id?: string
id: string
image_count?: number | null
meta?: Record<string, unknown>
name: string
nick_name?: string | null
scope?: string
type: KnowledgeType
update_time?: string
user_id?: string | null
workspace_id: string
}
2 changes: 2 additions & 0 deletions ui/src/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ declare module 'vue' {
MkSearchInput: typeof import('./components/global/mk-search-input/index.vue')['default']
MkStatusLabel: typeof import('./components/global/mk-status-label/index.vue')['default']
MkTable: typeof import('./components/global/mk-table/index.vue')['default']
MkTableMoreDropdown: typeof import('./components/global/mk-table/mk-table-more-dropdown.vue')['default']
MkTagGroup: typeof import('./components/global/mk-tag-group/index.vue')['default']
MkViewLayout: typeof import('./components/global/mk-view-layout/index.vue')['default']
RouterLink: typeof import('vue-router')['RouterLink']
Expand All @@ -54,6 +55,7 @@ declare global {
const MkSearchInput: typeof import('./components/global/mk-search-input/index.vue')['default']
const MkStatusLabel: typeof import('./components/global/mk-status-label/index.vue')['default']
const MkTable: typeof import('./components/global/mk-table/index.vue')['default']
const MkTableMoreDropdown: typeof import('./components/global/mk-table/mk-table-more-dropdown.vue')['default']
const MkTagGroup: typeof import('./components/global/mk-tag-group/index.vue')['default']
const MkViewLayout: typeof import('./components/global/mk-view-layout/index.vue')['default']
const RouterLink: typeof import('vue-router')['RouterLink']
Expand Down
36 changes: 23 additions & 13 deletions ui/src/components/COMPONENT_README.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,8 @@ src/components/
│ ├── mk-status-label/
│ │ └── index.vue # 布尔状态图标和文案
│ ├── mk-table/
│ │ └── index.vue # 表格、分页、列宽拖拽和批量操作
│ │ ├── index.vue # 表格、分页、列宽拖拽和批量操作
│ │ └── mk-table-more-dropdown.vue # 表格操作列 More 下拉菜单
│ └── mk-tag-group/
│ └── index.vue # 标签折叠和剩余标签浮层
├── mk-search-list/
Expand Down Expand Up @@ -409,7 +410,8 @@ Element Plus 的 `v-infinite-scroll`。组件通过 `v-model` 管理已经加载

数据驱动使用时传入 `row`。`label-field` 默认读取 `name`,`index` 默认为 `0`;未提供默认插槽时
组件显示对应字段文本。`action` 和 `action-dropdown` 插槽需要配合 `row` 使用,并接收 `row`、
`index`。
`index`。`action-dropdown` 由组件统一渲染 More 触发器、`MkDropdown` 和 `MkDropdownMenu`,插槽中
直接放置 `MkDropdownItem`。

```vue
<MkListItem :active="currentRole?.id === role.id" :row="role" @click="selectRole(role)" />
Expand Down Expand Up @@ -472,6 +474,17 @@ const paginationConfig = ref({
重新计算 `max-height`。传入 `resizable` 后启用列宽拖拽,并隐藏为拖拽借用的原生边框视觉。
需要显示 Element Plus 原生边框时直接使用 `el-table`。

表格操作列需要 More 菜单时使用 `MkTableMoreDropdown`。组件统一提供点击型、右下定位的 More
按钮以及 `MkDropdownMenu`,默认插槽中直接放置 `MkDropdownItem`。其他 Dropdown 属性和事件通过
`$attrs` 传入,菜单容器样式通过 `menu-class` 设置。

```vue
<MkTableMoreDropdown menu-class="w-40">
<MkDropdownItem>配额设置</MkDropdownItem>
<MkDropdownItem divided @click="deleteUser(row)">删除</MkDropdownItem>
</MkTableMoreDropdown>
```

包含 `type="selection"` 的选择列时,选择数据会显示页面底部操作栏。批量按钮放入
`footer-batch-actions` 插槽,当前选择通过 `selection-change` 返回。组件暴露 `tableRef` 和
`clearSelection()`。操作栏在 `MkViewLayout` 的主内容滚动区域内吸附于页面底部,不随表格内容
Expand Down Expand Up @@ -539,7 +552,8 @@ const config = defineModel<unknown>({ required: true })
`footer` 插槽作为左侧常驻内容并始终贴在卡片底部;无论是否传入内容,底部都会保留固定位置。
`footer` 作用域提供 `Action` 和 `ActionDropdown`。左侧常驻内容与 `Action` 写在同一个插槽内;
`Action` 是卡片悬浮或内部获得焦点时显示的右侧操作容器,可以只放开关或按钮。
需要 More 菜单时,再将 `ActionDropdown` 放入 `Action`,下拉菜单内容写入其默认插槽。
需要 More 菜单时,再将 `ActionDropdown` 放入 `Action`,组件会统一渲染 `MkDropdownMenu`,默认
插槽中直接放置 `MkDropdownItem`。
需要自定义头部时可
通过 `icon`、`title`、`subtitle` 和 `tag` 插槽覆盖对应区域;`title` 插槽提供 `{ title }`,
便于在保留标题文案的同时追加状态图标等内容。
Expand All @@ -561,10 +575,8 @@ import MkSourceCard from '@/components/mk-source-card/index.vue'
<component :is="Action">
<el-switch size="small" />
<component :is="ActionDropdown">
<MkDropdownMenu>
<MkDropdownItem>编辑</MkDropdownItem>
<MkDropdownItem>删除</MkDropdownItem>
</MkDropdownMenu>
<MkDropdownItem>编辑</MkDropdownItem>
<MkDropdownItem>删除</MkDropdownItem>
</component>
</component>
</template>
Expand Down Expand Up @@ -654,7 +666,7 @@ Props 和模型:
- `data` 应传入全量数据;组件内的 50 条分批仅用于控制 DOM 渲染数量,不替代后端分页。
- 搜索词或数据源变化时,渲染范围和滚动位置会重置到第一批。
- 提供 `action-dropdown` 时,组件内部使用固定 More 按钮和点击型、非 Teleport 的
`MkDropdown`。
`MkDropdown`,并统一包裹 `MkDropdownMenu`;插槽中直接放置 `MkDropdownItem`
- `action` 和 `action-dropdown` 二选一;同时提供时优先渲染 `action-dropdown`,不渲染 `action`。

#### 默认字段示例
Expand Down Expand Up @@ -711,11 +723,9 @@ function selectItem(item: SearchListItem, index: number) {
<span :class="{ 'font-medium': active }">{{ workspace.displayName }}</span>
</template>
<template #action-dropdown="{ row: workspace }">
<MkDropdownMenu>
<MkDropdownItem @click="editWorkspace(workspace)">
编辑 {{ workspace.displayName }}
</MkDropdownItem>
</MkDropdownMenu>
<MkDropdownItem @click="editWorkspace(workspace)">
编辑 {{ workspace.displayName }}
</MkDropdownItem>
</template>
</MkSearchList>
```
Expand Down
34 changes: 16 additions & 18 deletions ui/src/components/business/folder-tree/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -397,24 +397,22 @@ defineExpose({ refresh: loadFolders, openCreate: handleOpenCreateFolder })
</template>

<template v-if="canEdit" #action-dropdown="{ row }">
<MkDropdownMenu>
<MkDropdownItem @click="handleOpenCreateChildFolder(row)">
<template #icon><MkIcon name="icon_add-folder_outlined" /></template>
<span>创建子文件夹</span>
</MkDropdownItem>
<MkDropdownItem @click="handleOpenEditFolder(row)">
<template #icon><MkIcon name="icon_edit_outlined" /></template>
<span>编辑</span>
</MkDropdownItem>
<MkDropdownItem>
<template #icon><MkIcon name="a-icon_move2_outlined" /></template>
<span>移动到</span>
</MkDropdownItem>
<MkDropdownItem divided @click="handleDeleteFolder(row)">
<template #icon><MkIcon name="icon_delete-trash_outlined" /></template>
<span>删除</span>
</MkDropdownItem>
</MkDropdownMenu>
<MkDropdownItem @click="handleOpenCreateChildFolder(row)">
<template #icon><MkIcon name="icon_add-folder_outlined" /></template>
<span>创建子文件夹</span>
</MkDropdownItem>
<MkDropdownItem @click="handleOpenEditFolder(row)">
<template #icon><MkIcon name="icon_edit_outlined" /></template>
<span>编辑</span>
</MkDropdownItem>
<MkDropdownItem>
<template #icon><MkIcon name="a-icon_move2_outlined" /></template>
<span>移动到</span>
</MkDropdownItem>
<MkDropdownItem divided @click="handleDeleteFolder(row)">
<template #icon><MkIcon name="icon_delete-trash_outlined" /></template>
<span>删除</span>
</MkDropdownItem>
</template>
</VirtualizedTree>
</div>
Expand Down
4 changes: 3 additions & 1 deletion ui/src/components/global/mk-list-item/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,9 @@ const slotRow = computed(() => row as T)
<MkIcon name="icon_more_outlined" />
</el-button>
<template #dropdown>
<slot name="action-dropdown" :row="slotRow" :index="index" />
<MkDropdownMenu>
<slot name="action-dropdown" :row="slotRow" :index="index" />
</MkDropdownMenu>
</template>
</MkDropdown>
<slot v-else name="action" :row="slotRow" :index="index" />
Expand Down
2 changes: 1 addition & 1 deletion ui/src/components/global/mk-table/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ defineExpose({ clearSelection, tableRef })
</div>

<footer
v-if="selectedRows.length > 0 && $slots.footerBatchActions"
v-if="selectedRows.length > 0 && $slots['footer-batch-actions']"
class="sticky -mb-6 -ml-6 bottom-0 z-10 mt-auto flex shrink-0 items-center border-t bg-white px-6 py-4"
>
<div class="mr-4 flex items-center gap-3">
Expand Down
26 changes: 26 additions & 0 deletions ui/src/components/global/mk-table/mk-table-more-dropdown.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<script setup lang="ts">
defineOptions({ name: 'MkTableMoreDropdown', inheritAttrs: false })

defineProps<{
menuClass?: string
}>()

defineSlots<{
/** 表格 More 菜单项,仅使用 MkDropdownItem */
default(): unknown
}>()
</script>

<template>
<MkDropdown trigger="click" placement="bottom-end" v-bind="$attrs">
<el-button aria-label="更多操作" type="primary" text @click.stop>
<MkIcon name="icon_more_outlined" />
</el-button>

<template #dropdown>
<MkDropdownMenu :class="menuClass">
<slot />
</MkDropdownMenu>
</template>
</MkDropdown>
</template>
2 changes: 1 addition & 1 deletion ui/src/components/global/mk-tag-group/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ withDefaults(
<el-tag type="info" class="cursor-pointer">+{{ tags.length - 1 }}</el-tag>
</template>
<div class="flex-wrap gap-1">
<el-tag v-for="tag in tags.slice(1)" :key="tag" type="info">
<el-tag v-for="tag in tags.slice(1)" :key="tag" type="info" :title="tag">
{{ tag }}
</el-tag>
</div>
Expand Down
6 changes: 2 additions & 4 deletions ui/src/components/mk-source-card/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,15 @@ import MkSourceCardActionDropdown from './mk-source-card-action-dropdown.vue'
* <component :is="Action">
* <el-switch v-model="active" size="small" />
* <component :is="ActionDropdown">
* <MkDropdownMenu>
* <MkDropdownItem>编辑</MkDropdownItem>
* </MkDropdownMenu>
* <MkDropdownItem>编辑</MkDropdownItem>
* </component>
* </component>
* </template>
*/
defineOptions({ name: 'MkSourceCard' })

const props = defineProps<{
create_time?: string //创建日期
create_time?: string //创建日期
nick_name?: string // 创建者
title: string
}>()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@ defineSlots<{

<template>
<MkDropdown trigger="click" placement="bottom-end" :teleported="false">
<el-button class="-mb-[2px] -mr-1" text>
<el-button class="-mb-[2px] -mr-1" text>
<MkIcon name="icon_more_outlined" />
</el-button>

<template #dropdown>
<slot />
<MkDropdownMenu>
<slot />
</MkDropdownMenu>
</template>
</MkDropdown>
</template>
2 changes: 1 addition & 1 deletion ui/src/router/admin/workspace/modules/knowledge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export const knowledgeRoutes: RouteRecordRaw[] = [
{
path: '',
name: 'workspace-knowledge-list',
component: () => import('@/views/home/HomeView.vue'),
component: () => import('@/views/knowledge/KnowledgeView.vue'),
meta: { title: '知识库列表', hidden: true },
},
{
Expand Down
1 change: 1 addition & 0 deletions ui/src/stores/theme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ export const useThemeStore = defineStore('theme', {

/** 保存主题信息并同步项目运行时颜色变量。 */
applyThemeInfo(themeInfo: ThemeInfo) {
// TODO: 主题还未实现
this.themeInfo = { ...DEFAULT_THEME_INFO, ...themeInfo }
const themeColor = this.themeInfo.theme || DEFAULT_THEME_COLOR
const rootStyle = document.documentElement.style
Expand Down
17 changes: 17 additions & 0 deletions ui/src/utils/number.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/** 提供跨页面复用的数字转换和格式化函数。 */

type NullableNumber = number | null | undefined

/** 为数字添加千位分隔符,空值按 `0` 处理。 */
export function toThousands(value: NullableNumber | string): string {
return String(value ?? 0).replace(/\B(?=(\d{3})+(?!\d))/g, ',')
}

/** 格式化数量:千以内显示原值,千及以上缩写为一位小数的 `k`。 */
export function numberFormat(value: NullableNumber): string {
const normalizedValue = value ?? 0

return normalizedValue < 1000
? toThousands(normalizedValue)
: `${toThousands((normalizedValue / 1000).toFixed(1))}k`
}
Loading
Loading