feat(组件): 脑图支持新功能&部分组件调整
This commit is contained in:
parent
17215a686e
commit
bff4a60c58
|
@ -90,5 +90,16 @@ export default {
|
||||||
priority: 'Priority',
|
priority: 'Priority',
|
||||||
tag: 'Tag',
|
tag: 'Tag',
|
||||||
},
|
},
|
||||||
|
hotboxMenu: {
|
||||||
|
expand: 'Expand/Collapse',
|
||||||
|
insetParent: 'Insert one level up',
|
||||||
|
insetSon: 'Insert next level',
|
||||||
|
insetBrother: 'Insert sibling',
|
||||||
|
copy: 'Copy',
|
||||||
|
cut: 'Cut',
|
||||||
|
paste: 'Paste',
|
||||||
|
delete: 'Delete',
|
||||||
|
enterNode: 'Enter the current node',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -84,5 +84,16 @@ export default {
|
||||||
priority: '优先级',
|
priority: '优先级',
|
||||||
tag: '标签',
|
tag: '标签',
|
||||||
},
|
},
|
||||||
|
hotboxMenu: {
|
||||||
|
expand: '展开/收起',
|
||||||
|
insetParent: '插入上一级',
|
||||||
|
insetSon: '插入下一级',
|
||||||
|
insetBrother: '插入同级',
|
||||||
|
copy: '复制',
|
||||||
|
cut: '剪切',
|
||||||
|
paste: '粘贴',
|
||||||
|
delete: '删除',
|
||||||
|
enterNode: '进入当前节点',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
<edit-menu
|
<edit-menu
|
||||||
:minder="minder"
|
:minder="minder"
|
||||||
:move-enable="props.moveEnable"
|
:move-enable="props.moveEnable"
|
||||||
|
:move-confirm="props.moveConfirm"
|
||||||
:sequence-enable="props.sequenceEnable"
|
:sequence-enable="props.sequenceEnable"
|
||||||
:tag-enable="props.tagEnable"
|
:tag-enable="props.tagEnable"
|
||||||
:progress-enable="props.progressEnable"
|
:progress-enable="props.progressEnable"
|
||||||
|
|
|
@ -1,18 +1,96 @@
|
||||||
<template>
|
<template>
|
||||||
<div ref="mec" class="minder-container" :style="{ height: `${props.height}px` }">
|
<div ref="mec" class="minder-container" :style="{ height: `${props.height}px` }">
|
||||||
<a-button type="primary" :disabled="props.disabled" class="save-btn bottom-[30px] right-[30px]" @click="save">{{
|
<a-button type="primary" :disabled="props.disabled" class="save-btn bottom-[30px] right-[30px]" @click="save">
|
||||||
t('minder.main.main.save')
|
{{ t('minder.main.main.save') }}
|
||||||
}}</a-button>
|
</a-button>
|
||||||
<navigator />
|
<navigator />
|
||||||
|
<a-dropdown
|
||||||
|
v-model:popup-visible="menuVisible"
|
||||||
|
class="minder-dropdown"
|
||||||
|
position="bl"
|
||||||
|
:popup-translate="menuPopupOffset"
|
||||||
|
@select="handleMinderMenuSelect"
|
||||||
|
>
|
||||||
|
<span></span>
|
||||||
|
<template #content>
|
||||||
|
<a-doption value="expand">
|
||||||
|
<div class="flex items-center">
|
||||||
|
<div>{{ t('minder.hotboxMenu.expand') }}</div>
|
||||||
|
<div class="ml-[4px] text-[var(--color-text-4)]">( / )</div>
|
||||||
|
</div>
|
||||||
|
</a-doption>
|
||||||
|
<a-doption value="insetParent">
|
||||||
|
<div class="flex items-center">
|
||||||
|
<div>{{ t('minder.hotboxMenu.insetParent') }}</div>
|
||||||
|
<div class="ml-[4px] text-[var(--color-text-4)]">(Shift + Tab)</div>
|
||||||
|
</div>
|
||||||
|
</a-doption>
|
||||||
|
<a-doption value="insetSon">
|
||||||
|
<div class="flex items-center">
|
||||||
|
<div>{{ t('minder.hotboxMenu.insetSon') }}</div>
|
||||||
|
<div class="ml-[4px] text-[var(--color-text-4)]">(Tab)</div>
|
||||||
|
</div>
|
||||||
|
</a-doption>
|
||||||
|
<a-doption value="insetBrother">
|
||||||
|
<div class="flex items-center">
|
||||||
|
<div>{{ t('minder.hotboxMenu.insetBrother') }}</div>
|
||||||
|
<div class="ml-[4px] text-[var(--color-text-4)]">(Enter)</div>
|
||||||
|
</div>
|
||||||
|
</a-doption>
|
||||||
|
<a-doption value="copy">
|
||||||
|
<div class="flex items-center">
|
||||||
|
<div>{{ t('minder.hotboxMenu.copy') }}</div>
|
||||||
|
<div class="ml-[4px] text-[var(--color-text-4)]">(Ctrl + C)</div>
|
||||||
|
</div>
|
||||||
|
</a-doption>
|
||||||
|
<a-doption value="cut">
|
||||||
|
<div class="flex items-center">
|
||||||
|
<div>{{ t('minder.hotboxMenu.cut') }}</div>
|
||||||
|
<div class="ml-[4px] text-[var(--color-text-4)]">(Ctrl + X)</div>
|
||||||
|
</div>
|
||||||
|
</a-doption>
|
||||||
|
<a-doption value="paste">
|
||||||
|
<div class="flex items-center">
|
||||||
|
<div>{{ t('minder.hotboxMenu.paste') }}</div>
|
||||||
|
<div class="ml-[4px] text-[var(--color-text-4)]">(Ctrl + V)</div>
|
||||||
|
</div>
|
||||||
|
</a-doption>
|
||||||
|
<a-doption value="delete">
|
||||||
|
<div class="flex items-center">
|
||||||
|
<div>{{ t('minder.hotboxMenu.delete') }}</div>
|
||||||
|
<div class="ml-[4px] text-[var(--color-text-4)]">(Backspace)</div>
|
||||||
|
</div>
|
||||||
|
</a-doption>
|
||||||
|
<a-doption value="enterNode">
|
||||||
|
<div class="flex items-center">
|
||||||
|
<div>{{ t('minder.hotboxMenu.enterNode') }}</div>
|
||||||
|
<div class="ml-[4px] text-[var(--color-text-4)]">(Ctrl+ Enter)</div>
|
||||||
|
</div>
|
||||||
|
</a-doption>
|
||||||
|
</template>
|
||||||
|
</a-dropdown>
|
||||||
|
<div
|
||||||
|
v-if="innerImportJson.treePath?.length > 1"
|
||||||
|
class="absolute left-[50%] top-[24px] z-50 translate-x-[-50%] bg-white p-[8px]"
|
||||||
|
>
|
||||||
|
<a-breadcrumb>
|
||||||
|
<a-breadcrumb-item v-for="crumb of innerImportJson.treePath" :key="crumb.name" @click="switchNode(crumb)">
|
||||||
|
{{ crumb.text }}
|
||||||
|
</a-breadcrumb-item>
|
||||||
|
</a-breadcrumb>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" name="minderContainer" setup>
|
<script lang="ts" name="minderContainer" setup>
|
||||||
import { onMounted, ref } from 'vue';
|
import { onMounted, ref, watch } from 'vue';
|
||||||
|
import { cloneDeep } from 'lodash-es';
|
||||||
|
|
||||||
import Navigator from './navigator.vue';
|
import Navigator from './navigator.vue';
|
||||||
|
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
|
import useMinderStore from '@/store/modules/components/minder-editor';
|
||||||
|
import { findNodePathByKey } from '@/utils';
|
||||||
|
|
||||||
import { editMenuProps, mainEditorProps, priorityProps, tagProps } from '../props';
|
import { editMenuProps, mainEditorProps, priorityProps, tagProps } from '../props';
|
||||||
import Editor from '../script/editor';
|
import Editor from '../script/editor';
|
||||||
|
@ -25,9 +103,12 @@
|
||||||
const emit = defineEmits({
|
const emit = defineEmits({
|
||||||
afterMount: () => ({}),
|
afterMount: () => ({}),
|
||||||
save: (json) => json,
|
save: (json) => json,
|
||||||
|
enterNode: (data) => data,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const minderStore = useMinderStore();
|
||||||
const mec: Ref<HTMLDivElement | null> = ref(null);
|
const mec: Ref<HTMLDivElement | null> = ref(null);
|
||||||
|
const innerImportJson = ref<any>({});
|
||||||
|
|
||||||
function save() {
|
function save() {
|
||||||
emit('save', window.minder.exportJson());
|
emit('save', window.minder.exportJson());
|
||||||
|
@ -129,6 +210,80 @@
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
init();
|
init();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.importJson,
|
||||||
|
(val) => {
|
||||||
|
innerImportJson.value = val;
|
||||||
|
window.minder.importJson(val);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const menuVisible = ref(false);
|
||||||
|
const menuPopupOffset = ref([0, 0]);
|
||||||
|
|
||||||
|
function switchNode(node: any) {
|
||||||
|
innerImportJson.value = cloneDeep(findNodePathByKey([props.importJson.root], node.id, 'data', 'id'));
|
||||||
|
innerImportJson.value.data.expandState = 'expand';
|
||||||
|
window.minder.importJson(innerImportJson.value);
|
||||||
|
window.minder.execCommand('template', Object.keys(window.kityminder.Minder.getTemplateList())[minderStore.mold]);
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => minderStore.event.timestamp,
|
||||||
|
() => {
|
||||||
|
if (minderStore.event.name === 'hotbox') {
|
||||||
|
const nodeDomWidth = minderStore.event.nodeDom?.getBoundingClientRect().width || 0;
|
||||||
|
menuPopupOffset.value = [
|
||||||
|
minderStore.event.nodePosition.x + nodeDomWidth / 2,
|
||||||
|
minderStore.event.nodePosition.y - nodeDomWidth / 4,
|
||||||
|
];
|
||||||
|
menuVisible.value = true;
|
||||||
|
}
|
||||||
|
if (minderStore.event.name === 'enterNode') {
|
||||||
|
switchNode(minderStore.event.nodeData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
function handleMinderMenuSelect(val: string | number | Record<string, any> | undefined) {
|
||||||
|
const selectedNode = window.minder.getSelectedNode();
|
||||||
|
switch (val) {
|
||||||
|
case 'expand':
|
||||||
|
if (selectedNode.data.expandState === 'collapse') {
|
||||||
|
window.minder.execCommand('Expand');
|
||||||
|
} else {
|
||||||
|
window.minder.execCommand('Collapse');
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'insetParent':
|
||||||
|
window.minder.execCommand('AppendParentNode');
|
||||||
|
break;
|
||||||
|
case 'insetSon':
|
||||||
|
window.minder.execCommand('AppendChildNode');
|
||||||
|
break;
|
||||||
|
case 'insetBrother':
|
||||||
|
window.minder.execCommand('AppendSiblingNode');
|
||||||
|
break;
|
||||||
|
case 'copy':
|
||||||
|
window.minder.execCommand('Copy');
|
||||||
|
break;
|
||||||
|
case 'cut':
|
||||||
|
window.minder.execCommand('Cut');
|
||||||
|
break;
|
||||||
|
case 'paste':
|
||||||
|
window.minder.execCommand('Paste');
|
||||||
|
break;
|
||||||
|
case 'delete':
|
||||||
|
window.minder.execCommand('RemoveNode');
|
||||||
|
break;
|
||||||
|
case 'enterNode':
|
||||||
|
switchNode(selectedNode.data);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less">
|
<style lang="less">
|
||||||
|
@ -139,4 +294,9 @@
|
||||||
.minder-container {
|
.minder-container {
|
||||||
@apply relative;
|
@apply relative;
|
||||||
}
|
}
|
||||||
|
.minder-dropdown {
|
||||||
|
.arco-dropdown-list-wrapper {
|
||||||
|
max-height: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
</a-button>
|
</a-button>
|
||||||
{{ t('minder.menu.expand.folding') }}
|
{{ t('minder.menu.expand.folding') }}
|
||||||
</div>
|
</div>
|
||||||
<move-box :move-enable="props.moveEnable" />
|
<move-box :move-enable="props.moveEnable" :move-confirm="props.moveConfirm" />
|
||||||
<insert-box />
|
<insert-box />
|
||||||
<edit-del :del-confirm="props.delConfirm" />
|
<edit-del :del-confirm="props.delConfirm" />
|
||||||
</div>
|
</div>
|
||||||
|
@ -39,10 +39,14 @@
|
||||||
:priority-start-with-zero="props.priorityStartWithZero"
|
:priority-start-with-zero="props.priorityStartWithZero"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="menu-group">
|
||||||
|
<mold v-if="props.moldEnable" :default-mold="props.defaultMold" @mold-change="handleMoldChange" />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" name="editMenu" setup>
|
<script lang="ts" name="editMenu" setup>
|
||||||
|
import mold from '../view/mold.vue';
|
||||||
import editDel from './editDel.vue';
|
import editDel from './editDel.vue';
|
||||||
import insertBox from './insertBox.vue';
|
import insertBox from './insertBox.vue';
|
||||||
import moveBox from './moveBox.vue';
|
import moveBox from './moveBox.vue';
|
||||||
|
@ -51,9 +55,19 @@
|
||||||
|
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
|
|
||||||
import { delProps, editMenuProps, priorityProps, tagProps } from '../../props';
|
import { delProps, editMenuProps, moleProps, priorityProps, tagProps, viewMenuProps } from '../../props';
|
||||||
|
|
||||||
const props = defineProps({ ...editMenuProps, ...priorityProps, ...tagProps, ...delProps });
|
const props = defineProps({
|
||||||
|
...editMenuProps,
|
||||||
|
...priorityProps,
|
||||||
|
...tagProps,
|
||||||
|
...delProps,
|
||||||
|
...viewMenuProps,
|
||||||
|
...moleProps,
|
||||||
|
});
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: 'moldChange', data: number): void;
|
||||||
|
}>();
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
|
@ -94,4 +108,8 @@
|
||||||
window.minder?.execCommand('ExpandToLevel', 1);
|
window.minder?.execCommand('ExpandToLevel', 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function handleMoldChange(data: number) {
|
||||||
|
emit('moldChange', data);
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -40,6 +40,7 @@
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
moveEnable: boolean;
|
moveEnable: boolean;
|
||||||
|
moveConfirm: any;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
let minder = reactive<any>({});
|
let minder = reactive<any>({});
|
||||||
|
|
|
@ -1,27 +1,34 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="mold-group" :disabled="disabled">
|
<a-dropdown class="toggle" :disabled="disabled" @select="handleCommand">
|
||||||
<a-dropdown class="toggle" @select="handleCommand">
|
<span class="dropdown-toggle mold-icons menu-btn cursor-pointer" :class="'mold-' + (moldIndex + 1)" />
|
||||||
<div>
|
<template #content>
|
||||||
<span class="dropdown-toggle mold-icons menu-btn" :class="'mold-' + (moldIndex + 1)" />
|
<a-doption class="dropdown-item" :value="1">
|
||||||
<span class="dropdown-link">
|
<div class="mold-icons mold-1"></div>
|
||||||
<icon-caret-down />
|
</a-doption>
|
||||||
</span>
|
<a-doption class="dropdown-item" :value="2">
|
||||||
</div>
|
<div class="mold-icons mold-2"></div>
|
||||||
<template #content>
|
</a-doption>
|
||||||
<a-doption class="dropdown-item mold-icons mold-1" :value="1" />
|
<a-doption class="dropdown-item" :value="3">
|
||||||
<a-doption class="dropdown-item mold-icons mold-2" :value="2" />
|
<div class="mold-icons mold-3"></div>
|
||||||
<a-doption class="dropdown-item mold-icons mold-3" :value="3" />
|
</a-doption>
|
||||||
<a-doption class="dropdown-item mold-icons mold-4" :value="4" />
|
<a-doption class="dropdown-item" :value="4">
|
||||||
<a-doption class="dropdown-item mold-icons mold-5" :value="5" />
|
<div class="mold-icons mold-4"></div>
|
||||||
<a-doption class="dropdown-item mold-icons mold-6" :value="6" />
|
</a-doption>
|
||||||
</template>
|
<a-doption class="dropdown-item" :value="5">
|
||||||
</a-dropdown>
|
<div class="mold-icons mold-5"></div>
|
||||||
</div>
|
</a-doption>
|
||||||
|
<a-doption class="dropdown-item" :value="6">
|
||||||
|
<div class="mold-icons mold-6"></div>
|
||||||
|
</a-doption>
|
||||||
|
</template>
|
||||||
|
</a-dropdown>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" name="Mold" setup>
|
<script lang="ts" name="Mold" setup>
|
||||||
import { computed, nextTick, onMounted, ref } from 'vue';
|
import { computed, nextTick, onMounted, ref } from 'vue';
|
||||||
|
|
||||||
|
import useMinderStore from '@/store/modules/components/minder-editor';
|
||||||
|
|
||||||
import { moleProps } from '../../props';
|
import { moleProps } from '../../props';
|
||||||
|
|
||||||
const props = defineProps(moleProps);
|
const props = defineProps(moleProps);
|
||||||
|
@ -30,6 +37,7 @@
|
||||||
(e: 'moldChange', data: number): void;
|
(e: 'moldChange', data: number): void;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
|
const minderStore = useMinderStore();
|
||||||
const moldIndex = ref(0);
|
const moldIndex = ref(0);
|
||||||
|
|
||||||
const disabled = computed(() => {
|
const disabled = computed(() => {
|
||||||
|
@ -45,9 +53,10 @@
|
||||||
const templateList = computed(() => window.kityminder.Minder.getTemplateList());
|
const templateList = computed(() => window.kityminder.Minder.getTemplateList());
|
||||||
|
|
||||||
function handleCommand(value: string | number | Record<string, any> | undefined) {
|
function handleCommand(value: string | number | Record<string, any> | undefined) {
|
||||||
moldIndex.value = value as number;
|
moldIndex.value = (value as number) - 1;
|
||||||
window.minder.execCommand('template', Object.keys(templateList.value)[value as number]);
|
window.minder.execCommand('template', Object.keys(templateList.value)[(value as number) - 1]);
|
||||||
emit('moldChange', value as number);
|
minderStore.setMold((value as number) - 1);
|
||||||
|
emit('moldChange', (value as number) - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
@ -55,40 +64,19 @@
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less">
|
|
||||||
.toggle {
|
|
||||||
.arco-dropdown-list {
|
|
||||||
@apply grid grid-cols-2;
|
|
||||||
|
|
||||||
padding: 5px;
|
|
||||||
gap: 5px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
|
:deep(.arco-dropdown-list) {
|
||||||
|
@apply grid grid-cols-2;
|
||||||
|
}
|
||||||
.dropdown-toggle .mold-icons,
|
.dropdown-toggle .mold-icons,
|
||||||
.mold-icons {
|
.mold-icons {
|
||||||
background-image: url('@/assets/images/minder/mold.png');
|
background-image: url('@/assets/images/minder/mold.png');
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
}
|
}
|
||||||
.mold-group {
|
.dropdown-item {
|
||||||
@apply relative flex items-center justify-center;
|
@apply flex items-center justify-center;
|
||||||
|
|
||||||
width: 80px;
|
height: 50px !important;
|
||||||
.dropdown-toggle {
|
|
||||||
@apply flex;
|
|
||||||
|
|
||||||
margin-top: 5px;
|
|
||||||
width: 50px;
|
|
||||||
height: 50px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.dropdown-link {
|
|
||||||
@apply absolute cursor-pointer;
|
|
||||||
|
|
||||||
right: 3px;
|
|
||||||
bottom: 2px;
|
|
||||||
}
|
}
|
||||||
.mold-loop(@i) when (@i > 0) {
|
.mold-loop(@i) when (@i > 0) {
|
||||||
.mold-@{i} {
|
.mold-@{i} {
|
||||||
|
@ -96,7 +84,7 @@
|
||||||
|
|
||||||
margin-top: 5px;
|
margin-top: 5px;
|
||||||
width: 50px;
|
width: 50px;
|
||||||
height: 50px;
|
height: 45px;
|
||||||
background-position: (1 - @i) * 50px 0;
|
background-position: (1 - @i) * 50px 0;
|
||||||
}
|
}
|
||||||
.mold-loop(@i - 1);
|
.mold-loop(@i - 1);
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
:priority-start-with-zero="props.priorityStartWithZero"
|
:priority-start-with-zero="props.priorityStartWithZero"
|
||||||
:tags="props.tags"
|
:tags="props.tags"
|
||||||
:move-enable="props.moveEnable"
|
:move-enable="props.moveEnable"
|
||||||
|
:move-confirm="props.moveConfirm"
|
||||||
:tag-edit-check="props.tagEditCheck"
|
:tag-edit-check="props.tagEditCheck"
|
||||||
:tag-disable-check="props.tagDisableCheck"
|
:tag-disable-check="props.tagDisableCheck"
|
||||||
:priority-disable-check="props.priorityDisableCheck"
|
:priority-disable-check="props.priorityDisableCheck"
|
||||||
|
@ -26,6 +27,7 @@
|
||||||
:sequence-enable="props.sequenceEnable"
|
:sequence-enable="props.sequenceEnable"
|
||||||
:tag-enable="props.tagEnable"
|
:tag-enable="props.tagEnable"
|
||||||
:move-enable="props.moveEnable"
|
:move-enable="props.moveEnable"
|
||||||
|
:move-confirm="props.moveConfirm"
|
||||||
:progress-enable="props.progressEnable"
|
:progress-enable="props.progressEnable"
|
||||||
:import-json="props.importJson"
|
:import-json="props.importJson"
|
||||||
:height="props.height"
|
:height="props.height"
|
||||||
|
@ -38,6 +40,7 @@
|
||||||
:priority-start-with-zero="props.priorityStartWithZero"
|
:priority-start-with-zero="props.priorityStartWithZero"
|
||||||
@after-mount="emit('afterMount')"
|
@after-mount="emit('afterMount')"
|
||||||
@save="save"
|
@save="save"
|
||||||
|
@enter-node="handleEnterNode"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -54,6 +57,8 @@
|
||||||
(e: 'moldChange', data: number): void;
|
(e: 'moldChange', data: number): void;
|
||||||
(e: 'save', data: Record<string, any>): void;
|
(e: 'save', data: Record<string, any>): void;
|
||||||
(e: 'afterMount'): void;
|
(e: 'afterMount'): void;
|
||||||
|
(e: 'enterNode', data: any): void;
|
||||||
|
(e: 'nodeClick', data: any): void;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
|
@ -73,7 +78,28 @@
|
||||||
function handleMoldChange(data: number) {
|
function handleMoldChange(data: number) {
|
||||||
emit('moldChange', data);
|
emit('moldChange', data);
|
||||||
}
|
}
|
||||||
|
|
||||||
function save(data: Record<string, any>) {
|
function save(data: Record<string, any>) {
|
||||||
emit('save', data);
|
emit('save', data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function handleEnterNode(data: any) {
|
||||||
|
emit('enterNode', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
nextTick(() => {
|
||||||
|
if (window.minder.on) {
|
||||||
|
window.minder.on('mousedown', (e: any) => {
|
||||||
|
if (e.originEvent.button === 0) {
|
||||||
|
// 鼠标左键点击
|
||||||
|
const selectedNode = window.minder.getSelectedNode();
|
||||||
|
if (Object.keys(window.minder).length > 0 && selectedNode) {
|
||||||
|
emit('nodeClick', selectedNode.data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -7,25 +7,9 @@ export const mainEditorProps = {
|
||||||
type: Object,
|
type: Object,
|
||||||
default() {
|
default() {
|
||||||
return {
|
return {
|
||||||
root: {
|
root: {},
|
||||||
data: {
|
|
||||||
text: 'test111',
|
|
||||||
},
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
data: {
|
|
||||||
text: '地图',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
data: {
|
|
||||||
text: '百科',
|
|
||||||
expandState: 'collapse',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
template: 'default',
|
template: 'default',
|
||||||
|
treePath: [] as any[],
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -95,6 +79,10 @@ export const editMenuProps = {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: true,
|
default: true,
|
||||||
},
|
},
|
||||||
|
moveConfirm: {
|
||||||
|
type: Function,
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export const moleProps = {
|
export const moleProps = {
|
||||||
|
|
|
@ -16,20 +16,20 @@ const MimeType = () => {
|
||||||
'\uFFFF': 'application/km',
|
'\uFFFF': 'application/km',
|
||||||
};
|
};
|
||||||
|
|
||||||
function getSpitor(): string {
|
function getSplitor(): string {
|
||||||
return SPLITOR;
|
return SPLITOR;
|
||||||
}
|
}
|
||||||
|
|
||||||
function isPureText(text: string): boolean {
|
function isPureText(text: string): boolean {
|
||||||
// eslint-disable-next-line no-bitwise
|
// eslint-disable-next-line no-bitwise
|
||||||
return !~text.indexOf(getSpitor());
|
return !~text.indexOf(getSplitor());
|
||||||
}
|
}
|
||||||
|
|
||||||
function getPureText(text: string): string {
|
function getPureText(text: string): string {
|
||||||
if (isPureText(text)) {
|
if (isPureText(text)) {
|
||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
return text.split(getSpitor())[1];
|
return text.split(getSplitor())[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
function getMimeType(sign?: string): MimeTypes | string | null {
|
function getMimeType(sign?: string): MimeTypes | string | null {
|
||||||
|
@ -43,7 +43,7 @@ const MimeType = () => {
|
||||||
if (isPureText(text)) {
|
if (isPureText(text)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return getMimeType(text.split(getSpitor())[0]);
|
return getMimeType(text.split(getSplitor())[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
function process(mimetype: string | false, text: string): string {
|
function process(mimetype: string | false, text: string): string {
|
||||||
|
@ -84,8 +84,12 @@ const MimeType = () => {
|
||||||
return {
|
return {
|
||||||
registerMimeTypeProtocol,
|
registerMimeTypeProtocol,
|
||||||
getMimeTypeProtocol,
|
getMimeTypeProtocol,
|
||||||
getSpitor,
|
getSplitor,
|
||||||
getMimeType,
|
getMimeType,
|
||||||
|
whichMimeType,
|
||||||
|
process,
|
||||||
|
getPureText,
|
||||||
|
isPureText,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -13,10 +13,6 @@ interface IData {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ICliboardEvent extends ClipboardEvent {
|
|
||||||
clipboardData: DataTransfer;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function ClipboardRuntime(this: any) {
|
export default function ClipboardRuntime(this: any) {
|
||||||
const { minder } = this;
|
const { minder } = this;
|
||||||
const { receiver } = this;
|
const { receiver } = this;
|
||||||
|
@ -38,11 +34,10 @@ export default function ClipboardRuntime(this: any) {
|
||||||
return kmencode(Data.getRegisterProtocol('json').encode(_nodes));
|
return kmencode(Data.getRegisterProtocol('json').encode(_nodes));
|
||||||
}
|
}
|
||||||
|
|
||||||
const beforeCopy = (e: ICliboardEvent) => {
|
const beforeCopy = (e: ClipboardEvent) => {
|
||||||
if (document.activeElement === receiver.element) {
|
if (document.activeElement === receiver.element) {
|
||||||
const clipBoardEvent = e;
|
const clipBoardEvent = e;
|
||||||
const state = this.fsm.state();
|
const state = this.fsm.state();
|
||||||
|
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case 'input': {
|
case 'input': {
|
||||||
break;
|
break;
|
||||||
|
@ -80,7 +75,7 @@ export default function ClipboardRuntime(this: any) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const str = encode(nodes);
|
const str = encode(nodes);
|
||||||
clipBoardEvent.clipboardData.setData('text/plain', str);
|
clipBoardEvent.clipboardData?.setData('text/plain', str);
|
||||||
}
|
}
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
break;
|
break;
|
||||||
|
@ -193,7 +188,7 @@ export default function ClipboardRuntime(this: any) {
|
||||||
* @Editor: Naixor
|
* @Editor: Naixor
|
||||||
* @Date: 2015.9.24
|
* @Date: 2015.9.24
|
||||||
*/
|
*/
|
||||||
document.addEventListener('copy', () => beforeCopy);
|
document.addEventListener('copy', (e) => beforeCopy(e));
|
||||||
document.addEventListener('cut', () => beforeCut);
|
document.addEventListener('cut', (e) => beforeCut(e));
|
||||||
document.addEventListener('paste', () => beforePaste);
|
document.addEventListener('paste', (e) => beforePaste(e));
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,7 +51,7 @@ class FSM {
|
||||||
}
|
}
|
||||||
|
|
||||||
const oldState = this.currentState;
|
const oldState = this.currentState;
|
||||||
const notify = [oldState, newState].concat([].slice.call(args, 1));
|
const notify = [oldState, newState].concat([reason, args[0]]);
|
||||||
let i;
|
let i;
|
||||||
let handler;
|
let handler;
|
||||||
|
|
||||||
|
@ -67,7 +67,6 @@ class FSM {
|
||||||
|
|
||||||
this.currentState = newState;
|
this.currentState = newState;
|
||||||
this.debug.log('[{0}] {1} -> {2}', reason, oldState, newState);
|
this.debug.log('[{0}] {1} -> {2}', reason, oldState, newState);
|
||||||
|
|
||||||
// 跳转后
|
// 跳转后
|
||||||
for (i = 0; i < this.handlers.length; i++) {
|
for (i = 0; i < this.handlers.length; i++) {
|
||||||
handler = this.handlers[i];
|
handler = this.handlers[i];
|
||||||
|
@ -99,8 +98,9 @@ class FSM {
|
||||||
* * to - 跳转后的状态
|
* * to - 跳转后的状态
|
||||||
* * reason - 跳转的原因
|
* * reason - 跳转的原因
|
||||||
*/
|
*/
|
||||||
public when(condition: string, handler: Handler | string): void {
|
public when(...args: any[]): void {
|
||||||
if (arguments.length === 1) {
|
let [condition, handler] = args;
|
||||||
|
if (args.length === 1) {
|
||||||
handler = condition;
|
handler = condition;
|
||||||
condition = '* -> *';
|
condition = '* -> *';
|
||||||
}
|
}
|
||||||
|
@ -138,8 +138,8 @@ class FSM {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function FSMRumtime(this: any) {
|
function FSMRuntime(this: any) {
|
||||||
this.fsm = new FSM('normal');
|
this.fsm = new FSM('normal');
|
||||||
}
|
}
|
||||||
|
|
||||||
export default FSMRumtime;
|
export default FSMRuntime;
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
import useMinderStore from '@/store/modules/components/minder-editor';
|
||||||
|
|
||||||
interface Position {
|
interface Position {
|
||||||
x: number;
|
x: number;
|
||||||
y: number;
|
y: number;
|
||||||
|
@ -10,10 +12,11 @@ function HotboxRuntime(this: any) {
|
||||||
const { container } = this;
|
const { container } = this;
|
||||||
const { HotBox } = window;
|
const { HotBox } = window;
|
||||||
const hotbox = new HotBox(container);
|
const hotbox = new HotBox(container);
|
||||||
|
const minderStore = useMinderStore();
|
||||||
|
|
||||||
hotbox.setParentFSM(fsm);
|
hotbox.setParentFSM(fsm);
|
||||||
|
|
||||||
fsm.when('normal -> hotbox', () => {
|
function handleHotBoxShow() {
|
||||||
const node = minder.getSelectedNode();
|
const node = minder.getSelectedNode();
|
||||||
let position: Position | undefined;
|
let position: Position | undefined;
|
||||||
if (node) {
|
if (node) {
|
||||||
|
@ -22,18 +25,46 @@ function HotboxRuntime(this: any) {
|
||||||
x: box.cx,
|
x: box.cx,
|
||||||
y: box.cy,
|
y: box.cy,
|
||||||
};
|
};
|
||||||
|
minderStore.dispatchEvent('hotbox', position, node.rc.node);
|
||||||
}
|
}
|
||||||
hotbox.active('main', position);
|
}
|
||||||
|
|
||||||
|
fsm.when('normal -> hotbox', () => {
|
||||||
|
handleHotBoxShow();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
fsm.when('hotbox -> hotbox', () => {
|
||||||
|
handleHotBoxShow();
|
||||||
|
});
|
||||||
|
|
||||||
|
function handleShortcut(e: any) {
|
||||||
|
// 检查是否按下Ctrl键(Windows和Linux)或Command键(Mac)
|
||||||
|
const isCtrlKey = e.ctrlKey || e.metaKey;
|
||||||
|
// 检查是否按下Enter键
|
||||||
|
const isEnterKey = e.key === 'Enter';
|
||||||
|
// 检查是否同时按下Ctrl(或Command)和Enter键
|
||||||
|
if (isCtrlKey && isEnterKey) {
|
||||||
|
// 处理Ctrl+Enter组合键事件
|
||||||
|
e.preventDefault(); // 阻止默认行为
|
||||||
|
// 执行进入模块方法
|
||||||
|
const node = minder.getSelectedNode();
|
||||||
|
let position: Position | undefined;
|
||||||
|
if (node) {
|
||||||
|
const box = node.getRenderBox();
|
||||||
|
position = {
|
||||||
|
x: box.cx,
|
||||||
|
y: box.cy,
|
||||||
|
};
|
||||||
|
minderStore.dispatchEvent('enterNode', position, node.rc.node, node.data);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
minder.dispatchKeyEvent(e);
|
||||||
|
}
|
||||||
|
|
||||||
fsm.when('normal -> normal', (exit: any, enter: any, reason: any, e: any) => {
|
fsm.when('normal -> normal', (exit: any, enter: any, reason: any, e: any) => {
|
||||||
if (reason === 'shortcut-handle') {
|
if (reason === 'shortcut-handle') {
|
||||||
const handleResult = hotbox.dispatch(e);
|
handleShortcut(e);
|
||||||
if (handleResult) {
|
|
||||||
e.preventDefault();
|
|
||||||
} else {
|
|
||||||
minder.dispatchKeyEvent(e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -65,7 +65,6 @@ function isIntendToInput(e: KeyboardEvent): boolean {
|
||||||
function JumpingRuntime(this: IJumpingRuntime): void {
|
function JumpingRuntime(this: IJumpingRuntime): void {
|
||||||
const { fsm, minder, receiver, container, hotbox } = this;
|
const { fsm, minder, receiver, container, hotbox } = this;
|
||||||
const receiverElement = receiver.element;
|
const receiverElement = receiver.element;
|
||||||
|
|
||||||
// normal -> *
|
// normal -> *
|
||||||
receiver.listen('normal', (e: KeyboardEvent) => {
|
receiver.listen('normal', (e: KeyboardEvent) => {
|
||||||
// 为了防止处理进入edit模式而丢失处理的首字母,此时receiver必须为enable
|
// 为了防止处理进入edit模式而丢失处理的首字母,此时receiver必须为enable
|
||||||
|
@ -141,6 +140,7 @@ function JumpingRuntime(this: IJumpingRuntime): void {
|
||||||
/// ///////////////////////////////////////////
|
/// ///////////////////////////////////////////
|
||||||
let downX: number;
|
let downX: number;
|
||||||
let downY: number;
|
let downY: number;
|
||||||
|
const MOUSE_LB = 1; // 左键
|
||||||
const MOUSE_RB = 2; // 右键
|
const MOUSE_RB = 2; // 右键
|
||||||
|
|
||||||
container.addEventListener(
|
container.addEventListener(
|
||||||
|
@ -149,10 +149,10 @@ function JumpingRuntime(this: IJumpingRuntime): void {
|
||||||
if (e.button === MOUSE_RB) {
|
if (e.button === MOUSE_RB) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
}
|
}
|
||||||
if (fsm.state() === 'hotbox') {
|
|
||||||
hotbox.active(HotBox.STATE_IDLE);
|
if (fsm.state() === 'hotbox' && e.button === MOUSE_LB) {
|
||||||
fsm.jump('normal', 'blur');
|
fsm.jump('normal', 'blur');
|
||||||
} else if (fsm.state() === 'normal' && e.button === MOUSE_RB) {
|
} else if (e.button === MOUSE_RB) {
|
||||||
downX = e.clientX;
|
downX = e.clientX;
|
||||||
downY = e.clientY;
|
downY = e.clientY;
|
||||||
}
|
}
|
||||||
|
@ -164,7 +164,6 @@ function JumpingRuntime(this: IJumpingRuntime): void {
|
||||||
'mousewheel',
|
'mousewheel',
|
||||||
() => {
|
() => {
|
||||||
if (fsm.state() === 'hotbox') {
|
if (fsm.state() === 'hotbox') {
|
||||||
hotbox.active(HotBox.STATE_IDLE);
|
|
||||||
fsm.jump('normal', 'mousemove-blur');
|
fsm.jump('normal', 'mousemove-blur');
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -178,14 +177,14 @@ function JumpingRuntime(this: IJumpingRuntime): void {
|
||||||
container.addEventListener(
|
container.addEventListener(
|
||||||
'mouseup',
|
'mouseup',
|
||||||
(e) => {
|
(e) => {
|
||||||
if (fsm.state() !== 'normal') {
|
if (fsm.state() !== 'normal' && e.button === MOUSE_LB) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (e.button !== MOUSE_RB || e.clientX !== downX || e.clientY !== downY) {
|
if (e.button !== MOUSE_RB || e.clientX !== downX || e.clientY !== downY) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!minder.getSelectedNode()) {
|
if (!minder.getSelectedNode()) {
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
fsm.jump('hotbox', 'content-menu');
|
fsm.jump('hotbox', 'content-menu');
|
||||||
},
|
},
|
||||||
|
|
|
@ -50,6 +50,13 @@ export default function NodeRuntime(this: { minder: any; hotbox: any; editText:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
markDeleteNode(minder);
|
markDeleteNode(minder);
|
||||||
|
} else if (command.indexOf('ArrangeUp') > -1 || command.indexOf('ArrangeDown') > -1) {
|
||||||
|
if (
|
||||||
|
!window.minderProps.moveEnable ||
|
||||||
|
(window.minderProps.moveConfirm && !window.minderProps.moveConfirm())
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
minder.execCommand(command);
|
minder.execCommand(command);
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,33 +11,7 @@ function ReceiverRuntime(this: any) {
|
||||||
|
|
||||||
// 侦听器,接收到的事件会派发给所有侦听器
|
// 侦听器,接收到的事件会派发给所有侦听器
|
||||||
// eslint-disable-next-line no-unused-vars
|
// eslint-disable-next-line no-unused-vars
|
||||||
const listeners: ((event: KeyboardEvent) => boolean)[] = [];
|
const listeners: (((event: KeyboardEvent) => boolean) | string)[] = [];
|
||||||
|
|
||||||
const dispatchKeyEvent = (e: KeyboardEvent) => {
|
|
||||||
(e as any).is = (keyExpression: string) => {
|
|
||||||
const subs = keyExpression.split('|');
|
|
||||||
for (let i = 0; i < subs.length; i++) {
|
|
||||||
if (key.is(this, subs[i])) return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
let listener;
|
|
||||||
for (let i = 0; i < listeners.length; i++) {
|
|
||||||
listener = listeners[i];
|
|
||||||
// 忽略不在侦听状态的侦听器
|
|
||||||
if ((listener as any).notifyState !== '*' && (listener as any).notifyState !== this.fsm.state()) {
|
|
||||||
// eslint-disable-next-line no-continue
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (listener.call(null, e)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
element.onkeydown = element.onkeypress = element.onkeyup = dispatchKeyEvent;
|
|
||||||
this.container.appendChild(element);
|
|
||||||
|
|
||||||
interface Receiver {
|
interface Receiver {
|
||||||
element: HTMLDivElement;
|
element: HTMLDivElement;
|
||||||
|
@ -48,7 +22,7 @@ function ReceiverRuntime(this: any) {
|
||||||
// eslint-disable-next-line no-unused-vars
|
// eslint-disable-next-line no-unused-vars
|
||||||
onblur(handler: (event: FocusEvent) => void): void;
|
onblur(handler: (event: FocusEvent) => void): void;
|
||||||
// eslint-disable-next-line no-unused-vars
|
// eslint-disable-next-line no-unused-vars
|
||||||
listen?(state: string, listener: (event: KeyboardEvent) => boolean): void;
|
listen?(state: string, listener: ((event: KeyboardEvent) => boolean) | string): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
// receiver 对象
|
// receiver 对象
|
||||||
|
@ -76,11 +50,47 @@ function ReceiverRuntime(this: any) {
|
||||||
element.blur();
|
element.blur();
|
||||||
element.focus();
|
element.focus();
|
||||||
},
|
},
|
||||||
// eslint-disable-next-line no-unused-vars
|
|
||||||
onblur(handler: (event: FocusEvent) => void) {
|
onblur(handler: (event: FocusEvent) => void) {
|
||||||
element.onblur = handler;
|
element.onblur = handler;
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 侦听指定状态下的事件,如果不传 state,侦听所有状态
|
||||||
|
receiver.listen = (...args) => {
|
||||||
|
let [state, listener] = args;
|
||||||
|
if (args.length <= 1) {
|
||||||
|
listener = state;
|
||||||
|
state = '*';
|
||||||
|
}
|
||||||
|
(listener as any).notifyState = state;
|
||||||
|
listeners.push(listener as any);
|
||||||
|
};
|
||||||
|
|
||||||
|
const dispatchKeyEvent = (e: KeyboardEvent) => {
|
||||||
|
(e as any).is = (keyExpression: string) => {
|
||||||
|
const subs = keyExpression.split('|');
|
||||||
|
for (let i = 0; i < subs.length; i++) {
|
||||||
|
if (key.is(this, subs[i])) return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
for (let i = 0; i < listeners.length; i++) {
|
||||||
|
const listener = listeners[i];
|
||||||
|
// 忽略不在侦听状态的侦听器
|
||||||
|
if ((listener as any).notifyState !== '*' && (listener as any).notifyState !== this.fsm.state()) {
|
||||||
|
// eslint-disable-next-line no-continue
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof listener === 'function' && listener.call(null, e)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
element.onkeydown = element.onkeypress = element.onkeyup = dispatchKeyEvent;
|
||||||
|
this.container.appendChild(element);
|
||||||
|
|
||||||
receiver.selectAll();
|
receiver.selectAll();
|
||||||
this.minder.on('beforemousedown', receiver.selectAll);
|
this.minder.on('beforemousedown', receiver.selectAll);
|
||||||
this.minder.on('receiverfocus', receiver.selectAll);
|
this.minder.on('receiverfocus', receiver.selectAll);
|
||||||
|
@ -91,22 +101,6 @@ function ReceiverRuntime(this: any) {
|
||||||
window.editor.hotbox.$container.removeChild(window.editor.hotbox.$element);
|
window.editor.hotbox.$container.removeChild(window.editor.hotbox.$element);
|
||||||
});
|
});
|
||||||
|
|
||||||
// 侦听指定状态下的事件,如果不传 state,侦听所有状态
|
|
||||||
// eslint-disable-next-line no-unused-vars
|
|
||||||
receiver.listen = (state: string, listener: ((event: KeyboardEvent) => boolean) | string) => {
|
|
||||||
if (arguments.length === 1) {
|
|
||||||
// eslint-disable-next-line no-param-reassign
|
|
||||||
listener = state;
|
|
||||||
// eslint-disable-next-line no-param-reassign
|
|
||||||
state = '*';
|
|
||||||
}
|
|
||||||
// eslint-disable-next-line no-param-reassign
|
|
||||||
if (typeof listener === 'function') {
|
|
||||||
(listener as any).notifyState = state;
|
|
||||||
}
|
|
||||||
listeners.push(listener as any);
|
|
||||||
};
|
|
||||||
|
|
||||||
this.receiver = receiver as any;
|
this.receiver = receiver as any;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -92,7 +92,7 @@
|
||||||
|
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
import { useTableStore } from '@/store';
|
import { useTableStore } from '@/store';
|
||||||
import { TableOpenDetailMode } from '@/store/modules/ms-table/types';
|
import { TableOpenDetailMode } from '@/store/modules/components/ms-table/types';
|
||||||
|
|
||||||
import { MsTableColumn } from './type';
|
import { MsTableColumn } from './type';
|
||||||
import Draggable from 'vuedraggable';
|
import Draggable from 'vuedraggable';
|
||||||
|
@ -219,3 +219,4 @@
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@/store/modules/components/ms-table/types
|
||||||
|
|
|
@ -4,7 +4,7 @@ import localforage from 'localforage';
|
||||||
import { MsTableColumn, MsTableColumnData } from '@/components/pure/ms-table/type';
|
import { MsTableColumn, MsTableColumnData } from '@/components/pure/ms-table/type';
|
||||||
|
|
||||||
import { useAppStore } from '@/store';
|
import { useAppStore } from '@/store';
|
||||||
import { PageSizeMap, SelectorColumnMap, TableOpenDetailMode } from '@/store/modules/ms-table/types';
|
import { PageSizeMap, SelectorColumnMap, TableOpenDetailMode } from '@/store/modules/components/ms-table/types';
|
||||||
import { isArraysEqualWithOrder } from '@/utils/equal';
|
import { isArraysEqualWithOrder } from '@/utils/equal';
|
||||||
|
|
||||||
import { SpecialColumnEnum } from '@/enums/tableEnum';
|
import { SpecialColumnEnum } from '@/enums/tableEnum';
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
export default {
|
export default {
|
||||||
'common.pleaseSelectMember': 'Please select member',
|
'common.pleaseSelectMember': 'Please select a member',
|
||||||
'common.add': 'Add',
|
'common.add': 'Add',
|
||||||
'common.saveAndContinue': 'Save & Continue',
|
'common.saveAndContinue': 'Save & continue',
|
||||||
'common.edit': 'Edit',
|
'common.edit': 'Edit',
|
||||||
'common.delete': 'Delete',
|
'common.delete': 'Delete',
|
||||||
'common.save': 'Save',
|
'common.save': 'Save',
|
||||||
|
@ -17,6 +17,23 @@ export default {
|
||||||
'common.close': 'Close',
|
'common.close': 'Close',
|
||||||
'common.create': 'Create',
|
'common.create': 'Create',
|
||||||
'common.update': 'Update',
|
'common.update': 'Update',
|
||||||
|
'common.all': 'All',
|
||||||
|
'common.operation': 'Operation',
|
||||||
|
'common.remove': 'Remove',
|
||||||
|
'common.revoked': 'Revoked',
|
||||||
|
'common.createSuccess': 'Create success',
|
||||||
|
'common.createFailed': 'Create failed',
|
||||||
|
'common.updateSuccess': 'Update success',
|
||||||
|
'common.updateFailed': 'Update failed',
|
||||||
|
'common.deleteConfirm': 'Delete confirm',
|
||||||
|
'common.deleteSuccess': 'Delete success',
|
||||||
|
'common.deleteFailed': 'Delete failed',
|
||||||
|
'common.addSuccess': 'Added successfully',
|
||||||
|
'common.addFailed': 'Add failed',
|
||||||
|
'common.editSuccess': 'Edit success',
|
||||||
|
'common.editFailed': 'Edit failed',
|
||||||
|
'common.saveSuccess': 'Save success',
|
||||||
|
'common.saveFailed': 'Save failed',
|
||||||
'common.confirmEnable': 'Confirm enable',
|
'common.confirmEnable': 'Confirm enable',
|
||||||
'common.confirmDisable': 'Confirm disable',
|
'common.confirmDisable': 'Confirm disable',
|
||||||
'common.confirmClose': 'Confirm close',
|
'common.confirmClose': 'Confirm close',
|
||||||
|
@ -25,21 +42,6 @@ export default {
|
||||||
'common.enableFailed': 'Enable failed',
|
'common.enableFailed': 'Enable failed',
|
||||||
'common.closeSuccess': 'Close success',
|
'common.closeSuccess': 'Close success',
|
||||||
'common.closeFailed': 'Close failed',
|
'common.closeFailed': 'Close failed',
|
||||||
'common.updateSuccess': 'Update success',
|
|
||||||
'common.updateFailed': 'Update failed',
|
|
||||||
'common.all': 'All',
|
|
||||||
'common.operation': 'Operation',
|
|
||||||
'common.remove': 'Remove',
|
|
||||||
'common.revoked': 'Revoked',
|
|
||||||
'common.deleteConfirm': 'Confirm delete?',
|
|
||||||
'common.deleteSuccess': 'Delete success',
|
|
||||||
'common.deleteFailed': 'Delete failed',
|
|
||||||
'common.addSuccess': 'Add success',
|
|
||||||
'common.addFailed': 'Add failed',
|
|
||||||
'common.editSuccess': 'Edit success',
|
|
||||||
'common.editFailed': 'Edit failed',
|
|
||||||
'common.saveSuccess': 'Save success',
|
|
||||||
'common.saveFailed': 'Save failed',
|
|
||||||
'common.operationSuccess': 'Operation success',
|
'common.operationSuccess': 'Operation success',
|
||||||
'common.operationFailed': 'Operation failed',
|
'common.operationFailed': 'Operation failed',
|
||||||
'common.removeSuccess': 'Remove success',
|
'common.removeSuccess': 'Remove success',
|
||||||
|
@ -48,18 +50,20 @@ export default {
|
||||||
'common.revokeDelete': 'Revoke delete',
|
'common.revokeDelete': 'Revoke delete',
|
||||||
'common.revokeDeleteSuccess': 'Revoke delete success',
|
'common.revokeDeleteSuccess': 'Revoke delete success',
|
||||||
'common.unSaveLeaveTitle': 'Leave this page?',
|
'common.unSaveLeaveTitle': 'Leave this page?',
|
||||||
'common.unSaveLeaveContent': 'The system may not save your changes',
|
'common.unSaveLeaveContent': 'Your changes may not be saved',
|
||||||
'common.leave': 'Leave',
|
'common.leave': 'Leave',
|
||||||
'common.rename': 'Rename',
|
'common.rename': 'Rename',
|
||||||
'common.noData': 'No data',
|
'common.noData': 'No data',
|
||||||
'common.internal': 'Internal',
|
'common.internal': 'Internal',
|
||||||
'common.custom': 'Custom',
|
'common.custom': 'Custom',
|
||||||
'common.preview': 'Preview',
|
'common.preview': 'Preview',
|
||||||
'common.fullScreen': 'Full Screen',
|
'common.fullScreen': 'Full screen',
|
||||||
'common.offFullScreen': 'Exit',
|
'common.offFullScreen': 'Off full screen',
|
||||||
'common.allSelect': 'Select All',
|
'common.allSelect': 'All select',
|
||||||
'common.setting': 'Setting',
|
'common.setting': 'Setting',
|
||||||
'common.resetDefault': 'Restore default',
|
'common.resetDefault': 'Reset default',
|
||||||
'common.pleaseSelect': 'Please Select',
|
'common.tagPlaceholder': 'Add tag and press Enter to end',
|
||||||
'common.quickAddMember': 'Quick Add Member',
|
'common.batchModify': 'Batch Edit',
|
||||||
|
'common.pleaseSelect': 'please choose',
|
||||||
|
'common.quickAddMember': 'Quickly add members',
|
||||||
};
|
};
|
||||||
|
|
|
@ -35,10 +35,10 @@ function setI18nLanguage(locale: LocaleType) {
|
||||||
async function changeLocale(locale: LocaleType) {
|
async function changeLocale(locale: LocaleType) {
|
||||||
const globalI18n = i18n.global;
|
const globalI18n = i18n.global;
|
||||||
const currentLocale = unref(globalI18n.locale);
|
const currentLocale = unref(globalI18n.locale);
|
||||||
Message.loading(currentLocale === 'zh-CN' ? '语言切换中...' : 'Language switching...');
|
|
||||||
if (currentLocale === locale) {
|
if (currentLocale === locale) {
|
||||||
return locale;
|
return locale;
|
||||||
}
|
}
|
||||||
|
Message.loading(currentLocale === 'zh-CN' ? '语言切换中...' : 'Language switching...');
|
||||||
|
|
||||||
if (loadLocalePool.includes(locale)) {
|
if (loadLocalePool.includes(locale)) {
|
||||||
setI18nLanguage(locale);
|
setI18nLanguage(locale);
|
||||||
|
|
|
@ -4,11 +4,12 @@ import useTableStore from '@/hooks/useTableStore';
|
||||||
|
|
||||||
import useAppStore from './modules/app';
|
import useAppStore from './modules/app';
|
||||||
import useVisitStore from './modules/app/visit';
|
import useVisitStore from './modules/app/visit';
|
||||||
|
import useMinderStore from './modules/components/minder-editor';
|
||||||
import useUserStore from './modules/user';
|
import useUserStore from './modules/user';
|
||||||
import { debouncePlugin } from './plugins';
|
import { debouncePlugin } from './plugins';
|
||||||
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate';
|
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate';
|
||||||
|
|
||||||
const pinia = createPinia().use(debouncePlugin).use(piniaPluginPersistedstate);
|
const pinia = createPinia().use(debouncePlugin).use(piniaPluginPersistedstate);
|
||||||
|
|
||||||
export { useAppStore, useTableStore, useUserStore, useVisitStore };
|
export { useAppStore, useMinderStore, useTableStore, useUserStore, useVisitStore };
|
||||||
export default pinia;
|
export default pinia;
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
import { defineStore } from 'pinia';
|
||||||
|
|
||||||
|
import { MinderNodePosition, MinderState } from './types';
|
||||||
|
|
||||||
|
// 脑图组件的 store
|
||||||
|
const useMinderStore = defineStore('minder', {
|
||||||
|
state: (): MinderState => ({
|
||||||
|
event: {
|
||||||
|
name: '',
|
||||||
|
timestamp: 0,
|
||||||
|
nodePosition: {
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
},
|
||||||
|
nodeDom: undefined,
|
||||||
|
nodeData: undefined,
|
||||||
|
},
|
||||||
|
mold: 0,
|
||||||
|
}),
|
||||||
|
actions: {
|
||||||
|
dispatchEvent(name: string, position: MinderNodePosition, nodeDom?: HTMLElement, nodeData?: Record<string, any>) {
|
||||||
|
this.event = {
|
||||||
|
name,
|
||||||
|
timestamp: Date.now(),
|
||||||
|
nodePosition: position,
|
||||||
|
nodeDom,
|
||||||
|
nodeData,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
setMold(val: number) {
|
||||||
|
this.mold = val;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default useMinderStore;
|
|
@ -0,0 +1,17 @@
|
||||||
|
export interface MinderNodePosition {
|
||||||
|
x: number;
|
||||||
|
y: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface MinderEvent {
|
||||||
|
name: string;
|
||||||
|
timestamp: number;
|
||||||
|
nodePosition: MinderNodePosition;
|
||||||
|
nodeDom?: HTMLElement;
|
||||||
|
nodeData?: Record<string, any>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface MinderState {
|
||||||
|
event: MinderEvent;
|
||||||
|
mold: number;
|
||||||
|
}
|
|
@ -234,6 +234,32 @@ export function findNodeByKey<T>(trees: TreeNode<T>[], targetKey: string, custom
|
||||||
return null; // 如果在整个树形数组中都没有找到匹配的节点,则返回 null
|
return null; // 如果在整个树形数组中都没有找到匹配的节点,则返回 null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据 key 遍历树,并返回找到的节点路径和节点
|
||||||
|
*/
|
||||||
|
export function findNodePathByKey<T>(
|
||||||
|
tree: TreeNode<T>[],
|
||||||
|
targetKey: string,
|
||||||
|
dataKey?: string,
|
||||||
|
customKey = 'key'
|
||||||
|
): TreeNode<T> | null {
|
||||||
|
for (let i = 0; i < tree.length; i++) {
|
||||||
|
const node = tree[i];
|
||||||
|
if (dataKey ? node[dataKey]?.[customKey] === targetKey : node[customKey] === targetKey) {
|
||||||
|
return { ...node, treePath: [dataKey ? node[dataKey] : node] }; // 如果当前节点的 key 与目标 key 匹配,则返回当前节点
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Array.isArray(node.children) && node.children.length > 0) {
|
||||||
|
const result = findNodePathByKey(node.children, targetKey, dataKey, customKey); // 递归在子节点中查找
|
||||||
|
if (result) {
|
||||||
|
result.treePath.unshift(dataKey ? node[dataKey] : node);
|
||||||
|
return result; // 如果在子节点中找到了匹配的节点,则返回该节点
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* 找出俩数组之间的差异项并返回
|
* 找出俩数组之间的差异项并返回
|
||||||
* @param targetMap 目标项
|
* @param targetMap 目标项
|
||||||
|
|
|
@ -33,13 +33,23 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<FilterPanel v-show="isExpandFilter"></FilterPanel>
|
<FilterPanel v-show="isExpandFilter"></FilterPanel>
|
||||||
<MinderEditor :tags="['模块', '用例', '前置条件', '备注', '步骤', '预期结果']" tag-enable sequence-enable />
|
<MinderEditor
|
||||||
|
:import-json="importJson"
|
||||||
|
:tags="['模块', '用例', '前置条件', '备注', '步骤', '预期结果']"
|
||||||
|
tag-enable
|
||||||
|
sequence-enable
|
||||||
|
@node-click="handleNodeClick"
|
||||||
|
/>
|
||||||
|
<MsDrawer v-model:visible="visible" :width="480" :mask="false">
|
||||||
|
{{ nodeData.text }}
|
||||||
|
</MsDrawer>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
|
|
||||||
import MinderEditor from '@/components/pure/minder-editor/minderEditor.vue';
|
import MinderEditor from '@/components/pure/minder-editor/minderEditor.vue';
|
||||||
|
import MsDrawer from '@/components/pure/ms-drawer/index.vue';
|
||||||
import MsTag from '@/components/pure/ms-tag/ms-tag.vue';
|
import MsTag from '@/components/pure/ms-tag/ms-tag.vue';
|
||||||
import FilterPanel from '@/components/business/ms-filter-panel/searchForm.vue';
|
import FilterPanel from '@/components/business/ms-filter-panel/searchForm.vue';
|
||||||
|
|
||||||
|
@ -65,6 +75,62 @@
|
||||||
const isExpandFilterHandler = () => {
|
const isExpandFilterHandler = () => {
|
||||||
isExpandFilter.value = !isExpandFilter.value;
|
isExpandFilter.value = !isExpandFilter.value;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const visible = ref<boolean>(false);
|
||||||
|
const nodeData = ref<any>({});
|
||||||
|
|
||||||
|
const importJson = ref<any>({});
|
||||||
|
|
||||||
|
function handleNodeClick(data: any) {
|
||||||
|
if (data.resource && data.resource.includes('用例')) {
|
||||||
|
visible.value = true;
|
||||||
|
nodeData.value = data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onBeforeMount(() => {
|
||||||
|
importJson.value = {
|
||||||
|
root: {
|
||||||
|
data: {
|
||||||
|
text: '测试用例',
|
||||||
|
id: 'xxxx',
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
data: {
|
||||||
|
id: 'sdasdas',
|
||||||
|
text: '模块 1',
|
||||||
|
resource: ['模块'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
data: {
|
||||||
|
id: 'dasdasda',
|
||||||
|
text: '模块 2',
|
||||||
|
expandState: 'collapse',
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
data: {
|
||||||
|
id: 'frihofiuho3f',
|
||||||
|
text: '用例 1',
|
||||||
|
resource: ['用例'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
data: {
|
||||||
|
id: 'df09348f034f',
|
||||||
|
text: ' 用例 2',
|
||||||
|
resource: ['用例'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
template: 'default',
|
||||||
|
};
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="less">
|
<style scoped lang="less">
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
<template>
|
<template>
|
||||||
<a-spin v-if="!projectVersionStatus" :loading="loading" class="h-full w-full">
|
<a-spin v-if="!projectVersionStatus" :loading="loading" class="h-full w-full min-w-[930px]">
|
||||||
<div class="flex h-full flex-col items-center p-[24px]">
|
<div class="flex h-full flex-col items-center p-[24px]">
|
||||||
<div class="mt-[200px] text-[16px] font-medium text-[var(--color-text-1)]">
|
<div class="mt-[200px] text-[16px] font-medium text-[var(--color-text-1)]">
|
||||||
{{ t('project.projectVersion.version') }}
|
{{ t('project.projectVersion.version') }}
|
||||||
</div>
|
</div>
|
||||||
<div class="mt-[16px] text-[var(--color-text-4)]">{{ t('project.projectVersion.tip') }}</div>
|
<div class="mt-[16px] text-[var(--color-text-4)]">{{ t('project.projectVersion.tip') }}</div>
|
||||||
<div class="mt-[24px] flex justify-between gap-[16px]">
|
<div class="mt-[24px] grid grid-cols-3 gap-[16px]">
|
||||||
<div class="tip-card">
|
<div class="tip-card">
|
||||||
<img src="@/assets/images/project_assign.png" width="78" height="60" class="tip-icon" />
|
<img src="@/assets/images/project_assign.png" width="78" height="60" class="tip-icon" />
|
||||||
<div>
|
<div>
|
||||||
|
@ -61,8 +61,11 @@
|
||||||
<template #statusTitle>
|
<template #statusTitle>
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
{{ t('project.projectVersion.status') }}
|
{{ t('project.projectVersion.status') }}
|
||||||
<a-popover :title="t('project.projectVersion.statusTip')" position="right">
|
<a-popover position="rt">
|
||||||
<icon-info-circle class="ml-[4px] hover:text-[rgb(var(--primary-5))]" size="16" />
|
<icon-info-circle class="ml-[4px] hover:text-[rgb(var(--primary-5))]" size="16" />
|
||||||
|
<template #title>
|
||||||
|
<div class="w-[256px]"> {{ t('project.projectVersion.statusTip') }} </div>
|
||||||
|
</template>
|
||||||
<template #content>
|
<template #content>
|
||||||
<div class="mt-[12px] w-[256px] rounded-[var(--border-radius-small)] bg-[var(--color-text-n9)] p-[12px]">
|
<div class="mt-[12px] w-[256px] rounded-[var(--border-radius-small)] bg-[var(--color-text-n9)] p-[12px]">
|
||||||
<div class="statusTipContent">
|
<div class="statusTipContent">
|
||||||
|
@ -172,7 +175,7 @@
|
||||||
:on-before-ok="handleBeforeLatestModalOk"
|
:on-before-ok="handleBeforeLatestModalOk"
|
||||||
class="p-[4px]"
|
class="p-[4px]"
|
||||||
title-align="start"
|
title-align="start"
|
||||||
body-class="px-0 py-[8px]"
|
body-class="p-0"
|
||||||
:ok-text="t('common.confirmClose')"
|
:ok-text="t('common.confirmClose')"
|
||||||
:ok-button-props="{ status: 'danger' }"
|
:ok-button-props="{ status: 'danger' }"
|
||||||
@cancel="handleLatestModalCancel"
|
@cancel="handleLatestModalCancel"
|
||||||
|
@ -515,11 +518,11 @@
|
||||||
},
|
},
|
||||||
hideCancel: false,
|
hideCancel: false,
|
||||||
});
|
});
|
||||||
} else {
|
return false;
|
||||||
await toggleVersionStatus(record.id);
|
|
||||||
Message.success(t('project.projectVersion.open', { name: record.name }));
|
|
||||||
loadList();
|
|
||||||
}
|
}
|
||||||
|
await toggleVersionStatus(record.id);
|
||||||
|
Message.success(t('project.projectVersion.open', { name: record.name }));
|
||||||
|
loadList();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// eslint-disable-next-line no-console
|
// eslint-disable-next-line no-console
|
||||||
console.log(error);
|
console.log(error);
|
||||||
|
|
|
@ -14,7 +14,7 @@ export default {
|
||||||
'project.projectVersion.openVersionSuccess': 'Activated successfully',
|
'project.projectVersion.openVersionSuccess': 'Activated successfully',
|
||||||
'project.projectVersion.versionName': 'Version name',
|
'project.projectVersion.versionName': 'Version name',
|
||||||
'project.projectVersion.status': 'Status',
|
'project.projectVersion.status': 'Status',
|
||||||
'project.projectVersion.latest': 'Latest version',
|
'project.projectVersion.latest': 'Latest',
|
||||||
'project.projectVersion.publishTime': 'Release time',
|
'project.projectVersion.publishTime': 'Release time',
|
||||||
'project.projectVersion.createTime': 'Creation time',
|
'project.projectVersion.createTime': 'Creation time',
|
||||||
'project.projectVersion.creator': 'Creator',
|
'project.projectVersion.creator': 'Creator',
|
||||||
|
@ -34,4 +34,7 @@ export default {
|
||||||
'project.projectVersion.confirmCloseTipContent2': 'You can switch other versions to the latest version',
|
'project.projectVersion.confirmCloseTipContent2': 'You can switch other versions to the latest version',
|
||||||
'project.projectVersion.replaceVersionPlaceholder': 'Please select an alternative version',
|
'project.projectVersion.replaceVersionPlaceholder': 'Please select an alternative version',
|
||||||
'project.projectVersion.latestVersionDeleteTip': 'The latest version cannot be deleted',
|
'project.projectVersion.latestVersionDeleteTip': 'The latest version cannot be deleted',
|
||||||
|
'project.projectVersion.statusTip': 'After closing, the version information drop-down box will not be displayed.',
|
||||||
|
'project.projectVersion.versionInfo': 'Version information example',
|
||||||
|
'project.projectVersion.versionLatest': 'Latest',
|
||||||
};
|
};
|
||||||
|
|
|
@ -275,7 +275,10 @@
|
||||||
const type = ref(''); // 操作类型
|
const type = ref(''); // 操作类型
|
||||||
const _module = ref(''); // 操作对象
|
const _module = ref(''); // 操作对象
|
||||||
const content = ref(''); // 名称
|
const content = ref(''); // 名称
|
||||||
const time = ref<(Date | string | number)[]>([dayjs().subtract(1, 'M').valueOf(), dayjs().valueOf()]); // 操作时间
|
const time = ref<(Date | string | number)[]>([
|
||||||
|
dayjs().subtract(1, 'M').hour(0).minute(0).second(1).valueOf(),
|
||||||
|
dayjs().valueOf(),
|
||||||
|
]); // 操作时间
|
||||||
const selectedTime = ref<Date | string | number | undefined>(''); // 日期选择器选中但未确认的时间
|
const selectedTime = ref<Date | string | number | undefined>(''); // 日期选择器选中但未确认的时间
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in New Issue