diff --git a/ui/src/assets/iconfont.js b/ui/src/assets/iconfont.js index b565e8efe3c..6eb9b454743 100644 --- a/ui/src/assets/iconfont.js +++ b/ui/src/assets/iconfont.js @@ -1 +1 @@ -window._iconfont_svg_string_5200172='',(h=>{var a=(l=(l=document.getElementsByTagName("script"))[l.length-1]).getAttribute("data-injectcss"),l=l.getAttribute("data-disable-injectsvg");if(!l){var o,v,t,i,c,d=function(a,l){l.parentNode.insertBefore(a,l)};if(a&&!h.__iconfont__svg__cssinject__){h.__iconfont__svg__cssinject__=!0;try{document.write("")}catch(a){console&&console.log(a)}}o=function(){var a,l=document.createElement("div");l.innerHTML=h._iconfont_svg_string_5200172,(l=l.getElementsByTagName("svg")[0])&&(l.setAttribute("aria-hidden","true"),l.style.position="absolute",l.style.width=0,l.style.height=0,l.style.overflow="hidden",l=l,(a=document.body).firstChild?d(l,a.firstChild):a.appendChild(l))},document.addEventListener?~["complete","loaded","interactive"].indexOf(document.readyState)?setTimeout(o,0):(v=function(){document.removeEventListener("DOMContentLoaded",v,!1),o()},document.addEventListener("DOMContentLoaded",v,!1)):document.attachEvent&&(t=o,i=h.document,c=!1,m(),i.onreadystatechange=function(){"complete"==i.readyState&&(i.onreadystatechange=null,e())})}function e(){c||(c=!0,t())}function m(){try{i.documentElement.doScroll("left")}catch(a){return void setTimeout(m,50)}e()}})(window); \ No newline at end of file +window._iconfont_svg_string_5200172='',(h=>{var a=(l=(l=document.getElementsByTagName("script"))[l.length-1]).getAttribute("data-injectcss"),l=l.getAttribute("data-disable-injectsvg");if(!l){var o,v,t,i,c,d=function(a,l){l.parentNode.insertBefore(a,l)};if(a&&!h.__iconfont__svg__cssinject__){h.__iconfont__svg__cssinject__=!0;try{document.write("")}catch(a){console&&console.log(a)}}o=function(){var a,l=document.createElement("div");l.innerHTML=h._iconfont_svg_string_5200172,(l=l.getElementsByTagName("svg")[0])&&(l.setAttribute("aria-hidden","true"),l.style.position="absolute",l.style.width=0,l.style.height=0,l.style.overflow="hidden",l=l,(a=document.body).firstChild?d(l,a.firstChild):a.appendChild(l))},document.addEventListener?~["complete","loaded","interactive"].indexOf(document.readyState)?setTimeout(o,0):(v=function(){document.removeEventListener("DOMContentLoaded",v,!1),o()},document.addEventListener("DOMContentLoaded",v,!1)):document.attachEvent&&(t=o,i=h.document,c=!1,m(),i.onreadystatechange=function(){"complete"==i.readyState&&(i.onreadystatechange=null,e())})}function e(){c||(c=!0,t())}function m(){try{i.documentElement.doScroll("left")}catch(a){return void setTimeout(m,50)}e()}})(window); \ No newline at end of file diff --git a/ui/src/components/COMPONENT_README.md b/ui/src/components/COMPONENT_README.md index 69dc431bef3..33938d284d7 100644 --- a/ui/src/components/COMPONENT_README.md +++ b/ui/src/components/COMPONENT_README.md @@ -128,6 +128,10 @@ Admin、Chat 入口调用 `configureMarkdownEditor()` 配置本地高亮、KaTeX 标题折叠区,`title` 或 `label` 插槽提供标题,默认插槽提供内容。 `defaultExpanded` 默认 `true`,仅设置初始状态;展开状态通过 `v-model:expanded` 同步。 `indicatorPosition` 默认 `before`,可设为 `after`;`triggerClass`、`triggerStyle` 调整触发区。 +默认前置使用 14px 三角图标,后置使用 16px `icon_down_outlined`,保留各自展开时的旋转方式。 +需要定制时使用 `indicator` 插槽,通过 `{ expanded }` 获取展开状态;图标、尺寸、颜色及旋转由 +调用方设置。插槽仍位于组件的切换按钮内,不需要再绑定点击事件。标题悬停联动可通过 +`triggerClass="group"` 配合图标的 `group-hover:` 类实现,label 可独立设置颜色。 内容使用 `v-show`,收起时保留内部组件及表单状态。 ### MkEmpty diff --git a/ui/src/components/global/mk-collapse/index.vue b/ui/src/components/global/mk-collapse/index.vue index a4a8b82b42e..5f1ecbba778 100644 --- a/ui/src/components/global/mk-collapse/index.vue +++ b/ui/src/components/global/mk-collapse/index.vue @@ -16,7 +16,7 @@ const props = withDefaults( { defaultExpanded: true, indicatorPosition: 'before', trigger: 'header' }, ) -defineSlots<{ default?: () => unknown; label?: () => unknown }>() +defineSlots<{ default?: () => unknown; label?: () => unknown; indicator?: (props: { expanded: boolean }) => unknown }>() const expandedModel = defineModel('expanded') const localExpanded = ref(props.defaultExpanded) @@ -42,14 +42,16 @@ const expanded = computed({ :aria-expanded="expanded" @click.stop="expanded = !expanded" > - - + + + + {{ title }} diff --git a/ui/src/conversation-panel/components/content/items/reasoning.vue b/ui/src/conversation-panel/components/content/items/reasoning.vue index 225b6ce691c..4ed985f1a1c 100644 --- a/ui/src/conversation-panel/components/content/items/reasoning.vue +++ b/ui/src/conversation-panel/components/content/items/reasoning.vue @@ -1,83 +1,42 @@ - - - + diff --git a/ui/src/views/VIEW_README.md b/ui/src/views/VIEW_README.md index bb1c42b07d5..f417634a517 100644 --- a/ui/src/views/VIEW_README.md +++ b/ui/src/views/VIEW_README.md @@ -320,7 +320,13 @@ View 负责路由、资源与模式、图加载、保存/发布/调试编排 - 模板中心共享 UI 在 `workflow/components/template-store/`,业务入口查模板,View 确认覆盖、提交并重载详情和保存基准。 创建模板由资源创建流程负责,取消/失败保留模板中心。 - 调试与导出先保存未提交修改,保存失败不继续;打开历史、模板或默认模型时按原流程关闭调试。 -- 智能体复用对话模块 DebugPanel;工具使用 debug Drawer、SSE 和执行详情;知识库保留任务轮询与导入 Action。 +- 智能体页面专属按钮组件放在 `workflow/application/components/`。 + `ButtonDebug` 组合调试按钮与对话模块 DebugPanel,通过页面传入的改动检查、保存方法和共享 loading + 完成保存后调试流程;公开 `close()` 供页面其他操作关闭调试。 + `ButtonAiGenerate` 组合 AI 生成按钮与生成面板;生成面板与调试面板一样自行 Teleport 到 body, + 使用固定定位,顶部避开工作流工具栏。 + 智能体工作流页面通过 `label` 传入 AI 生成、模板中心、默认模型设置、调试和发布历史入口文案。 + 工具使用 debug Drawer、SSE 和执行详情;知识库保留任务轮询与导入 Action。 智能体画布按 Workspace/System 资源管理选择详情、保存、发布、模型和历史 API;DebugPanel 尚未按 System 范围适配。 客户端停止读取不等于服务端停止任务。 - 知识库导出仅工作流 `.kbwf`;导入确认覆盖后直接上传,不先保存旧草稿,成功重载;取消/失败保留图。 diff --git a/ui/src/views/document-detail/index.vue b/ui/src/views/document-detail/index.vue index 41b2cf453ca..cef926e2749 100644 --- a/ui/src/views/document-detail/index.vue +++ b/ui/src/views/document-detail/index.vue @@ -6,6 +6,7 @@ import { provideDocumentDetailContext } from './context' import type { ParamsPage } from '@/api/admin/core/types' import type { DocumentItem, ParagraphItem, ParagraphQuery } from '@/api/types' import { getFileIconUrl } from '@/utils/icon' +import { KNOWLEDGE_TYPE_KEY } from '@/constants/knowledge' import { MsgConfirm, MsgSuccess } from '@/utils/message' import { useParagraphSort } from './action-dropdown/move/useParagraphSort' import CreateParagraphDialog from './paragraph-dialog/CreateParagraphDialog.vue' @@ -255,8 +256,11 @@ onMounted(() => {
- -

