Skip to content

Commit f8c9713

Browse files
feat: thinking
1 parent f4691dc commit f8c9713

13 files changed

Lines changed: 241 additions & 193 deletions

File tree

‎ui/src/assets/iconfont.js‎

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎ui/src/components/COMPONENT_README.md‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,10 @@ Admin、Chat 入口调用 `configureMarkdownEditor()` 配置本地高亮、KaTeX
128128
标题折叠区,`title` 或 `label` 插槽提供标题,默认插槽提供内容。
129129
`defaultExpanded` 默认 `true`,仅设置初始状态;展开状态通过 `v-model:expanded` 同步。
130130
`indicatorPosition` 默认 `before`,可设为 `after`;`triggerClass`、`triggerStyle` 调整触发区。
131+
默认前置使用 14px 三角图标,后置使用 16px `icon_down_outlined`,保留各自展开时的旋转方式。
132+
需要定制时使用 `indicator` 插槽,通过 `{ expanded }` 获取展开状态;图标、尺寸、颜色及旋转由
133+
调用方设置。插槽仍位于组件的切换按钮内,不需要再绑定点击事件。标题悬停联动可通过
134+
`triggerClass="group"` 配合图标的 `group-hover:` 类实现,label 可独立设置颜色。
131135
内容使用 `v-show`,收起时保留内部组件及表单状态。
132136

133137
### MkEmpty

