finish work
This commit is contained in:
parent
27c3f24089
commit
a735bbf023
@ -3,6 +3,15 @@
|
||||
--main-color: #CB81DA;
|
||||
--main-dark-color: #2D323B;
|
||||
--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;
|
||||
--right-nav-width: 50px;
|
||||
--time-scale-height: 30px;
|
||||
|
@ -73,6 +73,6 @@ const onRadioGroupChange = () => {
|
||||
}
|
||||
|
||||
.setting-button:active {
|
||||
transform: scale(1.1);
|
||||
transform: scale(0.95);
|
||||
}
|
||||
</style>
|
@ -3,29 +3,18 @@
|
||||
<div class="tabs-container">
|
||||
<el-scrollbar>
|
||||
<div class="scroll-tabs-container">
|
||||
<span
|
||||
class="tab"
|
||||
v-for="(tab, index) of tabs.content"
|
||||
:key="tab.id"
|
||||
:class="{ 'active-tab': tabs.activeIndex === index }"
|
||||
@click="setActiveTab(index)"
|
||||
>
|
||||
<span class="tab" v-for="(tab, index) of tabs.content" :key="tab.id"
|
||||
:class="{ 'active-tab': tabs.activeIndex === index }" @click="setActiveTab(index)">
|
||||
<span>
|
||||
<span :class="`iconfont ${tab.icon}`"></span>
|
||||
<span class="tab-name">{{ tab.name }}</span>
|
||||
</span>
|
||||
<span
|
||||
class="iconfont icon-close"
|
||||
@click.stop="closeTab(index)"
|
||||
></span>
|
||||
<span class="iconfont icon-close" @click.stop="closeTab(index)"></span>
|
||||
</span>
|
||||
</div>
|
||||
</el-scrollbar>
|
||||
|
||||
<span
|
||||
class="add-button iconfont icon-add"
|
||||
@click="pageAddNewTab"
|
||||
>
|
||||
<span class="add-button iconfont icon-add" @click="pageAddNewTab">
|
||||
</span>
|
||||
</div>
|
||||
|
||||
@ -122,7 +111,7 @@ function setActiveTab(index: number) {
|
||||
}
|
||||
|
||||
.tabs-container .tab:active {
|
||||
transform: scale(1.05);
|
||||
transform: scale(0.95);
|
||||
transition: var(--animation-3s);
|
||||
}
|
||||
|
||||
|
@ -140,6 +140,11 @@ onMounted(async () => {
|
||||
transition: var(--animation-3s);
|
||||
}
|
||||
|
||||
.prompt-template-container>.item:active {
|
||||
transform: scale(0.95);
|
||||
transition: var(--animation-3s);
|
||||
}
|
||||
|
||||
.prompt-template-container>.item.active {
|
||||
background-color: var(--main-light-color);
|
||||
transition: var(--animation-3s);
|
||||
|
@ -157,6 +157,11 @@ h3.resource-template .iconfont.icon-restart:hover {
|
||||
transition: var(--animation-3s);
|
||||
}
|
||||
|
||||
.resource-template-container > .item:active {
|
||||
transform: scale(0.95);
|
||||
transition: var(--animation-3s);
|
||||
}
|
||||
|
||||
.resource-template-container > .item.active {
|
||||
background-color: var(--main-light-color);
|
||||
transition: var(--animation-3s);
|
||||
|
@ -167,6 +167,11 @@ h3.resource-template .iconfont.icon-restart:hover {
|
||||
transition: var(--animation-3s);
|
||||
}
|
||||
|
||||
.resource-template-container > .item:active {
|
||||
transform: scale(0.95);
|
||||
transition: var(--animation-3s);
|
||||
}
|
||||
|
||||
.resource-title {
|
||||
font-weight: bold;
|
||||
max-width: 250px;
|
||||
|
@ -4,14 +4,18 @@
|
||||
<div style="display: flex; align-items: center;">
|
||||
<span>Tool Diagram</span>
|
||||
 
|
||||
<el-button size="small" type="primary" @click="() => {}">重置</el-button>
|
||||
<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="() => startTest()">开启自检程序</el-button>
|
||||
</div>
|
||||
</template>
|
||||
<el-scrollbar height="80vh">
|
||||
<!-- <Diagram /> -->
|
||||
<SwimPool />
|
||||
<Diagram />
|
||||
</el-scrollbar>
|
||||
<transition name="main-fade" mode="out-in">
|
||||
<div class="caption" v-show="context.caption.value">
|
||||
{{ context.caption }}
|
||||
</div>
|
||||
</transition>
|
||||
</el-dialog>
|
||||
<!-- <el-button @click="showDiagram = true" type="primary" style="margin-bottom: 16px;">
|
||||
Show Tool Diagram
|
||||
@ -19,11 +23,21 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
import { provide, ref } from 'vue';
|
||||
import Diagram from './diagram.vue';
|
||||
import SwimPool from './swim-pool.vue';
|
||||
const showDiagram = ref(true);
|
||||
|
||||
const context = {
|
||||
reset: () => {},
|
||||
caption: ref('')
|
||||
};
|
||||
|
||||
provide('context', context);
|
||||
|
||||
function startTest() {
|
||||
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style>
|
||||
@ -31,4 +45,23 @@ const showDiagram = ref(true);
|
||||
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>
|
@ -5,7 +5,7 @@
|
||||
</template>
|
||||
|
||||
<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 ELK, { type ElkNode } from 'elkjs/lib/elk.bundled.js';
|
||||
import { mcpClientAdapter } from '@/views/connect/core';
|
||||
@ -195,7 +195,7 @@ function renderSvg() {
|
||||
.attr('y1', d => d.section.startPoint.y + 30)
|
||||
.attr('x2', d => d.section.endPoint.x + 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')
|
||||
@ -220,6 +220,15 @@ function renderSvg() {
|
||||
.on('mouseup', function (event, d) {
|
||||
event.stopPropagation();
|
||||
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({
|
||||
id: `e${state.selectedNodeId}_${d.id}_${Date.now()}`,
|
||||
sources: [state.selectedNodeId],
|
||||
@ -228,19 +237,43 @@ function renderSvg() {
|
||||
state.selectedNodeId = null;
|
||||
recomputeLayout().then(renderSvg);
|
||||
} else {
|
||||
state.selectedNodeId = d.id;
|
||||
// 已存在则只取消选中
|
||||
state.selectedNodeId = null;
|
||||
renderSvg();
|
||||
}
|
||||
context.caption.value = '';
|
||||
|
||||
} else {
|
||||
state.selectedNodeId = d.id;
|
||||
renderSvg();
|
||||
context.caption.value = '选择另一个节点以构建顺序';
|
||||
}
|
||||
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')
|
||||
.attr('width', d => d.width)
|
||||
.attr('height', d => d.height)
|
||||
.attr('rx', 16)
|
||||
.attr('fill', 'var(--main-color)')
|
||||
.attr('opacity', d => state.selectedNodeId === d.id ? 0.25 : 0.12)
|
||||
.attr('stroke', 'var(--main-color)')
|
||||
.attr('fill', 'var(--main-light-color-20)')
|
||||
.attr('stroke', d => state.selectedNodeId === d.id ? 'var(--main-color)' : 'var(--main-light-color-10)')
|
||||
.attr('stroke-width', 2);
|
||||
|
||||
nodeGroupEnter.append('text')
|
||||
@ -270,10 +303,47 @@ function renderSvg() {
|
||||
nodeGroup.select('rect')
|
||||
.transition()
|
||||
.duration(400)
|
||||
.attr('opacity', d => state.selectedNodeId === d.id ? 0.55 : 0.12)
|
||||
.attr('stroke-width', d => state.selectedNodeId === d.id ? 4 : 2)
|
||||
.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)');
|
||||
.attr('stroke-width', d => state.selectedNodeId === d.id ? 2 : 1)
|
||||
.attr('stroke', d => state.selectedNodeId === d.id ? 'var(--main-color)' : 'var(--main-light-color-10)');
|
||||
|
||||
// 边高亮
|
||||
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 }));
|
||||
@ -297,6 +367,9 @@ function resetConnections() {
|
||||
recomputeLayout().then(renderSvg);
|
||||
}
|
||||
|
||||
const context = inject('context') as any;
|
||||
context.reset = resetConnections;
|
||||
|
||||
onMounted(() => {
|
||||
nextTick(drawDiagram);
|
||||
});
|
||||
|
@ -296,7 +296,7 @@ watch(() => tabStorage.currentToolName, () => {
|
||||
}
|
||||
|
||||
.el-button:active {
|
||||
transform: scale(1.05);
|
||||
transform: scale(0.95);
|
||||
transition: transform 0.08s;
|
||||
}
|
||||
</style>
|
@ -128,6 +128,11 @@ onMounted(async () => {
|
||||
transition: var(--animation-3s);
|
||||
}
|
||||
|
||||
.tool-list-container>.item:active {
|
||||
transform: scale(0.95);
|
||||
transition: var(--animation-3s);
|
||||
}
|
||||
|
||||
.tool-list-container>.item:hover {
|
||||
background-color: var(--main-light-color);
|
||||
transition: var(--animation-3s);
|
||||
|
@ -108,6 +108,7 @@ function chooseDebugMode(index: number) {
|
||||
.welcome-container > span {
|
||||
flex: 1 1 calc(50% - 100px);
|
||||
box-sizing: border-box;
|
||||
transition: .3s transform ease-in-out;
|
||||
}
|
||||
|
||||
.debug-option {
|
||||
|
@ -32,6 +32,11 @@ export function onGeneralColorChange(colorString: string) {
|
||||
|
||||
document?.documentElement.style.setProperty(
|
||||
'--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 = [
|
||||
|
Loading…
x
Reference in New Issue
Block a user