{{ documentDetail?.name ?? '文档分段' }}

+ +

{{ documentDetail?.name ?? '-' }}

diff --git a/ui/src/views/workflow/application/components/ButtonAiGenerate.vue b/ui/src/views/workflow/application/components/ButtonAiGenerate.vue new file mode 100644 index 00000000000..6b64f844204 --- /dev/null +++ b/ui/src/views/workflow/application/components/ButtonAiGenerate.vue @@ -0,0 +1,39 @@ + + + diff --git a/ui/src/views/workflow/application/components/ButtonDebug.vue b/ui/src/views/workflow/application/components/ButtonDebug.vue new file mode 100644 index 00000000000..91d588cf884 --- /dev/null +++ b/ui/src/views/workflow/application/components/ButtonDebug.vue @@ -0,0 +1,47 @@ + + + diff --git a/ui/src/views/workflow/application/ButtonPublishHistory.vue b/ui/src/views/workflow/application/components/ButtonPublishHistory.vue similarity index 93% rename from ui/src/views/workflow/application/ButtonPublishHistory.vue rename to ui/src/views/workflow/application/components/ButtonPublishHistory.vue index a4bb8bbb828..1350fb51e58 100644 --- a/ui/src/views/workflow/application/ButtonPublishHistory.vue +++ b/ui/src/views/workflow/application/components/ButtonPublishHistory.vue @@ -7,7 +7,7 @@ import PublishHistoryDrawer from '@/views/workflow/components/publish-history/Pu defineOptions({ name: 'ButtonApplicationPublishHistory' }) -const props = defineProps<{ api: typeof WorkflowApi; applicationId: string; selectedId?: string; disabled?: boolean }>() +const props = defineProps<{ label: string; api: typeof WorkflowApi; applicationId: string; selectedId?: string; disabled?: boolean }>() const visible = defineModel('visible', { default: false }) const emit = defineEmits<{ open: [] @@ -65,7 +65,7 @@ function handleSubmit(payload: WorkflowVersionPayload, versionId?: string) { - 发布历史 + {{ label }} () const emit = defineEmits<{ open: []; use: [template: ApplicationStoreTemplate] }>() const templateStoreDialogRef = useTemplateRef>('templateStoreDialogRef') @@ -41,7 +42,7 @@ defineExpose({ close }) - 模板中心 + {{ label }} >('workflowRef') -const aiGeneratePanelRef = useTemplateRef>('aiGeneratePanelRef') - -/* AI 生成:在当前画布上按需求搭建并配置工作流 */ -function handleOpenAiGenerate() { - if (loading.value || historyVisible.value) return - closeDebug() - aiGeneratePanelRef.value?.open() -} /* 智能体工作流加载与保存 */ const applicationDetail = ref() @@ -140,23 +132,10 @@ function handleAutoSaveChange() { } /* 调试入口 */ -const debugPanelRef = useTemplateRef>('debugPanelRef') - -async function handleDebug() { - if (loading.value || historyVisible.value) return - loading.value = true - try { - if (hasUnsavedChanges()) await saveApplication() - debugPanelRef.value?.open() - } catch { - // 保存失败已由保存流程提示。 - } finally { - loading.value = false - } -} +const debugButtonRef = useTemplateRef>('debugButtonRef') function closeDebug() { - debugPanelRef.value?.close() + debugButtonRef.value?.close() } /* 发布历史:预览保留原草稿,恢复后交由页面保存流程持久化。 */ @@ -341,16 +320,20 @@ onBeforeUnmount(() => stopAutoSave())