‎ui/src/components/global/mk-collapse/index.vue‎

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ const props = withDefaults(
1616
{ defaultExpanded: true, indicatorPosition: 'before', trigger: 'header' },
1717
)
1818
19-
defineSlots<{ default?: () => unknown; label?: () => unknown }>()
19+
defineSlots<{ default?: () => unknown; label?: () => unknown; indicator?: (props: { expanded: boolean }) => unknown }>()
2020
2121
const expandedModel = defineModel<boolean>('expanded')
2222
const localExpanded = ref(props.defaultExpanded)
@@ -42,14 +42,16 @@ const expanded = computed({
4242
:aria-expanded="expanded"
4343
@click.stop="expanded = !expanded"
4444
>
45-
<MkIcon
46-
v-if="indicatorPosition === 'before'"
47-
:icon="CaretBottom"
48-
:size="14"
49-
class="transition-transform text-N600!"
50-
:class="{ '-rotate-90': !expanded }"
51-
/>
52-
<MkIcon v-else name="icon_down_outlined" class="transition-transform text-N600!" :class="{ '-rotate-180': expanded }" />
45+
<slot name="indicator" :expanded="expanded">
46+
<MkIcon
47+
v-if="indicatorPosition === 'before'"
48+
:icon="CaretBottom"
49+
:size="14"
50+
class="transition-transform text-N600!"
51+
:class="{ '-rotate-90': !expanded }"
52+
/>
53+
<MkIcon v-else name="icon_down_outlined" class="transition-transform text-N600!" :class="{ '-rotate-180': expanded }" />
54+
</slot>
5355
</button>
5456
<slot name="label">
5557
<span>{{ title }}</span>
Lines changed: 33 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -1,83 +1,42 @@
1-
<template>
2-
<div class="reasoning">
3-
<button class="rc-head" @click="isExpanded = !isExpanded">
4-
<svg class="rc-chevron" :class="{ open: isExpanded }" viewBox="0 0 16 16" fill="none">
5-
<path d="M6 4l4 4-4 4" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"/>
6-
</svg>
7-
<span class="rc-title">思考过程</span>
8-
</button>
9-
<div v-show="isExpanded" class="rc-body">
10-
<pre class="rc-text">{{ content.content }}</pre>
11-
</div>
12-
</div>
13-
</template>
14-
151
<script setup lang="ts">
162
import { ref, watch } from 'vue'
173
18-
const props = defineProps<{ content: any }>()
4+
defineOptions({ name: 'ConversationReasoningContent' })
5+
6+
const props = defineProps<{ content: { content?: string | null; status?: string } }>()
197
const isExpanded = ref(true)
208
let prevStatus = props.content.status
219
22-
watch(() => props.content.status, (status) => {
23-
if (prevStatus === 'RUNNING' && status !== 'RUNNING') {
24-
isExpanded.value = false
25-
}
26-
prevStatus = status
27-
})
10+
watch(
11+
() => props.content.status,
12+
(status) => {
13+
if (prevStatus === 'RUNNING' && status !== 'RUNNING') {
14+
isExpanded.value = false
15+
}
16+
prevStatus = status
17+
},
18+
)
2819
</script>
2920

30-
<style scoped lang="scss">
31-
.reasoning {
32-
width: 100%;
33-
margin-bottom: 8px;
34-
}
35-
36-
.rc-head {
37-
display: inline-flex;
38-
align-items: center;
39-
gap: 6px;
40-
padding: 3px 0;
41-
border: none;
42-
background: none;
43-
cursor: pointer;
44-
font-family: inherit;
45-
color: var(--t3, #909399);
46-
transition: color 0.15s;
47-
}
48-
49-
.rc-head:hover {
50-
color: var(--t1, #303133);
51-
}
52-
53-
.rc-chevron {
54-
width: 14px;
55-
height: 14px;
56-
flex-shrink: 0;
57-
transition: transform 0.15s;
58-
}
59-
60-
.rc-chevron.open {
61-
transform: rotate(90deg);
62-
}
63-
64-
.rc-title {
65-
font-size: 13px;
66-
font-weight: 500;
67-
color: var(--t2, #606266);
68-
}
69-
70-
.rc-body {
71-
padding: 6px 0 4px 8px;
72-
}
21+
<template>
22+
<!-- 展开或收起思考内容 -->
23+
<MkCollapse v-model:expanded="isExpanded" indicator-position="after" trigger-class="group text-N500! mb-2 w-fit hover:text-N900!">
24+
<template #indicator="{ expanded }">
25+
<MkIcon
26+
name="icon_right_outlined"
27+
:size="12"
28+
class="transition-transform text-N500! group-hover:text-N900!"
29+
:class="{ 'rotate-90': expanded }"
30+
/>
31+
</template>
32+
<template #label>
33+
<MkIcon name="icon_two-ellipses_outlined" />
34+
<span class="-mx-1">思考中</span>
35+
</template>
36+
<div class="text-N500! whitespace-pre-wrap break-words">
37+
{{ content.content }}
38+
</div>
39+
</MkCollapse>
40+
</template>
7341

74-
.rc-text {
75-
margin: 0;
76-
font-size: 13px;
77-
line-height: 1.65;
78-
color: var(--t2, #606266);
79-
white-space: pre-wrap;
80-
word-break: break-word;
81-
font-family: inherit;
82-
}
83-
</style>
42+
<style scoped lang="scss"></style>

‎ui/src/views/VIEW_README.md‎

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -320,7 +320,13 @@ View 负责路由、资源与模式、图加载、保存/发布/调试编排
320320
- 模板中心共享 UI 在 `workflow/components/template-store/`,业务入口查模板,View 确认覆盖、提交并重载详情和保存基准。
321321
创建模板由资源创建流程负责,取消/失败保留模板中心。
322322
- 调试与导出先保存未提交修改,保存失败不继续;打开历史、模板或默认模型时按原流程关闭调试。
323-
- 智能体复用对话模块 DebugPanel;工具使用 debug Drawer、SSE 和执行详情;知识库保留任务轮询与导入 Action。
323+
- 智能体页面专属按钮组件放在 `workflow/application/components/`。
324+
`ButtonDebug` 组合调试按钮与对话模块 DebugPanel,通过页面传入的改动检查、保存方法和共享 loading
325+
完成保存后调试流程;公开 `close()` 供页面其他操作关闭调试。
326+
`ButtonAiGenerate` 组合 AI 生成按钮与生成面板;生成面板与调试面板一样自行 Teleport 到 body,
327+
使用固定定位,顶部避开工作流工具栏。
328+
智能体工作流页面通过 `label` 传入 AI 生成、模板中心、默认模型设置、调试和发布历史入口文案。
329+
工具使用 debug Drawer、SSE 和执行详情;知识库保留任务轮询与导入 Action。
324330
智能体画布按 Workspace/System 资源管理选择详情、保存、发布、模型和历史 API;DebugPanel 尚未按 System 范围适配。
325331
客户端停止读取不等于服务端停止任务。
326332
- 知识库导出仅工作流 `.kbwf`;导入确认覆盖后直接上传,不先保存旧草稿,成功重载;取消/失败保留图。

‎ui/src/views/document-detail/index.vue‎

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { provideDocumentDetailContext } from './context'
66
import type { ParamsPage } from '@/api/admin/core/types'
77
import type { DocumentItem, ParagraphItem, ParagraphQuery } from '@/api/types'
88
import { getFileIconUrl } from '@/utils/icon'
9+
import { KNOWLEDGE_TYPE_KEY } from '@/constants/knowledge'
910
import { MsgConfirm, MsgSuccess } from '@/utils/message'
1011
import { useParagraphSort } from './action-dropdown/move/useParagraphSort'
1112
import CreateParagraphDialog from './paragraph-dialog/CreateParagraphDialog.vue'
@@ -255,8 +256,11 @@ onMounted(() => {
255256
<div class="flex-align-center min-w-0 gap-2">
256257
<!-- 返回文档列表 -->
257258
<el-button text @click="handleBack"><MkIcon name="icon_arrow-left_outlined" :size="20" /></el-button>
258-
<img v-if="documentDetail" :src="getFileIconUrl(documentDetail.name)" alt="" class="size-6 shrink-0" />
259-
<h4 class="truncate" :title="documentDetail?.name">{{ documentDetail?.name ?? '文档分段' }}</h4>
259+
<template v-if="documentDetail">
260+
<img v-if="route.params.type === KNOWLEDGE_TYPE_KEY.WEB" src="@/assets/file-type/web-link-icon.svg" alt="" class="size-6 shrink-0" />
261+
<img v-else :src="getFileIconUrl(documentDetail.name)" alt="" class="size-6 shrink-0" />
262+
</template>
263+
<h4 class="truncate" :title="documentDetail?.name">{{ documentDetail?.name ?? '-' }}</h4>
260264
</div>
261265
<div class="flex-align-center shrink-0 gap-3">
262266
<MkComplexSearch :key="searchKey" :fields="searchFields" @change="handleSearchChange" />
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<script setup lang="ts">
2+
import { useTemplateRef } from 'vue'
3+
import type LogicFlow from '@logicflow/core'
4+
import type { DefaultModelSettingPayload } from '@/api/types'
5+
import AiGeneratePanel from '@/workflow-canvas/ai-generate/panel/AiGeneratePanel.vue'
6+
import { WorkflowMode } from '@/workflow-canvas/types'
7+
8+
defineOptions({ name: 'ButtonAiGenerate' })
9+
const props = defineProps<{
10+
label: string
11+
disabled?: boolean
12+
getLogicFlow: () => LogicFlow | undefined
13+
defaultModelSettings: DefaultModelSettingPayload
14+
}>()
15+
const emit = defineEmits<{ open: [] }>()
16+
const aiGeneratePanelRef = useTemplateRef<InstanceType<typeof AiGeneratePanel>>('aiGeneratePanelRef')
17+
18+
/* 打开生成面板前通知页面关闭调试。 */
19+
function handleOpenAiGenerate() {
20+
if (props.disabled) return
21+
emit('open')
22+
aiGeneratePanelRef.value?.open()
23+
}
24+
</script>
25+
26+
<template>
27+
<!-- AI 生成智能体工作流 -->
28+
<el-button plain :disabled="disabled" @click="handleOpenAiGenerate">
29+
<!-- // TODO 图标 -->
30+
<MkIcon name="icon_star" />
31+
<span>{{ label }}</span>
32+
</el-button>
33+
<AiGeneratePanel
34+
ref="aiGeneratePanelRef"
35+
:get-logic-flow="getLogicFlow"
36+
:default-model-settings="defaultModelSettings"
37+
:workflow-mode="WorkflowMode.Application"
38+
/>
39+
</template>
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
<script setup lang="ts">
2+
import { useTemplateRef } from 'vue'
3+
import DebugPanel from '@/conversation-panel/view/debug/index.vue'
4+
5+
defineOptions({ name: 'ButtonDebug' })
6+
const props = defineProps<{
7+
label: string
8+
disabled?: boolean
9+
hasUnsavedChanges: () => boolean
10+
saveWorkflow: () => Promise<unknown>
11+
}>()
12+
const loading = defineModel<boolean>('loading', { default: false })
13+
const debugPanelRef = useTemplateRef<InstanceType<typeof DebugPanel>>('debugPanelRef')
14+
15+
/* 调试前保存未提交修改;保存失败时保留画布,不打开调试。 */
16+
async function handleDebug() {
17+
if (loading.value || props.disabled) return
18+
if (props.hasUnsavedChanges()) {
19+
loading.value = true
20+
try {
21+
await props.saveWorkflow()
22+
} catch {
23+
// 保存失败已由页面保存流程提示。
24+
return
25+
} finally {
26+
loading.value = false
27+
}
28+
}
29+
debugPanelRef.value?.open()
30+
}
31+
32+
function close() {
33+
debugPanelRef.value?.close()
34+
}
35+
36+
defineExpose({ close })
37+
</script>
38+
39+
<template>
40+
<!-- 调试智能体工作流 -->
41+
<MkTooltip :content="label" placement="bottom">
42+
<el-button plain :disabled="loading || disabled" @click="handleDebug" class="w-8! min-w-8!">
43+
<MkIcon name="icon_play_outlined" />
44+
</el-button>
45+
</MkTooltip>
46+
<DebugPanel ref="debugPanelRef" />
47+
</template>

ui/src/views/workflow/application/ButtonPublishHistory.vue renamed to ui/src/views/workflow/application/components/ButtonPublishHistory.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import PublishHistoryDrawer from '@/views/workflow/components/publish-history/Pu
77
88
defineOptions({ name: 'ButtonApplicationPublishHistory' })
99
10-
const props = defineProps<{ api: typeof WorkflowApi; applicationId: string; selectedId?: string; disabled?: boolean }>()
10+
const props = defineProps<{ label: string; api: typeof WorkflowApi; applicationId: string; selectedId?: string; disabled?: boolean }>()
1111
const visible = defineModel<boolean>('visible', { default: false })
1212
const emit = defineEmits<{
1313
open: []
@@ -65,7 +65,7 @@ function handleSubmit(payload: WorkflowVersionPayload, versionId?: string) {
6565
<!-- 打开智能体发布历史 -->
6666
<MkDropdownItem :disabled="disabled || loading || saving" @click="handleOpen">
6767
<template #icon><MkIcon name="icon_history_outlined" /></template>
68-
<span>发布历史</span>
68+
<span>{{ label }}</span>
6969
</MkDropdownItem>
7070
<!-- 发布历史抽屉:由 MkDrawer 按需渲染内容。 -->
7171
<PublishHistoryDrawer

ui/src/views/workflow/application/ButtonTemplateStore.vue renamed to ui/src/views/workflow/application/components/ButtonTemplateStore.vue

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import type { ApplicationStoreTemplate } from '@/api/types'
55
import TemplateStoreDialog from '@/views/workflow/components/template-store/TemplateStoreDialog.vue'
66
77
defineOptions({ name: 'ButtonApplicationTemplateStore' })
8+
defineProps<{ label: string }>()
89
const emit = defineEmits<{ open: []; use: [template: ApplicationStoreTemplate] }>()
910
const templateStoreDialogRef = useTemplateRef<InstanceType<typeof TemplateStoreDialog>>('templateStoreDialogRef')
1011
@@ -41,7 +42,7 @@ defineExpose({ close })
4142
<!-- 打开模板中心 -->
4243
<el-button plain :disabled="loading" @click="handleOpen">
4344
<MkIcon name="icon_template_outlined" />
44-
<span>模板中心</span>
45+
<span>{{ label }}</span>
4546
</el-button>
4647
<TemplateStoreDialog
4748
ref="templateStoreDialogRef"

0 commit comments

Comments
 (0)