finish work
This commit is contained in:
parent
27c3f24089
commit
a735bbf023
@ -3,6 +3,15 @@
|
|||||||
--main-color: #CB81DA;
|
--main-color: #CB81DA;
|
||||||
--main-dark-color: #2D323B;
|
--main-dark-color: #2D323B;
|
||||||
--main-light-color: rgba(203, 129, 218, 0.7);
|
--main-light-color: rgba(203, 129, 218, 0.7);
|
||||||
|
--main-light-color-90: rgba(203, 129, 218, 0.9);
|
||||||
|
--main-light-color-80: rgba(203, 129, 218, 0.8);
|
||||||
|
--main-light-color-70: rgba(203, 129, 218, 0.7);
|
||||||
|
--main-light-color-60: rgba(203, 129, 218, 0.6);
|
||||||
|
--main-light-color-50: rgba(203, 129, 218, 0.5);
|
||||||
|
--main-light-color-40: rgba(203, 129, 218, 0.4);
|
||||||
|
--main-light-color-30: rgba(203, 129, 218, 0.3);
|
||||||
|
--main-light-color-20: rgba(203, 129, 218, 0.2);
|
||||||
|
--main-light-color-10: rgba(203, 129, 218, 0.1);
|
||||||
--sidebar-width: 330px;
|
--sidebar-width: 330px;
|
||||||
--right-nav-width: 50px;
|
--right-nav-width: 50px;
|
||||||
--time-scale-height: 30px;
|
--time-scale-height: 30px;
|
||||||
|
@ -73,6 +73,6 @@ const onRadioGroupChange = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.setting-button:active {
|
.setting-button:active {
|
||||||
transform: scale(1.1);
|
transform: scale(0.95);
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
@ -3,29 +3,18 @@
|
|||||||
<div class="tabs-container">
|
<div class="tabs-container">
|
||||||
<el-scrollbar>
|
<el-scrollbar>
|
||||||
<div class="scroll-tabs-container">
|
<div class="scroll-tabs-container">
|
||||||
<span
|
<span class="tab" v-for="(tab, index) of tabs.content" :key="tab.id"
|
||||||
class="tab"
|
:class="{ 'active-tab': tabs.activeIndex === index }" @click="setActiveTab(index)">
|
||||||
v-for="(tab, index) of tabs.content"
|
|
||||||
:key="tab.id"
|
|
||||||
:class="{ 'active-tab': tabs.activeIndex === index }"
|
|
||||||
@click="setActiveTab(index)"
|
|
||||||
>
|
|
||||||
<span>
|
<span>
|
||||||
<span :class="`iconfont ${tab.icon}`"></span>
|
<span :class="`iconfont ${tab.icon}`"></span>
|
||||||
<span class="tab-name">{{ tab.name }}</span>
|
<span class="tab-name">{{ tab.name }}</span>
|
||||||
</span>
|
</span>
|
||||||
<span
|
<span class="iconfont icon-close" @click.stop="closeTab(index)"></span>
|
||||||
class="iconfont icon-close"
|
|
||||||
@click.stop="closeTab(index)"
|
|
||||||
></span>
|
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</el-scrollbar>
|
</el-scrollbar>
|
||||||
|
|
||||||
<span
|
<span class="add-button iconfont icon-add" @click="pageAddNewTab">
|
||||||
class="add-button iconfont icon-add"
|
|
||||||
@click="pageAddNewTab"
|
|
||||||
>
|
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -122,11 +111,11 @@ function setActiveTab(index: number) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.tabs-container .tab:active {
|
.tabs-container .tab:active {
|
||||||
transform: scale(1.05);
|
transform: scale(0.95);
|
||||||
transition: var(--animation-3s);
|
transition: var(--animation-3s);
|
||||||
}
|
}
|
||||||
|
|
||||||
.tabs-container .tab > span:first-child {
|
.tabs-container .tab>span:first-child {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
@ -140,6 +140,11 @@ onMounted(async () => {
|
|||||||
transition: var(--animation-3s);
|
transition: var(--animation-3s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.prompt-template-container>.item:active {
|
||||||
|
transform: scale(0.95);
|
||||||
|
transition: var(--animation-3s);
|
||||||
|
}
|
||||||
|
|
||||||
.prompt-template-container>.item.active {
|
.prompt-template-container>.item.active {
|
||||||
background-color: var(--main-light-color);
|
background-color: var(--main-light-color);
|
||||||
transition: var(--animation-3s);
|
transition: var(--animation-3s);
|
||||||
|
@ -157,6 +157,11 @@ h3.resource-template .iconfont.icon-restart:hover {
|
|||||||
transition: var(--animation-3s);
|
transition: var(--animation-3s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.resource-template-container > .item:active {
|
||||||
|
transform: scale(0.95);
|
||||||
|
transition: var(--animation-3s);
|
||||||
|
}
|
||||||
|
|
||||||
.resource-template-container > .item.active {
|
.resource-template-container > .item.active {
|
||||||
background-color: var(--main-light-color);
|
background-color: var(--main-light-color);
|
||||||
transition: var(--animation-3s);
|
transition: var(--animation-3s);
|
||||||
|
@ -167,6 +167,11 @@ h3.resource-template .iconfont.icon-restart:hover {
|
|||||||
transition: var(--animation-3s);
|
transition: var(--animation-3s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.resource-template-container > .item:active {
|
||||||
|
transform: scale(0.95);
|
||||||
|
transition: var(--animation-3s);
|
||||||
|
}
|
||||||
|
|
||||||
.resource-title {
|
.resource-title {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
max-width: 250px;
|
max-width: 250px;
|
||||||
|
@ -4,14 +4,18 @@
|
|||||||
<div style="display: flex; align-items: center;">
|
<div style="display: flex; align-items: center;">
|
||||||
<span>Tool Diagram</span>
|
<span>Tool Diagram</span>
|
||||||
 
|
 
|
||||||
<el-button size="small" type="primary" @click="() => {}">重置</el-button>
|
<el-button size="small" type="primary" @click="() => context.reset()">重置</el-button>
|
||||||
<el-button size="small" type="primary" @click="() => {}">开启自检程序</el-button>
|
<el-button size="small" type="primary" @click="() => startTest()">开启自检程序</el-button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<el-scrollbar height="80vh">
|
<el-scrollbar height="80vh">
|
||||||
<!-- <Diagram /> -->
|
<Diagram />
|
||||||
<SwimPool />
|
|
||||||
</el-scrollbar>
|
</el-scrollbar>
|
||||||
|
<transition name="main-fade" mode="out-in">
|
||||||
|
<div class="caption" v-show="context.caption.value">
|
||||||
|
{{ context.caption }}
|
||||||
|
</div>
|
||||||
|
</transition>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
<!-- <el-button @click="showDiagram = true" type="primary" style="margin-bottom: 16px;">
|
<!-- <el-button @click="showDiagram = true" type="primary" style="margin-bottom: 16px;">
|
||||||
Show Tool Diagram
|
Show Tool Diagram
|
||||||
@ -19,11 +23,21 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref } from 'vue';
|
import { provide, ref } from 'vue';
|
||||||
import Diagram from './diagram.vue';
|
import Diagram from './diagram.vue';
|
||||||
import SwimPool from './swim-pool.vue';
|
|
||||||
const showDiagram = ref(true);
|
const showDiagram = ref(true);
|
||||||
|
|
||||||
|
const context = {
|
||||||
|
reset: () => {},
|
||||||
|
caption: ref('')
|
||||||
|
};
|
||||||
|
|
||||||
|
provide('context', context);
|
||||||
|
|
||||||
|
function startTest() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
@ -31,4 +45,23 @@ const showDiagram = ref(true);
|
|||||||
margin-top: 30px !important;
|
margin-top: 30px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.no-padding-dialog .caption {
|
||||||
|
position: absolute;
|
||||||
|
left: 20px;
|
||||||
|
bottom: 10px;
|
||||||
|
margin: 0 auto;
|
||||||
|
width: fit-content;
|
||||||
|
min-height: 32px;
|
||||||
|
background: rgba(245, 247, 250, 0.05);
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 2px 8px 0 rgba(0,0,0,0.06);
|
||||||
|
color: var(--main-color);
|
||||||
|
font-size: 15px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 6px 16px;
|
||||||
|
z-index: 10;
|
||||||
|
transition: background 0.2s;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
@ -5,7 +5,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, onMounted, nextTick, reactive } from 'vue';
|
import { ref, onMounted, nextTick, reactive, inject } from 'vue';
|
||||||
import * as d3 from 'd3';
|
import * as d3 from 'd3';
|
||||||
import ELK, { type ElkNode } from 'elkjs/lib/elk.bundled.js';
|
import ELK, { type ElkNode } from 'elkjs/lib/elk.bundled.js';
|
||||||
import { mcpClientAdapter } from '@/views/connect/core';
|
import { mcpClientAdapter } from '@/views/connect/core';
|
||||||
@ -195,7 +195,7 @@ function renderSvg() {
|
|||||||
.attr('y1', d => d.section.startPoint.y + 30)
|
.attr('y1', d => d.section.startPoint.y + 30)
|
||||||
.attr('x2', d => d.section.endPoint.x + 30)
|
.attr('x2', d => d.section.endPoint.x + 30)
|
||||||
.attr('y2', d => d.section.endPoint.y + 30)
|
.attr('y2', d => d.section.endPoint.y + 30)
|
||||||
.attr('opacity', 1); // 保证 update 阶段 opacity 始终为 1
|
.attr('opacity', 1);
|
||||||
|
|
||||||
// --- 节点动画部分 ---
|
// --- 节点动画部分 ---
|
||||||
const nodeGroup = svg.selectAll<SVGGElement, any>('.node')
|
const nodeGroup = svg.selectAll<SVGGElement, any>('.node')
|
||||||
@ -220,6 +220,15 @@ function renderSvg() {
|
|||||||
.on('mouseup', function (event, d) {
|
.on('mouseup', function (event, d) {
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
if (state.selectedNodeId && state.selectedNodeId !== d.id) {
|
if (state.selectedNodeId && state.selectedNodeId !== d.id) {
|
||||||
|
// 检查是否已存在这条连线
|
||||||
|
const exists = state.edges.some(
|
||||||
|
e =>
|
||||||
|
Array.isArray(e.sources) &&
|
||||||
|
Array.isArray(e.targets) &&
|
||||||
|
e.sources[0] === state.selectedNodeId &&
|
||||||
|
e.targets[0] === d.id
|
||||||
|
);
|
||||||
|
if (!exists) {
|
||||||
state.edges.push({
|
state.edges.push({
|
||||||
id: `e${state.selectedNodeId}_${d.id}_${Date.now()}`,
|
id: `e${state.selectedNodeId}_${d.id}_${Date.now()}`,
|
||||||
sources: [state.selectedNodeId],
|
sources: [state.selectedNodeId],
|
||||||
@ -228,19 +237,43 @@ function renderSvg() {
|
|||||||
state.selectedNodeId = null;
|
state.selectedNodeId = null;
|
||||||
recomputeLayout().then(renderSvg);
|
recomputeLayout().then(renderSvg);
|
||||||
} else {
|
} else {
|
||||||
state.selectedNodeId = d.id;
|
// 已存在则只取消选中
|
||||||
|
state.selectedNodeId = null;
|
||||||
renderSvg();
|
renderSvg();
|
||||||
}
|
}
|
||||||
|
context.caption.value = '';
|
||||||
|
|
||||||
|
} else {
|
||||||
|
state.selectedNodeId = d.id;
|
||||||
|
renderSvg();
|
||||||
|
context.caption.value = '选择另一个节点以构建顺序';
|
||||||
|
}
|
||||||
state.draggingNodeId = null;
|
state.draggingNodeId = null;
|
||||||
|
})
|
||||||
|
.on('mouseover', function (event, d) {
|
||||||
|
d3.select(this).select('rect')
|
||||||
|
.transition()
|
||||||
|
.duration(200)
|
||||||
|
.attr('stroke', 'var(--main-color)')
|
||||||
|
.attr('stroke-width', 2);
|
||||||
|
})
|
||||||
|
.on('mouseout', function (event, d) {
|
||||||
|
if (state.selectedNodeId === d.id) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
d3.select(this).select('rect')
|
||||||
|
.transition()
|
||||||
|
.duration(200)
|
||||||
|
.attr('stroke', 'var(--main-light-color-10)')
|
||||||
|
.attr('stroke-width', 1);
|
||||||
});
|
});
|
||||||
|
|
||||||
nodeGroupEnter.append('rect')
|
nodeGroupEnter.append('rect')
|
||||||
.attr('width', d => d.width)
|
.attr('width', d => d.width)
|
||||||
.attr('height', d => d.height)
|
.attr('height', d => d.height)
|
||||||
.attr('rx', 16)
|
.attr('rx', 16)
|
||||||
.attr('fill', 'var(--main-color)')
|
.attr('fill', 'var(--main-light-color-20)')
|
||||||
.attr('opacity', d => state.selectedNodeId === d.id ? 0.25 : 0.12)
|
.attr('stroke', d => state.selectedNodeId === d.id ? 'var(--main-color)' : 'var(--main-light-color-10)')
|
||||||
.attr('stroke', 'var(--main-color)')
|
|
||||||
.attr('stroke-width', 2);
|
.attr('stroke-width', 2);
|
||||||
|
|
||||||
nodeGroupEnter.append('text')
|
nodeGroupEnter.append('text')
|
||||||
@ -270,10 +303,47 @@ function renderSvg() {
|
|||||||
nodeGroup.select('rect')
|
nodeGroup.select('rect')
|
||||||
.transition()
|
.transition()
|
||||||
.duration(400)
|
.duration(400)
|
||||||
.attr('opacity', d => state.selectedNodeId === d.id ? 0.55 : 0.12)
|
.attr('stroke-width', d => state.selectedNodeId === d.id ? 2 : 1)
|
||||||
.attr('stroke-width', d => state.selectedNodeId === d.id ? 4 : 2)
|
.attr('stroke', d => state.selectedNodeId === d.id ? 'var(--main-color)' : 'var(--main-light-color-10)');
|
||||||
.attr('stroke', d => state.selectedNodeId === d.id ? 'var(--main-color)' : 'var(--main-color)')
|
|
||||||
.attr('fill', d => state.selectedNodeId === d.id ? 'var(--main-color)' : 'var(--main-color)');
|
// 边高亮
|
||||||
|
svg.selectAll<SVGLineElement, any>('.edge')
|
||||||
|
.on('mouseover', function () {
|
||||||
|
d3.select(this)
|
||||||
|
.transition()
|
||||||
|
.duration(200)
|
||||||
|
.attr('stroke', 'var(--main-color)')
|
||||||
|
.attr('stroke-width', 4.5);
|
||||||
|
|
||||||
|
context.caption.value = '点击边以删除';
|
||||||
|
|
||||||
|
})
|
||||||
|
.on('mouseout', function () {
|
||||||
|
d3.select(this)
|
||||||
|
.transition()
|
||||||
|
.duration(200)
|
||||||
|
.attr('stroke', 'var(--main-color)')
|
||||||
|
.attr('stroke-width', 2.5);
|
||||||
|
|
||||||
|
context.caption.value = '';
|
||||||
|
|
||||||
|
})
|
||||||
|
.on('click', function (event, d) {
|
||||||
|
// 只删除当前 edge
|
||||||
|
state.edges = state.edges.filter(e => {
|
||||||
|
// 多段 edge 情况
|
||||||
|
if (e.sections) {
|
||||||
|
// 只保留不是当前 section 的
|
||||||
|
return !e.sections.some((section: any, idx: number) =>
|
||||||
|
((e.id || '') + '-' + (section.id || idx)) === d.id
|
||||||
|
);
|
||||||
|
}
|
||||||
|
// 单段 edge 情况
|
||||||
|
return e.id !== d.id && e.id !== d.section?.id;
|
||||||
|
});
|
||||||
|
recomputeLayout().then(renderSvg);
|
||||||
|
event.stopPropagation();
|
||||||
|
});
|
||||||
|
|
||||||
// 渲染结束后保存当前快照
|
// 渲染结束后保存当前快照
|
||||||
prevNodes = state.nodes.map(n => ({ ...n }));
|
prevNodes = state.nodes.map(n => ({ ...n }));
|
||||||
@ -284,7 +354,7 @@ function renderSvg() {
|
|||||||
function resetConnections() {
|
function resetConnections() {
|
||||||
if (!state.nodes.length) return;
|
if (!state.nodes.length) return;
|
||||||
const edges = [];
|
const edges = [];
|
||||||
for (let i = 0; i < state.nodes.length - 1; ++i) {
|
for (let i = 0; i < state.nodes.length - 1; ++ i) {
|
||||||
const prev = state.nodes[i];
|
const prev = state.nodes[i];
|
||||||
const next = state.nodes[i + 1];
|
const next = state.nodes[i + 1];
|
||||||
edges.push({
|
edges.push({
|
||||||
@ -297,6 +367,9 @@ function resetConnections() {
|
|||||||
recomputeLayout().then(renderSvg);
|
recomputeLayout().then(renderSvg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const context = inject('context') as any;
|
||||||
|
context.reset = resetConnections;
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
nextTick(drawDiagram);
|
nextTick(drawDiagram);
|
||||||
});
|
});
|
||||||
|
@ -296,7 +296,7 @@ watch(() => tabStorage.currentToolName, () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.el-button:active {
|
.el-button:active {
|
||||||
transform: scale(1.05);
|
transform: scale(0.95);
|
||||||
transition: transform 0.08s;
|
transition: transform 0.08s;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
@ -128,6 +128,11 @@ onMounted(async () => {
|
|||||||
transition: var(--animation-3s);
|
transition: var(--animation-3s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.tool-list-container>.item:active {
|
||||||
|
transform: scale(0.95);
|
||||||
|
transition: var(--animation-3s);
|
||||||
|
}
|
||||||
|
|
||||||
.tool-list-container>.item:hover {
|
.tool-list-container>.item:hover {
|
||||||
background-color: var(--main-light-color);
|
background-color: var(--main-light-color);
|
||||||
transition: var(--animation-3s);
|
transition: var(--animation-3s);
|
||||||
|
@ -108,6 +108,7 @@ function chooseDebugMode(index: number) {
|
|||||||
.welcome-container > span {
|
.welcome-container > span {
|
||||||
flex: 1 1 calc(50% - 100px);
|
flex: 1 1 calc(50% - 100px);
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
|
transition: .3s transform ease-in-out;
|
||||||
}
|
}
|
||||||
|
|
||||||
.debug-option {
|
.debug-option {
|
||||||
|
@ -32,6 +32,11 @@ export function onGeneralColorChange(colorString: string) {
|
|||||||
|
|
||||||
document?.documentElement.style.setProperty(
|
document?.documentElement.style.setProperty(
|
||||||
'--main-light-color', `rgba(${r}, ${g}, ${b}, 0.7)`);
|
'--main-light-color', `rgba(${r}, ${g}, ${b}, 0.7)`);
|
||||||
|
|
||||||
|
for (let i = 1; i <= 9; ++ i) {
|
||||||
|
document?.documentElement.style.setProperty(
|
||||||
|
`--main-light-color-${i}0`, `rgba(${r}, ${g}, ${b}, 0.${i})`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const predefinedColors = [
|
export const predefinedColors = [
|
||||||
|
Loading…
x
Reference in New Issue
Block a user