feat: 右键菜单

Re-1.0
咬轮猫 3 years ago
parent 8209dae48e
commit feb6f31d69

@ -39,6 +39,7 @@
@mousedown="onSvgMouseDown(item, index, $event)"
@mouseenter="onSvgMouseEnter(item, index, $event)"
@mouseleave="onSvgMouseLeave(item, index, $event)"
@contextmenu="onSvgContextMenuEvent(item, index, $event)"
>
<connection-line
v-if="item.type === EDoneJsonType.ConnectionLine"
@ -155,10 +156,23 @@
</g>
</g>
</svg>
<!-- 右键菜单 -->
<ul ref="contextMenuRef" class="contextMenu" v-show="contextMenuStore.display">
<li
v-for="(item, key) in contextMenuStore.info"
:key="item.title"
@click="contextMenuStore.onContextMenuClick(key)"
>
<p :class="item.enable ? '' : 'disabled'">
{{ item.title }}
<span class="shortcut">{{ item.hot_key }}</span>
</p>
</li>
</ul>
</div>
</template>
<script setup lang="ts">
import { computed, getCurrentInstance, onMounted, reactive } from 'vue';
import { computed, getCurrentInstance, onMounted, reactive, ref } from 'vue';
import { useConfigStore } from '@/store/config';
import { useGlobalStore } from '@/store/global';
import {
@ -192,6 +206,7 @@
import ConnectionLine from '@/components/webtopo-svgedit/components/connection-line/index.vue';
import { IVisiableInfo } from './types';
import { ComponentImport } from '@/config-center';
import { useContextMenuStore } from '@/store/system';
// import HandlePanel from '../handle-panel/index.vue';
//
const instance = getCurrentInstance();
@ -203,6 +218,8 @@
const globalStore = useGlobalStore();
const configStore = useConfigStore();
const svgEditLayoutStore = useSvgEditLayoutStore();
const contextMenuStore = useContextMenuStore();
const contextMenuRef = ref<HTMLElement>();
const cursor_style = computed(() =>
globalStore.intention == EGlobalStoreIntention.MoveCanvas
? 'grab'
@ -299,7 +316,6 @@
e.preventDefault();
};
const onSvgMouseDown = (select_item: IDoneJson, index: number, e: MouseEvent) => {
console.log('触发选中', e);
if (globalStore.intention === EGlobalStoreIntention.Connection) {
return;
}
@ -613,9 +629,9 @@
new_position_x: 0,
new_position_y: 0
});
contextMenuStore.display = false;
};
const onCanvasMouseDown = (e: MouseEvent) => {
console.log('onCanvasMouseDown', e);
const { clientX, clientY } = e;
if (globalStore.intention === EGlobalStoreIntention.Connection && globalStore.handle_svg_info) {
if (e.button === 0) {
@ -661,6 +677,32 @@
const onCanvasContextMenuEvent = (e: MouseEvent) => {
e.preventDefault(); //
};
const onSvgContextMenuEvent = (select_item: IDoneJson, index: number, e: MouseEvent) => {
if (globalStore.intention === EGlobalStoreIntention.Connection) {
return;
}
if (contextMenuRef.value) {
globalStore.intention = EGlobalStoreIntention.ContextMenu;
globalStore.setHandleSvgInfo(select_item, index);
contextMenuRef.value.style.left = e.pageX + 'px';
contextMenuRef.value.style.top = e.pageY + 'px';
contextMenuStore.info.MoveUpOneLevel.enable =
contextMenuStore.info.MoveUpTopLevel.enable =
contextMenuStore.info.MoveDownOneLevel.enable =
contextMenuStore.info.MoveDownTopLevel.enable =
true;
if (index === globalStore.done_json.length - 1) {
contextMenuStore.info.MoveUpOneLevel.enable = contextMenuStore.info.MoveUpTopLevel.enable =
false;
}
if (index === 0) {
contextMenuStore.info.MoveDownOneLevel.enable =
contextMenuStore.info.MoveDownTopLevel.enable = false;
}
contextMenuStore.display = true;
}
};
const getActualBoundScale = (
actual_bound: {
x: number;
@ -678,6 +720,7 @@
height: actual_bound.height * scale_y
};
};
onMounted(() => {
globalStore.setDoneJson([]);
});
@ -706,4 +749,56 @@
cursor: move;
outline: 1px solid rgb(23, 222, 30);
}
.contextMenu {
position: absolute;
z-index: 99999;
background: #ffffff;
padding: 5px 0;
margin: 0px;
display: block;
border-radius: 5px;
box-shadow: 2px 5px 10px rgba(0, 0, 0, 0.3);
li {
list-style: none;
padding: 0px;
margin: 0px;
}
.shortcut {
width: 115px;
text-align: right;
float: right;
}
p {
text-decoration: none;
display: block;
padding: 0px 15px 1px 20px;
margin: 0;
user-select: none;
-webkit-user-select: none;
}
p:hover {
background-color: #0cf;
color: #ffffff;
cursor: default;
}
.disabled {
color: #999;
}
.disabled:hover {
color: #999;
background-color: transparent;
}
li.separator {
border-top: solid 1px #e3e3e3;
padding-top: 5px;
margin-top: 5px;
}
}
</style>

@ -63,8 +63,6 @@
const libChange = (val: any) => {
config_center.value = [];
config_center.value = val;
console.log(val, 71474);
};
const createBegin = (svg_item: IConfigItem) => {

@ -14,13 +14,14 @@
<el-form-item label="y轴原点坐标" size="small">
<el-input-number v-model="configStore.svg.position_center.y"></el-input-number>
</el-form-item>
<el-form-item label="缩放" size="small">
<!-- 基础版不做画布缩放了 有需要自己写吧^-^ -->
<!-- <el-form-item label="缩放" size="small">
<el-input-number
v-model="configStore.svg.scale"
:step="0.1"
step-strictly
></el-input-number>
</el-form-item>
</el-form-item> -->
</el-form>
</div>
</div>

@ -0,0 +1,18 @@
import { IDoneJson } from '@/store/global/types';
import { useEditPrivateStore } from '@/store/system';
export const useHistoryRecord = (done_json: IDoneJson[]) => {
const edit_private_store = useEditPrivateStore();
if (edit_private_store.is_record_history) {
if (edit_private_store.history_nowindex + 1 < edit_private_store.history_doneComponent.length) {
edit_private_store.history_doneComponent.splice(edit_private_store.history_nowindex + 1);
}
edit_private_store.history_doneComponent.push(done_json);
edit_private_store.history_nowindex = edit_private_store.history_doneComponent.length - 1;
if (edit_private_store.history_doneComponent.length > edit_private_store.max_record_times) {
edit_private_store.history_doneComponent.shift();
edit_private_store.history_nowindex = edit_private_store.history_doneComponent.length - 1;
}
}
edit_private_store.is_record_history = true;
};

@ -12,7 +12,7 @@ import {
IMouseInfo,
IScaleInfo
} from './types';
import { useEditPrivateStore } from '../system';
import { useHistoryRecord } from '@/hooks';
/**
*
*/
@ -67,7 +67,6 @@ export const useGlobalStore = defineStore('global-store', {
this.create_svg_info = create_svg_info;
},
setDoneJson(done_json: IDoneJson[] | IDoneJson) {
console.log('这里要记录操作历史记录', done_json);
if (isOfType(done_json, 'id')) {
this.done_json.push(done_json);
nextTick(() => {
@ -77,29 +76,7 @@ export const useGlobalStore = defineStore('global-store', {
this.done_json = objectDeepClone<IDoneJson[]>(done_json);
}
nextTick(() => {
const edit_private_store = useEditPrivateStore();
if (edit_private_store.is_record_history) {
if (
edit_private_store.history_nowindex + 1 <
edit_private_store.history_doneComponent.length
) {
edit_private_store.history_doneComponent.splice(
edit_private_store.history_nowindex + 1
);
}
edit_private_store.history_doneComponent.push(
objectDeepClone<IDoneJson[]>(this.done_json)
);
edit_private_store.history_nowindex = edit_private_store.history_doneComponent.length - 1;
if (
edit_private_store.history_doneComponent.length > edit_private_store.max_record_times
) {
edit_private_store.history_doneComponent.shift();
edit_private_store.history_nowindex =
edit_private_store.history_doneComponent.length - 1;
}
}
edit_private_store.is_record_history = true;
useHistoryRecord(objectDeepClone<IDoneJson[]>(this.done_json));
});
},
setMouseInfo(mouse_info: IMouseInfo) {
@ -122,6 +99,11 @@ export const useGlobalStore = defineStore('global-store', {
},
setScaleInfo(info: IScaleInfo) {
this.scale_info = info;
},
spliceDoneJson(index: number) {
const globalStore = useGlobalStore();
globalStore.done_json.splice(index, 1);
useHistoryRecord(globalStore.done_json);
}
}
});

@ -45,7 +45,8 @@ export enum EGlobalStoreIntention {
Zoom = 'Zoom',
Rotate = 'Rotate',
Connection = 'Connection',
SetConnectionLineNode = 'SetConnectionLineNode'
SetConnectionLineNode = 'SetConnectionLineNode',
ContextMenu = 'ContextMenu'
}
export interface IMouseInfo {
state: EMouseInfoState;

@ -1,7 +1,9 @@
import { objectDeepClone, randomString } from '@/utils';
import { defineStore } from 'pinia';
import { useGlobalStore } from '../global';
import { EditPrivateStoreState } from './types';
import { IDoneJson } from '../global/types';
import { ContextMenuStoreState, EContextMenuInfoType, EditPrivateStoreState } from './types';
import { useHistoryRecord } from '@/hooks';
/**
*
*/
@ -53,3 +55,115 @@ export const useEditPrivateStore = defineStore('edit-private-store', {
}
}
});
export const useContextMenuStore = defineStore('context-menu-store', {
state: (): ContextMenuStoreState => {
return {
display: false,
info: {
[EContextMenuInfoType.Copy]: {
title: '复制',
hot_key: 'Ctrl+C',
enable: true
},
[EContextMenuInfoType.Delete]: {
title: '删除',
hot_key: 'Delete',
enable: true
},
[EContextMenuInfoType.MoveUpTopLevel]: {
title: '置于顶层',
hot_key: 'Ctrl+→',
enable: true
},
[EContextMenuInfoType.MoveDownTopLevel]: {
title: '置于底层',
hot_key: 'Ctrl+←',
enable: true
},
[EContextMenuInfoType.MoveUpOneLevel]: {
title: '置于上一层',
hot_key: 'Ctrl+↑',
enable: true
},
[EContextMenuInfoType.MoveDownOneLevel]: {
title: '置于下一层',
hot_key: 'Ctrl+↓',
enable: true
}
}
};
},
actions: {
onContextMenuClick(type: EContextMenuInfoType) {
const globalStore = useGlobalStore();
if (!globalStore.handle_svg_info) {
return;
}
switch (type) {
case EContextMenuInfoType.Copy:
const temp_item = objectDeepClone<IDoneJson>(globalStore.handle_svg_info.info);
temp_item.id = temp_item.name + randomString();
temp_item.title += '-copy';
temp_item.x += 10;
temp_item.y += 10;
globalStore.setDoneJson(temp_item);
this.display = false;
break;
case EContextMenuInfoType.Delete:
globalStore.spliceDoneJson(globalStore.handle_svg_info.index);
this.display = false;
break;
case EContextMenuInfoType.MoveUpOneLevel:
if (
globalStore.done_json.length === 1 ||
globalStore.handle_svg_info.index === globalStore.done_json.length - 1
) {
return;
}
const temp_up_one = globalStore.handle_svg_info.info;
globalStore.done_json[globalStore.handle_svg_info.index] =
globalStore.done_json[globalStore.handle_svg_info.index + 1];
globalStore.done_json[globalStore.handle_svg_info.index + 1] = temp_up_one;
useHistoryRecord(globalStore.done_json);
this.display = false;
break;
case EContextMenuInfoType.MoveDownOneLevel:
if (globalStore.done_json.length === 1 || globalStore.handle_svg_info.index === 0) {
return;
}
const temp_down_one = globalStore.handle_svg_info.info;
globalStore.done_json[globalStore.handle_svg_info.index] =
globalStore.done_json[globalStore.handle_svg_info.index - 1];
globalStore.done_json[globalStore.handle_svg_info.index - 1] = temp_down_one;
useHistoryRecord(globalStore.done_json);
this.display = false;
break;
case EContextMenuInfoType.MoveDownTopLevel:
if (globalStore.done_json.length === 1 || globalStore.handle_svg_info.index === 0) {
return;
}
const temp_up_top = globalStore.handle_svg_info.info;
globalStore.done_json.splice(globalStore.handle_svg_info.index, 1);
globalStore.done_json.unshift(temp_up_top);
useHistoryRecord(globalStore.done_json);
this.display = false;
break;
case EContextMenuInfoType.MoveUpTopLevel:
if (
globalStore.done_json.length === 1 ||
globalStore.handle_svg_info.index === globalStore.done_json.length
) {
return;
}
const temp_down_top = globalStore.handle_svg_info.info;
globalStore.done_json.splice(globalStore.handle_svg_info.index, 1);
globalStore.done_json.push(temp_down_top);
useHistoryRecord(globalStore.done_json);
this.display = false;
break;
default:
break;
}
}
}
});

@ -7,3 +7,22 @@ export interface EditPrivateStoreState {
is_record_history: boolean;
max_record_times: number;
}
export interface ContextMenuStoreState {
display: boolean;
info: {
[key in EContextMenuInfoType]: IContextMenuInfo;
};
}
export interface IContextMenuInfo {
title: string;
hot_key: string;
enable: boolean;
}
export enum EContextMenuInfoType {
Copy = 'Copy',
Delete = 'Delete',
MoveUpOneLevel = 'MoveUpOneLevel',
MoveDownOneLevel = 'MoveDownOneLevel',
MoveUpTopLevel = 'MoveUpTopLevel',
MoveDownTopLevel = 'MoveDownTopLevel'
}

@ -159,7 +159,6 @@ export const setSvgActualInfo = (done_json: IDoneJson) => {
rectBBox.getAttribute('width') === '0' &&
rectBBox.getAttribute('height') === '0'
) {
console.log(rectBBox.getAttribute('x'), 168);
rectBBox.setAttribute('x', x.toString());
rectBBox.setAttribute('y', y.toString());
rectBBox.setAttribute('width', width.toString());

Loading…
Cancel
Save