diff --git a/src/views/createapp/components/appConfig.vue b/src/views/createapp/components/appConfig.vue index f6f02a9106be01fd4429a4fd86bd67900b6ba26c..1d14c3a5c0a4c650c869495e8cdc5a3906d83bc8 100644 --- a/src/views/createapp/components/appConfig.vue +++ b/src/views/createapp/components/appConfig.vue @@ -4,7 +4,7 @@ import { useI18n } from 'vue-i18n'; const { t } = useI18n(); import { IconCaretRight, IconPlusCircle, IconDelete, IconSearch } from '@computing/opendesign-icons'; import DialogueSession from '../../dialogue/components/DialogueSession.vue'; -const activeName = ref([1,2,3]); +const activeName = ref([1, 2, 3]); const activeNames = ref([1, 2, 3]); const createAppForm = ref({ icon: '', @@ -17,6 +17,7 @@ const createAppForm = ref({ selectedPeople: [], }); const searchName = ref(''); +const imageUrl = ref('') const permissionTypeList = [ { label: '公开(所有人可见)', @@ -69,144 +70,152 @@ const delRecommendItem = idx => { const searchPerson = () => { curPersonList.value = permissionList.value.filter(item => item.toLowerCase().includes(searchName.value)); }; + +const handleAvatarSuccess = (res,file)=>{ + console.log(res,file) +} + - - - - 基本信息 - - - - - - - - 上传图标 - - - - - + :model="createAppForm" + ref="createAppFormRef" + label-width="118px" + :rules="createAppRole" + class="createAppContainerMainLeft" + > + + + + 基本信息 + + + + + + + + + + + 上传图标 + + + + + - - - + + + - - - 添加链接 - 最多添加5个链接 - - - - - - - - + + + 添加链接 + 最多添加5个链接 + + + + + + + + - - - 添加问题 + + 添加问题 + 最多添加3个问题 + + + + + + + + + + + + 多轮对话 + + + + + + + + (1 ~ 10) + + + + + + 权限配置 + + + + + + + + {{ + item.label + }} + + + + + + + + + {{ item }} - 最多添加3个问题 - - - - - - - - - - - - 多轮对话 - - - - - - - - (1 ~ 10) - - - - - - 权限配置 - - - - - - - - {{ - item.label - }} - - - - - - - - - {{ item }} - - - - - - - - - - + + + + + + + + + + diff --git a/src/views/createapp/components/workFlow.vue b/src/views/createapp/components/workFlow.vue index 9044a44e3711b0b4bfb6ea297ace07c8b6096db2..66bd43507816225a0cab3448c9cb279dab44baf4 100644 --- a/src/views/createapp/components/workFlow.vue +++ b/src/views/createapp/components/workFlow.vue @@ -10,7 +10,8 @@ import CustomEdge from './workFlowConfig/CustomEdge.vue'; import CustomNode from './workFlowConfig/CustomNode.vue'; import CustomSaENode from './workFlowConfig/CustomSaENode.vue'; import useDragAndDrop from './workFlowConfig/useDnD'; -import { IconSearch, IconCaretRight } from '@computing/opendesign-icons'; +import WorkFlowDialog from './workFlowConfig/workFlowDialog.vue'; +import { IconSearch, IconCaretRight, IconCaretDown, IconPlusCircle } from '@computing/opendesign-icons'; const { t } = useI18n(); const copilotAside = ref(); @@ -18,6 +19,10 @@ const isCopilotAsideVisible = ref(true); const apiSearchValue = ref(); const activeNames = ref([1]); const activeName = ref(1); +const workFlowItem = ref(); +const isAddWorkFlow = ref(false); +const editData = ref(); +const dialogType = ref(''); function hanleAsideVisible(): void { if (!copilotAside.value) return; if (isCopilotAsideVisible.value) { @@ -27,7 +32,7 @@ function hanleAsideVisible(): void { } } -const { onInit, onNodeDragStop, onConnect, addEdges, updateNode, getNodes, getEdges, removeNodes } = useVueFlow(); +const { onInit, onConnect, addEdges, updateNode, getNodes, getEdges, findNode, removeNodes } = useVueFlow(); const { onDragOver, onDrop, onDragLeave, isDragOver, onDragStart } = useDragAndDrop(); // 这里是初始化的开始结束的节点 @@ -56,12 +61,13 @@ const nodes = ref([ }, ]); // 开始的边默认为空数组【当然回显时应该有值】 -const edges = ref([] as any); +const edges = ref([]); // 下方为死数据--之后有接口请将其替换为接口 const nodeStancesList = ref([ { id: '11', type: 'custom', + mark: 'iiiiii', data: { label: '知识库(成功节点)', desc: '这里是知识库说明', @@ -71,6 +77,7 @@ const nodeStancesList = ref([ { id: '12', type: 'custom', + mark: 'iiiiii', data: { label: 'LLM(失败节点)', desc: '调用大模型,生成自然语言报告', @@ -80,6 +87,7 @@ const nodeStancesList = ref([ { id: '13', type: 'custom', + mark: 'iiiiii', data: { label: '条件(正常初始化节点)', desc: '条件说明', @@ -94,20 +102,24 @@ onConnect(e => { }); }); -// 这里设置/更新节点状态,更新所有-nodes.value = 新节点列表, edges.value = 新连线列表 -const setNodeStatus = () => { - // 通过使用updateNode方法对节点进行更新【包含状态以及位置等】如updateNode('1', { position:{ x: 400, y: 400 } }) - const curNodeList = getNodes.value; - const curEdgeList = getEdges.value; - curNodeList.forEach(item => { - if (item.id) { - updateNode(item.id, { - data: { ...item.data, status: 'error' }, - }); - } - }); -}; const handleChange = () => {}; +// 打开新增工作流弹窗 +const addWorkFlow = () => { + // 待增加新增弹窗 + dialogType.value = '新增'; + isAddWorkFlow.value = true; +}; +// 关闭工作流弹出 +const handleClose = () => { + isAddWorkFlow.value = false; +}; +// 删除节点 +const delNode = (id) => { + if (id) { + const node = findNode(id); + node ? removeNodes(node) : ''; + } +} @@ -173,7 +185,7 @@ const handleChange = () => {}; - + @@ -192,19 +204,65 @@ const handleChange = () => {}; + + + + + + + + + + + + + 新建工作流 + + + + + - diff --git a/src/views/createapp/components/workFlowConfig/CustomNode.vue b/src/views/createapp/components/workFlowConfig/CustomNode.vue index 2247bd315c99773417c85ecc20e4a0356602578a..2c46dd67784f5dabf7e6c44d336d64afc43794f1 100644 --- a/src/views/createapp/components/workFlowConfig/CustomNode.vue +++ b/src/views/createapp/components/workFlowConfig/CustomNode.vue @@ -18,9 +18,15 @@ const props = defineProps({ type: Object, required: false, }, + mark: { + type: String, + required: false, + }, }); +const emits = defineEmits(['delNode']); const statusList = ref(['waiting', 'success', 'error', 'default']); + const curStatus = ref(''); watch( @@ -35,19 +41,32 @@ watch( }, { deep: true, immediate: true }, ); + +const delNode = id => { + emits('delNode', id); +}; - + + {{ props.data.label }} + + + ··· + 编辑 + 删除 + + {{ props.data.desc }} + @@ -61,43 +80,118 @@ watch( border-radius: 4px; border: 4px solid transparent; box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.1); + background-color: var(--o-bg-color-base); + position: relative; .nodeBox { padding: 16px 18px; display: flex; flex-direction: column; - background-color: var(--o-bg-color-base); gap: 8px; .title { display: flex; height: 24px; font-size: 16px; - color: #000; + color: var(--o-text-color-primary); gap: 8px; .iconStyle { width: 24px; height: 24px; background: linear-gradient(120deg, rgba(109, 117, 250, 0.15), rgba(90, 179, 255, 0.15)); } + .label { + flex: 1; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + .moreTip { + margin-left: auto; + width: 24px; + &:hover { + color: #6395fd; + } + } } .desc { font-size: 12px; color: var(--o-text-color-tertiary); } } + .vue-flow__handle-right { + top: 50%; + right: 0px; + width: 16px; + height: 16px; + border-radius: 50%; + background: rgb(253, 254, 255); + display: flex; + align-items: center; + justify-content: center; + } + + .vue-flow__handle-right::after { + content: ''; + width: 12px; + height: 12px; + border: 3px solid rgb(223, 229, 239); + border-radius: 50%; + background: rgb(141, 152, 170); + } + .vue-flow__handle-left { + top: 50%; + left: 0px; + width: 16px; + height: 16px; + border-radius: 50%; + background: rgb(253, 254, 255); + display: flex; + align-items: center; + justify-content: center; + } + + .vue-flow__handle-left::after { + content: ''; + width: 12px; + height: 12px; + border: 3px solid rgb(223, 229, 239); + border-radius: 50%; + background: rgb(141, 152, 170); + } + .outHandleRing { + position: absolute; + display: block; + width: 24px; + height: 24px; + background: #fff; + border-radius: 50%; + top: 50%; + z-index: -1; + } + .outRingLeft { + display: none; + left: -12px; + margin-top: -12px; + } + .outRingRight { + display: none; + right: -12px; + margin-top: -12px; + } &:hover { - border: 4px solid rgba(122, 165, 255, 0.3); + border: 4px solid rgba(99, 149, 253, 0.3); + box-shadow: 0px 0px 0px 8px rgba(99, 149, 253, 0.1); .vue-flow__handle-left { width: 24px; height: 24px; - left: -8px; + left: -12px; margin-top: -12px; transform: rotate(-45deg); - border: 4px solid rgba(122, 165, 255, 0.3); + border: 4px solid rgba(99, 149, 253, 0.3); border-right: 4px solid transparent; border-bottom: 4px solid transparent; &::after { - border: 3px solid rgba(122, 165, 255, 0.3); - background: rgba(122, 165, 255); + border: 3px solid rgba(99, 149, 253, 0.3); + background: rgba(99, 149, 253); background-clip: content-box; } } @@ -105,33 +199,44 @@ watch( right: -8px; width: 24px; height: 24px; + right: -12px; margin-top: -12px; transform: rotate(45deg); - border: 4px solid rgba(122, 165, 255, 0.3); + border: 4px solid rgba(99, 149, 253, 0.3); border-left: 4px solid transparent; border-bottom: 4px solid transparent; &::after { - border: 3px solid rgba(122, 165, 255, 0.3); - background: rgba(122, 165, 255); + border: 3px solid rgba(99, 149, 253, 0.3); + background: rgba(99, 149, 253); background-clip: content-box; } } + .outRingLeft { + display: block; + box-shadow: 0px 0px 0px 8px rgba(99, 149, 253, 0.1); + background-clip: content-box; + } + .outRingRight { + display: block; + box-shadow: 0px 0px 0px 8px rgba(99, 149, 253, 0.1); + background-clip: content-box; + } } } .customNodeStyle.success { - border: 4px solid rgba(36, 171, 54, 0.2); + border: 4px solid rgba(36, 171, 54, 0.3); .vue-flow__handle-left { + transform: rotate(-45deg); width: 24px; height: 24px; - left: -8px; + left: -12px; margin-top: -12px; - transform: rotate(-45deg); - border: 4px solid rgba(36, 171, 54, 0.2); + border: 4px solid rgba(36, 171, 54, 0.3); border-right: 4px solid transparent; border-bottom: 4px solid transparent; &::after { - border: 3px solid rgb(36, 171, 54, 0.2); + border: 3px solid rgb(36, 171, 54, 0.3); background: rgb(36, 171, 54); background-clip: content-box; } @@ -139,103 +244,95 @@ watch( .vue-flow__handle-right { width: 24px; height: 24px; - right: -8px; + right: -12px; margin-top: -12px; transform: rotate(45deg); - border: 4px solid rgba(36, 171, 54, 0.2); + border: 4px solid rgba(36, 171, 54, 0.3); border-left: 4px solid transparent; border-bottom: 4px solid transparent; &::after { - border: 3px solid rgb(36, 171, 54, 0.2); + border: 3px solid rgb(36, 171, 54, 0.3); background: rgb(36, 171, 54); background-clip: content-box; } } &:hover { - .vue-flow__handle-left { - // 需添加阴影 + box-shadow: 0px 0px 0px 8px rgba(36, 171, 54, 0.1); + .outRingLeft { + box-shadow: 0px 0px 0px 8px rgba(36, 171, 54, 0.1); } - .vue-flow__handle-right { - // 需添加阴影 + .outRingRight { + box-shadow: 0px 0px 0px 8px rgba(36, 171, 54, 0.1); } } } .customNodeStyle.error { - border: 4px solid rgba(227, 32, 32, 0.2); + border: 4px solid rgba(227, 32, 32, 0.3); .vue-flow__handle-left { + transform: rotate(-45deg); width: 24px; height: 24px; - left: -8px; + left: -12px; margin-top: -12px; - transform: rotate(-45deg); - border: 4px solid rgba(227, 32, 32, 0.2); + border: 4px solid rgba(227, 32, 32, 0.3); border-right: 4px solid transparent; border-bottom: 4px solid transparent; - &::after { - border: 3px solid rgba(227, 32, 32, 0.2); - background: rgba(227, 32, 32); + border: 3px solid rgb(227, 32, 32, 0.3); + background: rgb(227, 32, 32); background-clip: content-box; } } .vue-flow__handle-right { width: 24px; height: 24px; - right: -8px; + right: -12px; margin-top: -12px; transform: rotate(45deg); - border: 4px solid rgba(227, 32, 32, 0.2); + border: 4px solid rgba(227, 32, 32, 0.3); border-left: 4px solid transparent; border-bottom: 4px solid transparent; - &::after { - border: 3px solid rgba(227, 32, 32, 0.2); - background: rgba(227, 32, 32); + border: 3px solid rgb(227, 32, 32, 0.3); + background: rgb(227, 32, 32); background-clip: content-box; } } + &:hover { + box-shadow: 0px 0px 0px 8px rgba(227, 32, 32, 0.1); + .outRingLeft { + box-shadow: 0px 0px 0px 8px rgba(227, 32, 32, 0.1); + } + .outRingRight { + box-shadow: 0px 0px 0px 8px rgba(227, 32, 32, 0.1); + } + } } - - .vue-flow__handle-right { - top: 50%; - right: 4px; - width: 16px; - height: 16px; - border-radius: 50%; - background: rgb(253, 254, 255); - display: flex; - align-items: center; - justify-content: center; - } - - .vue-flow__handle-right::after { - content: ''; - width: 10px; - height: 10px; - border: 3px solid rgb(223, 229, 239); - border-radius: 50%; - background: rgb(141, 152, 170); - } - .vue-flow__handle-left { - top: 50%; - left: 4px; - width: 16px; - height: 16px; - border-radius: 50%; - background: rgb(253, 254, 255); - display: flex; - align-items: center; - justify-content: center; +} +.nodeDealPopper { + width: 64px !important; + min-width: 64px !important; + height: 72px; + padding: 4px 0px !important; + border-radius: 4px; + .dealItem { + display: block; + width: 100%; + height: 32px; + line-height: 32px; + text-align: center; + margin-left: 0px; + color: var(--o-text-color-secondary); + &:hover { + span { + color: var(--o-color-white) !important; + } + background-color: var(--o-color-primary-secondary) !important; + } } - - .vue-flow__handle-left::after { - content: ''; - width: 10px; - height: 10px; - border: 3px solid rgb(223, 229, 239); - border-radius: 50%; - background: rgb(141, 152, 170); + &:hover { + border: 1px solid var(--o-color-primary-secondary) !important; } } diff --git a/src/views/createapp/components/workFlowConfig/workFlowDialog.vue b/src/views/createapp/components/workFlowConfig/workFlowDialog.vue new file mode 100644 index 0000000000000000000000000000000000000000..e6eede54dd2998eae6df6a05ab120c785da566cd --- /dev/null +++ b/src/views/createapp/components/workFlowConfig/workFlowDialog.vue @@ -0,0 +1,66 @@ + + + + + + + + + + + + + 确定 + 取消 + + + + + + + \ No newline at end of file diff --git a/src/views/createapp/index.vue b/src/views/createapp/index.vue index c2f4bcdf7581ebd2a0f07d12b3bad04027e42f01..788368f947a42988019ee8db9e275466f5b8f6c2 100644 --- a/src/views/createapp/index.vue +++ b/src/views/createapp/index.vue @@ -38,10 +38,10 @@ const handleChangeAppType = (type) => { - + - + diff --git a/src/views/dialogue/components/DialogueSession.vue b/src/views/dialogue/components/DialogueSession.vue index 0c910cea7f317771e325628eb5a35caffad49a96..22c3941a83a744049d4e6780a54756b2ad3bf61d 100644 --- a/src/views/dialogue/components/DialogueSession.vue +++ b/src/views/dialogue/components/DialogueSession.vue @@ -3,6 +3,7 @@ import { computed, nextTick, onMounted, ref, watch } from 'vue'; import DialoguePanel from 'src/components/dialoguePanel/DialoguePanel.vue'; import UploadFileGroup from 'src/components/uploadFile/UploadFileGroup.vue'; import InitalPanel from './InitalPanel.vue'; +import InterPreview from './InterPreview.vue'; import { storeToRefs } from 'pinia'; import { useSessionStore, useChangeThemeStore } from 'src/store'; @@ -37,7 +38,7 @@ enum SupportMap { const { pausedStream, reGenerateAnswer, prePage, nextPage } = useSessionStore(); const themeStore = useChangeThemeStore(); const modeOptions = ref(props.modeOptions); -const isCreateApp = ref(props?.isCreateApp) +const isCreateApp = ref(props?.isCreateApp); const questions = [ { groupId: 0, @@ -146,7 +147,6 @@ const questions = [ }, ]; - let groupid = ref(0); const tagNum = ref(3); @@ -812,9 +812,10 @@ const handlePauseAndReGenerate = (cid?: number) => { - - - + + + + { + + + + + + + diff --git a/src/views/styles/InterPreview.scss b/src/views/styles/InterPreview.scss new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391