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
2 changes: 1 addition & 1 deletion ui/src/components/COMPONENT_README.md
Original file line number Diff line number Diff line change
Expand Up @@ -865,7 +865,7 @@ Skills 场景传入 `[TOOL_TYPE.SKILL]`,并通过 `title` 指定标题。两
`prop`(字段名)和 `label`(列名),列宽由表格自动分配。组件不转换接口数据结构,
旧对象映射由调用页面转换为行数组。用户组直接传入 `user_group_workspace` 数组,
使用 `workspace`、`user_group_names` 两列;角色映射由用户列表页面转换。
数组单元格以“、”连接,空数组、空字符串、null 和 undefined 显示 `-`,长文本使用溢出提示。
数组单元格以“、”连接,空数组、空字符串、null、undefined 及字符串 `"None"`(含单元素数组)显示 `-`,长文本使用溢出提示。
`data` 为空时禁用关联浮层,保留标签展示;内部 `MkTagGroup` 的标签浮层保持禁用。

### ResourceAuthorizationDrawer
Expand Down
38 changes: 19 additions & 19 deletions ui/src/conversation-panel/components/message-list/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -83,25 +83,25 @@ const onScroll = () => {
// color: var(--t3, #909399);
// }

// .welcome {
// flex: 1;
// display: flex;
// flex-direction: column;
// align-items: center;
// justify-content: center;
// text-align: center;
// padding: 32px 16px;
// }
// .welcome-title {
// font-size: 18px;
// font-weight: 600;
// color: var(--t1, #303133);
// margin-bottom: 8px;
// }
// .welcome-sub {
// font-size: 14px;
// color: var(--t3, #909399);
// }
.welcome {
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
text-align: center;
padding: 32px 16px;
}
.welcome-title {
font-size: 18px;
font-weight: 600;
color: var(--t1, #303133);
margin-bottom: 8px;
}
.welcome-sub {
font-size: 14px;
color: var(--t3, #909399);
}

// .msg-row {
// display: flex;
Expand Down
5 changes: 4 additions & 1 deletion ui/src/conversation-panel/main/chat-panel/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@ const handleDrop = (e: DragEvent) => input.addFiles(e.dataTransfer?.files)
<main class="mk-conversation-main" @drop.prevent="handleDrop" @dragover.prevent>
<!-- 头部可被替换(如 debug 用 debug header);默认普通 chat header -->
<slot name="header"><ChatHeader /></slot>
<MessageList :app-name="list.appInfo.value?.name || 'AI 助手'" />
<div class="min-h-0 flex-1 overflow-y-auto">
<MessageList :app-name="list.appInfo.value?.name || 'AI 助手'" />
</div>

<footer class="flex-center shrink-0 p-4"><MessageInput /></footer>
</main>
</template>
5 changes: 4 additions & 1 deletion ui/src/views/VIEW_README.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,9 +83,12 @@
不包含 Workspace 共享或 System 共享,不将缺失方法回退到 Workspace。
切换二级菜单不重复挂载详情容器。
- 创建模型入口接收完整 Model API;创建成功刷新基础资料后通知调用方刷新选项。
选择供应商时将模型类型同步到创建抽屉的供应商筛选;未传类型时默认“全部模型”。
- 工具表单按类型放在 `tool-form/`,共用参数及 Python 设置放在 `tool-form/component/`。
创建和编辑复用同一表单,不把不同类型字段合并成通用表单。
- `ToolCard` 点击工作流进入画布,其他类型调用编辑 Action 的同一表单实例;编辑、启停成功局部更新。
- `ToolCard` 点击工作流进入画布,其他类型与编辑菜单共用页面级 `EditToolForm` 实例,
不依赖下拉菜单挂载或维护逐卡片 Action Ref;`EditToolAction` 复用相同表单调度组件。
表单按类型打开,关闭动画后卸载具体表单;编辑、启停成功局部更新。
- 智能体的 Workspace 卡片与 System 资源列表复用门户上下架和导出 Action;门户入口按 `is_portal`
显示“上架到门户/从门户下架”,当前通过 mock 接口更新列表局部状态,刷新后恢复服务端状态。
导出使用二级菜单,包含“导出为 Skills”和“导出智能体”;Skills 当前调用 mock 接口并明确提示
Expand Down
4 changes: 2 additions & 2 deletions ui/src/views/model/create-model/ButtonAddModel.vue
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ function handleOpenCreateModel() {
selectProviderDrawerRef.value?.open()
}

function handleCreateProviderSelect(provider: ModelProviderItem) {
createModelDrawerRef.value?.open(provider)
function handleCreateProviderSelect(provider: ModelProviderItem, modelType: string) {
createModelDrawerRef.value?.open(provider, modelType)
}

function handleBackToProviderSelect() {
Expand Down
16 changes: 11 additions & 5 deletions ui/src/views/model/create-model/CreateModelDrawer.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import type ModelApi from '@/api/admin/workspace/model'
import type SystemModelApi from '@/api/admin/system/resource-management/model'
import type SystemSharedModelApi from '@/api/admin/system/shared-resources/model'
import ProviderApi from '@/api/admin/model-provider'
import { MODEL_TYPE_LABELS } from '@/constants/model'
import { MkDynamicsForm, type DynamicFormValue, type FormField } from '@/components/mk-dynamics-form'
import { useStore } from '@/stores'
import { MsgSuccess } from '@/utils/message'
Expand All @@ -25,9 +26,10 @@ const emit = defineEmits<{ back: []; refresh: [] }>()
const visible = ref(false)
const loading = ref(false)
const providersLoading = ref(false)
const modelType = ref('all')
const currentProvider = ref<ModelProviderItem>()
const loadedProviders = ref<ModelProviderItem[]>([])
const providerOptions = computed(() => (props.providers.length ? props.providers : loadedProviders.value))
const providerOptions = computed(() => (modelType.value === 'all' && props.providers.length ? props.providers : loadedProviders.value))

const modelForm = reactive<ModelPayload>({ credential: {}, model_name: '', model_type: '', name: '', provider: '' })

Expand Down Expand Up @@ -65,7 +67,7 @@ function handleProviderSelect(provider: ModelProviderItem) {

function loadModelProviders() {
providersLoading.value = true
return ProviderApi.getProviderList()
return ProviderApi.getProviderList(modelType.value === 'all' ? undefined : { model_type: modelType.value })
.then((providers) => {
loadedProviders.value = [...providers].sort((left, right) => left.name.localeCompare(right.name))
})
Expand Down Expand Up @@ -147,8 +149,9 @@ function handleSubmit() {
})
}

function open(provider: ModelProviderItem) {
if (!props.providers.length) loadModelProviders()
function open(provider: ModelProviderItem, selectedModelType = 'all') {
modelType.value = selectedModelType
if (modelType.value !== 'all' || !props.providers.length) loadModelProviders()
loadModelTypes(provider)
visible.value = true
}
Expand All @@ -165,6 +168,7 @@ function resetModelSelection() {
}

function resetData() {
modelType.value = 'all'
currentProvider.value = undefined
loadedProviders.value = []
modelForm.name = ''
Expand Down Expand Up @@ -193,8 +197,10 @@ defineExpose({ open })
<MkViewLayout :loading="loading || providersLoading" :title="currentProvider?.name ?? ''">
<template #aside="{ Header }">
<component :is="Header">
<el-select model-value="all" class="w-full">
<!-- 选择模型类型 -->
<el-select v-model="modelType" class="w-full" @change="loadModelProviders">
<el-option label="全部模型" value="all" />
<el-option v-for="(label, value) in MODEL_TYPE_LABELS" :key="value" :label="label" :value="value" />
</el-select>
</component>

Expand Down
4 changes: 2 additions & 2 deletions ui/src/views/model/create-model/SelectProviderDrawer.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { MODEL_TYPE_LABELS } from '@/constants'

defineOptions({ name: 'SelectProviderDrawer' })

const emit = defineEmits<{ select: [provider: ModelProviderItem] }>()
const emit = defineEmits<{ select: [provider: ModelProviderItem, modelType: string] }>()

const visible = ref(false)
const modelType = ref('all')
Expand Down Expand Up @@ -38,7 +38,7 @@ function loadModelProviders() {

function handleProviderSelect(provider: ModelProviderItem) {
visible.value = false
emit('select', provider)
emit('select', provider, modelType.value)
}

function handleModelTypeChange(value: string) {
Expand Down
4 changes: 2 additions & 2 deletions ui/src/views/system/resource-management/knowledge/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ onMounted(() => {
</div>
</template>
</el-table-column>
<el-table-column prop="type" label="类型" width="180">
<el-table-column prop="type" label="类型" width="150">
<template #header>
<MkTableFilter mode="single" v-model="selectedType" label="类型" :options="typeOptions" @change="handleFilterChange" />
</template>
Expand All @@ -171,7 +171,7 @@ onMounted(() => {
<el-table-column prop="create_time" label="创建时间" width="180" sortable>
<template #default="{ row }">{{ datetimeFormat(row.create_time) }}</template>
</el-table-column>
<el-table-column label="操作" width="150" fixed="right">
<el-table-column label="操作" width="120" fixed="right">
<template #default="{ row }">
<div class="flex-align-center">
<!-- 进入知识库详情 -->
Expand Down
26 changes: 10 additions & 16 deletions ui/src/views/system/shared-resources/tool/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,14 @@ import ButtonCreateTool from '@/views/tool/components/ButtonCreateTool.vue'
import {
RelatedResourcesToolAction,
DeleteToolAction,
EditToolAction,
ExportToolAction,
ExecutionRecordToolAction,
InitParamAction,
McpConfigAction,
CopyToolAction,
} from '@/views/tool/tool-card/action-dropdown'
import ButtonToolStore from '@/views/tool/components/ButtonToolStore.vue'
import EditToolForm from '@/views/tool/tool-form/EditToolForm.vue'
import perm from '@/permission'

const router = useRouter()
Expand Down Expand Up @@ -68,7 +68,12 @@ function handleSearchChange(query?: Dict<unknown>) {

/* 共享工具维护 */
const toolOperationLoading = ref(false)
const editToolActionRefs: Record<string, InstanceType<typeof EditToolAction> | null> = {}
const editToolFormRef = useTemplateRef<InstanceType<typeof EditToolForm>>('editToolFormRef')

function handleOpenEditTool(tool: ToolItem) {
if (!perm.tool.share.edit()) return
return editToolFormRef.value?.open(tool)
}

function handleOpenTool(tool: ToolItem, event: MouseEvent) {
if (tool.tool_type === TOOL_TYPE.WORKFLOW) {
Expand All @@ -79,7 +84,7 @@ function handleOpenTool(tool: ToolItem, event: MouseEvent) {
}
return router.push(target)
}
editToolActionRefs[tool.id]?.handleOpenToolForm()
handleOpenEditTool(tool)
}

function handleToolUpdate(tool: ToolItem) {
Expand Down Expand Up @@ -141,19 +146,7 @@ function handleOpenWorkflow(tool: ToolItem, event: MouseEvent) {
</template>
<template #action-dropdown>
<!-- 编辑共享工具 -->
<EditToolAction
v-if="perm.tool.share.edit()"
:ref="
(instance) => {
if (instance) editToolActionRefs[tool.id] = instance as InstanceType<typeof EditToolAction>
else delete editToolActionRefs[tool.id]
}
"
label="编辑"
:api="SystemSharedToolApi"
:tool="tool"
@update="handleToolUpdate"
/>
<MkAction v-if="perm.tool.share.edit()" label="编辑" icon="icon_edit_outlined" @click="handleOpenEditTool(tool)" />
<!-- 复制 -->
<CopyToolAction
v-if="perm.tool.share.copy()"
Expand Down Expand Up @@ -228,4 +221,5 @@ function handleOpenWorkflow(tool: ToolItem, event: MouseEvent) {
</div>
</template>
</MkViewLayout>
<EditToolForm ref="editToolFormRef" :api="SystemSharedToolApi" @update="handleToolUpdate" />
</template>
73 changes: 62 additions & 11 deletions ui/src/views/tool/components/ButtonCreateTool.vue
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
<script setup lang="ts">
import { computed, ref, useTemplateRef, type CSSProperties } from 'vue'
import { computed, nextTick, ref, useTemplateRef, type CSSProperties } from 'vue'
import type { UploadFile, UploadInstance } from 'element-plus'
import ToolApi from '@/api/admin/workspace/tool/tool'
import type SystemSharedToolApi from '@/api/admin/system/shared-resources/tool/tool'
import { TOOL_TYPE } from '@/api/enums'
import type { ToolType } from '@/api/types'
import { useStore } from '@/stores'
import { MsgSuccess } from '@/utils/message'
import ToolFormDrawer from '../tool-form/tool-custom/ToolFormDrawer.vue'
Expand Down Expand Up @@ -51,30 +52,40 @@ function handleVisibleChange(visible: boolean) {
}

/* 工具创建表单 */
const activeFormType = ref<ToolType | null>(null)
const toolFormDrawerRef = useTemplateRef<InstanceType<typeof ToolFormDrawer>>('toolFormDrawerRef')
const workflowFormDialogRef = useTemplateRef<InstanceType<typeof WorkflowFormDialog>>('workflowFormDialogRef')
const skillToolFormDrawerRef = useTemplateRef<InstanceType<typeof SkillToolFormDrawer>>('skillToolFormDrawerRef')
const mcpFormDrawerRef = useTemplateRef<InstanceType<typeof McpFormDrawer>>('mcpFormDrawerRef')
const dataSourceFormDrawerRef = useTemplateRef<InstanceType<typeof DataSourceFormDrawer>>('dataSourceFormDrawerRef')

function handleOpenToolForm() {
toolFormDrawerRef.value?.open()
activeFormType.value = TOOL_TYPE.CUSTOM
return nextTick(() => toolFormDrawerRef.value?.open())
}

function handleOpenWorkflowForm() {
workflowFormDialogRef.value?.open()
activeFormType.value = TOOL_TYPE.WORKFLOW
return nextTick(() => workflowFormDialogRef.value?.open())
}

function handleOpenSkillForm() {
skillToolFormDrawerRef.value?.open()
activeFormType.value = TOOL_TYPE.SKILL
return nextTick(() => skillToolFormDrawerRef.value?.open())
}

function handleOpenMcpForm() {
mcpFormDrawerRef.value?.open()
activeFormType.value = TOOL_TYPE.MCP
return nextTick(() => mcpFormDrawerRef.value?.open())
}

function handleOpenDataSourceForm() {
dataSourceFormDrawerRef.value?.open()
activeFormType.value = TOOL_TYPE.DATA_SOURCE
return nextTick(() => dataSourceFormDrawerRef.value?.open())
}

function handleFormClosed() {
activeFormType.value = null
}

/* 导入创建 */
Expand Down Expand Up @@ -168,9 +179,49 @@ function handleRefresh() {
</MkDropdownMenu>
</template>
</MkDropdown>
<ToolFormDrawer ref="toolFormDrawerRef" title="创建工具" :api="api" :folder-id="folderId" @refresh="handleRefresh" />
<WorkflowFormDialog ref="workflowFormDialogRef" title="创建工作流" :api="api" :folder-id="folderId" @refresh="handleRefresh" />
<SkillToolFormDrawer ref="skillToolFormDrawerRef" title="创建 Skill" :api="api" :folder-id="folderId" @refresh="handleRefresh" />
<McpFormDrawer ref="mcpFormDrawerRef" title="创建 MCP" :api="api" :folder-id="folderId" @refresh="handleRefresh" />
<DataSourceFormDrawer ref="dataSourceFormDrawerRef" title="创建数据源" :api="api" :folder-id="folderId" @refresh="handleRefresh" />
<ToolFormDrawer
v-if="activeFormType === TOOL_TYPE.CUSTOM"
ref="toolFormDrawerRef"
title="创建工具"
:api="api"
:folder-id="folderId"
@refresh="handleRefresh"
@closed="handleFormClosed"
/>
<WorkflowFormDialog
v-if="activeFormType === TOOL_TYPE.WORKFLOW"
ref="workflowFormDialogRef"
title="创建工作流"
:api="api"
:folder-id="folderId"
@refresh="handleRefresh"
@closed="handleFormClosed"
/>
<SkillToolFormDrawer
v-if="activeFormType === TOOL_TYPE.SKILL"
ref="skillToolFormDrawerRef"
title="创建 Skill"
:api="api"
:folder-id="folderId"
@refresh="handleRefresh"
@closed="handleFormClosed"
/>
<McpFormDrawer
v-if="activeFormType === TOOL_TYPE.MCP"
ref="mcpFormDrawerRef"
title="创建 MCP"
:api="api"
:folder-id="folderId"
@refresh="handleRefresh"
@closed="handleFormClosed"
/>
<DataSourceFormDrawer
v-if="activeFormType === TOOL_TYPE.DATA_SOURCE"
ref="dataSourceFormDrawerRef"
title="创建数据源"
:api="api"
:folder-id="folderId"
@refresh="handleRefresh"
@closed="handleFormClosed"
/>
</template>
Loading
Loading