This commit is contained in:
lzp
2026-03-25 17:27:47 +08:00
17 changed files with 304 additions and 49 deletions

View File

@@ -79,3 +79,20 @@ body,
--el-color-primary-light-9: #fff2ec;
--el-color-primary-dark-2: #cc6241;
}
.el-select,
.el-popper {
--el-color-primary: #6c6c6c;
/* 主灰色 */
--el-color-primary-light-3: #8a8a8a;
/* 较浅的灰色混合20%白) */
--el-color-primary-light-5: #a8a8a8;
/* 更浅的灰色混合33%白) */
--el-color-primary-light-7: #c6c6c6;
/* 浅灰色混合47%白) */
--el-color-primary-light-8: #d4d4d4;
/* 很浅的灰色混合53%白) */
--el-color-primary-light-9: #e3e3e3;
/* 极浅的灰色混合60%白) */
--el-color-primary-dark-2: #565656;
/* 深灰色加深20% */
}

View File

@@ -95,4 +95,13 @@ body,
--el-color-primary-light-8: #ffe8df; // 很浅的橙红混合53%白)
--el-color-primary-light-9: #fff2ec; // 极浅的橙红混合60%白)
--el-color-primary-dark-2: #cc6241; // 深橙红加深20%
}
}
.el-select, .el-popper{
--el-color-primary: #6c6c6c; /* 主灰色 */
--el-color-primary-light-3: #8a8a8a; /* 较浅的灰色混合20%白) */
--el-color-primary-light-5: #a8a8a8; /* 更浅的灰色混合33%白) */
--el-color-primary-light-7: #c6c6c6; /* 浅灰色混合47%白) */
--el-color-primary-light-8: #d4d4d4; /* 很浅的灰色混合53%白) */
--el-color-primary-light-9: #e3e3e3; /* 极浅的灰色混合60%白) */
--el-color-primary-dark-2: #565656; /* 深灰色加深20% */
}

View File

