feat(脑图): 脑图未保存提示

This commit is contained in:
baiqi 2024-06-11 11:12:26 +08:00 committed by 刘瑞斌
parent 5be3cf217d
commit 1db33454a0
8 changed files with 63 additions and 18 deletions

View File

@ -198,7 +198,7 @@
}
}
watchEffect(() => {
onMounted(() => {
initCaseTree();
});

View File

@ -9,4 +9,5 @@ export default {
'ms.minders.caseNameNotNull': 'Test Case Name cannot be empty',
'ms.minders.commentTotal': '{num} Comments in Total',
'ms.minders.text': 'Text',
'ms.minders.leaveUnsavedTip': 'The mind map has unsaved changes, are you sure you want to exit?',
};

View File

@ -9,4 +9,5 @@ export default {
'ms.minders.caseNameNotNull': '用例名称不能为空',
'ms.minders.commentTotal': '共 {num} 评论',
'ms.minders.text': '文本',
'ms.minders.leaveUnsavedTip': '脑图有未保存的更改,确认离开吗?',
};

View File

@ -27,6 +27,7 @@
import minderHeader from './header.vue';
import Navigator from './navigator.vue';
import useLeaveUnSaveTip from '@/hooks/useLeaveUnSaveTip';
import useMinderStore from '@/store/modules/components/minder-editor';
import { findNodePathByKey, replaceNodeInTree } from '@/utils';
@ -63,6 +64,11 @@
}>();
const minderStore = useMinderStore();
const { setIsSave } = useLeaveUnSaveTip({
leaveContent: 'ms.minders.leaveUnsavedTip',
leaveTitle: 'common.unSaveLeaveTitle',
tipType: 'warning',
});
const mec: Ref<HTMLDivElement | null> = ref(null);
const importJson = defineModel<MinderJson>('importJson', {
required: true,
@ -72,7 +78,6 @@
template: 'default',
treePath: [],
});
const minderUnsaved = ref(false);
function handlePriorityButton() {
const { priorityPrefix } = props;
@ -148,7 +153,7 @@
'zoomOut',
]);
if (selectNodes && !notChangeCommands.has(env.commandName.toLocaleLowerCase())) {
minderUnsaved.value = true;
minderStore.setMinderUnsaved(true);
minderStore.dispatchEvent(MinderEventName.MINDER_CHANGED);
selectNodes.forEach((node: MinderJsonNode) => {
markChangeNode(node);
@ -179,7 +184,7 @@
* @param node 切换的节点
*/
function switchNode(node: MinderJsonNode | MinderJsonNodeData) {
if (minderUnsaved.value) {
if (minderStore.minderUnsaved) {
//
replaceNodeInTree(
[importJson.value.root],
@ -232,10 +237,17 @@
data = window.minder.exportJson();
}
emit('save', data, () => {
minderUnsaved.value = false;
minderStore.setMinderUnsaved(false);
menuVisible.value = false;
});
}
watch(
() => minderStore.getMinderUnsaved,
(val) => {
setIsSave(!val);
}
);
</script>
<style lang="less">

View File

@ -13,7 +13,7 @@ export interface LeaveProps {
const leaveProps: LeaveProps = {
leaveTitle: 'common.unSaveLeaveTitle',
leaveContent: 'common.unSaveLeaveContent',
tipType: 'error',
tipType: 'warning',
};
// 离开页面确认提示

View File

@ -22,7 +22,13 @@ const useMinderStore = defineStore('minder', {
},
mold: 0,
clipboard: [],
minderUnsaved: false,
}),
getters: {
getMinderUnsaved(): boolean {
return this.minderUnsaved;
},
},
actions: {
/**
*
@ -56,6 +62,9 @@ const useMinderStore = defineStore('minder', {
setClipboard(nodes?: MinderJsonNode[]) {
this.clipboard = nodes || [];
},
setMinderUnsaved(val: boolean) {
this.minderUnsaved = val;
},
},
});

View File

@ -28,4 +28,5 @@ export interface MinderState {
event: MinderCustomEvent;
mold: number;
clipboard: MinderJsonNode[]; // 剪切板
minderUnsaved: boolean; // 脑图是否有未保存的内容
}

View File

@ -20,7 +20,7 @@
<a-radio value="list" class="show-type-icon !m-[2px]">
<MsIcon :size="14" type="icon-icon_view-list_outlined" />
</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" />
</a-radio>
</a-radio-group>
@ -191,11 +191,17 @@
</template>
</a-popover>
<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]">
<MsIcon :size="14" type="icon-icon_view-list_outlined" />
</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" />
</a-radio>
</a-radio-group>
@ -203,7 +209,7 @@
</div>
<div class="mt-[16px] h-[calc(100%-32px)] border-t border-[var(--color-text-n8)]">
<!-- 脑图开始 -->
<MsMinder
<MsFeatureCaseMinder
minder-type="FeatureCase"
:module-id="props.activeFolder"
:modules-count="props.modulesCount"
@ -313,10 +319,9 @@
import useTable from '@/components/pure/ms-table/useTable';
import MsTableMoreAction from '@/components/pure/ms-table-more-action/index.vue';
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 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 CaseDetailDrawer from './caseDetailDrawer.vue';
import FeatureCaseTree from './caseTree.vue';
@ -343,6 +348,7 @@
import useModal from '@/hooks/useModal';
import { useAppStore, useTableStore } from '@/store';
import useFeatureCaseStore from '@/store/modules/case/featureCase';
import useMinderStore from '@/store/modules/components/minder-editor';
import { characterLimit, findNodeByKey, findNodePathByKey, mapTree } from '@/utils';
import { hasAnyPermission } from '@/utils/permission';
@ -382,18 +388,33 @@
(e: 'import', type: 'Excel' | 'Xmind'): void;
}>();
const minderStore = useMinderStore();
const keyword = ref<string>('');
const filterRowCount = ref(0);
const groupKeyword = ref<string>('');
const showType = ref<string>('list');
const versionOptions = ref([
{
id: '1001',
name: 'v_1.0',
function handleShowTypeChange(val: string | number | boolean) {
if (minderStore.minderUnsaved && val === 'list') {
showType.value = 'minder';
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(() => {
return mapTree<ModuleTreeNode>(featureCaseStore.caseTree, (e) => {