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
1 change: 0 additions & 1 deletion ui/src/api/admin/system/settings/theme-setting.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { get, put } from '../../core/request'
import type { ThemeInfo } from '../../auth/types'

/** 保存系统外观主题设置。 */
const putThemeSetting = (payload: FormData) => {
Expand Down
14 changes: 11 additions & 3 deletions ui/src/components/business/model-select/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,21 @@ const modelOptionGroups = computed<ModelOptionGroup[]>(() => {
})
})

const selectedProviderIcon = computed(() => modelOptionGroups.value.find(({ models }) => models.some(({ id }) => id === selectedModelId.value))?.icon ?? '')
const selectedProviderIcon = computed(
() => modelOptionGroups.value.find(({ models }) => models.some(({ id }) => id === selectedModelId.value))?.icon ?? '',
)
</script>

<template>
<el-select v-model="selectedModelId" v-bind="$attrs" class="w-full" clearable filterable :loading="loading">
<el-select v-model="selectedModelId" v-bind="$attrs" class="w-full" clearable filterable :loading="loading" :teleported="false">
<el-option-group v-for="group in modelOptionGroups" :key="group.provider" :label="group.name">
<el-option v-for="model in group.models" :key="model.id" :disabled="model.status !== MODEL_STATUS.SUCCESS" :label="model.name" :value="model.id">
<el-option
v-for="model in group.models"
:key="model.id"
:disabled="model.status !== MODEL_STATUS.SUCCESS"
:label="model.name"
:value="model.id"
>
<div class="flex h-full items-center gap-2">
<span class="h-5 w-5 shrink-0" v-html="group.icon" />
<span class="min-w-0 flex-1 truncate" :title="model.name">{{ model.name }}</span>
Expand Down
2 changes: 1 addition & 1 deletion ui/src/router/admin/workspace/modules/application.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export const applicationRoutes: RouteRecordRaw[] = [
children: [
{
path: 'overview',
name: 'workspace-application-detail',
name: 'workspace-application-overview',
component: () => import('@/views/application-detail/overview/OverviewView.vue'),
meta: { title: '概览', icon: 'icon_screen_outlined', activeIcon: 'icon_screen_filled', order: 10 },
},
Expand Down
6 changes: 4 additions & 2 deletions ui/src/styles/element-plus.scss
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
--el-border-radius-round: 16px;
--el-border-radius-small: 4px;
--el-box-shadow-light: 0 4px 8px 0 var(--mk-N900-transparent-10);
--el-box-shadow-lighter: 0px 2px 4px 0px rgb(var(--mk-N900-rgb) / 12%);
--el-menu-icon-width: auto;
--el-text-color-primary: var(--mk-N900);
--el-text-color-regular: var(--mk-N600);
Expand Down Expand Up @@ -137,7 +138,7 @@
&:hover,
&:active,
&.is-active {
box-shadow: 0px 2px 4px 0px rgb(var(--mk-N900-rgb) / 12%);
box-shadow: var(--el-box-shadow-lighter);
color: var(--el-text-color-primary);
background: white;
border-color: var(--el-border-color);
Expand Down Expand Up @@ -873,7 +874,7 @@
.el-switch__core {
min-width: 28px;
.el-switch__action {
box-shadow: 0px 2px 4px 0px rgb(var(--mk-N900-rgb) / 12%);
box-shadow: var(--el-box-shadow-lighter);
}
}
}
Expand Down Expand Up @@ -1051,6 +1052,7 @@

/* textarea */
.el-textarea {
--el-input-text-color: var(--el-text-color-primary);
&:has(.el-input__inner[readonly]) {
--el-input-focus-border-color: var(--el-input-border-color);
--el-input-hover-border-color: var(--el-input-border-color);
Expand Down
1 change: 1 addition & 0 deletions ui/src/styles/tailwind.css
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

/* shadows */
--shadow-md: var(--el-box-shadow-light);
--shadow-sm: var(--el-box-shadow-lighter);

/* typography */
--text-xs: 10px;
Expand Down
5 changes: 3 additions & 2 deletions ui/src/views/application/ApplicationView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,10 @@ function handleDeleteApplication(applicationId: string) {
if (applicationIndex >= 0) applicationData.value.splice(applicationIndex, 1)
}

/* card点击去详情 */
function handleToDetail(application: ApplicationDetail) {
void router.push({
name: 'workspace-application-detail',
router.push({
name: 'workspace-application-overview',
params: { applicationId: application.id, type: application.type, workspaceId: route.params.workspaceId },
})
}
Expand Down
3 changes: 3 additions & 0 deletions ui/src/views/application/application-card/ApplicationCard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@ function handleOpen() {
</template>

<component :is="Action">
<el-button text>
<MkIcon name="icon_new-chat_outlined" />
</el-button>
<el-divider direction="vertical" />
<component :is="ActionDropdown">
<slot name="action-dropdown" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,18 @@ const route = useRoute()

function handleSettingApplication(event: MouseEvent) {
event.stopPropagation()
if (!isWorkFlow(props.application.type)) {
if (isWorkFlow(props.application.type)) {
const workflowRoute = {
name: 'workflow-application',
params: { workspaceId: route.params.workspaceId, applicationId: props.application.id },
} as const

if (event.ctrlKey || event.metaKey) {
window.open(router.resolve(workflowRoute).href)
return
}
router.push(workflowRoute)
} else {
void router.push({
name: 'workspace-application-simple-setting',
params: {
Expand All @@ -21,19 +32,7 @@ function handleSettingApplication(event: MouseEvent) {
workspaceId: route.params.workspaceId,
},
})
return
}

const workflowRoute = {
name: 'workflow-application',
params: { workspaceId: route.params.workspaceId, applicationId: props.application.id },
} as const

if (event.ctrlKey || event.metaKey) {
window.open(router.resolve(workflowRoute).href)
return
}
router.push(workflowRoute)
}
</script>

Expand Down
2 changes: 1 addition & 1 deletion ui/src/views/workflow/ApplicationWorkflowView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,7 @@ onMounted(() => {

<div class="flex shrink-0 items-center gap-3">
<WorkflowComponentMenu @select="handleAddNode" />
<el-button :loading="saving && !publishing" :disabled="loading || saving || publishing" @click="handleSave"> 保存 </el-button>
<el-button plain :loading="saving && !publishing" :disabled="loading || saving || publishing" @click="handleSave"> 保存 </el-button>
<el-button type="primary" plain :disabled="loading || saving" @click="handleDebug"> 调试 </el-button>
<!-- <el-button
v-if="canPublish"
Expand Down
6 changes: 6 additions & 0 deletions ui/src/workflow-canvas/WORKFLOW_README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ src/workflow-canvas/
├── nodes/ # 已迁入节点的注册文件和 Vue 实现
├── plugins/ # 仅供画布使用的 LogicFlow 插件
├── index.vue # 画布入口组件 WorkflowCanvas
├── style.scss # 画布内 LogicFlow 全局样式覆盖
├── types.ts # 画布协议类型和枚举
└── README.md # 本文档
```
Expand All @@ -38,6 +39,11 @@ src/workflow-canvas/
这里。只有某项行为是全部或大多数节点都必须遵守的画布规则时,才修改 `core`。新增普通节点
不应要求调整核心层。

节点内需要跟随画布缩放的浮层应保留 `teleported="false"`。如果浮层可能与后绘制的 SVG 锚点
重叠,使用 `core/utils.ts` 的 `createAnchorGuard()`,通过唯一 key 同步各浮层的
`visible-change` 状态,并在节点组件卸载时调用 `reset()`;不要通过 Teleport 到 `body` 或增加
`z-index` 绕过画布的缩放和 SVG 绘制顺序。

### `config/`

`config` 是随业务持续维护的配置层,增加、删除或调整节点时通常会更新:
Expand Down
65 changes: 65 additions & 0 deletions ui/src/workflow-canvas/component/NodeConditionDropdown.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<script setup lang="ts">
import type { BaseNodeModel } from '@logicflow/core'
import { computed } from 'vue'
import { set } from 'lodash'

import { WorkflowKind, WorkflowNodeType } from '@/workflow-canvas/types'

defineOptions({ name: 'NodeConditionDropdown' })

const props = defineProps<{ model: BaseNodeModel }>()
const emit = defineEmits<{
'visible-change': [visible: boolean]
}>()

type NodeConditionProperties = {
condition?: boolean | 'AND' | 'OR'
kind?: WorkflowKind
}

const nodeProperties = computed(() => props.model.properties as unknown as NodeConditionProperties)
const visible = computed(() => {
return (
![
WorkflowNodeType.Start,
WorkflowNodeType.Base,
WorkflowNodeType.ToolBaseNode,
WorkflowNodeType.ToolStartNode,
WorkflowNodeType.KnowledgeBase,
WorkflowNodeType.LoopStartNode.toString(),
WorkflowNodeType.DataSourceLocalNode,
WorkflowNodeType.DataSourceWebNode,
].includes(String(props.model.type)) && nodeProperties.value.kind !== WorkflowKind.DataSource
)
})
const condition = computed({
get: () => {
if (nodeProperties.value.condition) return nodeProperties.value.condition

set(props.model.properties, 'condition', 'AND')
return true
},
set: (value: boolean | 'AND' | 'OR') => {
set(props.model.properties, 'condition', value)
},
})
</script>

<template>
<MkDropdown v-if="visible" :teleported="false" trigger="click" placement="bottom-start" @visible-change="emit('visible-change', $event)">
<el-button text>条件</el-button>
<template #dropdown>
<div class="w-[280px] px-4 py-3">
<h5>执行条件</h5>
<p class="mt-2 text-N600">
<span>前置</span>
<el-select v-model="condition" class="mx-2 w-[60px]" size="small">
<el-option label="所有" value="AND" />
<el-option label="任一" value="OR" />
</el-select>
<span>连线节点执行完,执行当前节点</span>
</p>
</div>
</template>
</MkDropdown>
</template>
Loading
Loading