@@ -0,0 +1,8 @@
<svg width="13" height="13" viewBox="0 0 13 13" fill="none" xmlns="http://www.w3.org/2000/svg">
<mask id="path-1-outside-1_3940_24441" maskUnits="userSpaceOnUse" x="-0.700195" y="-0.699219" width="14" height="14" fill="black">
<rect fill="white" x="-0.700195" y="-0.699219" width="14" height="14"/>
<path d="M11.7998 11.3008C12.0759 11.3008 12.2998 11.5246 12.2998 11.8008C12.2998 12.0769 12.0759 12.3008 11.7998 12.3008H0.799805C0.523663 12.3008 0.299805 12.0769 0.299805 11.8008C0.299805 11.5246 0.523663 11.3008 0.799805 11.3008H11.7998ZM9.7998 0.300781C10.0759 0.300781 10.2998 0.524639 10.2998 0.800781V5.30078C10.2998 7.50992 8.50894 9.30078 6.2998 9.30078C4.09067 9.30078 2.2998 7.50992 2.2998 5.30078V0.800781C2.2998 0.524639 2.52366 0.300781 2.7998 0.300781C3.07595 0.300781 3.2998 0.524639 3.2998 0.800781V5.30078C3.2998 6.95764 4.64295 8.30078 6.2998 8.30078C7.95666 8.30078 9.2998 6.95764 9.2998 5.30078V0.800781C9.2998 0.524639 9.52366 0.300781 9.7998 0.300781Z"/>
</mask>
<path d="M11.7998 11.3008C12.0759 11.3008 12.2998 11.5246 12.2998 11.8008C12.2998 12.0769 12.0759 12.3008 11.7998 12.3008H0.799805C0.523663 12.3008 0.299805 12.0769 0.299805 11.8008C0.299805 11.5246 0.523663 11.3008 0.799805 11.3008H11.7998ZM9.7998 0.300781C10.0759 0.300781 10.2998 0.524639 10.2998 0.800781V5.30078C10.2998 7.50992 8.50894 9.30078 6.2998 9.30078C4.09067 9.30078 2.2998 7.50992 2.2998 5.30078V0.800781C2.2998 0.524639 2.52366 0.300781 2.7998 0.300781C3.07595 0.300781 3.2998 0.524639 3.2998 0.800781V5.30078C3.2998 6.95764 4.64295 8.30078 6.2998 8.30078C7.95666 8.30078 9.2998 6.95764 9.2998 5.30078V0.800781C9.2998 0.524639 9.52366 0.300781 9.7998 0.300781Z" fill="#0D0D0D"/>
<path d="M11.7998 11.3008V11.0008V11.0008V11.3008ZM12.2998 11.8008H12.5998V11.8008H12.2998ZM11.7998 12.3008V12.0008V12.0008V12.3008ZM0.799805 12.3008L0.799805 12.6008H0.799805V12.3008ZM0.299805 11.8008H-0.000195324V11.8008H0.299805ZM0.799805 11.3008L0.799805 11.6008H0.799805V11.3008ZM11.7998 11.3008V11.6008C11.9103 11.6008 11.9998 11.6903 11.9998 11.8008H12.2998H12.5998C12.5998 11.359 12.2416 11.0008 11.7998 11.0008V11.3008ZM12.2998 11.8008H11.9998C11.9998 11.9112 11.9103 12.0008 11.7998 12.0008V12.3008V12.6008C12.2416 12.6008 12.5998 12.2426 12.5998 11.8008H12.2998ZM11.7998 12.3008V12.0008H0.799805V12.3008V12.6008H11.7998V12.3008ZM0.799805 12.3008V12.0008C0.689349 12.0008 0.599805 11.9112 0.599805 11.8008H0.299805H-0.000195324C-0.000194907 12.2426 0.357977 12.6008 0.799805 12.6008L0.799805 12.3008ZM0.299805 11.8008H0.599805C0.599805 11.6903 0.689348 11.6008 0.799805 11.6008L0.799805 11.3008V11.0008C0.357977 11.0008 -0.000195295 11.359 -0.000195324 11.8008H0.299805ZM0.799805 11.3008V11.6008H11.7998V11.3008V11.0008H0.799805V11.3008ZM9.7998 0.300781V0.600781C9.91026 0.600781 9.9998 0.690324 9.9998 0.800781H10.2998H10.5998C10.5998 0.358954 10.2416 0.000781238 9.7998 0.000781238V0.300781ZM10.2998 0.800781H9.9998V5.30078H10.2998H10.5998V0.800781H10.2998ZM10.2998 5.30078H9.9998C9.9998 7.34423 8.34326 9.00078 6.2998 9.00078V9.30078V9.60078C8.67463 9.60078 10.5998 7.67561 10.5998 5.30078H10.2998ZM6.2998 9.30078V9.00078C4.25635 9.00078 2.5998 7.34423 2.5998 5.30078H2.2998H1.9998C1.9998 7.67561 3.92498 9.60078 6.2998 9.60078V9.30078ZM2.2998 5.30078H2.5998V0.800781H2.2998H1.9998V5.30078H2.2998ZM2.2998 0.800781H2.5998C2.5998 0.690324 2.68935 0.600781 2.7998 0.600781V0.300781V0.000781238C2.35798 0.000781238 1.9998 0.358953 1.9998 0.800781H2.2998ZM2.7998 0.300781V0.600781C2.91026 0.600781 2.9998 0.690324 2.9998 0.800781H3.2998H3.5998C3.5998 0.358953 3.24163 0.000781238 2.7998 0.000781238V0.300781ZM3.2998 0.800781H2.9998V5.30078H3.2998H3.5998V0.800781H3.2998ZM3.2998 5.30078H2.9998C2.9998 7.12332 4.47726 8.60078 6.2998 8.60078V8.30078V8.00078C4.80864 8.00078 3.5998 6.79195 3.5998 5.30078H3.2998ZM6.2998 8.30078V8.60078C8.12234 8.60078 9.5998 7.12332 9.5998 5.30078H9.2998H8.9998C8.9998 6.79195 7.79097 8.00078 6.2998 8.00078V8.30078ZM9.2998 5.30078H9.5998V0.800781H9.2998H8.9998V5.30078H9.2998ZM9.2998 0.800781H9.5998C9.5998 0.690324 9.68935 0.600781 9.7998 0.600781V0.300781V0.000781238C9.35798 0.000781238 8.9998 0.358954 8.9998 0.800781H9.2998Z" fill="black" mask="url(#path-1-outside-1_3940_24441)"/>
</svg>

After

Width:  |  Height:  |  Size: 4.1 KiB

View File

