mirror of
https://github.com/MCSManager/MCSManager.git
synced 2025-01-24 15:14:01 +08:00
commit
51a4273d42
@ -1,7 +1,22 @@
|
||||
<script setup lang="ts">
|
||||
import { onMounted, onUnmounted, ref } from "vue";
|
||||
import { onBeforeUnmount, onMounted, ref } from "vue";
|
||||
import { EditorView, basicSetup } from "codemirror";
|
||||
import { javascript } from "@codemirror/lang-javascript";
|
||||
// import { cpp } from "@codemirror/lang-cpp";
|
||||
// import { css } from "@codemirror/lang-css";
|
||||
// import { html } from "@codemirror/lang-html";
|
||||
// import { java } from "@codemirror/lang-java";
|
||||
// import { json } from "@codemirror/lang-json";
|
||||
// import { less } from "@codemirror/lang-less";
|
||||
// import { markdown } from "@codemirror/lang-markdown";
|
||||
// import { php } from "@codemirror/lang-php";
|
||||
// import { python } from "@codemirror/lang-python";
|
||||
// import { sass } from "@codemirror/lang-sass";
|
||||
// import { sql } from "@codemirror/lang-sql";
|
||||
// import { vue } from "@codemirror/lang-vue";
|
||||
// import { xml } from "@codemirror/lang-xml";
|
||||
// import { getExtName } from "@/tools/fileManager";
|
||||
|
||||
import { EditorState } from "@codemirror/state";
|
||||
import { getRandomId } from "@/tools/randId";
|
||||
|
||||
@ -33,11 +48,11 @@ const theme = EditorView.theme({
|
||||
|
||||
let editor: EditorView;
|
||||
const initEditor = () => {
|
||||
let startState = EditorState.create({
|
||||
const startState = EditorState.create({
|
||||
doc: props.text,
|
||||
extensions: [
|
||||
basicSetup,
|
||||
theme,
|
||||
// theme,
|
||||
javascript(),
|
||||
EditorView.updateListener.of(function (e) {
|
||||
const text = e.view.state.doc.toString();
|
||||
@ -56,8 +71,8 @@ onMounted(() => {
|
||||
initEditor();
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
editor.destroy();
|
||||
onBeforeUnmount(() => {
|
||||
editor?.destroy();
|
||||
});
|
||||
</script>
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { useDefineApi } from "@/stores/useDefineApi";
|
||||
|
||||
// 获取文件列表
|
||||
export const getFileList = useDefineApi<
|
||||
export const fileList = useDefineApi<
|
||||
{
|
||||
params: {
|
||||
remote_uuid: string;
|
||||
@ -203,3 +203,21 @@ export const downloadAddress = useDefineApi<
|
||||
url: "/api/files/download",
|
||||
method: "POST"
|
||||
});
|
||||
|
||||
// 获取文件内容
|
||||
export const fileContent = useDefineApi<
|
||||
{
|
||||
params: {
|
||||
remote_uuid: string;
|
||||
uuid: string;
|
||||
};
|
||||
data: {
|
||||
target: string;
|
||||
text?: string;
|
||||
};
|
||||
},
|
||||
string
|
||||
>({
|
||||
url: "/api/files",
|
||||
method: "PUT"
|
||||
});
|
||||
|
@ -9,8 +9,6 @@ import dayjs from "dayjs";
|
||||
import {
|
||||
DownOutlined,
|
||||
SearchOutlined,
|
||||
FileOutlined,
|
||||
FolderOutlined,
|
||||
LoadingOutlined,
|
||||
ExclamationCircleOutlined,
|
||||
UploadOutlined
|
||||
@ -20,7 +18,7 @@ import { useScreen } from "@/hooks/useScreen";
|
||||
import { arrayFilter } from "@/tools/array";
|
||||
import { useLayoutCardTools } from "@/hooks/useCardTools";
|
||||
import {
|
||||
getFileList as getFileListApi,
|
||||
fileList as fileListApi,
|
||||
getFileStatus as getFileStatusApi,
|
||||
addFolder as addFolderApi,
|
||||
deleteFile as deleteFileApi,
|
||||
@ -149,9 +147,9 @@ const columns = computed(() => {
|
||||
});
|
||||
|
||||
const getFileList = async () => {
|
||||
const { execute } = getFileListApi();
|
||||
const { state, execute } = fileListApi();
|
||||
try {
|
||||
const res = await execute({
|
||||
await execute({
|
||||
params: {
|
||||
remote_uuid: daemonId || "",
|
||||
uuid: instanceId || "",
|
||||
@ -161,8 +159,10 @@ const getFileList = async () => {
|
||||
target: breadcrumbs[breadcrumbs.length - 1].path
|
||||
}
|
||||
});
|
||||
dataSource.value = res.value?.items || [];
|
||||
operationForm.value.total = res.value?.total || 0;
|
||||
if (state.value) {
|
||||
dataSource.value = state.value.items || [];
|
||||
operationForm.value.total = state.value.total || 0;
|
||||
}
|
||||
} catch (error: any) {
|
||||
return message.error(error.message);
|
||||
}
|
||||
@ -296,7 +296,7 @@ const paste = async () => {
|
||||
}
|
||||
};
|
||||
|
||||
const resetname = async (file: string) => {
|
||||
const resetName = async (file: string) => {
|
||||
const newname = await openDialog(t("重命名"), t("请输入新名称"), file);
|
||||
try {
|
||||
const { execute } = moveFileApi();
|
||||
@ -537,27 +537,34 @@ const handleTableChange = (e: { current: number; pageSize: number }) => {
|
||||
getFileList();
|
||||
};
|
||||
|
||||
const { execute } = getFileStatusApi();
|
||||
|
||||
setInterval(async () => {
|
||||
await getFileStatus();
|
||||
}, 3000);
|
||||
|
||||
const getFileStatus = async () => {
|
||||
const res = await execute({
|
||||
params: {
|
||||
remote_uuid: daemonId || "",
|
||||
uuid: instanceId || ""
|
||||
const { state, execute } = getFileStatusApi();
|
||||
try {
|
||||
await execute({
|
||||
params: {
|
||||
remote_uuid: daemonId || "",
|
||||
uuid: instanceId || ""
|
||||
}
|
||||
});
|
||||
if (state.value) {
|
||||
fileStatus.value = state.value;
|
||||
}
|
||||
});
|
||||
fileStatus.value = res.value;
|
||||
} catch (err: any) {
|
||||
console.error(err);
|
||||
return message.error(err.message);
|
||||
}
|
||||
};
|
||||
|
||||
import FileEditor from "./dialogs/FileEditor.vue";
|
||||
const FileEditorDialog = ref<InstanceType<typeof FileEditor>>();
|
||||
|
||||
const editFile = (fileName: string) => {
|
||||
FileEditorDialog.value?.openDialog(fileName);
|
||||
const path = breadcrumbs[breadcrumbs.length - 1].path + fileName;
|
||||
FileEditorDialog.value?.openDialog(path, fileName);
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
@ -712,21 +719,19 @@ onMounted(() => {
|
||||
<!-- eslint-disable-next-line vue/no-unused-vars -->
|
||||
<template #bodyCell="{ column, record }">
|
||||
<template v-if="column.key === 'name'">
|
||||
<a-popconfirm :title="t('下载此文件?')" @confirm="downloadFile(record.name)">
|
||||
<a-button
|
||||
type="link"
|
||||
class="file-name"
|
||||
@click="rowClickTable(record.name, record.type)"
|
||||
>
|
||||
<span class="mr-4">
|
||||
<component
|
||||
:is="getFileIcon(record.name, record.type)"
|
||||
style="font-size: 16px"
|
||||
/>
|
||||
</span>
|
||||
{{ record.name }}
|
||||
</a-button>
|
||||
</a-popconfirm>
|
||||
<a-button
|
||||
type="link"
|
||||
class="file-name"
|
||||
@click="rowClickTable(record.name, record.type)"
|
||||
>
|
||||
<span class="mr-4">
|
||||
<component
|
||||
:is="getFileIcon(record.name, record.type)"
|
||||
style="font-size: 16px"
|
||||
/>
|
||||
</span>
|
||||
{{ record.name }}
|
||||
</a-button>
|
||||
</template>
|
||||
<template v-if="column.key === 'action'">
|
||||
<a-dropdown>
|
||||
@ -735,7 +740,11 @@ onMounted(() => {
|
||||
<a-menu-item v-if="fileStatus?.platform != 'win32'" key="1">
|
||||
{{ t("TXT_CODE_16853efe") }}
|
||||
</a-menu-item>
|
||||
<a-menu-item key="2" @click="editFile(record.name)">
|
||||
<a-menu-item
|
||||
v-if="record.type === 1"
|
||||
key="2"
|
||||
@click="editFile(record.name)"
|
||||
>
|
||||
{{ t("TXT_CODE_ad207008") }}
|
||||
</a-menu-item>
|
||||
<a-menu-item key="3" @click="setClipBoard('copy', record.name)">
|
||||
@ -744,7 +753,7 @@ onMounted(() => {
|
||||
<a-menu-item key="4" @click="setClipBoard('move', record.name)">
|
||||
{{ t("剪切") }}
|
||||
</a-menu-item>
|
||||
<a-menu-item key="5" @click="resetname(record.name)">
|
||||
<a-menu-item key="5" @click="resetName(record.name)">
|
||||
{{ t("TXT_CODE_c83551f5") }}
|
||||
</a-menu-item>
|
||||
<a-menu-item key="6" @click="deleteFile(record.name)">
|
||||
@ -844,7 +853,7 @@ onMounted(() => {
|
||||
}
|
||||
|
||||
.file-name {
|
||||
color: initial;
|
||||
color: inherit;
|
||||
&:hover {
|
||||
color: #1677ff;
|
||||
}
|
||||
|
@ -1,28 +1,74 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, onMounted, ref } from "vue";
|
||||
import { computed, ref } from "vue";
|
||||
import { t } from "@/lang/i18n";
|
||||
import { message } from "ant-design-vue";
|
||||
import Editor from "@/components/Editor.vue";
|
||||
import { fileContent } from "@/services/apis/fileManager";
|
||||
import { useRoute } from "vue-router";
|
||||
|
||||
const route = useRoute();
|
||||
const open = ref(false);
|
||||
const text = ref("");
|
||||
const openEditor = ref(false);
|
||||
const editorText = ref("");
|
||||
const fileName = ref("");
|
||||
const path = ref("");
|
||||
const daemonId = String(route.query["daemonId"]) ?? "";
|
||||
const instanceId = String(route.query["instanceId"]) ?? "";
|
||||
|
||||
const openDialog = (path: string) => {
|
||||
const openDialog = async (path_: string, fileName_: string) => {
|
||||
open.value = true;
|
||||
text.value = "你好世界\n123";
|
||||
fileName.value = path;
|
||||
path.value = path_;
|
||||
fileName.value = fileName_;
|
||||
await render();
|
||||
};
|
||||
|
||||
const { state: text, execute } = fileContent();
|
||||
const render = async () => {
|
||||
try {
|
||||
await execute({
|
||||
params: {
|
||||
remote_uuid: daemonId,
|
||||
uuid: instanceId
|
||||
},
|
||||
data: {
|
||||
target: path.value
|
||||
}
|
||||
});
|
||||
|
||||
if (text.value) {
|
||||
typeof text.value === "boolean" ? (editorText.value = "") : (editorText.value = text.value);
|
||||
}
|
||||
|
||||
openEditor.value = true;
|
||||
} catch (err: any) {
|
||||
console.error(err.message);
|
||||
return message.error(err.message);
|
||||
}
|
||||
};
|
||||
|
||||
const submit = async () => {
|
||||
try {
|
||||
open.value = false;
|
||||
return message.success(t("更新成功"));
|
||||
await execute({
|
||||
params: {
|
||||
remote_uuid: daemonId,
|
||||
uuid: instanceId
|
||||
},
|
||||
data: {
|
||||
target: path.value,
|
||||
text: editorText.value
|
||||
}
|
||||
});
|
||||
return message.success(t("保存成功"));
|
||||
} catch (err: any) {
|
||||
console.error(err.message);
|
||||
return message.error(err.message);
|
||||
}
|
||||
};
|
||||
|
||||
const cancel = () => {
|
||||
open.value = openEditor.value = false;
|
||||
};
|
||||
|
||||
const dialogTitle = computed(() => {
|
||||
return `${t("编辑文件")} ${fileName.value}`;
|
||||
});
|
||||
@ -38,11 +84,14 @@ defineExpose({
|
||||
centered
|
||||
:mask-closable="false"
|
||||
:title="dialogTitle"
|
||||
:ok-text="t('保存')"
|
||||
width="1000px"
|
||||
@ok="submit"
|
||||
:footer="null"
|
||||
@cancel="cancel()"
|
||||
>
|
||||
RT:{{ text }}
|
||||
<Editor v-if="open" v-model:text="text" height="600px" />
|
||||
<a-space warp>
|
||||
<a-button @click="submit">保存</a-button>
|
||||
</a-space>
|
||||
<Editor v-if="openEditor" ref="EditorComponent" v-model:text="editorText" height="70vh" />
|
||||
<a-skeleton v-else active />
|
||||
</a-modal>
|
||||
</template>
|
||||
|
Loading…
Reference in New Issue
Block a user