feat(脑图): 脑图未保存提示
This commit is contained in:
parent
5be3cf217d
commit
1db33454a0
|
@ -198,7 +198,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
watchEffect(() => {
|
onMounted(() => {
|
||||||
initCaseTree();
|
initCaseTree();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -9,4 +9,5 @@ export default {
|
||||||
'ms.minders.caseNameNotNull': 'Test Case Name cannot be empty',
|
'ms.minders.caseNameNotNull': 'Test Case Name cannot be empty',
|
||||||
'ms.minders.commentTotal': '{num} Comments in Total',
|
'ms.minders.commentTotal': '{num} Comments in Total',
|
||||||
'ms.minders.text': 'Text',
|
'ms.minders.text': 'Text',
|
||||||
|
'ms.minders.leaveUnsavedTip': 'The mind map has unsaved changes, are you sure you want to exit?',
|
||||||
};
|
};
|
||||||
|
|
|
@ -9,4 +9,5 @@ export default {
|
||||||
'ms.minders.caseNameNotNull': '用例名称不能为空',
|
'ms.minders.caseNameNotNull': '用例名称不能为空',
|
||||||
'ms.minders.commentTotal': '共 {num} 评论',
|
'ms.minders.commentTotal': '共 {num} 评论',
|
||||||
'ms.minders.text': '文本',
|
'ms.minders.text': '文本',
|
||||||
|
'ms.minders.leaveUnsavedTip': '脑图有未保存的更改,确认离开吗?',
|
||||||
};
|
};
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
import minderHeader from './header.vue';
|
import minderHeader from './header.vue';
|
||||||
import Navigator from './navigator.vue';
|
import Navigator from './navigator.vue';
|
||||||
|
|
||||||
|
import useLeaveUnSaveTip from '@/hooks/useLeaveUnSaveTip';
|
||||||
import useMinderStore from '@/store/modules/components/minder-editor';
|
import useMinderStore from '@/store/modules/components/minder-editor';
|
||||||
import { findNodePathByKey, replaceNodeInTree } from '@/utils';
|
import { findNodePathByKey, replaceNodeInTree } from '@/utils';
|
||||||
|
|
||||||
|
@ -63,6 +64,11 @@
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const minderStore = useMinderStore();
|
const minderStore = useMinderStore();
|
||||||
|
const { setIsSave } = useLeaveUnSaveTip({
|
||||||
|
leaveContent: 'ms.minders.leaveUnsavedTip',
|
||||||
|
leaveTitle: 'common.unSaveLeaveTitle',
|
||||||
|
tipType: 'warning',
|
||||||
|
});
|
||||||
const mec: Ref<HTMLDivElement | null> = ref(null);
|
const mec: Ref<HTMLDivElement | null> = ref(null);
|
||||||
const importJson = defineModel<MinderJson>('importJson', {
|
const importJson = defineModel<MinderJson>('importJson', {
|
||||||
required: true,
|
required: true,
|
||||||
|
@ -72,7 +78,6 @@
|
||||||
template: 'default',
|
template: 'default',
|
||||||
treePath: [],
|
treePath: [],
|
||||||
});
|
});
|
||||||
const minderUnsaved = ref(false);
|
|
||||||
|
|
||||||
function handlePriorityButton() {
|
function handlePriorityButton() {
|
||||||
const { priorityPrefix } = props;
|
const { priorityPrefix } = props;
|
||||||
|
@ -148,7 +153,7 @@
|
||||||
'zoomOut',
|
'zoomOut',
|
||||||
]);
|
]);
|
||||||
if (selectNodes && !notChangeCommands.has(env.commandName.toLocaleLowerCase())) {
|
if (selectNodes && !notChangeCommands.has(env.commandName.toLocaleLowerCase())) {
|
||||||
minderUnsaved.value = true;
|
minderStore.setMinderUnsaved(true);
|
||||||
minderStore.dispatchEvent(MinderEventName.MINDER_CHANGED);
|
minderStore.dispatchEvent(MinderEventName.MINDER_CHANGED);
|
||||||
selectNodes.forEach((node: MinderJsonNode) => {
|
selectNodes.forEach((node: MinderJsonNode) => {
|
||||||
markChangeNode(node);
|
markChangeNode(node);
|
||||||
|
@ -179,7 +184,7 @@
|
||||||
* @param node 切换的节点
|
* @param node 切换的节点
|
||||||
*/
|
*/
|
||||||
function switchNode(node: MinderJsonNode | MinderJsonNodeData) {
|
function switchNode(node: MinderJsonNode | MinderJsonNodeData) {
|
||||||
if (minderUnsaved.value) {
|
if (minderStore.minderUnsaved) {
|
||||||
// 切换前,如果脑图未保存,先把更改的节点信息同步一次
|
// 切换前,如果脑图未保存,先把更改的节点信息同步一次
|
||||||
replaceNodeInTree(
|
replaceNodeInTree(
|
||||||
[importJson.value.root],
|
[importJson.value.root],
|
||||||
|
@ -232,10 +237,17 @@
|
||||||
data = window.minder.exportJson();
|
data = window.minder.exportJson();
|
||||||
}
|
}
|
||||||
emit('save', data, () => {
|
emit('save', data, () => {
|
||||||
minderUnsaved.value = false;
|
minderStore.setMinderUnsaved(false);
|
||||||
menuVisible.value = false;
|
menuVisible.value = false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => minderStore.getMinderUnsaved,
|
||||||
|
(val) => {
|
||||||
|
setIsSave(!val);
|
||||||
|
}
|
||||||
|
);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less">
|
<style lang="less">
|
||||||
|
|
|
@ -13,7 +13,7 @@ export interface LeaveProps {
|
||||||
const leaveProps: LeaveProps = {
|
const leaveProps: LeaveProps = {
|
||||||
leaveTitle: 'common.unSaveLeaveTitle',
|
leaveTitle: 'common.unSaveLeaveTitle',
|
||||||
leaveContent: 'common.unSaveLeaveContent',
|
leaveContent: 'common.unSaveLeaveContent',
|
||||||
tipType: 'error',
|
tipType: 'warning',
|
||||||
};
|
};
|
||||||
|
|
||||||
// 离开页面确认提示
|
// 离开页面确认提示
|
||||||
|
|
|
@ -22,7 +22,13 @@ const useMinderStore = defineStore('minder', {
|
||||||
},
|
},
|
||||||
mold: 0,
|
mold: 0,
|
||||||
clipboard: [],
|
clipboard: [],
|
||||||
|
minderUnsaved: false,
|
||||||
}),
|
}),
|
||||||
|
getters: {
|
||||||
|
getMinderUnsaved(): boolean {
|
||||||
|
return this.minderUnsaved;
|
||||||
|
},
|
||||||
|
},
|
||||||
actions: {
|
actions: {
|
||||||
/**
|
/**
|
||||||
* 脑图组件派发事件
|
* 脑图组件派发事件
|
||||||
|
@ -56,6 +62,9 @@ const useMinderStore = defineStore('minder', {
|
||||||
setClipboard(nodes?: MinderJsonNode[]) {
|
setClipboard(nodes?: MinderJsonNode[]) {
|
||||||
this.clipboard = nodes || [];
|
this.clipboard = nodes || [];
|
||||||
},
|
},
|
||||||
|
setMinderUnsaved(val: boolean) {
|
||||||
|
this.minderUnsaved = val;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -28,4 +28,5 @@ export interface MinderState {
|
||||||
event: MinderCustomEvent;
|
event: MinderCustomEvent;
|
||||||
mold: number;
|
mold: number;
|
||||||
clipboard: MinderJsonNode[]; // 剪切板
|
clipboard: MinderJsonNode[]; // 剪切板
|
||||||
|
minderUnsaved: boolean; // 脑图是否有未保存的内容
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
<a-radio value="list" class="show-type-icon !m-[2px]">
|
<a-radio value="list" class="show-type-icon !m-[2px]">
|
||||||
<MsIcon :size="14" type="icon-icon_view-list_outlined" />
|
<MsIcon :size="14" type="icon-icon_view-list_outlined" />
|
||||||
</a-radio>
|
</a-radio>
|
||||||
<a-radio value="xMind" class="show-type-icon !m-[2px]">
|
<a-radio value="minder" class="show-type-icon !m-[2px]">
|
||||||
<MsIcon :size="14" type="icon-icon_mindnote_outlined" />
|
<MsIcon :size="14" type="icon-icon_mindnote_outlined" />
|
||||||
</a-radio>
|
</a-radio>
|
||||||
</a-radio-group>
|
</a-radio-group>
|
||||||
|
@ -191,11 +191,17 @@
|
||||||
</template>
|
</template>
|
||||||
</a-popover>
|
</a-popover>
|
||||||
<div class="flex items-center gap-[12px]">
|
<div class="flex items-center gap-[12px]">
|
||||||
<a-radio-group v-model:model-value="showType" type="button" size="small" class="list-show-type">
|
<a-radio-group
|
||||||
|
v-model:model-value="showType"
|
||||||
|
type="button"
|
||||||
|
size="small"
|
||||||
|
class="list-show-type"
|
||||||
|
@change="handleShowTypeChange"
|
||||||
|
>
|
||||||
<a-radio value="list" class="show-type-icon !m-[2px]">
|
<a-radio value="list" class="show-type-icon !m-[2px]">
|
||||||
<MsIcon :size="14" type="icon-icon_view-list_outlined" />
|
<MsIcon :size="14" type="icon-icon_view-list_outlined" />
|
||||||
</a-radio>
|
</a-radio>
|
||||||
<a-radio value="xMind" class="show-type-icon !m-[2px]">
|
<a-radio value="minder" class="show-type-icon !m-[2px]">
|
||||||
<MsIcon :size="14" type="icon-icon_mindnote_outlined" />
|
<MsIcon :size="14" type="icon-icon_mindnote_outlined" />
|
||||||
</a-radio>
|
</a-radio>
|
||||||
</a-radio-group>
|
</a-radio-group>
|
||||||
|
@ -203,7 +209,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="mt-[16px] h-[calc(100%-32px)] border-t border-[var(--color-text-n8)]">
|
<div class="mt-[16px] h-[calc(100%-32px)] border-t border-[var(--color-text-n8)]">
|
||||||
<!-- 脑图开始 -->
|
<!-- 脑图开始 -->
|
||||||
<MsMinder
|
<MsFeatureCaseMinder
|
||||||
minder-type="FeatureCase"
|
minder-type="FeatureCase"
|
||||||
:module-id="props.activeFolder"
|
:module-id="props.activeFolder"
|
||||||
:modules-count="props.modulesCount"
|
:modules-count="props.modulesCount"
|
||||||
|
@ -313,10 +319,9 @@
|
||||||
import useTable from '@/components/pure/ms-table/useTable';
|
import useTable from '@/components/pure/ms-table/useTable';
|
||||||
import MsTableMoreAction from '@/components/pure/ms-table-more-action/index.vue';
|
import MsTableMoreAction from '@/components/pure/ms-table-more-action/index.vue';
|
||||||
import { ActionsItem } from '@/components/pure/ms-table-more-action/types';
|
import { ActionsItem } from '@/components/pure/ms-table-more-action/types';
|
||||||
import MsTag from '@/components/pure/ms-tag/ms-tag.vue';
|
|
||||||
import caseLevel from '@/components/business/ms-case-associate/caseLevel.vue';
|
import caseLevel from '@/components/business/ms-case-associate/caseLevel.vue';
|
||||||
import ExecuteStatusTag from '@/components/business/ms-case-associate/executeResult.vue';
|
import ExecuteStatusTag from '@/components/business/ms-case-associate/executeResult.vue';
|
||||||
import MsMinder from '@/components/business/ms-minders/index.vue';
|
import MsFeatureCaseMinder from '@/components/business/ms-minders/featureCaseMinder/index.vue';
|
||||||
import BatchEditModal from './batchEditModal.vue';
|
import BatchEditModal from './batchEditModal.vue';
|
||||||
import CaseDetailDrawer from './caseDetailDrawer.vue';
|
import CaseDetailDrawer from './caseDetailDrawer.vue';
|
||||||
import FeatureCaseTree from './caseTree.vue';
|
import FeatureCaseTree from './caseTree.vue';
|
||||||
|
@ -343,6 +348,7 @@
|
||||||
import useModal from '@/hooks/useModal';
|
import useModal from '@/hooks/useModal';
|
||||||
import { useAppStore, useTableStore } from '@/store';
|
import { useAppStore, useTableStore } from '@/store';
|
||||||
import useFeatureCaseStore from '@/store/modules/case/featureCase';
|
import useFeatureCaseStore from '@/store/modules/case/featureCase';
|
||||||
|
import useMinderStore from '@/store/modules/components/minder-editor';
|
||||||
import { characterLimit, findNodeByKey, findNodePathByKey, mapTree } from '@/utils';
|
import { characterLimit, findNodeByKey, findNodePathByKey, mapTree } from '@/utils';
|
||||||
import { hasAnyPermission } from '@/utils/permission';
|
import { hasAnyPermission } from '@/utils/permission';
|
||||||
|
|
||||||
|
@ -382,18 +388,33 @@
|
||||||
(e: 'import', type: 'Excel' | 'Xmind'): void;
|
(e: 'import', type: 'Excel' | 'Xmind'): void;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
|
const minderStore = useMinderStore();
|
||||||
|
|
||||||
const keyword = ref<string>('');
|
const keyword = ref<string>('');
|
||||||
const filterRowCount = ref(0);
|
const filterRowCount = ref(0);
|
||||||
const groupKeyword = ref<string>('');
|
const groupKeyword = ref<string>('');
|
||||||
|
|
||||||
const showType = ref<string>('list');
|
const showType = ref<string>('list');
|
||||||
|
|
||||||
const versionOptions = ref([
|
function handleShowTypeChange(val: string | number | boolean) {
|
||||||
{
|
if (minderStore.minderUnsaved && val === 'list') {
|
||||||
id: '1001',
|
showType.value = 'minder';
|
||||||
name: 'v_1.0',
|
openModal({
|
||||||
|
type: 'warning',
|
||||||
|
title: t('common.tip'),
|
||||||
|
content: t('ms.minders.leaveUnsavedTip'),
|
||||||
|
okText: t('common.confirm'),
|
||||||
|
cancelText: t('common.cancel'),
|
||||||
|
okButtonProps: {
|
||||||
|
status: 'normal',
|
||||||
},
|
},
|
||||||
]);
|
onBeforeOk: async () => {
|
||||||
|
showType.value = 'list';
|
||||||
|
},
|
||||||
|
hideCancel: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const caseTreeData = computed(() => {
|
const caseTreeData = computed(() => {
|
||||||
return mapTree<ModuleTreeNode>(featureCaseStore.caseTree, (e) => {
|
return mapTree<ModuleTreeNode>(featureCaseStore.caseTree, (e) => {
|
||||||
|
|
Loading…
Reference in New Issue