@@ -0,0 +1,4 @@
<svg width="9" height="13" viewBox="0 0 9 13" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M7.75 0.25C8.02614 0.25 8.25 0.473858 8.25 0.75C8.25 1.02614 8.02614 1.25 7.75 1.25H5.66797L3.84961 11.25H5.75C6.02614 11.25 6.25 11.4739 6.25 11.75C6.25 12.0261 6.02614 12.25 5.75 12.25H0.75C0.473858 12.25 0.25 12.0261 0.25 11.75C0.25 11.4739 0.473858 11.25 0.75 11.25H2.83203L4.65039 1.25H2.75C2.47386 1.25 2.25 1.02614 2.25 0.75C2.25 0.473858 2.47386 0.25 2.75 0.25H7.75Z" fill="#0D0D0D"/>
<path d="M5.66797 1.25V1H5.45933L5.422 1.20527L5.66797 1.25ZM3.84961 11.25L3.60364 11.2053L3.55005 11.5H3.84961V11.25ZM2.83203 11.25V11.5H3.04067L3.078 11.2947L2.83203 11.25ZM4.65039 1.25L4.89636 1.29473L4.94995 1H4.65039V1.25ZM7.75 0.25V0.5C7.88807 0.5 8 0.611929 8 0.75H8.25H8.5C8.5 0.335786 8.16421 0 7.75 0V0.25ZM8.25 0.75H8C8 0.888071 7.88807 1 7.75 1V1.25V1.5C8.16421 1.5 8.5 1.16421 8.5 0.75H8.25ZM7.75 1.25V1H5.66797V1.25V1.5H7.75V1.25ZM5.66797 1.25L5.422 1.20527L3.60364 11.2053L3.84961 11.25L4.09558 11.2947L5.91394 1.29473L5.66797 1.25ZM3.84961 11.25V11.5H5.75V11.25V11H3.84961V11.25ZM5.75 11.25V11.5C5.88807 11.5 6 11.6119 6 11.75H6.25H6.5C6.5 11.3358 6.16421 11 5.75 11V11.25ZM6.25 11.75H6C6 11.8881 5.88807 12 5.75 12V12.25V12.5C6.16421 12.5 6.5 12.1642 6.5 11.75H6.25ZM5.75 12.25V12H0.75V12.25V12.5H5.75V12.25ZM0.75 12.25V12C0.611929 12 0.5 11.8881 0.5 11.75H0.25H0C0 12.1642 0.335786 12.5 0.75 12.5V12.25ZM0.25 11.75H0.5C0.5 11.6119 0.611929 11.5 0.75 11.5V11.25V11C0.335786 11 0 11.3358 0 11.75H0.25ZM0.75 11.25V11.5H2.83203V11.25V11H0.75V11.25ZM2.83203 11.25L3.078 11.2947L4.89636 1.29473L4.65039 1.25L4.40442 1.20527L2.58606 11.2053L2.83203 11.25ZM4.65039 1.25V1H2.75V1.25V1.5H4.65039V1.25ZM2.75 1.25V1C2.61193 1 2.5 0.888071 2.5 0.75H2.25H2C2 1.16421 2.33579 1.5 2.75 1.5V1.25ZM2.25 0.75H2.5C2.5 0.611929 2.61193 0.5 2.75 0.5V0.25V0C2.33579 0 2 0.335786 2 0.75H2.25ZM2.75 0.25V0.5H7.75V0.25V0H2.75V0.25Z" fill="black"/>
</svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@@ -0,0 +1,7 @@
<svg width="9" height="12" viewBox="0 0 9 12" fill="none" xmlns="http://www.w3.org/2000/svg">
<mask id="path-1-inside-1_3940_24436" fill="white">
<path d="M4.75 0C6.54493 0 8 1.45507 8 3.25C8 4.08551 7.68116 4.84417 7.16309 5.41992C8.25691 6.01178 9 7.169 9 8.5C9 10.433 7.433 12 5.5 12H2C0.895431 12 0 11.1046 0 10V2C0 0.895431 0.895431 0 2 0H4.75ZM1.5 10C1.5 10.2761 1.72386 10.5 2 10.5H5.5C6.60457 10.5 7.5 9.60457 7.5 8.5C7.5 7.39543 6.60457 6.5 5.5 6.5H1.5V10ZM2 1.5C1.72386 1.5 1.5 1.72386 1.5 2V5H4.75C5.7165 5 6.5 4.2165 6.5 3.25C6.5 2.2835 5.7165 1.5 4.75 1.5H2Z"/>
</mask>
<path d="M4.75 0C6.54493 0 8 1.45507 8 3.25C8 4.08551 7.68116 4.84417 7.16309 5.41992C8.25691 6.01178 9 7.169 9 8.5C9 10.433 7.433 12 5.5 12H2C0.895431 12 0 11.1046 0 10V2C0 0.895431 0.895431 0 2 0H4.75ZM1.5 10C1.5 10.2761 1.72386 10.5 2 10.5H5.5C6.60457 10.5 7.5 9.60457 7.5 8.5C7.5 7.39543 6.60457 6.5 5.5 6.5H1.5V10ZM2 1.5C1.72386 1.5 1.5 1.72386 1.5 2V5H4.75C5.7165 5 6.5 4.2165 6.5 3.25C6.5 2.2835 5.7165 1.5 4.75 1.5H2Z" fill="#0D0D0D"/>
<path d="M7.16309 5.41992L6.79141 5.08548C6.6889 5.19939 6.6443 5.35402 6.67038 5.50503C6.69647 5.65604 6.79036 5.78675 6.92514 5.85967L7.16309 5.41992ZM1.5 6.5V6C1.22386 6 1 6.22386 1 6.5H1.5ZM1.5 5H1C1 5.27614 1.22386 5.5 1.5 5.5V5ZM4.75 0V0.5C6.26878 0.5 7.5 1.73122 7.5 3.25H8H8.5C8.5 1.17893 6.82107 -0.5 4.75 -0.5V0ZM8 3.25H7.5C7.5 3.95529 7.23147 4.59641 6.79141 5.08548L7.16309 5.41992L7.53477 5.75437C8.13085 5.09192 8.5 4.21573 8.5 3.25H8ZM7.16309 5.41992L6.92514 5.85967C7.86405 6.36771 8.5 7.3599 8.5 8.5H9H9.5C9.5 6.9781 8.64977 5.65585 7.40103 4.98017L7.16309 5.41992ZM9 8.5H8.5C8.5 10.1569 7.15685 11.5 5.5 11.5V12V12.5C7.70914 12.5 9.5 10.7091 9.5 8.5H9ZM5.5 12V11.5H2V12V12.5H5.5V12ZM2 12V11.5C1.17157 11.5 0.5 10.8284 0.5 10H0H-0.5C-0.5 11.3807 0.619288 12.5 2 12.5V12ZM0 10H0.5V2H0H-0.5V10H0ZM0 2H0.5C0.5 1.17157 1.17157 0.5 2 0.5V0V-0.5C0.619288 -0.5 -0.5 0.619288 -0.5 2H0ZM2 0V0.5H4.75V0V-0.5H2V0ZM1.5 10H1C1 10.5523 1.44772 11 2 11V10.5V10H1.5ZM2 10.5V11H5.5V10.5V10H2V10.5ZM5.5 10.5V11C6.88071 11 8 9.88071 8 8.5H7.5H7C7 9.32843 6.32843 10 5.5 10V10.5ZM7.5 8.5H8C8 7.11929 6.88071 6 5.5 6V6.5V7C6.32843 7 7 7.67157 7 8.5H7.5ZM5.5 6.5V6H1.5V6.5V7H5.5V6.5ZM1.5 6.5H1V10H1.5H2V6.5H1.5ZM2 1.5V1C1.44772 1 1 1.44772 1 2H1.5H2V1.5ZM1.5 2H1V5H1.5H2V2H1.5ZM1.5 5V5.5H4.75V5V4.5H1.5V5ZM4.75 5V5.5C5.99264 5.5 7 4.49264 7 3.25H6.5H6C6 3.94036 5.44036 4.5 4.75 4.5V5ZM6.5 3.25H7C7 2.00736 5.99264 1 4.75 1V1.5V2C5.44036 2 6 2.55964 6 3.25H6.5ZM4.75 1.5V1H2V1.5V2H4.75V1.5Z" fill="black" mask="url(#path-1-inside-1_3940_24436)"/>
</svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

