235 lines
6.0 KiB
Vue
235 lines
6.0 KiB
Vue
<template>
|
||
<ContentWrap>
|
||
<div class="mx-auto">
|
||
<!-- 头部导航栏 -->
|
||
<div
|
||
class="absolute top-0 left-0 right-0 h-50px bg-white border-bottom z-10 flex items-center px-20px"
|
||
>
|
||
<!-- 左侧标题 -->
|
||
<div class="w-200px flex items-center overflow-hidden">
|
||
<Icon icon="ep:arrow-left" class="cursor-pointer flex-shrink-0" @click="handleBack" />
|
||
<span class="ml-10px text-16px truncate" :title="formData.name || '创建流程'">
|
||
{{ formData.name || '创建流程' }}
|
||
</span>
|
||
</div>
|
||
|
||
<!-- 步骤条 -->
|
||
<div class="flex-1 flex items-center justify-center h-full">
|
||
<div class="w-400px flex items-center justify-between h-full">
|
||
<div
|
||
v-for="(step, index) in steps"
|
||
:key="index"
|
||
class="flex items-center cursor-pointer mx-15px relative h-full"
|
||
:class="[
|
||
currentStep === index
|
||
? 'text-[#3473ff] border-[#3473ff] border-b-2 border-b-solid'
|
||
: 'text-gray-500'
|
||
]"
|
||
@click="handleStepClick(index)"
|
||
>
|
||
<div
|
||
class="w-28px h-28px rounded-full flex items-center justify-center mr-8px border-2 border-solid text-15px"
|
||
:class="[
|
||
currentStep === index
|
||
? 'bg-[#3473ff] text-white border-[#3473ff]'
|
||
: 'border-gray-300 bg-white text-gray-500'
|
||
]"
|
||
>
|
||
{{ index + 1 }}
|
||
</div>
|
||
<span class="text-16px font-bold whitespace-nowrap">{{ step.title }}</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 右侧按钮 -->
|
||
<div class="w-200px flex items-center justify-end gap-2">
|
||
<el-button type="primary" @click="handleSave"> 保 存 </el-button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 主体内容 -->
|
||
<div class="mt-50px">
|
||
<!-- 第一步:基本信息 -->
|
||
<div v-if="currentStep === 0" class="mx-auto w-560px">
|
||
<BasicInfo v-model="formData" ref="basicInfoRef" />
|
||
</div>
|
||
|
||
<!-- 第二步:工作流设计 -->
|
||
<WorkflowDesign
|
||
v-if="currentStep === 1"
|
||
v-model="formData"
|
||
:provider="provider"
|
||
ref="workflowDesignRef"
|
||
/>
|
||
</div>
|
||
</div>
|
||
</ContentWrap>
|
||
</template>
|
||
|
||
<script setup lang="ts">
|
||
import { useTagsViewStore } from '@/store/modules/tagsView'
|
||
import { CommonStatusEnum } from '@/utils/constants'
|
||
import * as WorkflowApi from '@/api/ai/workflow'
|
||
import BasicInfo from './BasicInfo.vue'
|
||
import WorkflowDesign from './WorkflowDesign.vue'
|
||
import { ApiKeyApi } from '@/api/ai/model/apiKey'
|
||
|
||
const router = useRouter()
|
||
const { delView } = useTagsViewStore()
|
||
const route = useRoute()
|
||
const message = useMessage()
|
||
|
||
const basicInfoRef = ref()
|
||
const workflowDesignRef = ref()
|
||
|
||
const validateBasic = async () => {
|
||
await basicInfoRef.value?.validate()
|
||
}
|
||
const validateWorkflow = async () => {
|
||
await workflowDesignRef.value?.validate()
|
||
}
|
||
|
||
const currentStep = ref(-1)
|
||
const steps = [
|
||
{ title: '基本信息', validator: validateBasic },
|
||
{ title: '工作流设计', validator: validateWorkflow }
|
||
]
|
||
|
||
const formData: any = ref({
|
||
id: undefined,
|
||
name: '',
|
||
code: '',
|
||
remark: '',
|
||
graph: '',
|
||
status: CommonStatusEnum.ENABLE
|
||
})
|
||
// TODO @lesan:待接入
|
||
const provider = ref<any>()
|
||
const workflowData = ref<any>({})
|
||
provide('workflowData', workflowData)
|
||
|
||
/** 初始化数据 */
|
||
const actionType = route.params.type as string
|
||
const initData = async () => {
|
||
if (actionType === 'update') {
|
||
const workflowId = route.params.id as string
|
||
formData.value = await WorkflowApi.getWorkflow(workflowId)
|
||
workflowData.value = JSON.parse(formData.value.graph)
|
||
}
|
||
|
||
const apiKeys = await ApiKeyApi.getApiKeySimpleList()
|
||
provider.value = {
|
||
llm: () =>
|
||
apiKeys.map(({ id, name }) => ({
|
||
value: id,
|
||
label: name
|
||
})),
|
||
knowledge: () => [],
|
||
internal: () => []
|
||
}
|
||
|
||
currentStep.value = 0
|
||
}
|
||
|
||
/** 校验所有步骤数据是否完整 */
|
||
const validateAllSteps = async () => {
|
||
try {
|
||
// 基本信息校验
|
||
try {
|
||
await validateBasic()
|
||
} catch (error) {
|
||
currentStep.value = 0
|
||
throw new Error('请完善基本信息')
|
||
}
|
||
|
||
// 工作流设计校验
|
||
try {
|
||
await validateWorkflow()
|
||
} catch (error) {
|
||
currentStep.value = 1
|
||
throw new Error('请完善工作流信息')
|
||
}
|
||
return true
|
||
} catch (error) {
|
||
throw error
|
||
}
|
||
}
|
||
|
||
/** 保存操作 */
|
||
const handleSave = async () => {
|
||
try {
|
||
// 保存前校验所有步骤的数据
|
||
await validateAllSteps()
|
||
|
||
// 更新表单数据
|
||
const data = {
|
||
...formData.value
|
||
}
|
||
|
||
data.graph = JSON.stringify(workflowData.value)
|
||
|
||
if (actionType === 'update') {
|
||
await WorkflowApi.updateWorkflow(data)
|
||
} else {
|
||
await WorkflowApi.createWorkflow(data)
|
||
}
|
||
|
||
delView(unref(router.currentRoute))
|
||
await router.push({ name: 'AiWorkflow' })
|
||
} catch (error: any) {
|
||
console.error('保存失败:', error)
|
||
message.warning(error.message || '请完善所有步骤的必填信息')
|
||
}
|
||
}
|
||
|
||
/** 步骤切换处理 */
|
||
const handleStepClick = async (index: number) => {
|
||
try {
|
||
if (index !== 0) {
|
||
await validateBasic()
|
||
}
|
||
if (index !== 1) {
|
||
await validateWorkflow()
|
||
}
|
||
|
||
// 切换步骤
|
||
currentStep.value = index
|
||
} catch (error) {
|
||
console.error('步骤切换失败:', error)
|
||
message.warning('请先完善当前步骤必填信息')
|
||
}
|
||
}
|
||
|
||
/** 返回列表页 */
|
||
const handleBack = () => {
|
||
// 先删除当前页签
|
||
delView(unref(router.currentRoute))
|
||
// 跳转到列表页
|
||
router.push({ name: 'AiWorkflow' })
|
||
}
|
||
|
||
/** 初始化 */
|
||
onMounted(async () => {
|
||
await initData()
|
||
})
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
.border-bottom {
|
||
border-bottom: 1px solid #dcdfe6;
|
||
}
|
||
|
||
.text-primary {
|
||
color: #3473ff;
|
||
}
|
||
|
||
.bg-primary {
|
||
background-color: #3473ff;
|
||
}
|
||
|
||
.border-primary {
|
||
border-color: #3473ff;
|
||
}
|
||
</style>
|