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
10 changes: 8 additions & 2 deletions ui/src/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,15 @@ declare module 'vue' {
MkDropdownItem: typeof import('./components/global/mk-dropdown/mk-dropdown-item.vue')['default']
MkDropdownMenu: typeof import('./components/global/mk-dropdown/mk-dropdown-menu.vue')['default']
MkEmpty: typeof import('./components/global/mk-empty/index.vue')['default']
MkFilterableDropdown: typeof import('./components/global/mk-filterable-dropdown/index.vue')['default']
MkFormList: typeof import('./components/global/mk-form-list/index.vue')['default']
MkIcon: typeof import('./components/global/mk-icon/index.vue')['default']
MkInfiniteScroll: typeof import('./components/global/mk-infinite-scroll/index.vue')['default']
MkListItem: typeof import('./components/global/mk-list-item/index.vue')['default']
MkSearchInput: typeof import('./components/global/mk-search-input/index.vue')['default']
MkSlider: typeof import('./components/global/mk-slider/index.vue')['default']
MkSourceCard: typeof import('./components/global/mk-source-card/index.vue')['default']
MkSourceCardAction: typeof import('./components/global/mk-source-card/mk-source-card-action.vue')['default']
MkSourceCardActionDropdown: typeof import('./components/global/mk-source-card/mk-source-card-action-dropdown.vue')['default']
MkStatusLabel: typeof import('./components/global/mk-status-label/index.vue')['default']
MkTable: typeof import('./components/global/mk-table/index.vue')['default']
MkTableFilter: typeof import('./components/global/mk-table/mk-table-filter.vue')['default']
Expand Down Expand Up @@ -62,12 +65,15 @@ declare global {
const MkDropdownItem: typeof import('./components/global/mk-dropdown/mk-dropdown-item.vue')['default']
const MkDropdownMenu: typeof import('./components/global/mk-dropdown/mk-dropdown-menu.vue')['default']
const MkEmpty: typeof import('./components/global/mk-empty/index.vue')['default']
const MkFilterableDropdown: typeof import('./components/global/mk-filterable-dropdown/index.vue')['default']
const MkFormList: typeof import('./components/global/mk-form-list/index.vue')['default']
const MkIcon: typeof import('./components/global/mk-icon/index.vue')['default']
const MkInfiniteScroll: typeof import('./components/global/mk-infinite-scroll/index.vue')['default']
const MkListItem: typeof import('./components/global/mk-list-item/index.vue')['default']
const MkSearchInput: typeof import('./components/global/mk-search-input/index.vue')['default']
const MkSlider: typeof import('./components/global/mk-slider/index.vue')['default']
const MkSourceCard: typeof import('./components/global/mk-source-card/index.vue')['default']
const MkSourceCardAction: typeof import('./components/global/mk-source-card/mk-source-card-action.vue')['default']
const MkSourceCardActionDropdown: typeof import('./components/global/mk-source-card/mk-source-card-action-dropdown.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 MkTableFilter: typeof import('./components/global/mk-table/mk-table-filter.vue')['default']
Expand Down
345 changes: 183 additions & 162 deletions ui/src/components/COMPONENT_README.md

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import { RESOURCE_TYPE } from '@/api/enums'
import { FOLDER_ENTRIES } from '@/constants/folder'
import FolderTree from '@/components/business/folder-tree/index.vue'
import MkCardCheckbox from '@/components/mk-card-checkbox/index.vue'
import MkSourceCard from '@/components/mk-source-card/index.vue'

defineOptions({ name: 'SelectApplicationDialog' })

Expand Down
1 change: 0 additions & 1 deletion ui/src/components/business/select-tool-dialog/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import { RESOURCE_TYPE, TOOL_TYPE } from '@/api/enums'
import { FOLDER_ENTRIES, FOLDER_ENTRY_ID } from '@/constants/folder'
import FolderTree from '@/components/business/folder-tree/index.vue'
import MkCardCheckbox from '@/components/mk-card-checkbox/index.vue'
import MkSourceCard from '@/components/mk-source-card/index.vue'

defineOptions({ name: 'SelectToolDialog' })

Expand Down
1 change: 1 addition & 0 deletions ui/src/components/business/workspace-dropdown/index.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<script setup lang="ts">
import { CaretBottom } from '@element-plus/icons-vue'
import type { WorkspaceItem } from '@/api/types'
import MkFilterableDropdown from '@/components/mk-filterable-dropdown/index.vue'

defineOptions({ name: 'WorkspaceDropdown' })

Expand Down
8 changes: 6 additions & 2 deletions ui/src/components/global/mk-icon/KnowledgeIcon.vue
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
<script setup lang="ts">
import { computed } from 'vue'
import { KNOWLEDGE_TYPE } from '@/api/enums'
import type { KnowledgeType } from '@/api/types'
import { KNOWLEDGE_TYPE_KEY, KNOWLEDGE_TYPE_MAP } from '@/constants/knowledge'

defineOptions({ name: 'KnowledgeIcon' })

const props = withDefaults(defineProps<{ size?: number | string; type?: KnowledgeType }>(), { size: 24 })
const knowledgeType = computed(() => (props.type === undefined ? undefined : KNOWLEDGE_TYPE_MAP[props.type]))
const props = withDefaults(defineProps<{ size?: number | string; type?: KnowledgeType | string }>(), { size: 24 })
const knowledgeType = computed(() => {
const type = Object.values(KNOWLEDGE_TYPE).find((type) => String(type) === String(props.type))
return type === undefined ? undefined : KNOWLEDGE_TYPE_MAP[type]
})
</script>
<template>
<el-avatar v-if="knowledgeType === KNOWLEDGE_TYPE_KEY.WEB" class="bg-purple!" shape="square" :size="size">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
import { referenceOptionsHelp } from '../../constant'
import { computed, onMounted, inject } from 'vue'
import MultiRow from '@/components/mk-dynamics-form/items/MultiRow.vue'
import MkFormList from '@/components/mk-form-list/index.vue'
import NodeCascader from '@/workflow-canvas/core/NodeCascader.vue'
import type { DynamicFormConstructorOption, DynamicFormValidatorCallback, DynamicFormValue, FormField } from '../../type'
const getModel = inject<() => DynamicFormValue>('getModel')
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
<script setup lang="ts">
import { referenceOptionsHelp } from '../../constant'
import { computed, onMounted, inject } from 'vue'
import MkFormList from '@/components/mk-form-list/index.vue'
import NodeCascader from '@/workflow-canvas/core/NodeCascader.vue'
import type { DynamicFormConstructorOption, DynamicFormValidatorCallback, DynamicFormValue } from '../../type'
const getModel = inject<() => DynamicFormValue>('getModel')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
import { referenceOptionsHelp } from '../../constant'
import { computed, onMounted, inject } from 'vue'
import RadioCard from '@/components/mk-dynamics-form/items/radio/RadioCard.vue'
import MkFormList from '@/components/mk-form-list/index.vue'
import NodeCascader from '@/workflow-canvas/core/NodeCascader.vue'
import type { DynamicFormConstructorOption, DynamicFormValidatorCallback, DynamicFormValue, FormField } from '../../type'
const getModel = inject<() => DynamicFormValue>('getModel')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
import { referenceOptionsHelp } from '../../constant'
import { computed, onMounted, inject } from 'vue'
import RadioRow from '@/components/mk-dynamics-form/items/radio/RadioRow.vue'
import MkFormList from '@/components/mk-form-list/index.vue'
import NodeCascader from '@/workflow-canvas/core/NodeCascader.vue'
import type { DynamicFormConstructorOption, DynamicFormValidatorCallback, DynamicFormValue, FormField } from '../../type'

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
import { referenceOptionsHelp } from '../../constant'
import type { DynamicFormConstructorOption, DynamicFormValidatorCallback, DynamicFormValue } from '../../type'
import { computed, onMounted, inject } from 'vue'
import MkFormList from '@/components/mk-form-list/index.vue'
import NodeCascader from '@/workflow-canvas/core/NodeCascader.vue'
const getModel = inject<() => DynamicFormValue>('getModel')

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
<script setup lang="ts">
import { computed, ref } from 'vue'
import { randomId } from '@/utils/common'
import MkFormList from '@/components/mk-form-list/index.vue'
import type { VisibilityConditionState, VisibilityFieldOption, VisibilityRules } from '../../type'
import { inferFieldType, getAllowedOps, getFieldConfig } from './utils'
import { compareList } from '@/workflow-canvas/config/constants'
Expand Down
60 changes: 60 additions & 0 deletions ui/src/components/mk-tags-edit/index.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<script setup lang="ts">
import { nextTick, ref, useTemplateRef } from 'vue'
import type { InputInstance } from 'element-plus'
import { MsgWarning } from '@/utils/message'

defineOptions({ name: 'MkTagsEdit' })

const extensions = defineModel<string[]>({ required: true })
const props = withDefaults(defineProps<{ reservedExtensions?: readonly string[] }>(), {
reservedExtensions: () => [],
})

// 扩展名编辑:自动聚焦,确认时归一化并检查重复值。
const extensionInputVisible = ref(false)
const extensionInput = ref('')
const inputRef = useTemplateRef<InputInstance>('inputRef')

function showExtensionInput() {
extensionInputVisible.value = true
nextTick(() => inputRef.value?.focus())
}

function confirmExtension() {
const extension = extensionInput.value.trim().replace(/^\./, '').toUpperCase()
if (extension) {
if (props.reservedExtensions.includes(extension) || extensions.value.includes(extension)) {
MsgWarning('该扩展名已存在')
} else {
extensions.value = [...extensions.value, extension]
}
}
extensionInput.value = ''
extensionInputVisible.value = false
}

function removeExtension(extension: string) {
extensions.value = extensions.value.filter((currentExtension) => currentExtension !== extension)
}
</script>

<template>
<div class="flex flex-wrap gap-2" @click.stop>
<el-tag v-for="extension in extensions" :key="extension" closable effect="plain" type="info" @close="removeExtension(extension)">
{{ extension }}
</el-tag>
<el-input
v-if="extensionInputVisible"
ref="inputRef"
v-model="extensionInput"
class="w-24!"
size="small"
@blur="confirmExtension"
@keyup.enter="confirmExtension"
/>
<el-button v-else size="small" @click="showExtensionInput">
<MkIcon name="icon_add_outlined" />
添加扩展名
</el-button>
</div>
</template>
3 changes: 3 additions & 0 deletions ui/src/views/VIEW_README.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,9 @@ System 共享资源的四类特殊资源。它们统一遵循以下页面组织
使用 `<action-name>-action/` 业务目录。专属浮层点击时按需挂载,并在 `closed` 后卸载;多个 Action
共用的浮层才提升到最近共同功能目录。

资源卡片的共享外壳使用全局自动注册的 `MkSourceCard`,模板无需手动导入。其操作插槽约定
以 `../components/COMPONENT_README.md` 为准;各资源的业务 Card 与 Action 继续显式导入。

这套三范围资源规则只适用于上述四类特殊资源,不扩展到普通 System 设置、身份管理或其他页面。

当前智能体列表按卡片展示、菜单 Action 和页面批量流程分层维护:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
<script setup lang="ts">
import type { ApplicationDetail } from '@/api/types'
import MkSourceCard from '@/components/mk-source-card/index.vue'
import { isWorkFlow } from '@/utils/application'
import { dateFormat } from '@/utils/time'

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import type { FormInstance, FormRules } from 'element-plus'
import ApplicationApi from '@/api/admin/workspace/application/application'
import { APPLICATION_TYPE } from '@/api/enums'
import type { ApplicationFormPayload } from '@/api/types'
import MkSourceCard from '@/components/mk-source-card/index.vue'
import { useStore } from '@/stores'
import { MsgSuccess } from '@/utils/message'
import { applicationTemplate } from './template'
Expand Down
1 change: 0 additions & 1 deletion ui/src/views/knowledge/knowledge-card/KnowledgeCard.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
<script setup lang="ts">
import type { KnowledgeItem } from '@/api/types'
import MkSourceCard from '@/components/mk-source-card/index.vue'
import { numberFormat } from '@/utils/number'

defineOptions({ name: 'KnowledgeCard' })
Expand Down
1 change: 0 additions & 1 deletion ui/src/views/model/model-card/ModelCard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import type ModelApi from '@/api/admin/workspace/model/model'
import type { ModelItem, ModelProviderItem } from '@/api/types'
import { MODEL_STATUS } from '@/api/enums'
import { MODEL_TYPE_LABELS } from '@/constants'
import MkSourceCard from '@/components/mk-source-card/index.vue'
import ModelDownloadStatus from './ModelDownloadStatus.vue'

defineOptions({ name: 'ModelCard' })
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -171,11 +171,14 @@ watch(
<el-table-column type="selection" width="40" reserve-selection />
<el-table-column class-name="resource-name-column" label="名称" min-width="260" prop="name">
<template #default="{ row }: { row: ResourcePermissionItem }">
<div class="flex min-w-0 items-center gap-2">
<div class="flex min-w-0 flex-1 items-center gap-2">
<MkIcon v-if="row.resource_type === 'folder'" name="icon_file-folder_colorful" :size="18" />
<span v-else-if="resourceType === RESOURCE_TYPE.MODEL" class="block h-5 w-5 shrink-0" :innerHTML="getModelProviderIcon(row)" />

<ToolIcon v-else-if="resourceType === RESOURCE_TYPE.TOOL" :icon="row.icon ?? undefined" :size="20" :type="row.tool_type ?? undefined" />
<ApplicationIcon v-else-if="resourceType === RESOURCE_TYPE.APPLICATION" :icon="row?.icon ?? undefined" :size="20" />
<KnowledgeIcon v-else-if="resourceType === RESOURCE_TYPE.KNOWLEDGE" :type="row.icon ?? undefined" :size="20" />

<span class="min-w-0 truncate" :title="row.name">{{ row.name }}</span>
</div>
</template>
Expand All @@ -199,5 +202,11 @@ watch(
:deep(.resource-name-column .cell) {
align-items: center;
display: flex;

.el-table__expand-icon,
.el-table__indent,
.el-table__placeholder {
flex-shrink: 0;
}
}
</style>
1 change: 0 additions & 1 deletion ui/src/views/system/identity/roles/AddMemberDrawer.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import { ROLE_TYPE } from '@/api/enums'
import type { CreateRoleMemberItem, RoleItem, SystemUserOption, WorkspaceItem } from '@/api/types'
import { useStore } from '@/stores'
import { MsgSuccess } from '@/utils/message'
import MkFormList from '@/components/mk-form-list/index.vue'

defineOptions({ name: 'AddRoleMemberDrawer' })

Expand Down
1 change: 0 additions & 1 deletion ui/src/views/system/identity/users/UserFromDrawer.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import { ROLE_TYPE } from '@/api/enums'
import { useStore } from '@/stores'
import { copyText } from '@/utils/clipboard'
import { MsgSuccess } from '@/utils/message'
import MkFormList from '@/components/mk-form-list/index.vue'
import UserGroupSetting from './components/UserGroupSetting.vue'
import type { ListItem, SystemUser, SystemUserPayload, SystemUserRoleAssignment } from '@/api/types/index.ts'
import type { FormInstance, FormRules } from 'element-plus'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import { ROLE_TYPE } from '@/api/enums'
import type { ListItem, BatchSetUserWorkspaceRolesRequest, SystemUserRoleAssignment } from '@/api/types'
import { useStore } from '@/stores'
import { MsgSuccess } from '@/utils/message'
import MkFormList from '@/components/mk-form-list/index.vue'

defineOptions({ name: 'BatchSetUserRoleDialog' })

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import CommonSystemApi from '@/api/admin/system/common'
import WorkspaceApi from '@/api/admin/system/workspace'
import type { CreateWorkspaceMemberPayload, ListItem, SystemUserOption, WorkspaceItem } from '@/api/types'
import { MsgSuccess } from '@/utils/message'
import MkFormList from '@/components/mk-form-list/index.vue'

defineOptions({ name: 'AddWorkspaceMemberDrawer' })

Expand Down
1 change: 0 additions & 1 deletion ui/src/views/tool/tool-card/ToolCard.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
<script setup lang="ts">
import type ToolApi from '@/api/admin/workspace/tool/tool'
import type { ToolItem, ToolStoreResponse } from '@/api/types'
import MkSourceCard from '@/components/mk-source-card/index.vue'
import ToolStatusSwitch from './ToolStatusSwitch.vue'
import UpdateVersionButton from './UpdateVersionButton.vue'

Expand Down
1 change: 0 additions & 1 deletion ui/src/views/tool/tool-store/component/ToolStoreCard.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
<script setup lang="ts">
import { computed, nextTick, ref, useTemplateRef } from 'vue'
import type { ToolStoreItem } from '@/api/types'
import MkSourceCard from '@/components/mk-source-card/index.vue'
import { resetUrl } from '@/utils/icon'
import { numberFormat } from '@/utils/number'
import StoreToolFormDialog from '../../tool-form/StoreToolFormDialog.vue'
Expand Down
9 changes: 7 additions & 2 deletions ui/src/workflow-canvas/WORKFLOW_README.md
Original file line number Diff line number Diff line change
Expand Up @@ -177,8 +177,10 @@ AI 对话、意图识别、问题优化、参数提取、图片理解、视频
通过 `v-model` 接收 `FileUploadSettingData`。节点入口根据上传开关挂载组件,并在配置写回后发送
`refreshFileUploadConfig` 刷新开始节点文件变量;弹窗打开时重置并深拷贝草稿,确认时保留上传方式
的表单必填校验,取消不修改节点,关闭动画结束后统一清理草稿与校验状态。
文件类型与其他文件选择复用手动导入的 `MkCardCheckbox`;扩展名编辑区域阻止点击冒泡,
避免添加或删除扩展名时切换文件类型。
文件类型与其他文件选择复用手动导入的 `MkCardCheckbox`;扩展名编辑复用非全局组件
`MkTagsEdit`,通过 `v-model` 编辑草稿的 `otherExtensions`,文件类型中已有的扩展名通过
`reservedExtensions` 传入用于重复检查。组件内部阻止点击冒泡,避免增删扩展名时切换文件类型;
输入临时状态随弹窗内容卸载而清理。

表单收集节点的 `component/form-setting/FormSettingTable` 通过 `v-model` 编辑动态表单的
`FormField[]`,负责增删改、排序和重名检查;`FormFieldDialog` 复用 `MkDynamicsFormConstructor`,
Expand Down Expand Up @@ -241,6 +243,9 @@ Break 和 Continue 节点在各自入口维护 `condition`、`condition_list`

### 节点列表排序

`MkFormList` 和 `MkTable` 均为全局自动注册组件,节点模板直接使用,无需手动导入;
组件 API 与注册规则以 `../components/COMPONENT_README.md` 为准。

普通节点列表、表单行和字段表格统一复用 VueDraggablePlus 支撑的共享排序能力:表单行使用
`MkFormList` 的 `sortable` 与稳定 `item-key`,字段表格使用 `MkTable` 的 `sortable` 与
`v-model:data`,其他列表使用 `@/utils/use-sortable`。不要在节点中直接创建 SortableJS 实例、
Expand Down
Loading
Loading