@@ -44,7 +44,7 @@
const tools = ref([
{ name: TOOLS.SELECT, icon: 'c-select', iconSize: 16, disabled: ref(false) },
{ name: TOOLS.MOVE, icon: 'c-move', iconSize: 18, disabled: ref(false) },
{ name: TOOLS.TEXT, icon: 'c-text', iconSize: 18, disabled: ref(false) },
{ name: TOOLS.TEXT, icon: 'c-text', iconSize: 22, disabled: ref(false) },
{ type: 'line' },
{
name: TOOLS.UNDO,

View File

@@ -4,6 +4,7 @@
<div
tabindex="0"
class="input"
:style="data.textStyle"
ref="inputRef"
:contenteditable="active"
@input="onInput"
@@ -11,6 +12,9 @@
@paste.prevent
@keydown.stop
></div>
<div class="tools" @mousedown="onMouseDown" v-if="active">
<myTextTools :textStyle="data.textStyle"></myTextTools>
</div>
<span class="delete" @mousedown.stop @click="emit('delete-node')" v-show="active">
<svg-icon name="close" size="7" size-unit="px" />
</span>
@@ -19,6 +23,7 @@
<script setup lang="ts">
import { reactive, ref, onMounted, nextTick, watch } from 'vue'
import myTextTools from '@/components/Canvas/FlowCanvas/components/tools/my-textTools.vue'
const props = defineProps({
active: {
type: Boolean,
@@ -31,7 +36,15 @@
})
const emit = defineEmits(['update-data', 'delete-node'])
const data = reactive({
text: props.data?.text || '点击编辑文本'
text: props.data?.text || '点击编辑文本',
textStyle:{
'--font-size':props.data?.textStyle?.['--font-size'] || '16px',
'--font-color':props.data?.textStyle?.['--font-color'] || '#000',
'--font-style':props.data?.textStyle?.['--font-style'] || 'normal',//italic
'--font-family':props.data?.textStyle?.['--font-family'] || 'Medium',
'--font-weight':props.data?.textStyle?.['--font-weight'] || 'initial',//blod
'--font-decoration':props.data?.textStyle?.['--font-decoration'] || 'none',//underline
}
})
const time = ref(null)
const inputRef = ref<any>()
@@ -70,19 +83,25 @@
<style lang="less" scoped>
.text {
user-select: none;
border: 1px solid transparent;
padding: 2px;
position: relative;
&.active {
border-color: #000;
> .input {
border-color: #000;
cursor: text;
}
}
> .input {
border: 1px solid transparent;
padding: 2px;
outline: none;
min-width: 2px;
font-size: 16px;
color: var(--font-color);
font-style: var(--font-style);
font-weight: var(--font-weight);
font-size: var(--font-size);
text-decoration: var(--font-decoration);
font-family: var(--font-family);
}
> .delete {
position: absolute;
@@ -94,5 +113,15 @@
border-radius: 50%;
cursor: pointer;
}
> .tools{
position: absolute;
left: 50%;
transform: translate(-50%,-100%);
top: -10px;
height: 41px;
border: 2px solid #EBEBEB;
border-radius: 11px;
background-color: #fff;
}
}
</style>

View File

@@ -43,6 +43,7 @@
.el-select-dropdown {
li {
padding-left: 8px;
padding-right: 8px;
height: 30px;
line-height: 30px;
font-size: 12px;

View File

@@ -0,0 +1,141 @@
<template>
<div class="my-textTools">
<input class="color" type="color" ref="colorInput" @change="changeColor" />
<div class="interval"></div>
<div class="fontFamily">
<my-select v-model="textStyle['--font-family']" @change="changeFontFamily" :list="fontFamilyList[locale]" />
</div>
<div class="interval"></div>
<div class="size">
<div class="label" @click="changeFontSize(-1)">
-
</div>
<div class="value">{{ parseInt(props.textStyle?.['--font-size']) }}</div>
<div class="label" @click="changeFontSize(1)">
+
</div>
</div>
<div class="interval"></div>
<div class="fontStyle">
<div class="label" @click="changeFontStyle('--font-weight',['bold','normal'])" :class="{'active': props.textStyle['--font-weight'] === 'bold'}">
<svg-icon name="textToolsweight" size="12" size-unit="px" color="#000" />
</div>
<div class="label" @click="changeFontStyle('--font-style',['italic','normal'])" :class="{'active': props.textStyle['--font-style'] === 'italic'}">
<svg-icon name="textToolsStyle" size="12" size-unit="px" color="#000" />
</div>
<div class="label" @click="changeFontStyle('--font-decoration',['underline','none'])" :class="{'active': props.textStyle['--font-decoration'] === 'underline'}">
<svg-icon name="textToolsDecoration" size="12" size-unit="px" color="#000" />
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { reactive, ref, markRaw, onMounted } from 'vue'
import { useI18n } from 'vue-i18n'
const emit = defineEmits(['update:textStyle'])
const { locale } = useI18n()
const fontFamilyList = ref({
ENGLISH: [
{ value:'Medium',label:'Medium' },
{ value:'Arial',label:'Arial' },
{ value:'Helvetica',label:'Helvetica' },
{ value:'Times New Roman',label:'Times New Roman' },
{ value:'Georgia',label:'Georgia' },
{ value:'Verdana',label:'Verdana' },
{ value:'Courier New',label:'Courier New' },
{ value:'Lucida Console',label:'Lucida Console' },
{ value:'General Sans',label:'General Sans' },
{ value:'Inter',label:'Inter' },
],
CHINESE_SIMPLIFIED: [
{ value:'Medium',label:'Medium' },
{ value:'微软雅黑',label:'微软雅黑' },
{ value:'宋体',label:'宋体' },
{ value:'黑体',label:'黑体' },
{ value:'仿宋',label:'仿宋' },
{ value:'楷体',label:'楷体' },
{ value:'苹方',label:'苹方' },
{ value:'华文黑体',label:'华文黑体' },
{ value:'华文宋体',label:'华文宋体' },
{ value:'华文楷体',label:'华文楷体' },
{ value:'思源黑体',label:'思源黑体' },
{ value:'MiSans',label:'MiSans' },
]
})
const props = defineProps({
textStyle: { type: Object },
})
const changeFontFamily = (val: string) => {
props.textStyle['--font-family'] = val
onChange()
}
const changeColor = (e: Event) => {
const target = e.target as HTMLInputElement
props.textStyle['--font-color'] = target.value
onChange()
}
const changeFontSize = (val: number) => {
if (parseInt(props.textStyle?.['--font-size']) + val <= 9 || parseInt(props.textStyle?.['--font-size']) + val >= 51) {
return
}
props.textStyle['--font-size'] = parseInt(props.textStyle?.['--font-size']) + val + 'px'
onChange()
}
const changeFontStyle = (key: string,value: string[]) => {
props.textStyle[key] = props.textStyle[key] === value[0] ? value[1] : value[0]
onChange()
}
const onChange = () => {
emit('update:textStyle', props.textStyle)
}
</script>
<style lang="less" scoped>
.my-textTools {
height: 100%;
display: flex;
padding: 6px 19px;
align-items: center;
.interval{
margin: 0 16px;
height: 25px;
width: 1px;
background-color: #EBEBEB;
}
.label{
height: 20px;
width: 20px;
border-radius: 2px;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
font-size: 12px;
&:hover{
background-color: #e5e5e5;
}
&.active{
background-color: #e5e5e5;
}
}
.fontFamily{
width: 103px;
--el-text-color-regular: #000
}
.color{
width: 55px;
height: 25px;
}
.size{
display: flex;
align-items: center;
gap: 16px;
}
.fontStyle{
display: flex;
gap: 16px;
}
}
</style>

View File

@@ -47,7 +47,7 @@ export class NodeManager {
//获取上级节点所生成的最后一个node设置位置为最后一个节点的xy 加上 节点间距
const superiorGenerateNodes = this.stateManager.getSubordNodes(superiorID)
const currentNode = superiorGenerateNodes.find((node) => {
return node.data.createIndexPosition === options?.data?.createIndexPosition
return (node.data.createIndexPosition === options?.data?.createIndexPosition && options?.data?.createIndexPosition)
})
const endGenerateNode = superiorGenerateNodes.reduce((max, current) => {
return current.data.createIndexPosition > max.data.createIndexPosition ? current : max

View File

@@ -127,7 +127,7 @@ export class StateManager {
getNodeById(id: string) { return this.nodes.value.find((node: NodesItem) => node.id === id) }
/** 获取下级节点 */
getSubordNodeById(id: string) { return this.nodes.value.find((node: NodesItem) => node.data.superiorID === id) }
getLastNode() { console.log(this.nodes.value); return this.nodes.value[this.nodes.value.length - 1] }
getLastNode() { return this.nodes.value[this.nodes.value.length - 1] }
/** 获取上级生成节点的图片 */
getSuperiorNodeImage(superiorID: string) {

View File

@@ -36,7 +36,7 @@ export default {
wechatLogin: 'Sign in with Wechat',
indexTip: 'A multi-agent canvas for rapid, trend driven design iteration.',
sendCodeError: 'Send code error',
retrievePassword: 'Retrieve password',
retrievePassword: 'Retrieve password'
},
Nuic: {
hiName: 'Hi, {name}. This is Fiphant.',
@@ -51,7 +51,7 @@ export default {
basedIn: 'Based in',
role: 'Role',
allSet: 'All set!',
loadingTip: 'Were customizing your dashboard.',
loadingTip: 'Were customizing your dashboard.'
},
Home: {
creditsNum: 'Credits: {num}',
@@ -81,9 +81,9 @@ export default {
userAgreement: 'User Agreement',
privacyPolicy: 'Privacy Policy',
view: 'View',
remainingNum: 'Remaining number of times to upload profile picture:',
remainingNum: 'Remaining number of times to upload profile picture:'
},
Country:{
Country: {
unitedStates: 'United States',
singapore: 'Singapore',
australia: 'Australia',
@@ -93,17 +93,18 @@ export default {
france: 'France',
japan: 'Japan',
canada: 'Canada',
germany: 'Germany',
germany: 'Germany'
},
Role: {
designer: 'Designer',
student: 'Student',
teacher: 'Teacher',
parent: 'Parent',
other: 'Other',
other: 'Other'
},
Input: {
placeholder: 'Describe the design you want to create... e.g. Modern wooden chair, Bauhaus style',
placeholder:
'Describe the design you want to create... e.g. Modern wooden chair, Bauhaus style',
selectPlaceholder: 'Please select',
typePlaceholder: 'Type',
areaPlaceholder: 'Region',
@@ -146,11 +147,12 @@ export default {
france: 'France',
japan: 'Japan',
canada: 'Canada',
germany: 'Germany',
germany: 'Germany'
},
agent: {
copySuccess: 'Text copied to clipboard',
copyFaild: 'Copy failed. Your browser may be restricting clipboard access. Please try copying manually.',
copyFaild:
'Copy failed. Your browser may be restricting clipboard access. Please try copying manually.',
Download: 'Download',
deleteSuccess: 'Successfully deleted',
thinking: 'Thinking...',
@@ -158,6 +160,8 @@ export default {
quote: 'Quote',
delete: 'Delete',
edit: 'Edit',
generatingReport:
'We are generating your report. This may take a few minutes, but you can continue with other tasks while its being generated.'
},
// Version Tree
@@ -172,13 +176,13 @@ export default {
restore: 'Restore',
newChat: 'New Chat',
delete: 'Delete',
deleteChat:'Delete chat?',
deleteHint:'Once deleted, you wont be able to view this conversation again.',
restoreChat:'Restore chat?',
restoreHint:'Once deleted, you wont be able to view this conversation again.',
deleteChat: 'Delete chat?',
deleteHint: 'Once deleted, you wont be able to view this conversation again.',
restoreChat: 'Restore chat?',
restoreHint: 'Once deleted, you wont be able to view this conversation again.',
Cancel: 'Cancel',
Confirm: 'Confirm',
export: 'Export',
export: 'Export'
},
flowCanvas: {
deleteCardConfirm: 'Are you sure you want to delete this function card?',
@@ -187,14 +191,14 @@ export default {
confirmLeave: 'Are you sure you want to leave? You may have unsaved changes.',
cannotFindSuperiorImage: 'Cannot find the superior image',
deleteSubordinateCard: 'After deletion, all the function cards will also be deleted.',
initialNodeProhibited: 'Initial node is prohibited from being deleted.',
initialNodeProhibited: 'Initial node is prohibited from being deleted.'
},
assistant: {
inputPlaceholder: 'Ask anything',
inputPlaceholder: 'Ask anything'
},
//3d面板
threeModel: {
loading: 'Loading',
download: 'Download',
download: 'Download'
}
}

View File

@@ -82,7 +82,7 @@ export default {
userAgreement: '用户协议',
privacyPolicy: '隐私政策',
view: '查看',
remainingNum: '剩余上传头像次数:',
remainingNum: '剩余上传头像次数:'
},
Country: {
unitedStates: '美国',
@@ -148,11 +148,12 @@ export default {
'复制失败。您的浏览器可能限制了剪贴板访问,请允许浏览器访问剪贴板或尝试手动复制。',
Download: '下载',
deleteSuccess: '删除成功',
thinking:'已思考',
thinking: '已思考',
thinkComplete: '思考完成。',
quote: '引用',
delete: '删除',
edit: '编辑',
generatingReport:'正在为您生成报告,可能需要几分钟时间,生成期间你可以继续进行其他任务'
},
// Version Tree
@@ -173,7 +174,7 @@ export default {
restoreHint: '恢复后将显示该对话。',
Cancel: '取消',
Confirm: '确认',
export: '导出',
export: '导出'
},
//generateSketch
generateSketch: {
@@ -187,7 +188,7 @@ export default {
cancel: '取消',
confirmLeave: '您可能有未保存的更改,确定要离开吗?',
cannotFindSuperiorImage: '找不到上级图片',
initialNodeProhibited: 'Initial node is prohibited from being deleted.',
initialNodeProhibited: 'Initial node is prohibited from being deleted.'
},
assistant: {
inputPlaceholder: '请输入'

View File

@@ -28,6 +28,9 @@
import type { AgentParamsType } from '@/api/agent'
import { useUserInfoStore, useProjectStore, useAgentStore } from '@/stores'
import MyEvent from '@/utils/myEvent'
import { useI18n } from 'vue-i18n'
const { t } = useI18n()
const userStore = useUserInfoStore()
const agentStore = useAgentStore()
@@ -267,6 +270,7 @@
hasReportEvent = true
// contentBody += `<slot slot-name="card" title="Report" content="Report"></slot>`
hasReportStarted = true
ElMessage.success(t('agent.generatingReport'))
}
if (
@@ -337,6 +341,7 @@
}
if (jsonData.title) {
emits('setTitle', jsonData.title)
MyEvent.emit('newTitle', jsonData.title)
}
if (hasSketch) {
@@ -460,7 +465,13 @@
}
// 处理对话列表,将连续的 assistant 消息合并为一条
const processDialogue = (dialogue, startIndex, existingImgList, sessionId) => {
const processDialogue = (
dialogue,
startIndex,
existingImgList,
sessionId,
firstReportIndex = -1
) => {
if (!dialogue || dialogue.length === 0) return []
const result = []
@@ -495,6 +506,11 @@
j++
}
// 如果 firstReportIndex 在当前合并范围内,则把 slot 追加到末尾
if (firstReportIndex >= i && firstReportIndex < j) {
combinedContent += `<slot slot-name="card" title="Report" content="Report"></slot>`
}
result.push({
...item,
content: combinedContent,
@@ -525,13 +541,12 @@
const processSession = (session, imgList, ancestorsList, idCounterRef) => {
if (!session) return
// 1. 在 dialogue 第一个 report 有值的项的 content 中插入报告卡片
// 1. 找到第一个 report 项的索引,供 processDialogue 使用
let firstReportIndex = -1
if (session.dialogue) {
for (let i = 0; i < session.dialogue.length; i++) {
if (session.dialogue[i].report) {
session.dialogue[i].content =
`<slot slot-name="card" title="123" content="123">123</slot>` +
(session.dialogue[i].content || '')
firstReportIndex = i
break
}
}
@@ -554,10 +569,11 @@
}
// 4. 处理 dialogue
const list = processDialogue(session.dialogue, 0, imgList, session.id)
const list = processDialogue(session.dialogue, 0, imgList, session.id, firstReportIndex)
list.forEach((el) => {
el.id = idCounterRef.value++
})
ancestorsList.push(...list)
}

View File

@@ -5,7 +5,7 @@
:class="{ 'is-user': content.isUser, 'is-loading': content.loading }"
>
<div class="thumb">
<img :src="content.isUser ? userThumb : agentThumb" class="thumb-icon" />
<img :src="content.isUser ? userAvatar : agentThumb" class="thumb-icon" />
</div>
<div class="message-context" v-show="!content.loading">
<div class="img-list flex" v-if="imageList.length > 0">
@@ -120,6 +120,9 @@
import type { CustomAttrs } from '@crazydos/vue-markdown'
import rehypeRaw from 'rehype-raw'
import MyEvent from '@/utils/myEvent'
import { useUserInfoStore } from '@/stores'
const userStore = useUserInfoStore()
const { t } = useI18n()
@@ -128,16 +131,12 @@
isLast: Boolean
}>()
// watch(
// () => props,
// (newVal) => {
// console.log('newVal-----', newVal)
// },
// { immediate: true }
// )
const emit = defineEmits(['regenerate'])
const userAvatar = computed(() => {
return userStore.state.userInfo?.avatar || userThumb
})
const imageList = computed(() => {
const { imageUrls, role } = props.content
const list = []
@@ -340,6 +339,7 @@
.img-list {
column-gap: 1rem;
margin-bottom: 1.4rem;
justify-content: flex-end;
.img-item {
width: 6.8rem;
height: 6.8rem;

View File

@@ -5,6 +5,7 @@ import Tree from './tree/index.vue'
import { findAndAddChild, findAndRemoveChild } from '../../../../../utils/treeDiagram'
import { useProjectStore } from '@/stores'
import { versionTree } from '@/api/versitonTree'
import { downloadImage } from '@/components/Canvas/tools/tools'
const props = defineProps({
versionTreeData: {
@@ -138,7 +139,7 @@ const {} = toRefs(data)
</div>
</div>
<div class="expandBtnBox" v-if="versionsList.length > 0">
<div class="btn" @click="openTree(true)">
<div class="btn" v-if="selectItem.url" @click="downloadImage(selectItem.url,'image.png')">
<div class="versionExport">
<SvgIcon name="versionExport" size="17" color="rgba(0, 0, 0, 0.6)" />
</div>
@@ -211,8 +212,10 @@ const {} = toRefs(data)
margin-left: auto;
margin-top: 2.2rem;
margin-right: 3rem;
height: 3.3rem;
> .btn{
padding: .6rem 1.8rem;
padding: 0 1.8rem;
line-height: 3rem;
cursor: pointer;
display: flex;
align-items: center;

View File

@@ -84,7 +84,7 @@
</template>
<script setup lang="ts">
import { computed, ref, nextTick } from 'vue'
import { computed, ref, nextTick, onMounted, onUnmounted } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { useI18n } from 'vue-i18n'
import { getProjectList, updateProject, deleteProject } from '@/api/agent'
@@ -93,7 +93,8 @@
const { t: $t } = useI18n()
const route = useRoute()
const router = useRouter()
import { useGlobalStore } from '@/stores'
import { useGlobalStore, useProjectStore } from '@/stores'
const projectStore = useProjectStore()
const id = computed(() => route.params.id)
const globalStore = useGlobalStore()
const isCollapse = computed(() => globalStore.state.homeLeftNavCollapse)
@@ -198,8 +199,22 @@
}
MyEvent.add('updateProjectList', GetProjectList)
GetProjectList()
const replaceTitle = (title: string) => {
list.value.forEach((item: any) => {
if (String(item.id) === String(projectStore.state.id)) {
item.name = title
}
})
}
onMounted(() => {
MyEvent.add('newTitle', replaceTitle)
})
onUnmounted(() => {
MyEvent.remove('newTitle', replaceTitle)
})
</script>
<style lang="less" scoped>
.left-nav {
width: var(--left-nav-collapse-width, 30rem);