feat: 文件管理文本编辑后退出前保存提示 (#5636)

#### What this PR does / why we need it?
Refs #5356
#### Summary of your change
检测文本是否编辑,退出/切换文件作出提示,可以重置当前修改!
#### Please indicate you've done the following:

- [ ] Made sure tests are passing and test coverage is added if needed.
- [ ] Made sure commit message follow the rule of [Conventional Commits specification](https://www.conventionalcommits.org/).
- [ ] Considered the docs impact and opened a new docs issue or PR with docs changes if needed.
This commit is contained in:
2024-07-02 17:27:24 +08:00 committed by GitHub
parent f131aae344
commit 7f77a13b0c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 101 additions and 25 deletions

View File

@ -64,6 +64,8 @@ const message = {
agree: 'Agree',
notAgree: 'Not Agree',
preview: 'Preview',
open: 'Open',
notSave: 'Not Save',
},
search: {
timeStart: 'Time start',
@ -143,6 +145,7 @@ const message = {
recoverHelper: 'Restoring from {0} file. This operation is irreversible. Do you want to continue?',
refreshSuccess: 'Refresh successful',
rootInfoErr: "It's already the root directory",
resetSuccess: 'Reset successful',
},
login: {
username: 'UserName',
@ -1240,9 +1243,12 @@ const message = {
back: 'Back',
top: 'Go Back',
refresh: 'Refresh',
up: 'Go back',
openWithVscode: 'Open with VS Code',
vscodeHelper: 'Please make sure that VS Code is installed locally and the SSH Remote plugin is configured',
up: 'Go back',
saveContentAndClose: 'The file has been modified, do you want to save and close it?',
saveAndOpenNewFile: 'The file has been modified, do you want to save and open the new file?',
noEdit: 'The file has not been modified, no need to do this!',
},
ssh: {
autoStart: 'Auto Start',

View File

@ -63,6 +63,8 @@ const message = {
agree: '同意',
notAgree: '不同意',
preview: '預覽',
open: '打開',
notSave: '不保存',
},
search: {
timeStart: '開始時間',
@ -143,6 +145,7 @@ const message = {
recoverHelper: '將從 {0} 文件進行恢復該操作不可回滾是否繼續',
refreshSuccess: '重繪成功',
rootInfoErr: '已經是根目錄了',
resetSuccess: '重置成功',
},
login: {
username: '用戶名',
@ -1180,6 +1183,9 @@ const message = {
up: '上一層',
openWithVscode: 'VS Code 打開',
vscodeHelper: '請確保本地已安裝 VS Code 並配置了 SSH Remote 插件',
saveContentAndClose: '檔案已被修改是否保存並關閉',
saveAndOpenNewFile: '檔案已被修改是否保存並打開新檔案',
noEdit: '檔案未修改無需此操作',
},
ssh: {
autoStart: '開機自啟',

View File

@ -63,6 +63,8 @@ const message = {
agree: '同意',
notAgree: '不同意',
preview: '预览',
open: '打开',
notSave: '不保存',
},
search: {
timeStart: '开始时间',
@ -143,6 +145,7 @@ const message = {
recoverHelper: '将从 {0} 文件进行恢复该操作不可回滚是否继续',
refreshSuccess: '刷新成功',
rootInfoErr: '已经是根目录了',
resetSuccess: '重置成功',
},
login: {
username: '用户名',
@ -1181,6 +1184,9 @@ const message = {
up: '上一级',
openWithVscode: 'VS Code 打开',
vscodeHelper: '请确保本地已安装 VS Code 并配置了 SSH Remote 插件',
saveContentAndClose: '文件已被修改是否保存并关闭',
saveAndOpenNewFile: '文件已被修改是否保存并打开新文件',
noEdit: '文件未修改,无需此操作',
},
ssh: {
autoStart: '开机自启',

View File

@ -131,8 +131,8 @@
</div>
<template #footer>
<span class="dialog-footer">
<el-button @click="handleClose">{{ $t('commons.button.cancel') }}</el-button>
<el-button type="primary" @click="saveContent(true)">{{ $t('commons.button.confirm') }}</el-button>
<el-button @click="handleReset">{{ $t('commons.button.reset') }}</el-button>
<el-button type="primary" @click="saveContent()">{{ $t('commons.button.confirm') }}</el-button>
</span>
</template>
</el-dialog>
@ -151,7 +151,7 @@ import htmlWorker from 'monaco-editor/esm/vs/language/html/html.worker?worker';
import tsWorker from 'monaco-editor/esm/vs/language/typescript/ts.worker?worker';
import EditorWorker from 'monaco-editor/esm/vs/editor/editor.worker?worker';
import { ElTreeV2 } from 'element-plus';
import { ElMessageBox, ElTreeV2 } from 'element-plus';
import { ResultData } from '@/api/interface';
import { File } from '@/api/interface/file';
import { getIcon } from '@/utils/util';
@ -221,6 +221,8 @@ const treeHeight = ref(0);
const codeHeight = ref('55vh');
const codeReq = reactive({ path: '', expand: false, page: 1, pageSize: 100 });
const isShow = ref(true);
const isEdit = ref(false);
const oldFileContent = ref('');
const toggleShow = () => {
isShow.value = !isShow.value;
@ -271,11 +273,43 @@ let form = ref({
const em = defineEmits(['close']);
const handleClose = () => {
open.value = false;
if (editor) {
editor.dispose();
const closeEditor = () => {
open.value = false;
if (editor) {
editor.dispose();
}
em('close', open.value);
};
if (isEdit.value) {
ElMessageBox.confirm(i18n.global.t('file.saveContentAndClose'), {
confirmButtonText: i18n.global.t('commons.button.save'),
cancelButtonText: i18n.global.t('commons.button.notSave'),
type: 'info',
distinguishCancelAndClose: true,
})
.then(() => {
saveContent();
})
.finally(() => {
closeEditor();
});
} else {
closeEditor();
}
};
const handleReset = () => {
if (isEdit.value) {
loading.value = true;
form.value.content = oldFileContent.value;
editor.setValue(oldFileContent.value);
isEdit.value = false;
MsgSuccess(i18n.global.t('commons.msg.resetSuccess'));
loading.value = false;
} else {
MsgInfo(i18n.global.t('file.noEdit'));
}
em('close', open.value);
};
const loadTooltip = () => {
@ -347,6 +381,7 @@ const initEditor = () => {
editor.onDidChangeModelContent(() => {
if (editor) {
form.value.content = editor.getValue();
isEdit.value = true;
}
});
@ -358,27 +393,30 @@ const initEditor = () => {
};
const quickSave = () => {
saveContent(false);
saveContent();
};
const saveContent = (closePage: boolean) => {
loading.value = true;
SaveFileContent(form.value)
.then(() => {
loading.value = false;
open.value = !closePage;
MsgSuccess(i18n.global.t('commons.msg.updateSuccess'));
if (closePage) {
handleClose();
}
})
.catch(() => {
loading.value = false;
});
const saveContent = () => {
if (isEdit.value) {
loading.value = true;
SaveFileContent(form.value)
.then(() => {
loading.value = false;
isEdit.value = false;
oldFileContent.value = form.value.content;
MsgSuccess(i18n.global.t('commons.msg.updateSuccess'));
})
.catch(() => {
loading.value = false;
});
} else {
MsgInfo(i18n.global.t('file.noEdit'));
}
};
const acceptParams = (props: EditProps) => {
form.value.content = props.content;
oldFileContent.value = props.content;
form.value.path = props.path;
directoryPath.value = getDirectoryPath(props.path);
fileExtension.value = props.extension;
@ -447,11 +485,15 @@ const getRefresh = (path: string) => {
};
const getContent = (path: string, extension: string) => {
if (form.value.path !== path) {
if (form.value.path === path) {
return;
}
const fetchFileContent = () => {
codeReq.path = path;
codeReq.expand = true;
if (extension != '') {
if (extension !== '') {
Languages.forEach((language) => {
const ext = extension.substring(1);
if (language.value.indexOf(ext) > -1) {
@ -463,12 +505,28 @@ const getContent = (path: string, extension: string) => {
GetFileContent(codeReq)
.then((res) => {
form.value.content = res.data.content;
oldFileContent.value = res.data.content;
form.value.path = res.data.path;
fileExtension.value = res.data.extension;
fileName.value = res.data.name;
initEditor();
})
.catch(() => {});
};
if (isEdit.value) {
ElMessageBox.confirm(i18n.global.t('file.saveAndOpenNewFile'), {
confirmButtonText: i18n.global.t('commons.button.open'),
cancelButtonText: i18n.global.t('commons.button.cancel'),
type: 'info',
})
.then(() => {
saveContent();
fetchFileContent();
})
.finally(() => {});
} else {
fetchFileContent();
}
};