实现保存另存为
This commit is contained in:
parent
67b008fa31
commit
f9a62bfe09
@ -18,7 +18,7 @@
|
||||
<script>
|
||||
window.readVcdFile = async () => {
|
||||
let inputVcdFile = 'test.vcd';
|
||||
let inputViewFile = 'test.vcd.view';
|
||||
let inputViewFile = 'test.view';
|
||||
|
||||
const response = await fetch(inputVcdFile);
|
||||
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:
|
||||
html = fp.read()
|
||||
|
||||
html = html.replace("''", "'<workerRoot>'")
|
||||
html = html.replace("''", "'<root>'")
|
||||
|
||||
with open('./dist/index.html', 'w', encoding='utf-8') as fp:
|
||||
fp.write(html)
|
@ -30,6 +30,7 @@ import RightNav from '@/components/right-nav.vue';
|
||||
import Pivot from '@/components/pivot';
|
||||
import { recoverFromInputFile, recoverSession } from './hook/recover';
|
||||
import { setDefaultCss } from './hook/css';
|
||||
import { handleVscodeMessage } from './api/message';
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
@ -114,14 +115,19 @@ onMounted(async () => {
|
||||
globalLookup.topModules.push(mod);
|
||||
}
|
||||
}
|
||||
loading.close();
|
||||
worker.terminate();
|
||||
|
||||
// 根据 recoverConfig 完成现场回复
|
||||
recoverSession(VcdInfo.topModules);
|
||||
loading.close();
|
||||
});
|
||||
});
|
||||
|
||||
// vscode 传递事件
|
||||
window.addEventListener('message', event => {
|
||||
handleVscodeMessage(event);
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
@ -26,7 +26,7 @@ export async function saveView(originVcdFile, originVcdViewFile, payload) {
|
||||
} else {
|
||||
vscode.postMessage({
|
||||
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 {
|
||||
vscode.postMessage({
|
||||
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
|
||||
|
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>
|
||||
<div>
|
||||
<div class="status"></div>
|
||||
<div class="item">
|
||||
<div class="item" @click="manualLoadView()">
|
||||
<span>{{ t('filemenu.load-view') }}</span>
|
||||
<span><code>Ctrl K</code></span>
|
||||
</div>
|
||||
@ -9,6 +9,10 @@
|
||||
</template>
|
||||
|
||||
<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 { useI18n } from 'vue-i18n';
|
||||
|
||||
@ -16,4 +20,26 @@ const { t } = useI18n();
|
||||
|
||||
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>
|
@ -66,6 +66,11 @@ async function attemptRecover(inputFile, inputViewFile) {
|
||||
globalLookup.originVcdViewFile = inputViewFile;
|
||||
return recoverResult;
|
||||
}
|
||||
|
||||
// 不存在则创建一个和 inputFile 同名的 view 文件
|
||||
if (inputFile.endsWith('.vcd')) {
|
||||
inputFile = inputFile.slice(0, -4);
|
||||
}
|
||||
globalLookup.originVcdViewFile = inputFile + '.view';
|
||||
return await findRecoverFile(globalLookup.originVcdViewFile);
|
||||
}
|
||||
@ -82,13 +87,16 @@ export async function recoverFromInputFile(inputFile, inputViewFile) {
|
||||
recoverFromJson(recoverJson);
|
||||
}
|
||||
|
||||
function recoverFromJson(recoverJson) {
|
||||
export function recoverFromJson(recoverJson) {
|
||||
if (recoverJson === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 加载 waves
|
||||
const waves = recoverJson.waves;
|
||||
if (!recoverConfig.waves) {
|
||||
recoverConfig.waves = new Map();
|
||||
}
|
||||
if (waves instanceof Array && waves.length > 0) {
|
||||
for (const wave of waves) {
|
||||
const name = wave.name;
|
||||
@ -401,7 +409,8 @@ export function makeSaveViewPayload(config) {
|
||||
|
||||
// 窗口状态
|
||||
if (all || defaultFalseWrapper(config, 'state')) {
|
||||
const state = globalLookup.pstate;
|
||||
// proxy 对象在一定情况下无法序列化
|
||||
const state = JSON.parse(JSON.stringify(globalLookup.pstate));
|
||||
Object.assign(payload, { state });
|
||||
}
|
||||
|
||||
|
@ -3,6 +3,7 @@
|
||||
* 设计参考文档:https://nc-ai-lab.feishu.cn/wiki/Fy3ZwtbYbiatmxkhOp2cyHSFnlw
|
||||
*/
|
||||
|
||||
import { groupColorDispatcher } from "@/components/sidebar/manage-group";
|
||||
import { globalLookup } from "./global";
|
||||
import { getSmartCurrentSignalValue } from "./utils";
|
||||
|
||||
@ -65,11 +66,28 @@ export const WaveContainerView = {
|
||||
delete globalLookup.currentSignalValues[signal.link];
|
||||
|
||||
// 从 currentWiresRenderView 中删除
|
||||
const i = findViewIndexByLink(signal.link);
|
||||
const tailElements = renderView.slice(i + 1);
|
||||
renderView.length = i;
|
||||
tailElements.forEach(view => renderView.push(view));
|
||||
// 此处需要考虑到处于 group 中的 link 的情况
|
||||
const { index, childIndex } = findViewIndexTuple(signal.link);
|
||||
|
||||
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) {
|
||||
const renderView = globalLookup.currentWiresRenderView;
|
||||
|
||||
let i = 0;
|
||||
while (renderView[i].signalInfo.link !== link && i < renderView.length) {
|
||||
while (i < renderView.length && renderView[i].signalInfo.link !== link) {
|
||||
++ i;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user