实现保存另存为
This commit is contained in:
parent
67b008fa31
commit
f9a62bfe09
@ -18,7 +18,7 @@
|
|||||||
<script>
|
<script>
|
||||||
window.readVcdFile = async () => {
|
window.readVcdFile = async () => {
|
||||||
let inputVcdFile = 'test.vcd';
|
let inputVcdFile = 'test.vcd';
|
||||||
let inputViewFile = 'test.vcd.view';
|
let inputViewFile = 'test.view';
|
||||||
|
|
||||||
const response = await fetch(inputVcdFile);
|
const response = await fetch(inputVcdFile);
|
||||||
const blob = await response.blob();
|
const blob = await response.blob();
|
||||||
|
Binary file not shown.
BIN
public/test.view
Normal file
BIN
public/test.view
Normal file
Binary file not shown.
@ -8,7 +8,7 @@ for file in os.listdir('dist'):
|
|||||||
with open('./dist/index.html', 'r', encoding='utf-8') as fp:
|
with open('./dist/index.html', 'r', encoding='utf-8') as fp:
|
||||||
html = fp.read()
|
html = fp.read()
|
||||||
|
|
||||||
html = html.replace("''", "'<workerRoot>'")
|
html = html.replace("''", "'<root>'")
|
||||||
|
|
||||||
with open('./dist/index.html', 'w', encoding='utf-8') as fp:
|
with open('./dist/index.html', 'w', encoding='utf-8') as fp:
|
||||||
fp.write(html)
|
fp.write(html)
|
@ -30,6 +30,7 @@ import RightNav from '@/components/right-nav.vue';
|
|||||||
import Pivot from '@/components/pivot';
|
import Pivot from '@/components/pivot';
|
||||||
import { recoverFromInputFile, recoverSession } from './hook/recover';
|
import { recoverFromInputFile, recoverSession } from './hook/recover';
|
||||||
import { setDefaultCss } from './hook/css';
|
import { setDefaultCss } from './hook/css';
|
||||||
|
import { handleVscodeMessage } from './api/message';
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
@ -114,14 +115,19 @@ onMounted(async () => {
|
|||||||
globalLookup.topModules.push(mod);
|
globalLookup.topModules.push(mod);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
loading.close();
|
|
||||||
worker.terminate();
|
worker.terminate();
|
||||||
|
|
||||||
// 根据 recoverConfig 完成现场回复
|
// 根据 recoverConfig 完成现场回复
|
||||||
recoverSession(VcdInfo.topModules);
|
recoverSession(VcdInfo.topModules);
|
||||||
|
loading.close();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// vscode 传递事件
|
||||||
|
window.addEventListener('message', event => {
|
||||||
|
handleVscodeMessage(event);
|
||||||
|
});
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
@ -26,7 +26,7 @@ export async function saveView(originVcdFile, originVcdViewFile, payload) {
|
|||||||
} else {
|
} else {
|
||||||
vscode.postMessage({
|
vscode.postMessage({
|
||||||
command: 'save-view',
|
command: 'save-view',
|
||||||
data: { originVcdFile, originVcdViewFile, payload }
|
data: { originVcdFile, originVcdViewFile, payload: structuredClone(payload) }
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -47,11 +47,28 @@ export async function saveViewAs(originVcdFile, originVcdViewFile, payload) {
|
|||||||
} else {
|
} else {
|
||||||
vscode.postMessage({
|
vscode.postMessage({
|
||||||
command: 'save-view-as',
|
command: 'save-view-as',
|
||||||
data: { originVcdFile, originVcdViewFile, payload }
|
data: { originVcdFile, originVcdViewFile, payload: structuredClone(payload) }
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function loadView(originVcdFile) {
|
||||||
|
if (mode === 'debug') {
|
||||||
|
const res = await axios.post('http://localhost:3000/load-view', { originVcdFile });
|
||||||
|
if (res.data && res.data.recoverJson && res.data.viewPath) {
|
||||||
|
globalLookup.originVcdViewFile = res.data.viewPath;
|
||||||
|
return res.data.recoverJson;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
vscode.postMessage({
|
||||||
|
command: 'load-view',
|
||||||
|
data: { originVcdFile }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param {number} delay
|
* @param {number} delay
|
||||||
|
48
src/api/message.js
Normal file
48
src/api/message.js
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
import { globalLookup } from "@/hook/global";
|
||||||
|
import { recoverFromJson, recoverSession } from "@/hook/recover";
|
||||||
|
import { ElLoading } from "element-plus";
|
||||||
|
import i18n from "@/i18n/index";
|
||||||
|
|
||||||
|
const { t } = i18n.global;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {MessageEvent} event
|
||||||
|
*/
|
||||||
|
export function handleVscodeMessage(event) {
|
||||||
|
const command = event.data.command;
|
||||||
|
switch (command) {
|
||||||
|
case 'save-view-as':
|
||||||
|
saveViewAs(event.data);
|
||||||
|
break;
|
||||||
|
case 'load-view':
|
||||||
|
loadView(event.data);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function loadView(data) {
|
||||||
|
const { recoverJson, viewPath } = data;
|
||||||
|
if (recoverJson === undefined || viewPath === undefined) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const loading = new ElLoading.service({
|
||||||
|
lock: true,
|
||||||
|
text: t('loading'),
|
||||||
|
background: 'rgba(0, 0, 0, 0.7)'
|
||||||
|
});
|
||||||
|
globalLookup.originVcdViewFile = viewPath;
|
||||||
|
recoverFromJson(recoverJson);
|
||||||
|
recoverSession(globalLookup.topModules);
|
||||||
|
loading.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
function saveViewAs(data) {
|
||||||
|
const { viewPath } = data;
|
||||||
|
if (viewPath === undefined) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
globalLookup.originVcdViewFile = viewPath;
|
||||||
|
}
|
@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<div class="status"></div>
|
<div class="status"></div>
|
||||||
<div class="item">
|
<div class="item" @click="manualLoadView()">
|
||||||
<span>{{ t('filemenu.load-view') }}</span>
|
<span>{{ t('filemenu.load-view') }}</span>
|
||||||
<span><code>Ctrl K</code></span>
|
<span><code>Ctrl K</code></span>
|
||||||
</div>
|
</div>
|
||||||
@ -9,6 +9,10 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
|
import { loadView } from '@/api';
|
||||||
|
import { globalLookup } from '@/hook/global';
|
||||||
|
import { recoverFromJson, recoverSession } from '@/hook/recover';
|
||||||
|
import { ElLoading } from 'element-plus';
|
||||||
import { defineComponent } from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
|
|
||||||
@ -16,4 +20,26 @@ const { t } = useI18n();
|
|||||||
|
|
||||||
defineComponent({ name: 'load-view' });
|
defineComponent({ name: 'load-view' });
|
||||||
|
|
||||||
|
async function manualLoadView() {
|
||||||
|
const loading = new ElLoading.service({
|
||||||
|
lock: true,
|
||||||
|
text: t('loading'),
|
||||||
|
background: 'rgba(0, 0, 0, 0.7)'
|
||||||
|
});
|
||||||
|
|
||||||
|
const recoverJson = await loadView(globalLookup.originVcdFile);
|
||||||
|
if (recoverJson) {
|
||||||
|
recoverFromJson(recoverJson);
|
||||||
|
recoverSession(globalLookup.topModules);
|
||||||
|
}
|
||||||
|
loading.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
document.addEventListener('keydown', async event => {
|
||||||
|
if (event.ctrlKey && event.key === 'k') {
|
||||||
|
event.preventDefault();
|
||||||
|
manualLoadView();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
</script>
|
</script>
|
@ -66,6 +66,11 @@ async function attemptRecover(inputFile, inputViewFile) {
|
|||||||
globalLookup.originVcdViewFile = inputViewFile;
|
globalLookup.originVcdViewFile = inputViewFile;
|
||||||
return recoverResult;
|
return recoverResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 不存在则创建一个和 inputFile 同名的 view 文件
|
||||||
|
if (inputFile.endsWith('.vcd')) {
|
||||||
|
inputFile = inputFile.slice(0, -4);
|
||||||
|
}
|
||||||
globalLookup.originVcdViewFile = inputFile + '.view';
|
globalLookup.originVcdViewFile = inputFile + '.view';
|
||||||
return await findRecoverFile(globalLookup.originVcdViewFile);
|
return await findRecoverFile(globalLookup.originVcdViewFile);
|
||||||
}
|
}
|
||||||
@ -82,13 +87,16 @@ export async function recoverFromInputFile(inputFile, inputViewFile) {
|
|||||||
recoverFromJson(recoverJson);
|
recoverFromJson(recoverJson);
|
||||||
}
|
}
|
||||||
|
|
||||||
function recoverFromJson(recoverJson) {
|
export function recoverFromJson(recoverJson) {
|
||||||
if (recoverJson === undefined) {
|
if (recoverJson === undefined) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 加载 waves
|
// 加载 waves
|
||||||
const waves = recoverJson.waves;
|
const waves = recoverJson.waves;
|
||||||
|
if (!recoverConfig.waves) {
|
||||||
|
recoverConfig.waves = new Map();
|
||||||
|
}
|
||||||
if (waves instanceof Array && waves.length > 0) {
|
if (waves instanceof Array && waves.length > 0) {
|
||||||
for (const wave of waves) {
|
for (const wave of waves) {
|
||||||
const name = wave.name;
|
const name = wave.name;
|
||||||
@ -401,7 +409,8 @@ export function makeSaveViewPayload(config) {
|
|||||||
|
|
||||||
// 窗口状态
|
// 窗口状态
|
||||||
if (all || defaultFalseWrapper(config, 'state')) {
|
if (all || defaultFalseWrapper(config, 'state')) {
|
||||||
const state = globalLookup.pstate;
|
// proxy 对象在一定情况下无法序列化
|
||||||
|
const state = JSON.parse(JSON.stringify(globalLookup.pstate));
|
||||||
Object.assign(payload, { state });
|
Object.assign(payload, { state });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
* 设计参考文档:https://nc-ai-lab.feishu.cn/wiki/Fy3ZwtbYbiatmxkhOp2cyHSFnlw
|
* 设计参考文档:https://nc-ai-lab.feishu.cn/wiki/Fy3ZwtbYbiatmxkhOp2cyHSFnlw
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { groupColorDispatcher } from "@/components/sidebar/manage-group";
|
||||||
import { globalLookup } from "./global";
|
import { globalLookup } from "./global";
|
||||||
import { getSmartCurrentSignalValue } from "./utils";
|
import { getSmartCurrentSignalValue } from "./utils";
|
||||||
|
|
||||||
@ -65,11 +66,28 @@ export const WaveContainerView = {
|
|||||||
delete globalLookup.currentSignalValues[signal.link];
|
delete globalLookup.currentSignalValues[signal.link];
|
||||||
|
|
||||||
// 从 currentWiresRenderView 中删除
|
// 从 currentWiresRenderView 中删除
|
||||||
const i = findViewIndexByLink(signal.link);
|
// 此处需要考虑到处于 group 中的 link 的情况
|
||||||
const tailElements = renderView.slice(i + 1);
|
const { index, childIndex } = findViewIndexTuple(signal.link);
|
||||||
renderView.length = i;
|
|
||||||
tailElements.forEach(view => renderView.push(view));
|
|
||||||
|
|
||||||
|
function deleteElement(container, index) {
|
||||||
|
const tailElements = container.slice(index + 1);
|
||||||
|
container.length = index;
|
||||||
|
tailElements.forEach(el => container.push(el));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (childIndex >= 0) {
|
||||||
|
// 删除 group 内元素
|
||||||
|
const view = renderView[index];
|
||||||
|
deleteElement(view.children, childIndex);
|
||||||
|
// 如果 group 空了,则也删除
|
||||||
|
if (view.children.length === 0) {
|
||||||
|
deleteElement(renderView, index);
|
||||||
|
groupColorDispatcher.put(view.groupInfo.color);
|
||||||
|
}
|
||||||
|
} else if (index >= 0) {
|
||||||
|
// 删除总体的元素
|
||||||
|
deleteElement(renderView, index);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -82,12 +100,36 @@ export const WaveContainerView = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 找到位于嵌套结构中的索引
|
||||||
|
* @param {string} link
|
||||||
|
* @returns {{ index: number, childIndex: number }} index: 位于 renderView 的索引,位于 group 的 children 中的索引
|
||||||
|
*/
|
||||||
|
function findViewIndexTuple(link) {
|
||||||
|
const renderView = globalLookup.currentWiresRenderView;
|
||||||
|
|
||||||
|
for (let i = 0; i < renderView.length; ++ i) {
|
||||||
|
const view = renderView[i];
|
||||||
|
if (view.signalInfo.link === link) {
|
||||||
|
return { index: i, childIndex: -1 };
|
||||||
|
}
|
||||||
|
for (let j = 0; j < view.children.length; ++ j) {
|
||||||
|
const child = view.children[j];
|
||||||
|
if (child.signalInfo.link === link) {
|
||||||
|
return { index: i, childIndex: j };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return { index: -1, childIndex: -1 };
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
export function findViewIndexByLink(link) {
|
export function findViewIndexByLink(link) {
|
||||||
const renderView = globalLookup.currentWiresRenderView;
|
const renderView = globalLookup.currentWiresRenderView;
|
||||||
|
|
||||||
let i = 0;
|
let i = 0;
|
||||||
while (renderView[i].signalInfo.link !== link && i < renderView.length) {
|
while (i < renderView.length && renderView[i].signalInfo.link !== link) {
|
||||||
++ i;
|
++ i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user