Merge branch 'main' of ssh://18.167.251.121:10002/aidlab/FiDA_Front

This commit is contained in:
X1627315083@163.com
2026-03-05 13:51:17 +08:00
11 changed files with 246 additions and 211 deletions

View File

@@ -0,0 +1,5 @@
<svg width="13" height="14" viewBox="0 0 13 14" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M5.77778 6.3C5.77778 5.9134 5.45443 5.6 5.05556 5.6C4.65668 5.6 4.33333 5.9134 4.33333 6.3V9.8C4.33333 10.1866 4.65668 10.5 5.05556 10.5C5.45443 10.5 5.77778 10.1866 5.77778 9.8V6.3Z" fill="#FFEAE2"/>
<path d="M8.66667 6.3C8.66667 5.9134 8.34332 5.6 7.94444 5.6C7.54557 5.6 7.22222 5.9134 7.22222 6.3V9.8C7.22222 10.1866 7.54557 10.5 7.94444 10.5C8.34332 10.5 8.66667 10.1866 8.66667 9.8V6.3Z" fill="#FFEAE2"/>
<path d="M6.97498 0C8.3006 0 9.45611 0.874433 9.77762 2.1209L9.95278 2.8H11.5453C11.5515 2.79992 11.5578 2.79992 11.564 2.8H12.2778C12.6767 2.8 13 3.1134 13 3.5C13 3.8866 12.6767 4.2 12.2778 4.2H12.2045L11.3977 11.4983C11.2405 12.9211 10.0017 14 8.5253 14H4.4747C2.99834 14 1.75954 12.9211 1.60225 11.4983L0.79547 4.2H0.722222C0.32335 4.2 0 3.8866 0 3.5C0 3.1134 0.32335 2.8 0.722222 2.8H1.43598C1.44223 2.79992 1.44846 2.79992 1.45467 2.8H3.04722L3.22238 2.1209C3.54389 0.874431 4.6994 0 6.02502 0H6.97498ZM9.40399 4.2C9.39353 4.20022 9.3831 4.20022 9.37269 4.2H3.6273C3.6169 4.20022 3.60647 4.20022 3.59601 4.2H2.24818L3.03848 11.3491C3.11712 12.0605 3.73652 12.6 4.4747 12.6H8.5253C9.26348 12.6 9.88288 12.0605 9.96152 11.3491L10.7518 4.2H9.40399ZM4.62369 2.46045L4.53611 2.8H8.46387L8.37629 2.46045C8.21554 1.83722 7.63778 1.4 6.97497 1.4H6.025C5.3622 1.4 4.78444 1.83722 4.62369 2.46045Z" fill="#FFEAE2"/>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@@ -30,7 +30,7 @@
<script setup lang="ts"> <script setup lang="ts">
import flowCanvas from './FlowCanvas/flow-canvas.vue' import flowCanvas from './FlowCanvas/flow-canvas.vue'
import card from './FlowCanvas/components/cards/index.vue' import card from './FlowCanvas/components/nodes/cards/index.vue'
import { computed, ref, markRaw, onMounted, reactive, nextTick } from 'vue' import { computed, ref, markRaw, onMounted, reactive, nextTick } from 'vue'
const data = reactive({ const data = reactive({
x: 100, x: 100,

View File

@@ -8,7 +8,7 @@
:position="handle.position" :position="handle.position"
:connectable="false" :connectable="false"
/> />
<div class="item"> <div class="item" @mousedown="(e) => stateManager.setActiveNodeID(node.id)">
<slot></slot> <slot></slot>
</div> </div>
<div class="add" @mousedown.stop v-if="isAdd" @click="onAdd"> <div class="add" @mousedown.stop v-if="isAdd" @click="onAdd">

View File

@@ -156,7 +156,7 @@
<style lang="less" scoped> <style lang="less" scoped>
.card { .card {
width: 250px; width: 244px;
height: auto; height: auto;
--border-radius: 16px; --border-radius: 16px;
border-radius: var(--border-radius); border-radius: var(--border-radius);
@@ -164,6 +164,9 @@
box-shadow: 0 15px 21px 0 rgba(0, 0, 0, 0.05); box-shadow: 0 15px 21px 0 rgba(0, 0, 0, 0.05);
display: flex; display: flex;
flex-direction: column; flex-direction: column;
&.active {
box-shadow: 0 15px 21px 0 rgba(0, 0, 0, 0.05), 0 0 0 2px #fae5d8;
}
> .header { > .header {
border-radius: var(--border-radius) var(--border-radius) 0 0; border-radius: var(--border-radius) var(--border-radius) 0 0;
height: 50px; height: 50px;

View File

@@ -1,17 +1,11 @@
<template> <template>
<!-- 结果图片 --> <!-- 结果图片 -->
<div <div class="text" @mousedown="onMouseDown">
class="text"
:class="{ edit }"
@click="onClick"
@mousedown="onMouseDown"
@dblclick="onDoubleClick"
>
<div <div
tabindex="0" tabindex="0"
class="input" class="input"
ref="inputRef" ref="inputRef"
:contenteditable="edit" :contenteditable="active"
@input="onInput" @input="onInput"
@blur="onBlur" @blur="onBlur"
@paste.prevent @paste.prevent
@@ -20,8 +14,12 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { reactive, ref, onMounted, nextTick } from 'vue' import { reactive, ref, onMounted, nextTick, watch } from 'vue'
const props = defineProps({ const props = defineProps({
active: {
type: Boolean,
default: false
},
data: { data: {
type: Object, type: Object,
default: () => ({}) default: () => ({})
@@ -31,7 +29,6 @@
const data = reactive({ const data = reactive({
text: props.data?.text || '点击编辑文本' text: props.data?.text || '点击编辑文本'
}) })
const edit = ref(false)
const time = ref(null) const time = ref(null)
const inputRef = ref<any>() const inputRef = ref<any>()
const onInput = () => { const onInput = () => {
@@ -39,27 +36,26 @@
data.text = text data.text = text
emit('update-data', data) emit('update-data', data)
} }
const onBlur = () => { // watch(
edit.value = false // () => props.active,
} // (newVal) => {
const onClick = () => { // if (!newVal) return
if (edit.value) return // nextTick(() => {
edit.value = true // // 光标定位到文本末尾
nextTick(() => { // const range = document.createRange()
// 光标定位到文本末尾 // const selection = window.getSelection()
const range = document.createRange() // range.selectNodeContents(inputRef.value)
const selection = window.getSelection() // range.collapse(false)
range.selectNodeContents(inputRef.value) // selection.removeAllRanges()
range.collapse(false) // selection.addRange(range)
selection.removeAllRanges() // })
selection.addRange(range) // }
}) // )
}
const onDoubleClick = () => {
clearTimeout(time.value)
}
const onMouseDown = (e: MouseEvent) => { const onMouseDown = (e: MouseEvent) => {
if (edit.value) e.stopPropagation() if (props.active) e.stopPropagation()
}
const onBlur = () => {
// emit('update-data', data)
} }
onMounted(() => { onMounted(() => {
inputRef.value.innerHTML = data.text inputRef.value.innerHTML = data.text
@@ -73,7 +69,7 @@
user-select: none; user-select: none;
border: 1px solid transparent; border: 1px solid transparent;
padding: 2px; padding: 2px;
&.edit { &.active {
border-color: #000; border-color: #000;
> .input { > .input {
cursor: text; cursor: text;

View File

@@ -27,6 +27,8 @@
> >
<component <component
:is="components[node.data.component]" :is="components[node.data.component]"
:class="{ active: stateManager.activeNodeID.value === node.id }"
:active="stateManager.activeNodeID.value === node.id"
:node="node" :node="node"
:config="node.data" :config="node.data"
:data="node.data.data" :data="node.data.data"
@@ -127,7 +129,11 @@
stateManager.nodes.value = layout( stateManager.nodes.value = layout(
stateManager.nodes.value, stateManager.nodes.value,
stateManager.edges.value, stateManager.edges.value,
direction direction,
{
nodesep: nodeManager.nodesep,
ranksep: nodeManager.ranksep
}
) )
nextTick(() => { nextTick(() => {
fitView({ maxZoom: 1 }) fitView({ maxZoom: 1 })
@@ -187,6 +193,15 @@
} }
} }
}) })
nodeManager.createResultNode({
data: {
disableDelete: true,
isHeader: false,
data: {
url: props.config.url
}
}
})
}) })
</script> </script>
<style lang="less"> <style lang="less">

View File

@@ -26,6 +26,7 @@ export class EventManager {
} }
/** 处理点击 */ /** 处理点击 */
handleClick(event: any) { handleClick(event: any) {
this.stateManager.setActiveNodeID("")
const tool = this.stateManager.tool.value const tool = this.stateManager.tool.value
if (tool === TOOLS.TEXT) { if (tool === TOOLS.TEXT) {
const { x, y, zoom } = this.vueFlow.value.viewport const { x, y, zoom } = this.vueFlow.value.viewport

View File

@@ -12,6 +12,8 @@ interface NodeOptions {
export class NodeManager { export class NodeManager {
stateManager: any stateManager: any
vueFlow: any vueFlow: any
nodesep = 100 // 节点间距
ranksep = 100 // 层级间距
constructor(options) { constructor(options) {
this.stateManager = options.stateManager; this.stateManager = options.stateManager;
this.vueFlow = options.vueFlow this.vueFlow = options.vueFlow
@@ -37,7 +39,7 @@ export class NodeManager {
(!snode ? (!snode ?
{ x: positionX, y: positionY } : { x: positionX, y: positionY } :
{ {
x: snode.position.x + snode.dimensions.width + 50 + positionX, x: snode.position.x + snode.dimensions.width + this.nodesep + positionX,
y: snode.position.y + positionY y: snode.position.y + positionY
}) })
const data = options?.data || {} const data = options?.data || {}
@@ -111,7 +113,7 @@ export class NodeManager {
id: createId(), id: createId(),
position: { position: {
x: node.position.x, x: node.position.x,
y: node.position.y + (flowNode?.dimensions?.height || 0) + 50, y: node.position.y + (flowNode?.dimensions?.height || 0) + this.ranksep,
} }
} }
delete node_.data?.superiorID delete node_.data?.superiorID

View File

@@ -10,6 +10,7 @@ export interface NodesItem {
} }
export class StateManager { export class StateManager {
vueFlow: any vueFlow: any
activeNodeID: any
nodes: any nodes: any
nodes_: any nodes_: any
edges: any edges: any
@@ -49,6 +50,7 @@ export class StateManager {
this.historyList = ref([]) this.historyList = ref([])
this.historyIndex = ref(0) this.historyIndex = ref(0)
this.activeNodeID = ref("")
this.nodes = ref<NodesItem[]>([]); this.nodes = ref<NodesItem[]>([]);
this.nodes_ = computed(() => { this.nodes_ = computed(() => {
return this.nodes.value.map((node, index) => { return this.nodes.value.map((node, index) => {
@@ -90,6 +92,8 @@ export class StateManager {
}) })
} }
/** 设置激活节点 */
setActiveNodeID(id: string) { this.activeNodeID.value = id }
/** 添加节点 */ /** 添加节点 */
addNode(node: NodesItem) { addNode(node: NodesItem) {
this.nodes.value.push(node); this.nodes.value.push(node);

View File

@@ -14,7 +14,9 @@ export function useLayout() {
const previousDirection = ref('LR') const previousDirection = ref('LR')
function layout(nodes, edges, direction = 'LR') { function layout(nodes, edges, direction = 'LR', options) {
const nodesep = options?.nodesep || 50 // 节点间距
const ranksep = options?.ranksep || 50 // 层级间距
// 验证和规范化方向参数 // 验证和规范化方向参数
const validDirections = ['TB', 'BT', 'LR', 'RL'] const validDirections = ['TB', 'BT', 'LR', 'RL']
const layoutDirection = validDirections.includes(direction) ? direction : 'LR' const layoutDirection = validDirections.includes(direction) ? direction : 'LR'
@@ -28,7 +30,11 @@ export function useLayout() {
// 根据方向判断是否为水平布局 // 根据方向判断是否为水平布局
const isHorizontal = layoutDirection === 'LR' || layoutDirection === 'RL' const isHorizontal = layoutDirection === 'LR' || layoutDirection === 'RL'
dagreGraph.setGraph({ rankdir: layoutDirection }) dagreGraph.setGraph({
rankdir: layoutDirection,
nodesep,
ranksep,
})
previousDirection.value = layoutDirection previousDirection.value = layoutDirection

View File

@@ -1,5 +1,6 @@
<template> <template>
<div class="assist-input-wrapper flex flex-col" :class="{ agent: isAgentMode }"> <div class="assist-input-wrapper flex flex-col" :class="{ agent: isAgentMode }">
<div class="animate-container flex-1 flex flex-col">
<div class="scroll-content flex-col"> <div class="scroll-content flex-col">
<!-- 图片预览区域 --> <!-- 图片预览区域 -->
<div v-if="uploadedImages.length > 0" class="image-preview-list flex wrap"> <div v-if="uploadedImages.length > 0" class="image-preview-list flex wrap">
@@ -127,7 +128,9 @@
<img src="@/assets/images/setting.png" class="setting-icon" /> <img src="@/assets/images/setting.png" class="setting-icon" />
</template> </template>
<div class="fida-setting-popover-content flex flex-col"> <div class="fida-setting-popover-content flex flex-col">
<div class="fida-setting-popover-header">{{ $t('Input.styleTitle') }}</div> <div class="fida-setting-popover-header">
{{ $t('Input.styleTitle') }}
</div>
<div class="fida-setting-slider-list"> <div class="fida-setting-slider-list">
<div <div
v-for="item in settingOptions" v-for="item in settingOptions"
@@ -169,6 +172,8 @@
</div> </div>
</div> </div>
</div> </div>
</div>
<div v-if="!isAgentMode" class="report-btn flex flex-center" @click="toogltReportTag"> <div v-if="!isAgentMode" class="report-btn flex flex-center" @click="toogltReportTag">
<SvgIcon class="light-icon" name="light" size="16" /> <SvgIcon class="light-icon" name="light" size="16" />
<span>{{ $t('Input.trendingReport') }}</span> <span>{{ $t('Input.trendingReport') }}</span>
@@ -618,24 +623,22 @@
min-height: 23.5rem; min-height: 23.5rem;
max-height: 43.5rem; max-height: 43.5rem;
width: 106.3rem; width: 106.3rem;
border-radius: 2.8rem;
background-color: #fff;
border: 0.1rem solid #00000005;
box-shadow: 0px 0.5rem 1.4rem 0px #0000001a;
margin: 0 auto; margin: 0 auto;
padding: 0; padding: 0;
position: relative; position: relative;
&:not(.agent) .animate-container {
box-shadow: 0px 0.5rem 1.4rem 0px #0000001a;
transition: all 0.3s ease;
border-radius: 2.8rem;
background-color: #fff;
border: 0.1rem solid #00000005;
&:not(.agent):hover { &:not(.agent):hover {
box-shadow: 0px 0.5rem 3.36rem 2.2rem #f1ede999; box-shadow: 0px 0.5rem 3.36rem 2.2rem #f1ede999;
transition: all 0.3s ease; transform: translateY(-1rem);
top: -1rem;
.report-btn {
bottom: -8.4rem;
} }
} }
.scroll-content { .scroll-content {
display: flex; display: flex;
flex: 1; flex: 1;