finish work

This commit is contained in:
锦恢 2025-07-02 04:56:41 +08:00
parent 27c3f24089
commit a735bbf023
13 changed files with 747 additions and 485 deletions

View File

@ -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;

View File

@ -73,6 +73,6 @@ const onRadioGroupChange = () => {
}
.setting-button:active {
transform: scale(1.1);
transform: scale(0.95);
}
</style>

View File

@ -1,39 +1,28 @@
<template>
<div class="main-panel-container">
<div class="tabs-container">
<div class="main-panel-container">
<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>
</div>
<span class="add-button iconfont icon-add" @click="pageAddNewTab">
</span>
</div>
<div class="main-panel">
<router-view />
</div>
</div>
<div class="main-panel">
<router-view />
</div>
</div>
</template>
<script setup lang="ts">
@ -50,41 +39,41 @@ const route = useRoute();
const router = useRouter();
function pageAddNewTab() {
addNewTab();
addNewTab();
// debug debug
if (route.name !== 'debug') {
router.push(baseURL + 'debug');
}
// debug debug
if (route.name !== 'debug') {
router.push(baseURL + 'debug');
}
}
function setActiveTab(index: number) {
if (index >= 0 && index < tabs.content.length) {
tabs.activeIndex = index;
// debug
if (route.name !== 'debug') {
router.push(baseURL + 'debug');
}
}
function setActiveTab(index: number) {
if (index >= 0 && index < tabs.content.length) {
tabs.activeIndex = index;
// debug
if (route.name !== 'debug') {
router.push(baseURL + 'debug');
}
}
}
</script>
<style>
.main-panel-container {
justify-content: center;
flex-direction: column;
width: 100%;
min-width: 800px;
height: 100%;
margin-left: 5px;
justify-content: center;
flex-direction: column;
width: 100%;
min-width: 800px;
height: 100%;
margin-left: 5px;
}
.main-panel {
background-color: var(--sidebar);
border-radius: 1.2em;
width: 100%;
height: calc(100% - 35px);
background-color: var(--sidebar);
border-radius: 1.2em;
width: 100%;
height: calc(100% - 35px);
}
.scroll-tabs-container {
@ -93,13 +82,13 @@ function setActiveTab(index: number) {
}
.tabs-container {
height: 30px;
width: 90%;
background-color: var(--background);
display: flex;
align-items: center;
height: 30px;
width: 90%;
background-color: var(--background);
display: flex;
align-items: center;
user-select: none;
margin-bottom: 5px;
margin-bottom: 5px;
}
.tabs-container .el-scrollbar {
@ -107,47 +96,47 @@ function setActiveTab(index: number) {
}
.tabs-container .tab {
white-space: nowrap;
margin-right: 5px;
white-space: nowrap;
margin-right: 5px;
font-size: 12px;
width: 120px;
border-radius: .5em;
background-color: var(--sidebar);
padding: 3px 10px;
display: flex;
align-items: center;
transition: var(--animation-3s);
border-radius: .5em;
background-color: var(--sidebar);
padding: 3px 10px;
display: flex;
align-items: center;
transition: var(--animation-3s);
justify-content: space-between;
position: relative;
position: relative;
}
.tabs-container .tab:active {
transform: scale(1.05);
transition: var(--animation-3s);
transform: scale(0.95);
transition: var(--animation-3s);
}
.tabs-container .tab > span:first-child {
.tabs-container .tab>span:first-child {
display: flex;
align-items: center;
}
.tabs-container .tab .tab-name {
max-width: 70px;
overflow: hidden;
text-overflow: ellipsis;
max-width: 70px;
overflow: hidden;
text-overflow: ellipsis;
}
.tabs-container .tab:hover {
background-color: var(--input-active-background);
background-color: var(--input-active-background);
}
.tabs-container .tab.active-tab {
background-color: var(--main-color);
color: white;
background-color: var(--main-color);
color: white;
}
.tabs-container .tab .iconfont {
margin-right: 10px;
margin-right: 10px;
}
.tabs-container .icon-close {
@ -165,30 +154,30 @@ function setActiveTab(index: number) {
}
.tabs-container .add-button {
cursor: pointer;
font-size: 15px;
margin-left: 5px;
border-radius: .5em;
display: flex;
align-items: center;
justify-content: center;
transition: var(--animation-3s);
cursor: pointer;
font-size: 15px;
margin-left: 5px;
border-radius: .5em;
display: flex;
align-items: center;
justify-content: center;
transition: var(--animation-3s);
}
.tabs-container .add-button:hover {
color: var(--main-color);
background-color: var(--sidebar);
transition: var(--animation-3s);
color: var(--main-color);
background-color: var(--sidebar);
transition: var(--animation-3s);
}
.close-icon {
margin-left: 8px;
font-size: 14px;
padding: 2px;
border-radius: 50%;
margin-left: 8px;
font-size: 14px;
padding: 2px;
border-radius: 50%;
}
.close-icon:hover {
background-color: rgba(255, 255, 255, 0.2);
background-color: rgba(255, 255, 255, 0.2);
}
</style>

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -4,14 +4,18 @@
<div style="display: flex; align-items: center;">
<span>Tool Diagram</span>
&ensp;
<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>

View File

@ -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,27 +220,60 @@ function renderSvg() {
.on('mouseup', function (event, d) {
event.stopPropagation();
if (state.selectedNodeId && state.selectedNodeId !== d.id) {
state.edges.push({
id: `e${state.selectedNodeId}_${d.id}_${Date.now()}`,
sources: [state.selectedNodeId],
targets: [d.id]
});
state.selectedNodeId = null;
recomputeLayout().then(renderSvg);
// 线
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],
targets: [d.id]
});
state.selectedNodeId = null;
recomputeLayout().then(renderSvg);
} else {
//
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 }));
@ -284,7 +354,7 @@ function renderSvg() {
function resetConnections() {
if (!state.nodes.length) return;
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 next = state.nodes[i + 1];
edges.push({
@ -297,6 +367,9 @@ function resetConnections() {
recomputeLayout().then(renderSvg);
}
const context = inject('context') as any;
context.reset = resetConnections;
onMounted(() => {
nextTick(drawDiagram);
});

View File

@ -296,7 +296,7 @@ watch(() => tabStorage.currentToolName, () => {
}
.el-button:active {
transform: scale(1.05);
transform: scale(0.95);
transition: transform 0.08s;
}
</style>

View File

@ -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);

View File

@ -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 {

View File

@ -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 = [

878
yarn.lock

File diff suppressed because it is too large Load Diff