mirror of
https://github.com/MCSManager/MCSManager.git
synced 2025-04-06 17:10:29 +08:00
Merge branch 'main' into abandon
This commit is contained in:
commit
03ccafc996
4
frontend/components.d.ts
vendored
4
frontend/components.d.ts
vendored
@ -64,6 +64,8 @@ declare module 'vue' {
|
||||
CardError: typeof import('./src/components/CardError.vue')['default']
|
||||
CardOperator: typeof import('./src/components/CardOperator.vue')['default']
|
||||
CardPanel: typeof import('./src/components/CardPanel.vue')['default']
|
||||
CmdAssistantDialog: typeof import('./src/components/fc/CmdAssistantDialog.vue')['default']
|
||||
CommandDialog: typeof import('./src/components/commandDialog.vue')['default']
|
||||
CopyButton: typeof import('./src/components/CopyButton.vue')['default']
|
||||
DataStatistic: typeof import('./src/components/DataStatistic.vue')['default']
|
||||
Editor: typeof import('./src/components/Editor.vue')['default']
|
||||
@ -84,6 +86,6 @@ declare module 'vue' {
|
||||
PlaceHolderCard: typeof import('./src/components/PlaceHolderCard.vue')['default']
|
||||
RouterLink: typeof import('vue-router')['RouterLink']
|
||||
RouterView: typeof import('vue-router')['RouterView']
|
||||
SelectInstances: typeof import('./src/components/SelectInstances.vue')['default']
|
||||
SelectInstances: typeof import('./src/components/fc/SelectInstances.vue')['default']
|
||||
}
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ import type { MapData } from "@/types/index";
|
||||
import type { FormInstance } from "ant-design-vue";
|
||||
import { BulbOutlined } from "@ant-design/icons-vue";
|
||||
import { $t as t } from "@/lang/i18n";
|
||||
import { useSelectInstances } from "@/hooks/useSelectInstances";
|
||||
import { useSelectInstances } from "@/components/fc";
|
||||
|
||||
const open = ref(false);
|
||||
const card = ref<LayoutCard>();
|
||||
|
192
frontend/src/components/fc/CmdAssistantDialog.vue
Normal file
192
frontend/src/components/fc/CmdAssistantDialog.vue
Normal file
@ -0,0 +1,192 @@
|
||||
<script setup lang="ts">
|
||||
import { ref } from "vue";
|
||||
import type { MountComponent } from "@/types";
|
||||
import ActionButton from "@/components/ActionButton.vue";
|
||||
import { t } from "@/lang/i18n";
|
||||
import { BuildFilled, DropboxSquareFilled, SwitcherFilled } from "@ant-design/icons-vue";
|
||||
import { QUICKSTART_ACTION_TYPE } from "@/hooks/widgets/quickStartFlow";
|
||||
import FadeUpAnimation from "@/components/FadeUpAnimation.vue";
|
||||
import { useStartCmdBuilder } from "../../hooks/useGenerateStartCmd";
|
||||
import { message } from "ant-design-vue";
|
||||
import {
|
||||
TYPE_MINECRAFT_BEDROCK,
|
||||
TYPE_MINECRAFT_JAVA,
|
||||
TYPE_STEAM_SERVER_UNIVERSAL,
|
||||
TYPE_UNIVERSAL
|
||||
} from "@/hooks/useInstance";
|
||||
|
||||
const { minecraftJava, buildCmd, setGameType } = useStartCmdBuilder();
|
||||
|
||||
enum STEP {
|
||||
SELECT_TYPE = "A",
|
||||
SELECT_SOFTWARE = "B"
|
||||
}
|
||||
|
||||
const props = defineProps<MountComponent>();
|
||||
const open = ref(true);
|
||||
const activeKey = ref<string>();
|
||||
const step = ref<STEP>(STEP.SELECT_TYPE);
|
||||
const gameType = ref<QUICKSTART_ACTION_TYPE>();
|
||||
const formRef = ref();
|
||||
|
||||
const cancel = async () => {
|
||||
open.value = false;
|
||||
if (props.destroyComponent) props.destroyComponent();
|
||||
};
|
||||
|
||||
const submit = async () => {
|
||||
try {
|
||||
await formRef.value.validate();
|
||||
} catch (error) {
|
||||
return message.warning(t("请完善表单中的必填项!"));
|
||||
}
|
||||
const command = buildCmd();
|
||||
if (props.emitResult) props.emitResult(command);
|
||||
await cancel();
|
||||
};
|
||||
|
||||
const handleNext = () => {
|
||||
if (step.value === STEP.SELECT_TYPE) {
|
||||
step.value = STEP.SELECT_SOFTWARE;
|
||||
}
|
||||
};
|
||||
|
||||
const actions = [
|
||||
{
|
||||
icon: BuildFilled,
|
||||
title: t("Minecraft 游戏服务器"),
|
||||
click: () => {
|
||||
setGameType(QUICKSTART_ACTION_TYPE.Minecraft);
|
||||
handleNext();
|
||||
}
|
||||
},
|
||||
{
|
||||
icon: SwitcherFilled,
|
||||
title: t("Steam 游戏服务器"),
|
||||
click: () => {
|
||||
setGameType(QUICKSTART_ACTION_TYPE.SteamGameServer);
|
||||
handleNext();
|
||||
}
|
||||
},
|
||||
{
|
||||
icon: DropboxSquareFilled,
|
||||
title: t("任何二进制控制台程序"),
|
||||
click: () => {
|
||||
setGameType(QUICKSTART_ACTION_TYPE.AnyApp);
|
||||
handleNext();
|
||||
}
|
||||
}
|
||||
];
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<a-modal
|
||||
v-model:open="open"
|
||||
centered
|
||||
width="800px"
|
||||
:mask-closable="false"
|
||||
:title="t('命令助手')"
|
||||
:ok-text="t('确定')"
|
||||
:cancel-text="t('TXT_CODE_a0451c97')"
|
||||
:ok-button-props="{ disabled: step !== STEP.SELECT_SOFTWARE }"
|
||||
@ok="submit"
|
||||
@cancel="cancel"
|
||||
>
|
||||
<div>
|
||||
<div v-if="step === STEP.SELECT_TYPE">
|
||||
<a-row :gutter="[0, 12]">
|
||||
<a-typography-text>
|
||||
{{ t("请选择你的服务器程序类别") }}
|
||||
</a-typography-text>
|
||||
<fade-up-animation>
|
||||
<action-button
|
||||
v-for="(action, index) in actions"
|
||||
:key="action.title"
|
||||
:title="action.title"
|
||||
:click="actions[index].click"
|
||||
:icon="action.icon"
|
||||
:data-index="index"
|
||||
/>
|
||||
</fade-up-animation>
|
||||
</a-row>
|
||||
</div>
|
||||
<div v-if="gameType === QUICKSTART_ACTION_TYPE.Minecraft">
|
||||
<a-tabs v-model:activeKey="activeKey">
|
||||
<a-tab-pane :key="TYPE_MINECRAFT_JAVA" :tab="t('Java 版 Minecraft 服务器')">
|
||||
<a-form ref="formRef" layout="vertical" :model="minecraftJava">
|
||||
<a-form-item name="jarName" :label="t('服务端软件文件名')" required="true">
|
||||
<a-input
|
||||
v-model:value="minecraftJava.jarName"
|
||||
:placeholder="t('一般为 .jar 文件,列如 paper.jar 等')"
|
||||
/>
|
||||
</a-form-item>
|
||||
|
||||
<a-row gutter="24">
|
||||
<a-col :span="12">
|
||||
<a-form-item name="maxMemory" :label="t('最大内存')">
|
||||
<a-input
|
||||
v-model:value="minecraftJava.maxMemory"
|
||||
:placeholder="t('选填,-Xmx 参数,如:1024M')"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item name="minMemory" :label="t('初始内存')">
|
||||
<a-input
|
||||
v-model:value="minecraftJava.minMemory"
|
||||
:placeholder="t('选填,-Xms 参数,如:1024M')"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
|
||||
<a-col :span="24">
|
||||
<a-form-item name="javaPath" :label="t('Java 路径')">
|
||||
<a-input
|
||||
v-model:value="minecraftJava.javaPath"
|
||||
:placeholder="t('选填,请输入 Java 绝对路径,不填默认取环境变量')"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
|
||||
<a-col :span="24">
|
||||
<a-form-item name="additional" :label="t('附加参数')">
|
||||
<a-input
|
||||
v-model:value="minecraftJava.additional"
|
||||
:placeholder="t('选填,在 -jar 之前的参数')"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
|
||||
<a-col :span="24">
|
||||
<a-form-item name="suffix" :label="t('后缀参数')">
|
||||
<a-input
|
||||
v-model:value="minecraftJava.suffix"
|
||||
:placeholder="
|
||||
t('选填,Java 程序之后的附加参数,如 -nogui 等,多个参数用空格分隔')
|
||||
"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-form>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane :key="TYPE_MINECRAFT_BEDROCK" :tab="t('基岩版 Minecraft 服务器')">
|
||||
B
|
||||
</a-tab-pane>
|
||||
</a-tabs>
|
||||
</div>
|
||||
<div v-else-if="gameType === QUICKSTART_ACTION_TYPE.SteamGameServer">
|
||||
<a-tabs v-model:activeKey="activeKey">
|
||||
<a-tab-pane :key="TYPE_STEAM_SERVER_UNIVERSAL" :tab="t('全部类型')">C</a-tab-pane>
|
||||
</a-tabs>
|
||||
</div>
|
||||
<div v-else-if="gameType != null">
|
||||
<a-tabs v-model:activeKey="activeKey">
|
||||
<a-tab-pane :key="TYPE_UNIVERSAL" :tab="t('全部类型')">D</a-tab-pane>
|
||||
</a-tabs>
|
||||
</div>
|
||||
</div>
|
||||
</a-modal>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped></style>
|
@ -14,7 +14,7 @@ import { remoteInstances, remoteNodeList } from "@/services/apis";
|
||||
import { message } from "ant-design-vue";
|
||||
import { computeNodeName } from "@/tools/nodes";
|
||||
import { throttle } from "lodash";
|
||||
import { useScreen } from "../hooks/useScreen";
|
||||
import { useScreen } from "@/hooks/useScreen";
|
||||
|
||||
const props = defineProps<MountComponent>();
|
||||
const { isPhone } = useScreen();
|
13
frontend/src/components/fc/index.ts
Normal file
13
frontend/src/components/fc/index.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import { useMountComponent } from "@/hooks/useMountComponent";
|
||||
import type { UserInstance } from "@/types/user";
|
||||
|
||||
import SelectInstances from "@/components/fc/SelectInstances.vue";
|
||||
import CmdAssistantDialog from "@/components/fc/CmdAssistantDialog.vue";
|
||||
|
||||
export async function useSelectInstances() {
|
||||
return await useMountComponent().mount<UserInstance[]>(SelectInstances);
|
||||
}
|
||||
|
||||
export async function useCmdAssistantDialog() {
|
||||
return await useMountComponent().mount<string>(CmdAssistantDialog);
|
||||
}
|
60
frontend/src/hooks/useGenerateStartCmd.ts
Normal file
60
frontend/src/hooks/useGenerateStartCmd.ts
Normal file
@ -0,0 +1,60 @@
|
||||
import { ref } from "vue";
|
||||
import { QUICKSTART_ACTION_TYPE } from "./widgets/quickStartFlow";
|
||||
import { TYPE_MINECRAFT_JAVA } from "./useInstance";
|
||||
|
||||
type SystemType = "win32" | "linux";
|
||||
|
||||
export function useStartCmdBuilder() {
|
||||
const gameType = ref<QUICKSTART_ACTION_TYPE>();
|
||||
const appType = ref<string>();
|
||||
const systemType = ref<SystemType>("linux");
|
||||
|
||||
const browserLanguage = navigator.language;
|
||||
const [language, country] = browserLanguage.split("-");
|
||||
const additionalArray = ["-Dfile.encoding=UTF-8"];
|
||||
if (language) additionalArray.push(`-Duser.language=${language}`);
|
||||
if (country) additionalArray.push(`-Duser.country=${country}`);
|
||||
|
||||
const minecraftJava = ref({
|
||||
javaPath: "",
|
||||
jarName: "",
|
||||
maxMemory: "",
|
||||
minMemory: "",
|
||||
suffix: "nogui",
|
||||
additional: additionalArray.join(" ")
|
||||
});
|
||||
|
||||
const setSystem = (type: SystemType) => {
|
||||
systemType.value = type;
|
||||
};
|
||||
|
||||
const setAppType = (type: string) => {
|
||||
appType.value = type;
|
||||
};
|
||||
|
||||
const setGameType = (type: QUICKSTART_ACTION_TYPE) => {
|
||||
gameType.value = type;
|
||||
};
|
||||
|
||||
const buildCmd = () => {
|
||||
if (
|
||||
gameType.value === QUICKSTART_ACTION_TYPE.Minecraft &&
|
||||
appType.value === TYPE_MINECRAFT_JAVA
|
||||
) {
|
||||
const config = minecraftJava.value;
|
||||
const javaPath = config.javaPath ? `"${config.javaPath}"` : "java";
|
||||
const jarName = config.jarName.includes(" ") ? `"${config.jarName}"` : config.jarName;
|
||||
return `${javaPath} -Xms${config.minMemory} -Xmx${config.maxMemory} ${additionalArray} -jar "${jarName}" ${config.suffix}`;
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
setSystem,
|
||||
buildCmd,
|
||||
setAppType,
|
||||
setGameType,
|
||||
gameType,
|
||||
appType,
|
||||
minecraftJava
|
||||
};
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
import { createApp, type Component } from "vue";
|
||||
import { sleep } from "@/tools/common";
|
||||
|
||||
export function useMountComponent() {
|
||||
export function useMountComponent(data: Record<string, any> = {}) {
|
||||
let isOpen = false;
|
||||
const mount = <T>(component: Component) => {
|
||||
if (isOpen) return;
|
||||
@ -9,9 +9,9 @@ export function useMountComponent() {
|
||||
return new Promise<T>((resolve, reject) => {
|
||||
const div = document.createElement("div");
|
||||
document.body.appendChild(div);
|
||||
|
||||
const app = createApp(component, {
|
||||
async destroyComponent(delay = 0) {
|
||||
...data,
|
||||
async destroyComponent(delay = 1000) {
|
||||
await sleep(delay);
|
||||
app.unmount();
|
||||
div.remove();
|
||||
|
@ -1,8 +0,0 @@
|
||||
import { useMountComponent } from "./useMountComponent";
|
||||
import SelectInstances from "@/components/SelectInstances.vue";
|
||||
import type { UserInstance } from "@/types/user";
|
||||
|
||||
export function useSelectInstances() {
|
||||
const { mount } = useMountComponent();
|
||||
return mount<UserInstance[]>(SelectInstances);
|
||||
}
|
@ -195,8 +195,8 @@ export interface QuickStartTemplate {
|
||||
}
|
||||
|
||||
export interface MountComponent {
|
||||
destroyComponent: Function;
|
||||
emitResult: Function;
|
||||
destroyComponent(delay?: number): void;
|
||||
emitResult(data?: any): void;
|
||||
}
|
||||
|
||||
export interface Schedule {
|
||||
|
@ -62,6 +62,7 @@ const actions = [
|
||||
:key="action.title"
|
||||
:title="action.title"
|
||||
:click="actions[index].click"
|
||||
:icon="action.icon"
|
||||
:data-index="index"
|
||||
/>
|
||||
</fade-up-animation>
|
||||
|
@ -15,6 +15,7 @@ import { Dayjs } from "dayjs";
|
||||
import _ from "lodash";
|
||||
import { GLOBAL_INSTANCE_NAME } from "../../../config/const";
|
||||
import { dayjsToTimestamp, timestampToDayjs } from "../../../tools/time";
|
||||
import { useCmdAssistantDialog } from "@/components/fc";
|
||||
|
||||
interface FormDetail extends InstanceDetail {
|
||||
dayjsEndTime?: Dayjs;
|
||||
@ -157,6 +158,11 @@ const encodeFormData = () => {
|
||||
throw new Error("Ref Options is null");
|
||||
};
|
||||
|
||||
const openCmdAssistDialog = async () => {
|
||||
const cmd = useCmdAssistantDialog();
|
||||
console.debug("cmd:", cmd);
|
||||
};
|
||||
|
||||
defineExpose({
|
||||
openDialog
|
||||
});
|
||||
@ -238,7 +244,7 @@ defineExpose({
|
||||
:rows="3"
|
||||
style="min-height: 40px"
|
||||
/>
|
||||
<a-button type="default" style="height: auto">
|
||||
<a-button type="default" style="height: auto" @click="openCmdAssistDialog">
|
||||
{{ t("TXT_CODE_2728d0d4") }}
|
||||
</a-button>
|
||||
</a-input-group>
|
||||
|
@ -11,7 +11,7 @@ import { arrayFilter } from "@/tools/array";
|
||||
import { userInfoApiAdvanced } from "@/services/apis";
|
||||
import { useLayoutCardTools } from "@/hooks/useCardTools";
|
||||
import { updateUserInstance } from "@/services/apis";
|
||||
import { useSelectInstances } from "@/hooks/useSelectInstances";
|
||||
import { useSelectInstances } from "@/components/fc";
|
||||
import { message } from "ant-design-vue";
|
||||
import { INSTANCE_STATUS } from "@/types/const";
|
||||
|
||||
|
@ -1,18 +1,11 @@
|
||||
import "module-alias/register";
|
||||
|
||||
// Initialize the version manager & i18n
|
||||
import { $t } from "./app/i18n";
|
||||
import { initVersionManager, getVersion } from "./app/version";
|
||||
|
||||
// Storage
|
||||
import RedisStorage from "./app/common/storage/redis_storage";
|
||||
import Storage from "./app/common/storage/sys_storage";
|
||||
|
||||
import { initSystemConfig, systemConfig } from "./app/setting";
|
||||
import SystemUser from "./app/service/system_user";
|
||||
import SystemRemoteService from "./app/service/system_remote_service";
|
||||
|
||||
// Http server requirements
|
||||
import Koa from "koa";
|
||||
import { v4 } from "uuid";
|
||||
import path from "path";
|
||||
|
Loading…
x
Reference in New Issue
Block a user