Script: i18n code

This commit is contained in:
unitwk 2023-11-13 20:32:56 +08:00
parent 64a7a2727e
commit 611c66728b
48 changed files with 4230 additions and 1467 deletions

View File

@ -124,10 +124,8 @@ const appMenus = computed(() => {
icon: SaveOutlined,
click: async () => {
Modal.confirm({
title: $t("确定要保存布局吗?"),
content: $t(
"由于界面的高度可定制化,一旦保存布局后整个界面的语言将会被锁定,除非重置布局否则切换语言将无法很好的工作。如果您没有切换语言的需求,可以忽略这条建议。"
),
title: $t("TXT_CODE_d73c8510"),
content: $t("TXT_CODE_6d9b9f22"),
async onOk() {
changeDesignMode(false);
await saveGlobalLayoutConfig();
@ -144,12 +142,12 @@ const appMenus = computed(() => {
onlyPC: true
},
{
title: t("放弃保存布局"),
title: t("TXT_CODE_5b5d6f04"),
icon: CloseCircleOutlined,
click: async () => {
Modal.confirm({
title: $t("确定要放弃保存布局?"),
content: $t("当前布局将会丢失,是否继续?"),
title: $t("TXT_CODE_8f20c21c"),
content: $t("TXT_CODE_9740f199"),
async onOk() {
window.location.reload();
}
@ -159,17 +157,17 @@ const appMenus = computed(() => {
onlyPC: true
},
{
title: t("重置卡片布局"),
title: t("TXT_CODE_abd2f7e1"),
icon: RedoOutlined,
click: async () => {
Modal.confirm({
title: $t("确定要重置布局吗?"),
content: $t("这将会导致所有网页恢复到默认状态,请谨慎操作。重置后页面可以自动切换语言。"),
title: $t("TXT_CODE_74fa2f73"),
content: $t("TXT_CODE_f63bfe78"),
async onOk() {
await resetGlobalLayoutConfig();
notification.success({
placement: "top",
message: t("重置成功"),
message: t("TXT_CODE_15c6d4eb"),
description: t("TXT_CODE_e10c992a")
});
setTimeout(() => window.location.reload(), 400);
@ -247,7 +245,7 @@ const appMenus = computed(() => {
icon: LogoutOutlined,
click: async () => {
await execute();
message.success(t("成功退出登录"));
message.success(t("TXT_CODE_11673d8c"));
router.go(0);
},
conditions: !containerState.isDesignMode,

View File

@ -24,18 +24,18 @@ defineProps<{
<div class="">
<a-typography-paragraph v-if="containerState.showNewCardDialog" :level="5">
<ExclamationCircleOutlined />
{{ t("此卡片无法在新增时预览,请添加后填写相关参数卡片即可正常运作。") }}
{{ t("TXT_CODE_450481c5") }}
</a-typography-paragraph>
<template v-else>
<div>
<a-typography-paragraph>
<ExclamationCircleOutlined />
{{ t("此卡片运行错误,请刷新网页重试") }}
{{ t("TXT_CODE_4e627613") }}
</a-typography-paragraph>
<a-typography-paragraph>
<div>
{{ t("错误信息:") }}
{{ t("TXT_CODE_9c95b60f") }}
</div>
<pre>{{ error.message ? error.message : error }}</pre>
</a-typography-paragraph>

View File

@ -27,13 +27,13 @@ const parsedConfig = jsonToMap(props.config);
<template #body>
<a-typography>
<a-typography-title :level="5">
{{ data ? t("关于此配置文件") : t("未知配置文件") }}
{{ data ? t("TXT_CODE_fb2df398") : t("TXT_CODE_2ce953da") }}
</a-typography-title>
<a-typography-paragraph v-if="data">
{{ data?.desc }}
</a-typography-paragraph>
<a-typography-paragraph v-else>
{{ t("此配置文件暂不支持直接配置,请前往文件管理进行编辑。") }}
{{ t("TXT_CODE_75e5af9b") }}
</a-typography-paragraph>
</a-typography>
</template>
@ -51,7 +51,7 @@ const parsedConfig = jsonToMap(props.config);
</div>
</div>
<div v-else>
{{ t("配置文件内容为空,请检查文件是否正确,或点击上方 “编辑源文件” 按钮继续编辑。") }}
{{ t("TXT_CODE_1a730d48") }}
</div>
</template>
</CardPanel>

View File

@ -60,10 +60,10 @@ onMounted(() => {
v-if="type == CONTROL.SELECT"
v-model:value="value[key]"
style="width: 100%"
:placeholder="t('未选择')"
:placeholder="t('TXT_CODE_fe3f34e6')"
>
<a-select-option :value="true">{{ t("") }}</a-select-option>
<a-select-option :value="false">{{ t("") }}</a-select-option>
<a-select-option :value="true">{{ t("TXT_CODE_addfcb6b") }}</a-select-option>
<a-select-option :value="false">{{ t("TXT_CODE_1e9c479e") }}</a-select-option>
</a-select>
<a-button v-if="type == CONTROL.SELECT" class="ml-8" @click="forceType">
<EditOutlined />

View File

@ -34,7 +34,7 @@ const currentPageRole = route.meta.permission as ROLE;
const insertCardToLayout = async (card: NewCardItem) => {
if (card.permission > currentPageRole) {
return message.warning(t("无法添加,此卡片只能放置在更高权限的页面中"));
return message.warning(t("TXT_CODE_fb4cb9cb"));
}
if (card.params) {
@ -111,11 +111,7 @@ const handleTabClick = (value: string) => {
<a-col span="24" :md="24" :lg="card.width * 2">
<div class="card-container-wrapper">
<div v-if="card.permission > currentPageRole" class="card-alert">
<a-alert
show-icon
:message="t('此卡片只能放置在更高权限的页面中')"
type="warning"
/>
<a-alert show-icon :message="t('TXT_CODE_cd8cd5d2')" type="warning" />
</div>
<LayoutCardComponent
:id="'card-card-container-' + card.id"

View File

@ -80,7 +80,7 @@ defineExpose({
type="primary"
@click="openInstanceSelectDialog"
>
{{ t("选择实例") }}
{{ t("TXT_CODE_2c9083a1") }}
</a-button>
</a-form-item>
</a-col>

View File

@ -77,7 +77,7 @@ const initInstancesData = async () => {
}
});
} catch (err) {
return message.error(t("访问远程节点异常"));
return message.error(t("TXT_CODE_e109c091"));
}
};
@ -86,13 +86,13 @@ const selectedItems = ref<UserInstance[]>([]);
const columns = [
{
align: "center",
title: t("实例名称"),
title: t("TXT_CODE_f70badb9"),
dataIndex: "nickname",
key: "instanceUuid"
},
{
align: "center",
title: t("操作"),
title: t("TXT_CODE_fe731dfc"),
key: "operation"
}
];
@ -139,15 +139,15 @@ const handleChangeNode = async (item: NodeStatus) => {
v-model:open="open"
centered
:mask-closable="false"
:title="t('请选择实例')"
:ok-text="t('保存')"
:cancel-text="t('取消')"
:title="t('TXT_CODE_8145d25a')"
:ok-text="t('TXT_CODE_abfe9512')"
:cancel-text="t('TXT_CODE_a0451c97')"
@ok="submit"
@cancel="cancel"
>
<a-typography-paragraph>
<a-typography-text type="secondary">
{{ t("利用远程主机地址与模糊查询来为此用户增加应用实例") }}
{{ t("TXT_CODE_50697989") }}
</a-typography-text>
</a-typography-paragraph>
<a-row :gutter="[24, 24]" style="height: 100%">
@ -204,7 +204,7 @@ const handleChangeNode = async (item: NodeStatus) => {
<a-col :span="24">
<div v-if="instances" class="flex-between align-center">
<a-typography-text>
{{ t("已选择") }} {{ selectedItems.length }} {{ t("") }}
{{ t("TXT_CODE_379fa48a") }} {{ selectedItems.length }} {{ t("TXT_CODE_5cd3b4bd") }}
</a-typography-text>
<a-pagination
v-model:current="operationForm.currentPage"
@ -227,10 +227,10 @@ const handleChangeNode = async (item: NodeStatus) => {
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'operation'">
<a-button v-if="findItem(record)" danger size="" @click="removeItem(record)">
{{ t("移除") }}
{{ t("TXT_CODE_65fcbd09") }}
</a-button>
<a-button v-else size="" @click="selectItem(record)">
{{ t("选择") }}
{{ t("TXT_CODE_7b2c5414") }}
</a-button>
</template>
</template>

View File

@ -84,9 +84,9 @@ export function getLayoutCardPool() {
permission: ROLE.GUEST,
meta: {},
type: "EmptyCard",
title: t("占位卡片"),
title: t("TXT_CODE_b23e2bab"),
width: 2,
description: t("此卡片没有任何内容,可以用来占位,实现居中等排版需求。"),
description: t("TXT_CODE_b3e2f83e"),
height: LayoutCardHeight.MINI,
category: NEW_CARD_TYPE.OTHER
},
@ -95,9 +95,9 @@ export function getLayoutCardPool() {
id: getRandomId(),
permission: ROLE.USER,
type: "Terminal",
title: t("实例控制台"),
title: t("TXT_CODE_71a51d19"),
width: 6,
description: t("用于显示和交互某个实例的控制台。"),
description: t("TXT_CODE_10a6d36f"),
height: LayoutCardHeight.BIG,
category: NEW_CARD_TYPE.INSTANCE,
meta: {
@ -106,17 +106,17 @@ export function getLayoutCardPool() {
params: [
{
field: "instanceId",
label: t("实例 ID"),
label: t("TXT_CODE_e6a5c12b"),
type: "string"
},
{
field: "daemonId",
label: t("节点 ID"),
label: t("TXT_CODE_72cfab69"),
type: "string"
},
{
field: "instance",
label: t("实例"),
label: t("TXT_CODE_cb043d10"),
type: "instance"
}
]
@ -128,7 +128,7 @@ export function getLayoutCardPool() {
type: "StatusBlock",
title: t("TXT_CODE_b4a9d04a"),
meta: {
title: t("在线节点 / 总节点"),
title: t("TXT_CODE_4b7eba50"),
type: "node"
},
width: 3,
@ -142,9 +142,9 @@ export function getLayoutCardPool() {
permission: ROLE.ADMIN,
meta: {},
type: "Settings",
title: t("设置"),
title: t("TXT_CODE_b5c7b82d"),
width: 8,
description: t("用于操作面板的全局设置"),
description: t("TXT_CODE_e78047a5"),
height: LayoutCardHeight.MEDIUM,
category: NEW_CARD_TYPE.COMMON
},

File diff suppressed because it is too large Load Diff

View File

@ -94,7 +94,7 @@ let originRouterConfig: RouterConfig[] = [
children: [
{
path: "/instances/terminal/serverConfig/fileEdit",
name: t("编辑配置文件"),
name: t("TXT_CODE_78019c60"),
component: LayoutContainer,
meta: {
permission: ROLE.USER
@ -106,7 +106,7 @@ let originRouterConfig: RouterConfig[] = [
},
{
path: "/instances/schedule",
name: t("计划任务"),
name: t("TXT_CODE_b7d026f8"),
component: LayoutContainer,
meta: {
permission: ROLE.USER
@ -144,7 +144,7 @@ let originRouterConfig: RouterConfig[] = [
children: [
{
path: "/node/image",
name: t("镜像管理"),
name: t("TXT_CODE_e6c30866"),
component: LayoutContainer,
meta: {
permission: ROLE.ADMIN,
@ -153,7 +153,7 @@ let originRouterConfig: RouterConfig[] = [
children: [
{
path: "/node/image/new",
name: t("创建镜像"),
name: t("TXT_CODE_3d09f0ac"),
component: LayoutContainer,
meta: {
permission: ROLE.ADMIN,
@ -166,7 +166,7 @@ let originRouterConfig: RouterConfig[] = [
},
{
path: "/customer",
name: t("我的应用"),
name: t("TXT_CODE_ec299306"),
component: LayoutContainer,
meta: {
permission: ROLE.USER,
@ -212,7 +212,7 @@ let originRouterConfig: RouterConfig[] = [
children: [
{
path: "/quickstart/minecraft",
name: t("创建 Minecraft 实例"),
name: t("TXT_CODE_8d8b1d6a"),
component: LayoutContainer,
meta: {
permission: ROLE.ADMIN

View File

@ -22,9 +22,7 @@ export function useLayoutCardTools(card: LayoutCard) {
}
if (require)
throw new Error(
[t("卡片所需参数"), `"${key}"`, t("不存在于 URL 地址或初始化设定中。")].join(" ")
);
throw new Error([t("TXT_CODE_93a70cda"), `"${key}"`, t("TXT_CODE_2222777e")].join(" "));
return undefined;
};

View File

@ -93,7 +93,7 @@ export const useFileManager = (instanceId?: string, daemonId?: string) => {
dialog.value.mode != "unzip" &&
dialog.value.mode != "permission"
) {
return message.error(t("请输入内容"));
return message.error(t("TXT_CODE_4ea93630"));
}
resolve(dialog.value.value);
dialog.value.show = false;
@ -128,13 +128,13 @@ export const useFileManager = (instanceId?: string, daemonId?: string) => {
const reloadList = async () => {
await getFileList();
return message.success(t("刷新文件列表成功"));
return message.success(t("TXT_CODE_8ccb5428"));
};
const touchFile = async (dir?: boolean) => {
const dirname = dir
? await openDialog(t("新建目录"), t("请输入目录名称"))
: await openDialog(t("新建文件"), t("请输入文件名"));
? await openDialog(t("TXT_CODE_6215388a"), t("TXT_CODE_1b450b79"))
: await openDialog(t("TXT_CODE_791c73e9"), t("TXT_CODE_59cb16ff"));
const execute = dir ? addFolderApi().execute : touchFileApi().execute;
try {
@ -148,7 +148,7 @@ export const useFileManager = (instanceId?: string, daemonId?: string) => {
}
});
await getFileList();
message.success(t("创建成功"));
message.success(t("TXT_CODE_d28c05df"));
} catch (error: any) {
return message.error(error.message);
}
@ -162,17 +162,18 @@ export const useFileManager = (instanceId?: string, daemonId?: string) => {
};
} else {
if (!selectionData.value || selectionData.value.length === 0)
return message.error(t("请先选择文件"));
return message.error(t("TXT_CODE_b152cd75"));
clipboard.value = {
type,
value: selectionData.value?.map((e) => breadcrumbs[breadcrumbs.length - 1].path + e.name)
};
}
message.success(t("已保存至剪切板"));
message.success(t("TXT_CODE_25cb04bb"));
};
const paste = async () => {
if (!clipboard?.value?.type || !clipboard.value.value) return message.error(t("请先选择文件"));
if (!clipboard?.value?.type || !clipboard.value.value)
return message.error(t("TXT_CODE_b152cd75"));
const execute = clipboard.value.type == "copy" ? copyFileApi().execute : moveFileApi().execute;
try {
await execute({
@ -188,7 +189,7 @@ export const useFileManager = (instanceId?: string, daemonId?: string) => {
}
});
await getFileList();
message.success(t("文件操作任务开始,如果文件数量过多,则需要一定时间"));
message.success(t("TXT_CODE_93d4b66a"));
clipboard.value.value = [];
} catch (error: any) {
message.error(error.message);
@ -196,7 +197,7 @@ export const useFileManager = (instanceId?: string, daemonId?: string) => {
};
const resetName = async (file: string) => {
const newname = await openDialog(t("重命名"), t("请输入新名称"), file);
const newname = await openDialog(t("TXT_CODE_c83551f5"), t("TXT_CODE_a5830778"), file);
try {
const { execute } = moveFileApi();
await execute({
@ -213,7 +214,7 @@ export const useFileManager = (instanceId?: string, daemonId?: string) => {
]
}
});
message.success(t("重命名成功"));
message.success(t("TXT_CODE_5b990e2e"));
await getFileList();
} catch (error: any) {
return error.message;
@ -234,7 +235,7 @@ export const useFileManager = (instanceId?: string, daemonId?: string) => {
}
});
await getFileList();
message.success(t("文件删除任务开始,如果文件数量过多,则需要一定时间"));
message.success(t("TXT_CODE_cae10a08"));
if (dataSource?.value?.length === 0 && operationForm.value.current > 1) {
operationForm.value.current -= 1;
await getFileList();
@ -245,23 +246,23 @@ export const useFileManager = (instanceId?: string, daemonId?: string) => {
};
Modal.confirm({
title: t("你确定要删除吗?"),
title: t("TXT_CODE_71155575"),
icon: createVNode(ExclamationCircleOutlined),
content: createVNode("div", { style: "color:red;" }, t("删除后将无法恢复!")),
content: createVNode("div", { style: "color:red;" }, t("TXT_CODE_6a10302d")),
async onOk() {
if (file) {
// one file
await useDeleteFileApi([breadcrumbs[breadcrumbs.length - 1].path + file]);
} else {
// more file
if (!selectionData.value) return message.error(t("请选择要删除的内容"));
if (!selectionData.value) return message.error(t("TXT_CODE_f41ad30a"));
await useDeleteFileApi(
selectionData.value.map((e) => breadcrumbs[breadcrumbs.length - 1].path + e.name)
);
}
},
okType: "danger",
okText: t("确定"),
okText: t("TXT_CODE_d507abff"),
class: "test"
});
return;
@ -269,8 +270,8 @@ export const useFileManager = (instanceId?: string, daemonId?: string) => {
const zipFile = async () => {
if (!selectionData.value || selectionData.value.length === 0)
return message.error(t("请先选择文件"));
const filename = await openDialog(t("压缩文件"), t("请输入压缩后的文件名"), "", "zip");
return message.error(t("TXT_CODE_b152cd75"));
const filename = await openDialog(t("TXT_CODE_f8a15a94"), t("TXT_CODE_366bad15"), "", "zip");
const { execute } = compressFileApi();
try {
await execute({
@ -285,7 +286,7 @@ export const useFileManager = (instanceId?: string, daemonId?: string) => {
targets: selectionData.value.map((e) => breadcrumbs[breadcrumbs.length - 1].path + e.name)
}
});
message.success(t("文件压缩任务开始,如果文件数量过多,则需要一定时间"));
message.success(t("TXT_CODE_377e142"));
await getFileList();
} catch (error: any) {
message.error(error.message);
@ -293,7 +294,7 @@ export const useFileManager = (instanceId?: string, daemonId?: string) => {
};
const unzipFile = async (name: string) => {
const dirname = await openDialog(t("解压文件"), "", "", "unzip");
const dirname = await openDialog(t("TXT_CODE_7669fd3f"), "", "", "unzip");
const { execute } = compressFileApi();
try {
@ -312,7 +313,7 @@ export const useFileManager = (instanceId?: string, daemonId?: string) => {
: breadcrumbs[breadcrumbs.length - 1].path + dirname
}
});
message.success(t("文件解压任务开始,如果文件数量过多,则需要一定时间"));
message.success(t("TXT_CODE_16f55a9b"));
await getFileList();
} catch (error: any) {
message.error(error.message);
@ -334,7 +335,7 @@ export const useFileManager = (instanceId?: string, daemonId?: string) => {
uuid: instanceId!
}
});
if (!uploadCfg.value) throw new Error(t("获取上传地址失败"));
if (!uploadCfg.value) throw new Error(t("TXT_CODE_e8ce38c2"));
const uploadFormData = new FormData();
uploadFormData.append("file", file);
@ -350,7 +351,7 @@ export const useFileManager = (instanceId?: string, daemonId?: string) => {
});
await getFileList();
percentComplete.value = 0;
return message.success(t("上传成功"));
return message.success(t("TXT_CODE_773f36a0"));
} catch (err: any) {
console.error(err);
return message.error(err.message);
@ -390,7 +391,7 @@ export const useFileManager = (instanceId?: string, daemonId?: string) => {
uuid: instanceId!
}
});
if (!downloadCfg.value) throw new Error(t("获取下载地址失败"));
if (!downloadCfg.value) throw new Error(t("TXT_CODE_6d772765"));
window.open(
`${parseForwardAddress(downloadCfg.value.addr, "http")}/download/${
downloadCfg.value.password
@ -403,7 +404,8 @@ export const useFileManager = (instanceId?: string, daemonId?: string) => {
};
const handleChangeDir = async (dir: string) => {
if (breadcrumbs.findIndex((e) => e.path === dir) === -1) return message.error(t("找不到路径"));
if (breadcrumbs.findIndex((e) => e.path === dir) === -1)
return message.error(t("TXT_CODE_96281410"));
spinning.value = true;
breadcrumbs.splice(breadcrumbs.findIndex((e) => e.path === dir) + 1);
await getFileList();
@ -446,15 +448,15 @@ export const useFileManager = (instanceId?: string, daemonId?: string) => {
loading: false,
item: [
{
key: t("所有者"),
key: t("TXT_CODE_2e5d3d0f"),
role: "owner"
},
{
key: t("用户组"),
key: t("TXT_CODE_e7b75c0e"),
role: "usergroup"
},
{
key: t("任何人"),
key: t("TXT_CODE_5c54f599"),
role: "everyone"
}
]
@ -463,7 +465,7 @@ export const useFileManager = (instanceId?: string, daemonId?: string) => {
permission.loading = true;
permission.data = number2permission(mode);
permission.loading = false;
await openDialog(t("更改权限"), "", "", "permission", {
await openDialog(t("TXT_CODE_16853efe"), "", "", "permission", {
maxWidth: "450px"
});
const { execute } = changePermissionApi();
@ -483,7 +485,7 @@ export const useFileManager = (instanceId?: string, daemonId?: string) => {
target: breadcrumbs[breadcrumbs.length - 1].path + name
}
});
message.success(t("更改权限成功"));
message.success(t("TXT_CODE_b05948d1"));
await getFileList();
} catch (err: any) {
return message.error(err.message);

View File

@ -162,7 +162,7 @@ export function getInstanceConfigByType(type: string) {
export const INSTANCE_CONFIGS: InstanceConfigs[] = [
{
// 配置文件显示名
fileName: t("[通用] server.properties"),
fileName: t("TXT_CODE_9b36d5a2"),
// 配置文件对应的实际路径(相对于实例根目录)
path: "server.properties",
// 配置文件用于显示界面的组件名
@ -170,9 +170,7 @@ export const INSTANCE_CONFIGS: InstanceConfigs[] = [
// 配置文件解析类型,支持 yml,json,txt,properties
type: "properties",
// 配置文件中文解释
info: t(
"Minecraft 服务端极其重要的配置文件,几乎绝大部分常用配置(端口,人数,视距等)均在此文件中进行编辑"
),
info: t("TXT_CODE_12e3afa9"),
// 在哪些服务端类型下此配置文件可见
category: [
TYPE_MINECRAFT_SPIGOT,
@ -185,9 +183,9 @@ export const INSTANCE_CONFIGS: InstanceConfigs[] = [
]
},
{
fileName: t("[通用] eula.txt"),
fileName: t("TXT_CODE_90f684dc"),
type: "properties",
info: t("软件最终用户协议,此协议必须设置同意,否则无法启用服务端软件"),
info: t("TXT_CODE_ab4cc2dc"),
path: "eula.txt",
redirect: "common/eula.txt",
category: [
@ -204,9 +202,7 @@ export const INSTANCE_CONFIGS: InstanceConfigs[] = [
path: "spigot.yml",
redirect: "bukkit/spigot.yml",
type: "yml",
info: t(
"Spigot 配置文件,能够进一步的控制服务器的行为和具体参数,一些更为高级的限制都在此配置文件中"
),
info: t("TXT_CODE_509d7d9a"),
category: [
TYPE_MINECRAFT_SPIGOT,
TYPE_MINECRAFT_PAPER,
@ -219,7 +215,7 @@ export const INSTANCE_CONFIGS: InstanceConfigs[] = [
path: "bukkit.yml",
redirect: "bukkit/bukkit.yml",
type: "yml",
info: t("Bukkit 原始配置文件"),
info: t("TXT_CODE_d03c3e0e"),
category: [
TYPE_MINECRAFT_SPIGOT,
TYPE_MINECRAFT_PAPER,
@ -230,9 +226,7 @@ export const INSTANCE_CONFIGS: InstanceConfigs[] = [
{
fileName: "[Bungeecord] config.yml",
type: "yml",
info: t(
"Bungeecord 群组服务端的重要配置文件,可以进行分布式管理,节点控制等,但此配置文件较为复杂,此处仅供简单的配置和操作"
),
info: t("TXT_CODE_e9dcbfe4"),
path: "config.yml",
redirect: "bungeecord/config.yml",
category: [TYPE_MINECRAFT_JAVA, TYPE_MINECRAFT_BUNGEECORD]
@ -240,9 +234,7 @@ export const INSTANCE_CONFIGS: InstanceConfigs[] = [
{
fileName: "[Velocity] velocity.toml",
type: "toml",
info: t(
"Velocity 群组服务端的重要配置文件,可以进行分布式管理,节点控制等,但此配置文件较为复杂,此处仅供简单的配置和操作"
),
info: t("TXT_CODE_751f9bc1"),
path: "velocity.toml",
redirect: "velocity/velocity.toml",
category: [TYPE_MINECRAFT_JAVA, TYPE_MINECRAFT_VELOCITY]
@ -252,9 +244,7 @@ export const INSTANCE_CONFIGS: InstanceConfigs[] = [
path: "server.properties",
redirect: "bds/server.properties",
type: "properties",
info: t(
"Minecraft Bedrock 服务端极其重要的配置文件,几乎绝大部分常用配置(端口,人数,视距等)均在此文件中进行编辑"
),
info: t("TXT_CODE_3a3f9a57"),
category: [TYPE_MINECRAFT_BDS, TYPE_MINECRAFT_BEDROCK]
},
{
@ -262,15 +252,13 @@ export const INSTANCE_CONFIGS: InstanceConfigs[] = [
path: "mohist.yml",
redirect: "mohist/mohist.yml",
type: "yml",
info: t("mohist.yml 服务端配置文件"),
info: t("TXT_CODE_6eead111"),
category: [TYPE_MINECRAFT_JAVA, TYPE_MINECRAFT_MOHIST]
},
{
fileName: "[Paper] paper.yml",
type: "yml",
info: t(
"PaperSpigot 服务端软件配置文件,能够进一步的配置高级参数以及更具体化的游戏设置,对整体性能有极大的决定效果,他拓展了 Spigot 配置文件上的不足之处。"
),
info: t("TXT_CODE_f3fc17f3"),
path: "paper.yml",
redirect: "paper/paper.yml",
category: [TYPE_MINECRAFT_JAVA, TYPE_MINECRAFT_PAPER]
@ -278,9 +266,7 @@ export const INSTANCE_CONFIGS: InstanceConfigs[] = [
{
fileName: "[Paper] paper-global.yml",
type: "yml",
info: t(
"PaperSpigot 服务端软件全局配置文件,能够进一步的配置高级参数以及更具体化的游戏设置,对整体性能有极大的决定效果"
),
info: t("TXT_CODE_2931127f"),
path: "config/paper-global.yml",
redirect: "paper/paper-global.yml",
category: [TYPE_MINECRAFT_JAVA, TYPE_MINECRAFT_PAPER]
@ -288,7 +274,7 @@ export const INSTANCE_CONFIGS: InstanceConfigs[] = [
{
fileName: "[Paper] paper-world-defaults.yml",
type: "yml",
info: t("PaperSpigot 服务端软件世界配置文件,能够进一步在每个世界的基础上进行配置"),
info: t("TXT_CODE_4880ef77"),
path: "config/paper-world-defaults.yml",
redirect: "paper/paper-world-defaults.yml",
category: [TYPE_MINECRAFT_JAVA, TYPE_MINECRAFT_PAPER]
@ -296,9 +282,7 @@ export const INSTANCE_CONFIGS: InstanceConfigs[] = [
{
fileName: "[Geyser] config.yml",
type: "yml",
info: t(
"Geyser 独立版服务端软件配置文件,拥有基本的服务器参数设定(如端口,最大玩家数等)并且也可以设定服务端细节参数(区块缓存,线程数等)"
),
info: t("TXT_CODE_1d39feca"),
path: "config.yml",
redirect: "geyser/config.yml",
category: [TYPE_MINECRAFT_JAVA, TYPE_MINECRAFT_GEYSER]
@ -306,7 +290,7 @@ export const INSTANCE_CONFIGS: InstanceConfigs[] = [
{
fileName: "[MCDR] config.yml",
type: "yml",
info: t("MCDReforged 服务端控制工具配置文件"),
info: t("TXT_CODE_25699fea"),
path: "config.yml",
redirect: "mcdr/config.yml",
category: [TYPE_MINECRAFT_JAVA, TYPE_MINECRAFT_MCDR]
@ -314,7 +298,7 @@ export const INSTANCE_CONFIGS: InstanceConfigs[] = [
{
fileName: "[MCDR] permission.yml",
type: "yml",
info: t("MCDReforged 服务端控制工具权限配置文件"),
info: t("TXT_CODE_5207688f"),
path: "permission.yml",
redirect: "mcdr/permission.yml",
category: [TYPE_MINECRAFT_JAVA, TYPE_MINECRAFT_MCDR]

View File

@ -52,22 +52,22 @@ export function useQuickStartFlow() {
const step1: ActionButtons[] = [
{
title: t("Minecraft Java版游戏服务器"),
title: t("TXT_CODE_9e3f25e0"),
key: QUICKSTART_ACTION_TYPE.Minecraft,
icon: AppstoreAddOutlined
},
{
title: t("Minecraft 基岩版游戏服务器"),
title: t("TXT_CODE_c8261c85"),
key: QUICKSTART_ACTION_TYPE.Bedrock,
icon: AppstoreAddOutlined
},
{
title: t("Steam 游戏服务器"),
title: t("TXT_CODE_dd8d27ce"),
key: QUICKSTART_ACTION_TYPE.SteamGameServer,
icon: ShoppingCartOutlined
},
{
title: t("部署任何控制台可执行程序"),
title: t("TXT_CODE_e08e63b5"),
key: QUICKSTART_ACTION_TYPE.AnyApp,
icon: TransactionOutlined
}
@ -81,7 +81,7 @@ export function useQuickStartFlow() {
createMethod?: QUICKSTART_METHOD;
remoteUuid?: string;
}>({
title: t("您想部署一个什么应用实例?"),
title: t("TXT_CODE_724ce74d"),
step: 1,
actions: step1
});
@ -98,17 +98,17 @@ export function useQuickStartFlow() {
icon: NodeIndexOutlined
};
});
formData.title = t("新的程序部署在哪台机器?");
formData.title = t("TXT_CODE_d182c422");
};
const toStep3 = (remoteUuid: string) => {
formData.step = 3;
formData.title = t("请选择部署应用实例的方式?");
formData.title = t("TXT_CODE_49981cb9");
formData.remoteUuid = remoteUuid;
currentIcon.value = CalculatorTwoTone;
formData.actions = arrayFilter<ActionButtons>([
{
title: t("Minecraft 快速部署"),
title: t("TXT_CODE_266b7246"),
key: QUICKSTART_METHOD.FAST,
icon: AppstoreAddOutlined,
condition: () =>
@ -124,22 +124,22 @@ export function useQuickStartFlow() {
}
},
{
title: t("上传单个服务端软件"),
title: t("TXT_CODE_444db70f"),
key: QUICKSTART_METHOD.FILE,
icon: CloudUploadOutlined
},
{
title: t("上传服务端文件压缩包"),
title: t("TXT_CODE_f2a58270"),
key: QUICKSTART_METHOD.IMPORT,
icon: FileZipOutlined
},
{
title: t("选择服务器现有目录"),
title: t("TXT_CODE_1baf656e"),
key: QUICKSTART_METHOD.SELECT,
icon: FolderOpenOutlined
},
{
title: t("无需额外文件"),
title: t("TXT_CODE_c14caab"),
key: QUICKSTART_METHOD.EXIST,
icon: FileExcelOutlined
}
@ -154,12 +154,12 @@ export function useQuickStartFlow() {
const toStep5 = (instanceId?: string) => {
formData.step = 5;
formData.title = t("恭喜,实例创建成功");
formData.title = t("TXT_CODE_2958a0f8");
currentIcon.value = SmileTwoTone;
formData.actions = arrayFilter<ActionButtons>([
{
title: t("前往实例控制台"),
title: t("TXT_CODE_36417656"),
key: "console",
icon: CodeOutlined,
click: () => {
@ -174,7 +174,7 @@ export function useQuickStartFlow() {
}
},
{
title: t("前往实例文件管理"),
title: t("TXT_CODE_2864bfbc"),
key: "files",
icon: FolderOpenOutlined,
click: () => {
@ -189,7 +189,7 @@ export function useQuickStartFlow() {
}
},
{
title: t("返回面板首页"),
title: t("TXT_CODE_d4146944"),
key: "main",
icon: HomeOutlined,
click: () => {

View File

@ -1,6 +1,6 @@
import { t } from "@/lang/i18n";
export function computeNodeName(ip: string, available: boolean, remark?: string) {
const online = available ? "" : t("(离线)");
const online = available ? "" : t("TXT_CODE_836addb9");
return remark ? `${remark} - ${ip} ${online}` : `${ip} ${online}`;
}

View File

@ -14,11 +14,11 @@ export const TERMINAL_CODE = [
];
export const INSTANCE_STATUS = {
"-1": t("状态未知"),
"0": t("已停止"),
"1": t("正在停止"),
"2": t("正在启动"),
"3": t("正在运行")
"-1": t("TXT_CODE_6ffdeae8"),
"0": t("TXT_CODE_4ef6b040"),
"1": t("TXT_CODE_6bb63f94"),
"2": t("TXT_CODE_ecfe33cb"),
"3": t("TXT_CODE_f912fadc")
};
export const defaultDockerFile = `FROM ubuntu:latest\nRUN mkdir -p /workspace\nWORKDIR /workspace\n`;
@ -82,17 +82,17 @@ WORKDIR /workspace
`;
export const ScheduleAction = {
command: t("发送命令"),
stop: t("停止实例"),
start: t("开启实例"),
restart: t("重启实例"),
kill: t("终止实例")
command: t("TXT_CODE_b7cab91d"),
stop: t("TXT_CODE_148d6467"),
start: t("TXT_CODE_8c7318b3"),
restart: t("TXT_CODE_77cc12da"),
kill: t("TXT_CODE_1c36c8f2")
};
export const ScheduleType = {
1: t("间隔时间性任务"),
2: t("周期时间性任务"),
3: t("指定时间性任务")
1: t("TXT_CODE_ba497a8b"),
2: t("TXT_CODE_f17af923"),
3: t("TXT_CODE_c4f90da6")
};
export enum ScheduleCreateType {

View File

@ -89,7 +89,7 @@ onMounted(async () => {});
</a-typography-title>
<a-typography-paragraph>
<a-typography-text>
{{ t("开源,分布式,开箱即用,支持 Minecraft 游戏服务端和所有控制台程序的管理面板") }}
{{ t("TXT_CODE_81d7e7c5") }}
</a-typography-text>
</a-typography-paragraph>
</a-typography>
@ -101,10 +101,10 @@ onMounted(async () => {});
size="large"
@click="step = 2"
>
{{ t("面板已安装,不可重复安装") }}
{{ t("TXT_CODE_3371000d") }}
</a-button>
<a-button v-else class="mt-45 mb-45" type="primary" size="large" @click="step = 2">
{{ t("开始使用") }}
{{ t("TXT_CODE_351aaf7") }}
</a-button>
<a-typography>
<a-typography-paragraph>
@ -114,7 +114,7 @@ onMounted(async () => {});
</a>
</a-typography-text>
<br />
<a-typography-text> Released under the Apache-2.0 License. </a-typography-text>
<a-typography-text>Released under the Apache-2.0 License.</a-typography-text>
</a-typography-paragraph>
</a-typography>
</template>
@ -125,20 +125,23 @@ onMounted(async () => {});
<template #body>
<a-typography>
<a-typography-title :level="3">
{{ t("创建一个访问面板的管理员账号") }}
{{ t("TXT_CODE_f880b5ad") }}
</a-typography-title>
<a-typography-paragraph>
<a-typography-text>
{{ t("用户名支持任何语言,请务必保证您的密码安全。") }}
{{ t("TXT_CODE_3a056dc8") }}
</a-typography-text>
</a-typography-paragraph>
</a-typography>
<a-form ref="formRef" :model="formData" :label-col="{ span: 4 }" autocomplete="off">
<a-form-item name="username" :rules="[{ required: true, message: t('请输入用户名') }]">
<a-form-item
name="username"
:rules="[{ required: true, message: t('TXT_CODE_2695488c') }]"
>
<a-input
v-model:value="formData.username"
autocomplete="off"
:placeholder="t('用户名')"
:placeholder="t('TXT_CODE_eb9fcdad')"
/>
</a-form-item>
@ -148,20 +151,20 @@ onMounted(async () => {});
{
required: true,
pattern: /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).{9,36}$/,
message: t('密码必须是 9 到 36 个字符,并且包含大小写字母和数字')
message: t('TXT_CODE_ad533c70')
}
]"
>
<a-input-password
v-model:value="formData.password"
autocomplete="off"
:placeholder="t('密码')"
:placeholder="t('TXT_CODE_551b0348')"
/>
</a-form-item>
<a-form-item :wrapper-col="{ span: 16 }">
<a-button :loading="installLoading" type="primary" @click="createUser">
{{ t("创建账号") }}
{{ t("TXT_CODE_11d5caea") }}
</a-button>
</a-form-item>
</a-form>
@ -173,28 +176,28 @@ onMounted(async () => {});
<template #body>
<a-typography>
<a-typography-title :level="3">
{{ t("大功告成!") }}
{{ t("TXT_CODE_97be50a8") }}
</a-typography-title>
<a-typography-paragraph>
<a-typography-text>
{{ t("最后,您是第一次使用此软件吗?") }}
{{ t("TXT_CODE_cd923ade") }}
</a-typography-text>
</a-typography-paragraph>
</a-typography>
<div class="final-btn mb-15" @click="toQuickStart">
<a-typography-title :level="5">
{{ t("首次使用") }}
{{ t("TXT_CODE_6f98ccd7") }}
</a-typography-title>
<a-typography-text>
{{ t("我们将引导你使用并部署你的应用程序。") }}
{{ t("TXT_CODE_b5ca0563") }}
</a-typography-text>
</div>
<div class="final-btn" @click="toOverview">
<a-typography-title :level="5">
{{ t("老用户") }}
{{ t("TXT_CODE_b69550bf") }}
</a-typography-title>
<a-typography-text>
{{ t("以更专业化的界面供你使用。") }}
{{ t("TXT_CODE_95df80df") }}
</a-typography-text>
</div>
</template>

View File

@ -83,7 +83,7 @@ const initInstancesData = async () => {
}
});
} catch (err) {
return message.error(t("访问远程节点异常"));
return message.error(t("TXT_CODE_e109c091"));
}
};
@ -176,23 +176,23 @@ const instanceOperations = [
}
},
{
title: t("删除"),
title: t("TXT_CODE_ecbd7449"),
icon: DeleteOutlined,
click: () => batchDeleteInstance(false)
},
{
title: t("彻底删除"),
title: t("TXT_CODE_9ef27367"),
icon: WarningOutlined,
click: () => batchDeleteInstance(true)
}
];
const batchOperation = async (actName: "start" | "stop" | "kill") => {
if (selectedInstance.value.length === 0) return message.error(t("无法执行,请至少选择一个实例"));
if (selectedInstance.value.length === 0) return message.error(t("TXT_CODE_a0a77be5"));
const operationMap = {
start: async () => exec(batchStart().execute, t("开启命令已发出")),
stop: async () => exec(batchStop().execute, t("关闭命令已发出")),
kill: async () => exec(batchKill().execute, t("终止命令已发出"))
start: async () => exec(batchStart().execute, t("TXT_CODE_2b5fd76e")),
stop: async () => exec(batchStop().execute, t("TXT_CODE_4822a21")),
kill: async () => exec(batchKill().execute, t("TXT_CODE_effefaab"))
};
const exec = async (fn: Function, msg: string) => {
@ -206,9 +206,7 @@ const batchOperation = async (actName: "start" | "stop" | "kill") => {
if (state.value) {
notification.success({
message: msg,
description: t(
"已成功向各个远程主机发布命令,具体操作可能略有延时,请稍等一段时间后查看结果"
)
description: t("TXT_CODE_1514d08f")
});
exitMultipleMode();
await initInstancesData();
@ -223,19 +221,17 @@ const batchOperation = async (actName: "start" | "stop" | "kill") => {
};
const batchDeleteInstance = async (deleteFile: boolean) => {
if (selectedInstance.value.length === 0) return message.error(t("无法执行,请至少选择一个实例"));
if (selectedInstance.value.length === 0) return message.error(t("TXT_CODE_a0a77be5"));
const { execute, state } = batchDelete();
const uuids: string[] = [];
for (const i of selectedInstance.value) {
uuids.push(i.instanceUuid);
}
const confirmDeleteInstanceModal = Modal.confirm({
title: t("最终确认"),
title: t("TXT_CODE_2a3b0c17"),
icon: h(InfoCircleOutlined),
content: deleteFile
? t("确定要删除此实例和文件吗?此操作将会删除实例目录的所有文件,请谨慎操作")
: t("确定要进行批量移除吗?此操作不会删除实例实际文件,只会删除实例"),
okText: t("确定"),
content: deleteFile ? t("TXT_CODE_18d2f8ae") : t("TXT_CODE_ac01315a"),
okText: t("TXT_CODE_d507abff"),
async onOk() {
try {
await execute({
@ -251,8 +247,8 @@ const batchDeleteInstance = async (deleteFile: boolean) => {
confirmDeleteInstanceModal.destroy();
exitMultipleMode();
notification.success({
message: t("批量删除成功"),
description: t("可能会存在一定延迟,文件删除需要一定的时间")
message: t("TXT_CODE_c3c06801"),
description: t("TXT_CODE_50075e02")
});
await initInstancesData();
}
@ -337,7 +333,7 @@ onMounted(async () => {
<template v-if="instances" #left>
<div v-if="multipleMode">
<a-button class="mr-10" :class="{ 'mb-10': isPhone }" @click="exitMultipleMode">
{{ t("退出批量操作") }}
{{ t("TXT_CODE_5366af54") }}
</a-button>
<a-button
@ -346,7 +342,7 @@ onMounted(async () => {
:class="{ 'mb-10': isPhone }"
@click="selectedInstance = []"
>
{{ t("取消全选") }}
{{ t("TXT_CODE_df87c46d") }}
</a-button>
<a-button
v-else
@ -354,7 +350,7 @@ onMounted(async () => {
:class="{ 'mb-10': isPhone }"
@click="selectAllInstances"
>
{{ t("全选") }}
{{ t("TXT_CODE_f466d7a") }}
</a-button>
<a-dropdown>
<template #overlay>
@ -370,18 +366,18 @@ onMounted(async () => {
</a-menu>
</template>
<a-button type="primary">
{{ t("选中项") }}
{{ t("TXT_CODE_8fd8bfd3") }}
<DownOutlined />
</a-button>
</a-dropdown>
</div>
<div v-else>
<a-button @click="multipleMode = true">{{ t("批量操作") }}</a-button>
<a-button @click="multipleMode = true">{{ t("TXT_CODE_5cb656b9") }}</a-button>
</div>
</template>
<template v-if="multipleMode" #center>
<a-typography-text>
{{ t("已选择:") }}{{ selectedInstance.length }} {{ t("") }}
{{ t("TXT_CODE_432cbc38") }}{{ selectedInstance.length }} {{ t("TXT_CODE_5cd3b4bd") }}
</a-typography-text>
</template>
<template v-if="instances" #right>

View File

@ -136,9 +136,9 @@ const addNode = async () => {
}
});
editDialog.value.hidden();
message.success(t("添加节点成功"));
message.success(t("TXT_CODE_38c6392f"));
} catch (error: any) {
message.error(t("添加节点失败"));
message.error(t("TXT_CODE_2dfc1043"));
}
editDialog.value.loading = false;
};
@ -151,10 +151,10 @@ const deleteNode = async () => {
uuid: editDialog.value.uuid
}
});
message.success(t("删除节点成功"));
message.success(t("TXT_CODE_e53b3f9"));
editDialog.value.hidden();
} catch (error) {
message.error(t("删除节点失败"));
message.error(t("TXT_CODE_1b699a95"));
}
editDialog.value.loading = false;
};
@ -179,11 +179,11 @@ const editNode = async () => {
uuid: editDialog.value.uuid
}
});
message.success(t("保存成功"));
message.success(t("TXT_CODE_a7907771"));
editDialog.value.loading = false;
editDialog.value.hidden();
} catch (error) {
message.error(t("编辑节点失败"));
message.error(t("TXT_CODE_fdca0695"));
}
};
@ -191,7 +191,7 @@ const editMode = ref(false);
const editDialog = ref({
status: false,
loading: false,
title: computed(() => (editMode.value ? t("编辑节点信息") : t("新增节点"))),
title: computed(() => (editMode.value ? t("TXT_CODE_39c5229e") : t("TXT_CODE_15a381d5"))),
data: {
ip: "",
port: 24444,
@ -227,7 +227,7 @@ const editDialog = ref({
},
submit: async () => {
if (editDialog.value.check() === false) {
return message.error(t("请正确填写表单"));
return message.error(t("TXT_CODE_633415e2"));
}
editDialog.value.loading = true;
if (editMode.value) {
@ -333,32 +333,32 @@ const editDialog = ref({
<a-modal v-model:open="editDialog.status" :title="editDialog.title">
<a-form layout="vertical">
<a-form-item>
<a-typography-title :level="5">{{ t("备注信息") }}</a-typography-title>
<a-typography-title :level="5">{{ t("TXT_CODE_a884de59") }}</a-typography-title>
<a-typography-paragraph>
<a-typography-text type="secondary">
{{ t("必填,支持中文,用于填写相关备注信息") }}
{{ t("TXT_CODE_4b1d5199") }}
</a-typography-text>
</a-typography-paragraph>
<a-input v-model:value="editDialog.data.remarks" />
</a-form-item>
<a-form-item>
<a-typography-title :level="5">{{ t("远程节点所在主机的 IP 地址") }}</a-typography-title>
<a-typography-title :level="5">{{ t("TXT_CODE_93f9b02a") }}</a-typography-title>
<a-typography-paragraph>
<a-typography-text type="secondary">
{{ t("必须使用外网地址或 localhost 地址,否则将导致远程实例无法连接") }}
{{ t("TXT_CODE_be7a689a") }}
<br />
{{ t("可以是域名或者 IP 地址,例如 mcsmanager.com43.123.211.12") }}
{{ t("TXT_CODE_c82a51b0") }}
</a-typography-text>
</a-typography-paragraph>
<a-input v-model:value="editDialog.data.ip" />
</a-form-item>
<a-form-item>
<a-typography-title :level="5">{{ t("远程节点端口") }}</a-typography-title>
<a-typography-title :level="5">{{ t("TXT_CODE_4a6bf8c6") }}</a-typography-title>
<a-typography-paragraph>
<a-typography-text type="secondary">
{{ t("默认情况下是 24444。") }}
{{ t("TXT_CODE_df455795") }}
</a-typography-text>
</a-typography-paragraph>
<a-input v-model:value="editDialog.data.port" />
@ -366,40 +366,40 @@ const editDialog = ref({
<a-form-item>
<a-typography-title class="flex" :level="5">
{{ t("远程节点密钥") }}
{{ t("TXT_CODE_300c2ff4") }}
</a-typography-title>
<a-typography-paragraph>
<a-typography-text type="secondary">
{{ t("通过远程节点生成的密钥来认证身份,以确保多台机器集成工作的安全性。") }}
{{ t("TXT_CODE_5ef2cf20") }}
<a href="https://docs.mcsmanager.com/" target="_blank">{{ t("如何获取密钥?") }}</a>
<a href="https://docs.mcsmanager.com/" target="_blank">{{ t("TXT_CODE_be1351ce") }}</a>
</a-typography-text>
</a-typography-paragraph>
<a-input
v-model:value="editDialog.data.apiKey"
:placeholder="editMode ? t('留空表示不进行修改') : t('请输入密钥')"
:placeholder="editMode ? t('TXT_CODE_dc570cf2') : t('TXT_CODE_fe25087f')"
/>
</a-form-item>
</a-form>
<template #footer>
<div class="justify-space-between">
<a-popconfirm
:title="t('确定要永久删除该节点吗?')"
:title="t('TXT_CODE_fb267b0b')"
ok-text="Yes"
cancel-text="No"
@confirm="deleteNode()"
>
<a-button danger v-if="editMode" key="delete">{{ t("删除节点") }}</a-button>
<a-button danger v-if="editMode" key="delete">{{ t("TXT_CODE_8b937b23") }}</a-button>
</a-popconfirm>
<div class="right">
<a-button key="back" @click="editDialog.hidden()">{{ t("取消") }}</a-button>
<a-button key="back" @click="editDialog.hidden()">{{ t("TXT_CODE_a0451c97") }}</a-button>
<a-button
key="submit"
type="primary"
:loading="editDialog.loading"
@click="editDialog.submit()"
>
{{ t("确定") }}
{{ t("TXT_CODE_d507abff") }}
</a-button>
</div>
</div>

View File

@ -7,7 +7,7 @@ import { ExclamationCircleTwoTone } from "@ant-design/icons-vue";
<div style="height: 100%">
<ExclamationCircleTwoTone style="font-size: 70px" />
<a-typography-title class="mt-24" :level="3">
{{ t("当前地址不存在网页") }}
{{ t("TXT_CODE_fd63a181") }}
</a-typography-title>
</div>
</template>

View File

@ -91,17 +91,17 @@ const aboutLinks = [
url: "https://github.com/MCSManager/MCSManager"
},
{
title: t("官方网站"),
title: t("TXT_CODE_41dd4d19"),
icon: BankOutlined,
url: "https://mcsmanager.com/"
},
{
title: t("官方文档"),
title: t("TXT_CODE_74c3d3e5"),
icon: BookOutlined,
url: "https://docs.mcsmanager.com/"
},
{
title: t("反馈问题"),
title: t("TXT_CODE_26407d1f"),
icon: BookOutlined,
url: "https://github.com/MCSManager/MCSManager/issues"
}
@ -200,7 +200,7 @@ onMounted(async () => {
<div class="button">
<a-button type="primary" :loading="submitIsLoading" @click="submit()">
{{ t("保存") }}
{{ t("TXT_CODE_abfe9512") }}
</a-button>
</div>
</a-form>
@ -289,7 +289,7 @@ onMounted(async () => {
</a-form-item>
<div class="button">
<a-button type="primary" :loading="submitIsLoading" @click="submit()">
{{ t("保存") }}
{{ t("TXT_CODE_abfe9512") }}
</a-button>
</div>
</a-form>
@ -314,13 +314,13 @@ onMounted(async () => {
</div>
<a-typography-paragraph>
<p>
{{ $t("MCSManager 管理面板的进步离不开贡献者们与赞助者们的无私奉献。") }}
{{ $t("TXT_CODE_d0c670df") }}
</p>
<p v-if="isZhCN">
<span>
{{ $t("如果您愿意支持 MCSManager 后续发展,") }}
{{ $t("TXT_CODE_d2c79249") }}
<a href="https://github.com/MCSManager/MCSManager" target="_blank">
{{ t("请点击这里。") }}
{{ t("TXT_CODE_e4794d20") }}
</a>
</span>
</p>

View File

@ -16,12 +16,12 @@ const { execute, state } = userInfoApi();
const columns = [
{
title: t("实例名称"),
title: t("TXT_CODE_f70badb9"),
dataIndex: "nickname",
key: "nickname"
},
{
title: t("运行状态"),
title: t("TXT_CODE_5476e012"),
dataIndex: "status",
key: "status",
customRender: (e: { text: "-1" | "1" | "2" | "3" }) => {
@ -29,27 +29,27 @@ const columns = [
}
},
{
title: t("字节流编码"),
title: t("TXT_CODE_662ad338"),
dataIndex: "ie",
customRender: (e: { text: string; record: { oe: string; ie: string } }) => {
return `${e.text}/${e.record?.oe}`;
}
},
{
title: t("最后启动"),
title: t("TXT_CODE_5ab2062d"),
dataIndex: "lastDatetime",
key: "lastDatetime"
},
{
title: t("到期时间"),
title: t("TXT_CODE_fa920c0"),
dataIndex: "endTime",
key: "endTime",
customRender: (e: { text: string }) => {
return e.text || t("无期限");
return e.text || t("TXT_CODE_abc080d");
}
},
{
title: t("操作"),
title: t("TXT_CODE_fe731dfc"),
key: "operate"
}
];
@ -89,7 +89,9 @@ onMounted(() => {
>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'operate'">
<a-button @click="operate(record.serviceUuid, record.uuid)">{{ t("管理") }}</a-button>
<a-button @click="operate(record.serviceUuid, record.uuid)">{{
t("TXT_CODE_5974bf24")
}}</a-button>
</template>
</template>
</a-table>

View File

@ -31,22 +31,22 @@ const computedStatusList = computed(() => {
return [
{
type: "instance_all",
title: t("管理员所分配给您的所有实例总数"),
title: t("TXT_CODE_53745cc0"),
value: state.value.instances.length
},
{
type: "instance_running",
title: t("实例正在运行中的数量"),
title: t("TXT_CODE_7638590c"),
value: state.value.instances.filter((e) => e.status == 3).length
},
{
type: "instance_stop",
title: t("实例未处于运行中的数量"),
title: t("TXT_CODE_9bc7f49e"),
value: state.value.instances.filter((e) => e.status == 0).length
},
{
type: "instance_error",
title: t("暂时不可使用的实例数"),
title: t("TXT_CODE_ecf17071"),
value: state.value.instances.filter((e) => e.status == -1 || e.status == 1 || e.status == 2)
.length
}

View File

@ -19,9 +19,9 @@ const openDialog = async () => {
const progressList = ref<{ name: string; status: number }[]>([]);
const statusType: { [propsName: string]: string } = {
"-1": t("构建失败"),
"1": t("正在构建"),
"2": t("构建完成")
"-1": t("TXT_CODE_20ce2aae"),
"1": t("TXT_CODE_978da1c1"),
"2": t("TXT_CODE_47e182a5")
};
const { execute, state, isLoading } = buildProgress();
@ -57,7 +57,7 @@ defineExpose({
v-model:open="open"
centered
:width="isPhone ? '100%' : 'calc(100% - 30vw)'"
:title="t('构建进度')"
:title="t('TXT_CODE_4bbd3fde')"
>
<a-row v-if="!isLoading" :gutter="[24, 24]">
<a-col v-for="i in progressList" :key="i" :span="24" :lg="6" :md="8" :sm="12">
@ -78,8 +78,8 @@ defineExpose({
</a-row>
<template #footer>
<a-space>
<a-button :loading="isLoading" @click="getProgress">{{ t("刷新") }}</a-button>
<a-button type="primary" @click="open = false">{{ t("关闭") }}</a-button>
<a-button :loading="isLoading" @click="getProgress">{{ t("TXT_CODE_b76d94e0") }}</a-button>
<a-button type="primary" @click="open = false">{{ t("TXT_CODE_b1dedda3") }}</a-button>
</a-space>
</template>
</a-modal>

View File

@ -23,7 +23,7 @@ const { execute } = imageList();
const submit = async () => {
try {
if (!options.dockerFile || !options.name || !options.version)
return message.error(t("请填写表单完整"));
return message.error(t("TXT_CODE_2764f197"));
await execute({
params: {
remote_uuid: props.daemonId
@ -36,8 +36,8 @@ const submit = async () => {
method: "POST"
});
notification["info"]({
message: t("创建镜像任务已经开始"),
description: t("请耐心等待")
message: t("TXT_CODE_55edf44d"),
description: t("TXT_CODE_b340c04a")
});
emit("close");
} catch (err: any) {
@ -56,15 +56,15 @@ onMounted(() => {
<template>
<a-typography>
<a-typography-paragraph>
<a-typography-title :level="5">{{ t("关于 DockerFile 文件") }}</a-typography-title>
<a-typography-title :level="5">{{ t("TXT_CODE_868df02c") }}</a-typography-title>
<a-typography-text>
{{ t("官方参考文档https://docs.docker.com/engine/reference/builder/") }}
{{ t("TXT_CODE_77d93d7d") }}
</a-typography-text>
</a-typography-paragraph>
<a-typography-paragraph>
<a-typography-title :level="5">{{ t("注意事项") }}</a-typography-title>
<a-typography-title :level="5">{{ t("TXT_CODE_ef0ce2e") }}</a-typography-title>
<a-typography-text>
{{ t("必须创建 /workspace 目录,此目录将自动挂载到实例的文件根目录") }}
{{ t("TXT_CODE_5024d817") }}
</a-typography-text>
</a-typography-paragraph>
</a-typography>
@ -75,7 +75,7 @@ onMounted(() => {
<a-form-item>
<a-typography-text>
{{ t("创建后的镜像名与版本标识") }}
{{ t("TXT_CODE_7cf078e8") }}
</a-typography-text>
<a-input-group compact>
<a-input v-model:value="options.name" style="width: 65%" />
@ -83,10 +83,7 @@ onMounted(() => {
</a-input-group>
</a-form-item>
<a-popconfirm
:title="t('此构建过程可能需要几分钟时间,请确保网络畅通,是否继续?')"
@confirm="submit"
>
<a-button type="primary">{{ t("创建镜像") }}</a-button>
<a-popconfirm :title="t('TXT_CODE_4e4b52a0')" @confirm="submit">
<a-button type="primary">{{ t("TXT_CODE_3d09f0ac") }}</a-button>
</a-popconfirm>
</template>

View File

@ -35,28 +35,28 @@ const buildProgressDialog = ref<InstanceType<typeof BuildProgress>>();
const dockerFileDrawer = ref(false);
const imageList = [
{
title: t("创建 OpenJDK 8 环境镜像"),
description: t("内置 Java 16 运行时环境,适用于 Minecraft 1.7 ~ 1.16 版本的服务端"),
title: t("TXT_CODE_b09eff8f"),
description: t("TXT_CODE_d7c5823e"),
type: 1
},
{
title: t("创建 OpenJDK 16 环境镜像"),
description: t("内置 Java 16 运行时环境,适用于 Minecraft 1.17 版本的服务端"),
title: t("TXT_CODE_694952a"),
description: t("TXT_CODE_4fdbb351"),
type: 2
},
{
title: t("创建 OpenJDK 17 环境镜像"),
description: t("内置 Java 17 运行时环境,适用于 Minecraft 1.18 以上版本的服务端"),
title: t("TXT_CODE_9b9b745c"),
description: t("TXT_CODE_7d1a9487"),
type: 3
},
{
title: t("创建 Ubuntu 22.04 环境镜像"),
description: t("适用于 MC 基岩版服务端运行环境或者其他 Linux 程序"),
title: t("TXT_CODE_495027e1"),
description: t("TXT_CODE_41d79430"),
type: 4
},
{
title: t("使用 DockerFile 自定义创建"),
description: t("使用 DockerFile 自定义创建任何环境镜像,建议技术人员进行此操作"),
title: t("TXT_CODE_123bcd09"),
description: t("TXT_CODE_3d14442a"),
type: 5
}
];
@ -93,7 +93,7 @@ const selectType = (type: number) => {
version.value = "latest";
break;
default:
return message.error(t("未知的环境类型"));
return message.error(t("TXT_CODE_fb1ff943"));
}
dockerFileDrawer.value = true;
};
@ -122,10 +122,10 @@ onMounted(async () => {});
</template>
<template #right>
<a-button v-show="!screen.isPhone.value" class="mr-8" @click="toImageListPage">
{{ t("回到镜像列表") }}
{{ t("TXT_CODE_3a818e91") }}
</a-button>
<a-button type="primary" @click="buildProgressDialog?.openDialog()">
{{ t("查看构建进度") }}
{{ t("TXT_CODE_5544ec22") }}
</a-button>
</template>
</BetweenMenus>
@ -136,25 +136,17 @@ onMounted(async () => {});
<template #body>
<a-typography>
<a-typography-paragraph>
<a-typography-title :level="5">{{ t("什么是环境镜像?") }}</a-typography-title>
<a-typography-title :level="5">{{ t("TXT_CODE_d76ccb4f") }}</a-typography-title>
<a-typography-text>
{{
t(
"由于 Minecraft 或其他程序需要特定的运行环境,比如 Java/Python/.NET 等等,不同版本在同一台机器上安装管理十分复杂,使用不同的环境镜像可以很方便的管理不同版本不同类型的服务环境。"
)
}}
{{ t("TXT_CODE_528753e7") }}
</a-typography-text>
</a-typography-paragraph>
<a-typography-paragraph>
<a-typography-title :level="5">
{{ t("什么是 Docker为什么需要它") }}
{{ t("TXT_CODE_2ea7af21") }}
</a-typography-title>
<a-typography-text>
{{
t(
"Docker 是一款轻量级虚拟化软件,能够利用环境镜像来创建容器(就像一个盒子)包裹你的实际应用程序,让你的应用程序在一个虚拟的沙箱环境中运行,不论应用程序做任何恶意操作,都不会影响到宿主机的任何文件。"
)
}}
{{ t("TXT_CODE_ba1eb3b5") }}
</a-typography-text>
</a-typography-paragraph>
</a-typography>

View File

@ -37,7 +37,7 @@ const getImageList = async () => {
centered: true,
closable: true,
content: err.message,
title: t("错误")
title: t("TXT_CODE_ac405b50")
});
}
};
@ -54,14 +54,14 @@ const imageColumns = computed(() => {
},
{
align: "center",
title: t("名称"),
title: t("TXT_CODE_bff43de3"),
dataIndex: "RepoTags",
key: "RepoTags",
customRender: (e: { text: string[] }) => e.text[0]
},
{
align: "center",
title: t("占用空间"),
title: t("TXT_CODE_6f91f3ba"),
dataIndex: "Size",
key: "Size",
customRender: (e: { text: number }) => `${parseInt((e.text / 1024 / 1024).toString())} MB`
@ -80,11 +80,8 @@ const showDetail = (info: ImageInfo) => {
centered: true,
closable: true,
content: [
h("b", t("关于详情信息")),
h(
"p",
t("Docker 镜像与容器等详细信息建议由技术人员阅读,此处提供完整的 JSON 格式信息内容。")
),
h("b", t("TXT_CODE_c372cef8")),
h("p", t("TXT_CODE_bbd7d448")),
h("pre", {
innerHTML: JSON.stringify(info, null, 4),
style: {
@ -93,7 +90,7 @@ const showDetail = (info: ImageInfo) => {
}
})
],
title: t("信息详情"),
title: t("TXT_CODE_9d820cb4"),
width: 666
});
};
@ -108,8 +105,8 @@ const delImage = async (item: ImageInfo) => {
method: "DELETE"
});
notification["info"]({
message: t("删除指令已发出"),
description: t("请耐心等待,使用刷新功能加载列表,稍后此镜像预计将会被删除")
message: t("TXT_CODE_638bca20"),
description: t("TXT_CODE_d11bf156")
});
} catch (err: any) {
console.error(err);
@ -129,25 +126,25 @@ const containerColumns = computed(() => {
},
{
align: "center",
title: t("启动命令"),
title: t("TXT_CODE_d12fa808"),
dataIndex: "Command",
key: "Command"
},
{
align: "center",
title: t("使用镜像"),
title: t("TXT_CODE_47c62dac"),
dataIndex: "Image",
key: "Image"
},
{
align: "center",
title: t("状态"),
title: t("TXT_CODE_759fb403"),
dataIndex: "State",
key: "State"
},
{
align: "center",
title: t("情况"),
title: t("TXT_CODE_24e5bff2"),
dataIndex: "Status",
key: "Status"
},
@ -206,10 +203,10 @@ onMounted(async () => {
</template>
<template #right>
<a-button v-show="!screen.isPhone.value" class="mr-8" @click="getImageList">
{{ t("刷新") }}
{{ t("TXT_CODE_b76d94e0") }}
</a-button>
<a-button type="primary" @click="toNewImagePage">
{{ t("新增镜像") }}
{{ t("TXT_CODE_59ac0239") }}
<PlusOutlined />
</a-button>
</template>
@ -219,14 +216,12 @@ onMounted(async () => {
<a-col :span="24">
<CardPanel style="height: 100%">
<template #title>
{{ t("远程主机镜像列表") }}
{{ t("TXT_CODE_8b62abb2") }}
</template>
<template #body>
<a-typography-paragraph>
<a-typography-text>
{{
t("镜像构建与容器运行依赖于 Docker 软件,物理主机上所有远程节点将共享所有镜像。")
}}
{{ t("TXT_CODE_ba82dddb") }}
</a-typography-text>
</a-typography-paragraph>
<a-table
@ -246,14 +241,11 @@ onMounted(async () => {
</template>
<template v-if="column.key === 'action'">
<a-button class="mr-8" size="" @click="showDetail(record)">
{{ t("详情") }}
{{ t("TXT_CODE_f1b166e7") }}
</a-button>
<a-popconfirm
:title="t('此操作将永久删除该镜像, 是否继续?')"
@confirm="delImage(record)"
>
<a-popconfirm :title="t('TXT_CODE_dfa17b2d')" @confirm="delImage(record)">
<a-button size="" danger>
{{ t("删除") }}
{{ t("TXT_CODE_ecbd7449") }}
</a-button>
</a-popconfirm>
</template>
@ -266,16 +258,12 @@ onMounted(async () => {
<a-col :span="24">
<CardPanel style="height: 100%">
<template #title>
{{ t("远程主机容器列表") }}
{{ t("TXT_CODE_cb36c80e") }}
</template>
<template #body>
<a-typography-paragraph>
<a-typography-text>
{{
t(
"容器列表代表所有正在独立镜像环境运行的应用实例,此处列表不仅仅包括面板所启动的容器。"
)
}}
{{ t("TXT_CODE_b34efc1") }}
</a-typography-text>
</a-typography-paragraph>
<a-table
@ -295,7 +283,7 @@ onMounted(async () => {
</template>
<template v-if="column.key === 'action'">
<a-button class="mr-8" size="" @click="showDetail(record)">
{{ t("详情") }}
{{ t("TXT_CODE_f1b166e7") }}
</a-button>
</template>
</template>

View File

@ -25,7 +25,7 @@ const { statusText, isRunning, isStopped, instanceTypeText, instanceInfo, execut
const getInstanceName = computed(() => {
if (instanceInfo.value?.config.nickname === GLOBAL_INSTANCE_NAME) {
return t("节点终端");
return t("TXT_CODE_5bdaf23d");
} else {
return instanceInfo.value?.config.nickname;
}
@ -79,7 +79,7 @@ onMounted(async () => {
{{ t("TXT_CODE_8b8e08a6") }}{{ instanceInfo?.config.createDatetime }}
</a-typography-paragraph>
<a-typography-paragraph>
{{ t("启动次数:") }}{{ instanceInfo?.started }}
{{ t("TXT_CODE_ad30f3c5") }}{{ instanceInfo?.started }}
</a-typography-paragraph>
<a-typography-paragraph>
<span>{{ t("TXT_CODE_cec321b4") }}{{ instanceInfo?.config.oe.toUpperCase() }} </span>

View File

@ -2,7 +2,7 @@
import CardPanel from "@/components/CardPanel.vue";
import type { LayoutCard } from "@/types/index";
import { ref, computed, onMounted, watch } from "vue";
import { t } from "@/lang/i18n";
import { getCurrentLang, t } from "@/lang/i18n";
import { convertFileSize } from "@/tools/fileSize";
import dayjs from "dayjs";
import { DownOutlined, SearchOutlined, UploadOutlined } from "@ant-design/icons-vue";
@ -60,24 +60,24 @@ const columns = computed(() => {
return arrayFilter([
{
align: "left",
title: t("文件名"),
title: t("TXT_CODE_94c193de"),
dataIndex: "name",
key: "name",
minWidth: "200px"
},
{
align: "center",
title: t("类型"),
title: t("TXT_CODE_67d68dd1"),
dataIndex: "type",
key: "type",
customRender: (e: { text: number; record: { name: string } }) => {
return e.text == 1 ? filterFileName(e.record.name) : t("文件夹");
return e.text == 1 ? filterFileName(e.record.name) : t("TXT_CODE_e5f949c");
},
minWidth: "200px"
},
{
align: "center",
title: t("大小"),
title: t("TXT_CODE_94bb113a"),
dataIndex: "size",
key: "size",
customRender: (e: { text: number }) =>
@ -87,7 +87,7 @@ const columns = computed(() => {
},
{
align: "center",
title: t("修改时间"),
title: t("TXT_CODE_d3b29478"),
dataIndex: "time",
key: "time",
customRender: (e: { text: string }) => {
@ -98,7 +98,7 @@ const columns = computed(() => {
},
{
align: "center",
title: t("权限"),
title: t("TXT_CODE_511aea70"),
dataIndex: "mode",
key: "mode",
minWidth: "200px",
@ -106,7 +106,7 @@ const columns = computed(() => {
},
{
align: "center",
title: t("操作"),
title: t("TXT_CODE_fe731dfc"),
dataIndex: "action",
key: "action",
minWidth: "200px"
@ -163,7 +163,7 @@ onMounted(() => {
<upload-outlined v-if="percentComplete === 0" />
{{
percentComplete > 0
? t("正在上传:") + percentComplete + "%"
? t("TXT_CODE_b625dbf0") + percentComplete + "%"
: t("TXT_CODE_e00c858c")
}}
</a-button>
@ -178,7 +178,7 @@ onMounted(() => {
{{ t("TXT_CODE_f0260e51") }}
</a-button>
<a-button v-else class="mr-8" type="default" @click="reloadList()">
{{ t("刷新列表") }}
{{ t("TXT_CODE_a53573af") }}
</a-button>
<a-dropdown>
@ -192,7 +192,7 @@ onMounted(() => {
:show-upload-list="false"
>
<a-menu-item key="1" :disabled="percentComplete > 0">
{{ percentComplete > 0 ? t("上传中...") : t("TXT_CODE_e00c858c") }}
{{ percentComplete > 0 ? t("TXT_CODE_72608c07") : t("TXT_CODE_e00c858c") }}
</a-menu-item>
<template #itemRender=""></template>
</a-upload>
@ -208,7 +208,7 @@ onMounted(() => {
{{ t("TXT_CODE_13ae6a93") }}
</a-menu-item>
<a-menu-item key="6" @click="setClipBoard('move')">
{{ t("剪切") }}
{{ t("TXT_CODE_46c4169b") }}
</a-menu-item>
<a-menu-item key="7" @click="deleteFile()">
{{ t("TXT_CODE_ecbd7449") }}
@ -259,9 +259,7 @@ onMounted(() => {
style="color: #1677ff"
>
<a-spin />
{{
t("当前有 ") + fileStatus?.instanceFileTask + t(" 个压缩 / 解压任务正在运行中...")
}}
{{ t("TXT_CODE_dd06dea2") + fileStatus?.instanceFileTask + t("TXT_CODE_3e959ce7") }}
</p>
<a-spin :spinning="spinning">
<a-table
@ -328,7 +326,7 @@ onMounted(() => {
{{ t("TXT_CODE_13ae6a93") }}
</a-menu-item>
<a-menu-item key="4" @click="setClipBoard('move', record.name)">
{{ t("剪切") }}
{{ t("TXT_CODE_46c4169b") }}
</a-menu-item>
<a-menu-item key="5" @click="resetName(record.name)">
{{ t("TXT_CODE_c83551f5") }}
@ -340,7 +338,7 @@ onMounted(() => {
{{ t("TXT_CODE_a64f3007") }}
</a-menu-item>
<a-menu-item key="8" @click="downloadFile(record.name)">
{{ t("下载") }}
{{ t("TXT_CODE_65b21404") }}
</a-menu-item>
</a-menu>
</template>
@ -373,20 +371,20 @@ onMounted(() => {
v-if="dialog.mode == ''"
:ref="dialog.ref"
v-model:value="dialog.value"
:placeholder="t('请输入内容')"
:placeholder="t('TXT_CODE_4ea93630')"
/>
<a-space v-if="dialog.mode == 'unzip'" direction="vertical" class="w-100">
<a-typography-title :level="5">{{ t("请选择解压模式") }}</a-typography-title>
<a-typography-title :level="5">{{ t("TXT_CODE_a6453188") }}</a-typography-title>
<a-radio-group v-model:value="dialog.unzipmode">
<a-radio-button value="0">{{ t("解压到当前目录") }}</a-radio-button>
<a-radio-button value="1">{{ t("解压到新文件夹") }}</a-radio-button>
<a-radio-button value="0">{{ t("TXT_CODE_7907c99") }}</a-radio-button>
<a-radio-button value="1">{{ t("TXT_CODE_329fb904") }}</a-radio-button>
</a-radio-group>
<a-input
v-if="dialog.unzipmode == '1'"
v-model:value="dialog.value"
:placeholder="t('请输入文件夹名')"
:placeholder="t('TXT_CODE_377e5535')"
/>
</a-space>
@ -394,7 +392,7 @@ onMounted(() => {
<a-input
:ref="dialog.ref"
v-model:value="dialog.value"
:placeholder="t('请输入压缩后的文件名')"
:placeholder="t('TXT_CODE_366bad15')"
addon-after=". zip"
/>
</a-space>
@ -404,13 +402,13 @@ onMounted(() => {
direction="vertical"
class="w-100 mt-16"
>
<a-typography-title :level="5">{{ t("请选择压缩文件的格式") }}</a-typography-title>
<a-typography-text type="secondary">
{{ t("在解压/压缩文件时发现文件名存在乱码现象时,可以修改此选项解决。") }}
<a-typography-title :level="5">{{ t("TXT_CODE_2841f4a") }}</a-typography-title>
<a-typography-text v-if="getCurrentLang() == 'zh_cn'" type="secondary">
{{ t("TXT_CODE_b278707d") }}
<br />
{{ t("如果压缩包来源是中国大陆,一般可选 GBK;") }}
{{ t("TXT_CODE_48044fc2") }}
<br />
{{ t("如果是来自台湾香港地区可以选择BIG5如果来自其他地区可以选择 UTF-8。") }}
{{ t("TXT_CODE_76a82338") }}
</a-typography-text>
<a-radio-group v-model:value="dialog.code">
<a-radio-button value="utf-8">utf-8</a-radio-button>
@ -430,20 +428,20 @@ onMounted(() => {
<a-row class="direction-column son">
<h3 class="m-0">{{ item.key }}</h3>
<a-col class="m-5 options">
<a-checkbox value="4">{{ t("读取") }}</a-checkbox>
<a-checkbox value="4">{{ t("TXT_CODE_798f592e") }}</a-checkbox>
</a-col>
<a-col class="m-5 options">
<a-checkbox value="2">{{ t("写入") }}</a-checkbox>
<a-checkbox value="2">{{ t("TXT_CODE_46c4e9ac") }}</a-checkbox>
</a-col>
<a-col class="m-5 options">
<a-checkbox value="1">{{ t("执行") }}</a-checkbox>
<a-checkbox value="1">{{ t("TXT_CODE_e97669d8") }}</a-checkbox>
</a-col>
</a-row>
</a-checkbox-group>
</div>
<a-checkbox v-model:checked="permission.deep" class="mt-15">
{{ t("应用到子目录") }}
{{ t("TXT_CODE_74fd665e") }}
</a-checkbox>
</a-spin>
</a-space>

View File

@ -48,7 +48,7 @@ const deleteSchedule = async (name: string) => {
}
});
if (state.value) {
message.success(t("删除成功"));
message.success(t("TXT_CODE_28190dbc"));
await getScheduleList();
}
} catch (err: any) {
@ -72,7 +72,9 @@ const rendTime = (text: string, schedule: Schedule) => {
m -= 60;
h += 1;
}
return `${t("每隔")} ${h} ${t("小时")} ${m} ${t("分钟")} ${s} ${t("秒")}`;
return `${t("TXT_CODE_ec6d29f4")} ${h} ${t("TXT_CODE_e3db239d")} ${m} ${t(
"TXT_CODE_3b1bb444"
)} ${s} ${t("TXT_CODE_acabc771")}`;
}
case ScheduleCreateType.CYCLE: {
const time = text;
@ -81,7 +83,7 @@ const rendTime = (text: string, schedule: Schedule) => {
const m = timeArr[1];
const s = timeArr[0];
const w = timeArr[5];
return `${t("每星期")} ${w} ${t("的")} ${h}:${m}:${s}`;
return `${t("TXT_CODE_76750199")} ${w} / ${h}:${m}:${s}`;
}
case ScheduleCreateType.SPECIFY: {
const time = text;
@ -91,7 +93,7 @@ const rendTime = (text: string, schedule: Schedule) => {
const s = timeArr[0];
const dd = timeArr[3];
const mm = timeArr[4];
return `${mm} ${t("")} ${dd} ${t("")} ${h}:${m}:${s}`;
return `${mm} ${t("TXT_CODE_6cb9bb04")} ${dd} ${t("TXT_CODE_ca923eba")} ${h}:${m}:${s}`;
}
default:
return "Unknown Time";
@ -101,27 +103,27 @@ const rendTime = (text: string, schedule: Schedule) => {
const columns = [
{
align: "center",
title: t("任务名"),
title: t("TXT_CODE_2d542e4c"),
dataIndex: "name",
key: "name"
},
{
align: "center",
title: t("有效载荷"),
title: t("TXT_CODE_1544562"),
dataIndex: "payload",
key: "payload"
},
{
align: "center",
title: t("剩余次数"),
title: t("TXT_CODE_485e2d41"),
dataIndex: "count",
key: "count",
minWidth: "80px",
customRender: (e: { text: number }) => (e.text > 0 ? e.text : t("无限"))
customRender: (e: { text: number }) => (e.text > 0 ? e.text : t("TXT_CODE_a92df201"))
},
{
align: "center",
title: t("动作"),
title: t("TXT_CODE_82fbc5ad"),
dataIndex: "action",
key: "action",
minWidth: "180px",
@ -130,7 +132,7 @@ const columns = [
},
{
align: "center",
title: t("类型"),
title: t("TXT_CODE_67d68dd1"),
dataIndex: "type",
key: "type",
minWidth: "180px",
@ -138,7 +140,7 @@ const columns = [
},
{
align: "center",
title: t("触发时间"),
title: t("TXT_CODE_3554dac0"),
dataIndex: "time",
key: "time",
minWidth: "240px",
@ -154,7 +156,7 @@ const columns = [
const refresh = async () => {
await getScheduleList();
message.success(t("已刷新"));
message.success(t("TXT_CODE_fbde647e"));
};
const toConsole = () => {
@ -185,13 +187,13 @@ onMounted(async () => {
</template>
<template #right>
<a-button class="mr-10" @click="toConsole()">
{{ t("返回") }}
{{ t("TXT_CODE_c14b2ea3") }}
</a-button>
<a-button class="mr-10" @click="refresh">
{{ t("刷新") }}
{{ t("TXT_CODE_b76d94e0") }}
</a-button>
<a-button type="primary" @click="newScheduleDialog?.openDialog()">
{{ t("新增") }}
{{ t("TXT_CODE_1644b775") }}
</a-button>
</template>
</BetweenMenus>
@ -211,11 +213,11 @@ onMounted(async () => {
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'actions'">
<a-popconfirm
:title="t('你确定要删除这条计划任务吗?')"
:title="t('TXT_CODE_6ff0668f')"
@confirm="deleteSchedule(record.name)"
>
<a-button size="">
{{ t("删除") }}
{{ t("TXT_CODE_ecbd7449") }}
<DeleteOutlined />
</a-button>
</a-popconfirm>

View File

@ -84,7 +84,7 @@ const save = async () => {
data: config_
});
if (isOK.value) {
message.success(t("保存成功"));
message.success(t("TXT_CODE_a7907771"));
}
} catch (err: any) {
console.error(err);
@ -94,7 +94,7 @@ const save = async () => {
const refresh = async () => {
await render();
message.success(t("刷新成功"));
message.success(t("TXT_CODE_7863f28d"));
};
onMounted(async () => {
@ -109,31 +109,31 @@ onMounted(async () => {
<BetweenMenus>
<template #left>
<a-button class="mr-8" @click="toConfigOverview">
{{ t("返回配置文件列表") }}
{{ t("TXT_CODE_16ed68d") }}
</a-button>
</template>
<template #right>
<a-button type="primary" :loading="updateConfigFileLoading" class="mr-8" @click="save">
{{ t("保存文件") }}
{{ t("TXT_CODE_30a3c45d") }}
</a-button>
<a-button v-if="!isPhone" :loading="getConfigFileLoading" class="mr-8" @click="refresh">
{{ t("重新加载") }}
{{ t("TXT_CODE_d080f2d7") }}
</a-button>
<a-button v-if="!isPhone" type="dashed">
{{ t("编辑源文件") }}
{{ t("TXT_CODE_1f61e5a3") }}
</a-button>
<a-dropdown v-if="isPhone">
<template #overlay>
<a-menu>
<a-menu-item key="2" @click="refresh">
{{ t("重新加载") }}
{{ t("TXT_CODE_d080f2d7") }}
</a-menu-item>
<a-menu-item key="3">
{{ t("编辑源文件") }}
{{ t("TXT_CODE_1f61e5a3") }}
</a-menu-item>
</a-menu>
</template>
<a-button type="primary"> {{ t("更多操作") }}<DownOutlined /> </a-button>
<a-button type="primary"> {{ t("TXT_CODE_fbf985cb") }}<DownOutlined /> </a-button>
</a-dropdown>
</template>
</BetweenMenus>
@ -149,14 +149,10 @@ onMounted(async () => {
<Loading v-if="!isFailure" />
</a-col>
<a-col v-if="isFailure" :span="24">
<a-result
status="error"
:title="t('暂不支持编辑此文件')"
:sub-title="t('可能是面板无权访问此文件,可尝试使用 “文件管理” 对本文件进行编辑。')"
>
<a-result status="error" :title="t('TXT_CODE_f859eac')" :sub-title="t('TXT_CODE_b8814f15')">
<template #extra>
<a-button type="primary" @click="toConfigOverview">
{{ t("回到配置文件列表") }}
{{ t("TXT_CODE_537cd5ad") }}
</a-button>
</template>
</a-result>

View File

@ -46,7 +46,7 @@ const render = async () => {
files: files
}
});
if (!realFiles.value) return message.error(t("获取配置文件列表失败"));
if (!realFiles.value) return message.error(t("TXT_CODE_83e553fc"));
realFiles.value.forEach((v) => {
configFiles.forEach((z) => {
if (z.path === v.file) {
@ -93,10 +93,10 @@ onMounted(async () => {
</template>
<template #right>
<a-button class="mr-8" :loading="isLoading" @click="render">
{{ t("刷新") }}
{{ t("TXT_CODE_b76d94e0") }}
</a-button>
<a-button @click="toConsole">
{{ t("回到控制台") }}
{{ t("TXT_CODE_95b9833f") }}
</a-button>
</template>
</BetweenMenus>
@ -115,24 +115,22 @@ onMounted(async () => {
<a-list-item v-if="item.check">
<a-list-item-meta>
<template #title>
<a-tag v-if="item.conflict" color="warning">{{ t("存在同名文件") }}</a-tag>
<a-tag v-if="item.conflict" color="warning">{{
t("TXT_CODE_1af148fe")
}}</a-tag>
{{ item.fileName }}
</template>
<template #description>
{{ item.info }}
<br />
<a-typography-text v-if="item.conflict" type="danger">
{{
t(
"面板无法得知此配置文件是否兼容,请您自行根据类型进入相应配置文件界面。"
)
}}
{{ t("TXT_CODE_91b3fa98") }}
</a-typography-text>
</template>
</a-list-item-meta>
<template #actions>
<a-button size="" @click="toEdit(item.redirect, item.path, item.type)">
{{ t("编辑") }}
{{ t("TXT_CODE_ad207008") }}
</a-button>
</template>
</a-list-item>
@ -140,13 +138,9 @@ onMounted(async () => {
</a-list>
<a-empty v-else>
<template #description>
{{ t("暂无任何配置文件") }}
{{ t("TXT_CODE_432cfb62") }}
</template>
{{
t(
"经过特定实例类型(minecraft/java)并配合文件扫描未检测出有任何符合条件的配置文件,请进行进程配置初始化或更改实例类型来进行调整"
)
}}
{{ t("TXT_CODE_70a2613b") }}
</a-empty>
</template>
</CardPanel>

View File

@ -161,18 +161,18 @@ const initTerminal = () => {
const getInstanceName = computed(() => {
if (instanceInfo.value?.config.nickname === GLOBAL_INSTANCE_NAME) {
return t("节点终端");
return t("TXT_CODE_5bdaf23d");
} else {
return instanceInfo.value?.config.nickname;
}
});
events.on("opened", () => {
message.success(t("实例已运行"));
message.success(t("TXT_CODE_e13abbb1"));
});
events.on("stopped", () => {
message.success(t("实例已停止运行"));
message.success(t("TXT_CODE_efb6d377"));
});
events.on("error", (error: Error) => {
@ -189,7 +189,7 @@ onMounted(async () => {
}
initTerminal();
} catch (error) {
throw new Error(t("初始化终端失败,可能是远程节点或实例已不存在,请刷新网页重试。"));
throw new Error(t("TXT_CODE_9885543f"));
}
});
@ -199,27 +199,27 @@ const innerTerminalType = viewType === "inner";
<template>
<div v-if="socketError" class="error-card">
<div class="error-card-container">
<a-typography-title :level="5">{{ $t("无法连接到远程节点") }}</a-typography-title>
<a-typography-title :level="5">{{ $t("TXT_CODE_6929b0b2") }}</a-typography-title>
<a-typography-paragraph>
{{ $t("浏览器无法连接到地址:") + socketAddress }}
{{ $t("TXT_CODE_812a629e") + socketAddress }}
</a-typography-paragraph>
<div>
<img :src="connectErrorImage" style="width: 100%" />
</div>
<a-typography-title :level="5">{{ $t("解决方案:") }}</a-typography-title>
<a-typography-title :level="5">{{ $t("TXT_CODE_f1c96d8a") }}</a-typography-title>
<a-typography-paragraph>
<ul>
<li>
{{ $t("如果您只是一名普通用户,请联系面板管理员。") }}
{{ $t("TXT_CODE_ceba9262") }}
</li>
<li>
{{ $t("确保连接远程节点地址是公开IP且节点端口正常开放。") }}
{{ $t("TXT_CODE_84099e5") }}
</li>
<li>
{{ $t("配置 SSL反向代理等需要额外支持 Websocket 协议。") }}
{{ $t("TXT_CODE_86ff658a") }}
</li>
<li>
{{ $t("访问 https://docs.mcsmanager.com 了解更多。") }}
{{ $t("TXT_CODE_9c188ec8") }}
</li>
</ul>
</a-typography-paragraph>
@ -272,7 +272,7 @@ const innerTerminalType = viewType === "inner";
</template>
</BetweenMenus>
</div>
<a-spin :spinning="!isConnect" :tip="t('正在连接终端中...')">
<a-spin :spinning="!isConnect" :tip="t('TXT_CODE_686c9ca9')">
<div v-if="!containerState.isDesignMode" class="console-wrapper">
<div class="terminal-wrapper global-card-container-shadow">
<div class="terminal-container">

View File

@ -48,31 +48,31 @@ defineExpose({
<a-modal
v-model:open="open"
centered
:title="t('事件触发型任务')"
:title="t('TXT_CODE_10150756')"
:confirm-loading="isLoading"
:ok-text="t('保存')"
:ok-text="t('TXT_CODE_abfe9512')"
@ok="submit"
>
<a-form v-if="options" layout="vertical">
<a-form-item>
<a-typography-title :level="5">{{ t("自动重启") }}</a-typography-title>
<a-typography-title :level="5">{{ t("TXT_CODE_a64da7c4") }}</a-typography-title>
<a-typography-paragraph>
<a-typography-text type="secondary">
{{ t("若实例状态在未经面板操作的情况下变为非运行状态将立刻发起启动实例操作。") }}
{{ t("TXT_CODE_619faab6") }}
<br />
{{ t("可用于崩溃后自动重启功能。") }}
{{ t("TXT_CODE_3eb58633") }}
</a-typography-text>
</a-typography-paragraph>
<a-switch v-model:checked="options.config.eventTask.autoRestart" />
</a-form-item>
<a-form-item>
<a-typography-title :level="5">{{ t("自动启动") }}</a-typography-title>
<a-typography-title :level="5">{{ t("TXT_CODE_273d24e0") }}</a-typography-title>
<a-typography-paragraph>
<a-typography-text type="secondary">
{{ t("只要远程节点(远程节点)运行,就自动发起一次启动实例操作。") }}
{{ t("TXT_CODE_8d9f5a4e") }}
<br />
{{ t("如果将远程节点开机自启则可用于开机自启实例。") }}
{{ t("TXT_CODE_64bf4386") }}
</a-typography-text>
</a-typography-paragraph>
<a-switch v-model:checked="options.config.eventTask.autoStart" />

View File

@ -58,7 +58,7 @@ const submit = async () => {
text: editorText.value
}
});
message.success(t("保存成功"));
message.success(t("TXT_CODE_a7907771"));
open.value = openEditor.value = false;
} catch (err: any) {
console.error(err.message);
@ -71,7 +71,7 @@ const cancel = () => {
};
const dialogTitle = computed(() => {
return `${t("编辑文件")} ${fileName.value}`;
return `${t("TXT_CODE_b0dc1f17")} ${fileName.value}`;
});
defineExpose({
@ -83,8 +83,8 @@ defineExpose({
<a-modal
v-model:open="open"
centered
:cancel-text="t('放弃')"
:ok-text="t('保存')"
:cancel-text="t('TXT_CODE_3b1cc020')"
:ok-text="t('TXT_CODE_abfe9512')"
:mask-closable="false"
:title="dialogTitle"
width="1000px"

View File

@ -66,7 +66,7 @@ const loadImages = async () => {
method: "GET"
});
if (images.value) {
dockerImages.value = [t("--- 新建镜像 ---")];
dockerImages.value = [t("TXT_CODE_3362d4b7")];
for (const iterator of images.value) {
const repoTags = (iterator?.RepoTags ?? [])[0];
if (repoTags) dockerImages.value.push(repoTags);
@ -100,14 +100,13 @@ const loadNetworkModes = async () => {
};
const rules: Record<string, Rule[]> = {
nickname: [{ required: true, message: t("请输入实例名称") }],
nickname: [{ required: true, message: t("TXT_CODE_68a504b3") }],
startCommand: [
{
required: true,
validator: async (_rule: Rule, value: string) => {
if (value === "") throw new Error(t("请输入启动命令"));
if (value.includes("\n"))
throw new Error(t("启动命令中不可包含换行,这并非脚本文件,不可执行多条命令"));
if (value === "") throw new Error(t("TXT_CODE_4e810102"));
if (value.includes("\n")) throw new Error(t("TXT_CODE_bbbda29"));
},
trigger: "change"
}
@ -120,7 +119,7 @@ const rules: Record<string, Rule[]> = {
options.value?.config.processType === "docker" &&
options.value?.config.docker.image === ""
)
throw new Error(t("请选择实例镜像"));
throw new Error(t("TXT_CODE_be6484f7"));
},
trigger: "change"
}
@ -168,9 +167,9 @@ defineExpose({
centered
:mask-closable="false"
:width="isPhone ? '100%' : 'calc(100% - 30vw)'"
:title="t('实例详细信息设置')"
:title="t('TXT_CODE_aac98b2a')"
:confirm-loading="isLoading"
:ok-text="t('保存')"
:ok-text="t('TXT_CODE_abfe9512')"
@ok="submit"
>
<div class="dialog-overflow-container">
@ -186,11 +185,11 @@ defineExpose({
<a-col :xs="24" :md="12" :offset="0">
<a-form-item name="nickname">
<a-typography-title :level="5" class="require-field">
{{ t("实例名称") }}
{{ t("TXT_CODE_f70badb9") }}
</a-typography-title>
<a-typography-paragraph>
<a-typography-text type="secondary" :class="!isPhone && 'two-line-height'">
{{ t("支持中文,尽可能保证唯一性") }}
{{ t("TXT_CODE_818928ba") }}
</a-typography-text>
</a-typography-paragraph>
<a-input v-model:value="options.config.nickname" :disabled="isGlobalTerminal" />
@ -199,20 +198,16 @@ defineExpose({
<a-col :xs="24" :md="12" :offset="0">
<a-form-item>
<a-typography-title :level="5" class="require-field">
{{ t("实例类型") }}
{{ t("TXT_CODE_2f291d8b") }}
</a-typography-title>
<a-typography-paragraph>
<a-typography-text type="secondary" :class="!isPhone && 'two-line-height'">
{{
t(
"不同类型会导致功能不同,若无需求类型,可以选择较为抽象的通用类型,例如 Java 通用版服务端"
)
}}
{{ t("TXT_CODE_1e1dfbbe") }}
</a-typography-text>
</a-typography-paragraph>
<a-select
v-model:value="options.config.type"
:placeholder="t('请选择')"
:placeholder="t('TXT_CODE_3bb646e4')"
:disabled="isGlobalTerminal"
>
<a-select-option
@ -229,15 +224,11 @@ defineExpose({
<a-col :xs="24" :offset="0">
<a-form-item name="startCommand">
<a-typography-title :level="5" class="require-field">
{{ t("启动命令") }}
{{ t("TXT_CODE_d12fa808") }}
</a-typography-title>
<a-typography-paragraph>
<a-typography-text type="secondary">
{{
t(
"适用于任何程序命令,若程序路径或附加参数中含有空格可使用引号作为边界,包含的文本将视作一段整体。整条命令不可有换行。如果您输入命令无反应,或者终端排版错乱,可以开启 控制台-终端设置-伪终端进行尝试。不同类型会导致功能不同,若无需求类型,可以选择较为抽象的通用类型,例如 Java 通用版服务端通常情况下,建议使用命令助手生成启动命令,如果有额外需求可以自定义启动命令。列如 C: \Program Files\Java\bin\java.exe -Dfile.encoding=utf-8 -Djline.terminal=jline.UnsupportedTerminal -jar my server.jar -nogui"
)
}}
{{ t("TXT_CODE_A0000001") }}
</a-typography-text>
</a-typography-paragraph>
<a-input-group compact style="display: flex">
@ -254,11 +245,11 @@ defineExpose({
<a-col :xs="24" :offset="0">
<a-form-item name="cwd">
<a-typography-title :level="5" class="require-field">
{{ t("工作目录") }}
{{ t("TXT_CODE_ee67e1a3") }}
</a-typography-title>
<a-typography-paragraph>
<a-typography-text type="secondary">
{{ t("实例运行的工作目录,可填绝对路径与相对路径") }}
{{ t("TXT_CODE_962d9320") }}
</a-typography-text>
</a-typography-paragraph>
<a-input v-model:value="options.config.cwd" />
@ -266,14 +257,10 @@ defineExpose({
</a-col>
<a-col :xs="24" :offset="0">
<a-form-item>
<a-typography-title :level="5">{{ t("更新/安装程序文件命令") }}</a-typography-title>
<a-typography-title :level="5">{{ t("TXT_CODE_bb0b9711") }}</a-typography-title>
<a-typography-paragraph>
<a-typography-text type="secondary">
{{
t(
"当用户执行更新/安装操作时,将会执行此命令,${mcsm_workspace} 代表工作目录,为空则不提供此功能"
)
}}
{{ t("TXT_CODE_41763172") }}
</a-typography-text>
</a-typography-paragraph>
<a-input v-model:value="options.config.updateCommand" />
@ -284,14 +271,17 @@ defineExpose({
<a-col :xs="24" :lg="6" :offset="0">
<a-form-item>
<a-typography-title :level="5" class="require-field">
{{ t("文件管理编码") }}
{{ t("TXT_CODE_f041de90") }}
</a-typography-title>
<a-typography-paragraph>
<a-typography-text type="secondary" :class="!isPhone && 'two-line-height'">
{{ t("文件管理功能的解压缩,编辑等编码") }}
{{ t("TXT_CODE_6e69b5a5") }}
</a-typography-text>
</a-typography-paragraph>
<a-select v-model:value="options.config.fileCode" :placeholder="t('请选择')">
<a-select
v-model:value="options.config.fileCode"
:placeholder="t('TXT_CODE_3bb646e4')"
>
<a-select-option v-for="item in TERMINAL_CODE" :key="item" :value="item">
</a-select-option>
</a-select>
@ -299,39 +289,35 @@ defineExpose({
</a-col>
<a-col :xs="24" :lg="6" :offset="0">
<a-form-item>
<a-typography-title :level="5">{{ t("到期时间") }}</a-typography-title>
<a-typography-title :level="5">{{ t("TXT_CODE_fa920c0") }}</a-typography-title>
<a-typography-paragraph>
<a-typography-text type="secondary" :class="!isPhone && 'two-line-height'">
{{ t("到期后实例将无法启动") }}
{{ t("TXT_CODE_b029a155") }}
</a-typography-text>
</a-typography-paragraph>
<a-date-picker
v-model:value="options.dayjsEndTime"
size="large"
style="width: 100%"
:placeholder="t('无限制')"
:placeholder="t('TXT_CODE_e3a77a77')"
:disabled="isGlobalTerminal"
/>
</a-form-item>
</a-col>
<a-col :xs="24" :lg="12" :offset="0">
<a-form-item>
<a-typography-title :level="5">{{ t("进程启动方式(推荐)") }}</a-typography-title>
<a-typography-title :level="5">{{ t("TXT_CODE_9eacb622") }}</a-typography-title>
<a-typography-paragraph>
<a-typography-text type="secondary" :class="!isPhone && 'two-line-height'">
{{
t(
"通常默认即可,如果从事商业活动则应当使用虚拟化容器启动方式,否则主机将可能被入侵。"
)
}}
{{ t("TXT_CODE_9278b7b0") }}
</a-typography-text>
</a-typography-paragraph>
<a-select v-model:value="options.config.processType" :disabled="isGlobalTerminal">
<a-select-option value="general">
{{ t("默认类型") }}
{{ t("TXT_CODE_5be6c38e") }}
</a-select-option>
<a-select-option value="docker">
{{ t("虚拟化容器Linux Docker") }}
{{ t("TXT_CODE_6c87dd18") }}
</a-select-option>
</a-select>
</a-form-item>
@ -341,18 +327,18 @@ defineExpose({
<a-col :xs="24" :lg="6" :offset="0">
<a-form-item name="dockerImage">
<a-typography-title :level="5" class="require-field">
{{ t("环境镜像") }}
{{ t("TXT_CODE_6904cb3") }}
</a-typography-title>
<a-typography-paragraph>
<a-typography-text type="secondary">
{{ t("指定实例镜像") }}
{{ t("TXT_CODE_a584cb71") }}
</a-typography-text>
</a-typography-paragraph>
<a-select
v-model:value="options.config.docker.image"
size="large"
style="width: 100%"
:placeholder="t('请选择')"
:placeholder="t('TXT_CODE_3bb646e4')"
@focus="loadImages"
@change="selectImage"
>
@ -366,14 +352,10 @@ defineExpose({
</a-col>
<a-col :xs="24" :lg="18" :offset="0">
<a-form-item>
<a-typography-title :level="5">{{ t("开放端口") }}</a-typography-title>
<a-typography-title :level="5">{{ t("TXT_CODE_cf88c936") }}</a-typography-title>
<a-typography-paragraph>
<a-typography-text type="secondary">
{{
t(
"多个以空格分割,冒号左边为宿主机暴露端口,右边为容器暴露端口,通常保持一致即可"
)
}}
{{ t("TXT_CODE_c7b95258") }}
</a-typography-text>
</a-typography-paragraph>
<a-input-group compact>
@ -381,20 +363,16 @@ defineExpose({
v-model:value="options.config.docker.ports"
style="width: calc(100% - 88px)"
/>
<a-button type="default">快速编辑</a-button>
<a-button type="default">{{ t("快速编辑") }}</a-button>
</a-input-group>
</a-form-item>
</a-col>
<a-col :xs="24" :offset="0">
<a-form-item>
<a-typography-title :level="5">{{ t("额外挂载路径") }}</a-typography-title>
<a-typography-title :level="5">{{ t("TXT_CODE_3e68ca00") }}</a-typography-title>
<a-typography-paragraph>
<a-typography-text type="secondary">
{{
t(
"向容器内挂载除工作目录外的其他目录,多个以空格分割,冒号左边为宿主机路径,右边为容器路径"
)
}}
{{ t("TXT_CODE_29c2884") }}
</a-typography-text>
</a-typography-paragraph>
<a-input-group compact>
@ -402,23 +380,23 @@ defineExpose({
v-model:value="options.config.docker.extraVolumes"
style="width: calc(100% - 88px)"
/>
<a-button type="default">快速编辑</a-button>
<a-button type="default">{{ t("快速编辑") }}</a-button>
</a-input-group>
</a-form-item>
</a-col>
<a-col :xs="24" :lg="8" :offset="0">
<a-form-item>
<a-typography-title :level="5">{{ t("容器名") }}</a-typography-title>
<a-typography-title :level="5">{{ t("TXT_CODE_c3a3b6b1") }}</a-typography-title>
<a-typography-paragraph>
<a-typography-text type="secondary">
{{ t("容器创建使用的名字,为空随机生成") }}
{{ t("TXT_CODE_d1c78fbf") }}
</a-typography-text>
</a-typography-paragraph>
<a-tooltip placement="bottom">
<template #title>{{ t("选填,无特殊需求不建议填写此项") }}</template>
<template #title>{{ t("TXT_CODE_8d4882b0") }}</template>
<a-input
v-model:value="options.config.docker.containerName"
:placeholder="t('选填,示例 lobby-1')"
:placeholder="t('TXT_CODE_f6047384')"
/>
</a-tooltip>
</a-form-item>
@ -426,18 +404,18 @@ defineExpose({
<a-col :xs="24" :lg="8" :offset="0">
<a-form-item>
<a-typography-title :level="5" class="require-field">
{{ t("网络模式") }}
{{ t("TXT_CODE_efcef926") }}
</a-typography-title>
<a-typography-paragraph>
<a-typography-text type="secondary">
{{ t("选择容器接入的网络模式 如 bridge 网桥") }}
{{ t("TXT_CODE_38a430d8") }}
</a-typography-text>
</a-typography-paragraph>
<a-select
v-model:value="options.config.docker.networkMode"
size="large"
style="width: 100%"
:placeholder="t('请选择')"
:placeholder="t('TXT_CODE_3bb646e4')"
@focus="loadNetworkModes"
>
<a-select-option
@ -450,77 +428,67 @@ defineExpose({
</a-col>
<a-col :xs="24" :lg="8" :offset="0">
<a-form-item>
<a-typography-title :level="5">{{ t("网络别名") }}</a-typography-title>
<a-typography-title :level="5">{{ t("TXT_CODE_10194e6a") }}</a-typography-title>
<a-typography-paragraph>
<a-typography-text type="secondary">
{{ t("用于在自定义网络中容器互相访问,空格分隔") }}
{{ t("TXT_CODE_97655c5d") }}
</a-typography-text>
</a-typography-paragraph>
<a-input
v-model:value="options.config.docker.networkAliases"
:placeholder="t('选填,无特殊需求不建议填写此项')"
:placeholder="t('TXT_CODE_8d4882b0')"
/>
</a-form-item>
</a-col>
<a-col :xs="24" :lg="8" :offset="0">
<a-form-item>
<a-typography-title :level="5">{{
t("限制 CPU 使用率(百分比)")
}}</a-typography-title>
<a-typography-title :level="5">{{ t("TXT_CODE_53046822") }}</a-typography-title>
<a-typography-paragraph>
<a-typography-text type="secondary">
{{ t("限制所有 CPU 总和使用率,会有少许偏差") }}
{{ t("TXT_CODE_750ab5c6") }}
</a-typography-text>
</a-typography-paragraph>
<a-tooltip placement="bottom">
<template #title>
{{
t(
"填写 50 代表所有核心使用率和限制在 50%,若填写 200 则代表准许使用所有核心使用率总和为 200%"
)
}}
{{ t("TXT_CODE_dce87e42") }}
</template>
<a-input
v-model:value="options.config.docker.cpuUsage"
:placeholder="t('选填0 到 无限大')"
:placeholder="t('TXT_CODE_91d857f5')"
/>
</a-tooltip>
</a-form-item>
</a-col>
<a-col :xs="24" :lg="8" :offset="0">
<a-form-item>
<a-typography-title :level="5">{{ t("指定 CPU 计算核心") }}</a-typography-title>
<a-typography-title :level="5">{{ t("TXT_CODE_b0c4e4ae") }}</a-typography-title>
<a-typography-paragraph>
<a-typography-text type="secondary">
{{ t("限制容器在指定的 CPU 核心上运行") }}
{{ t("TXT_CODE_2b9e9b5") }}
</a-typography-text>
</a-typography-paragraph>
<a-tooltip placement="bottom">
<template #title>
{{
t(
"指定进程在某些核心上运行,合理分配可以更好的利用您的系统硬件资源,例如 0,1 代表在第12核心上运作逗号隔开"
)
}}
{{ t("TXT_CODE_67c765be") }}
</template>
<a-input
v-model:value="options.config.docker.cpusetCpus"
:placeholder="t('选填,例如 0,1,2,3')"
:placeholder="t('TXT_CODE_30fe1717')"
/>
</a-tooltip>
</a-form-item>
</a-col>
<a-col :xs="24" :lg="8" :offset="0">
<a-form-item>
<a-typography-title :level="5">{{ t("最大内存(单位 MB") }}</a-typography-title>
<a-typography-title :level="5">{{ t("TXT_CODE_6fe24924") }}</a-typography-title>
<a-typography-paragraph>
<a-typography-text type="secondary">
{{ t("例如 10242048 等,请勿加单位") }}
{{ t("TXT_CODE_a0d214ac") }}
</a-typography-text>
</a-typography-paragraph>
<a-input
v-model:value="options.config.docker.memory"
:placeholder="t('选填,例如 1024')"
:placeholder="t('TXT_CODE_80790069')"
/>
</a-form-item>
</a-col>

View File

@ -21,13 +21,13 @@ const openDialog = () => {
const { isPhone } = useScreen();
const weeks = [
{ label: t("周一"), value: 1 },
{ label: t("周二"), value: 2 },
{ label: t("周三"), value: 3 },
{ label: t("周四"), value: 4 },
{ label: t("周五"), value: 5 },
{ label: t("周六"), value: 6 },
{ label: t("周日"), value: 7 }
{ label: t("TXT_CODE_fcbdcb34"), value: 1 },
{ label: t("TXT_CODE_c73de59d"), value: 2 },
{ label: t("TXT_CODE_85617390"), value: 3 },
{ label: t("TXT_CODE_c9b31f8e"), value: 4 },
{ label: t("TXT_CODE_d4517dcb"), value: 5 },
{ label: t("TXT_CODE_d248b5c8"), value: 6 },
{ label: t("TXT_CODE_a621f370"), value: 7 }
];
interface NewTask extends NewScheduleTask {
@ -63,8 +63,8 @@ const createTaskTypeInterval = async () => {
const createTaskTypeCycle = async () => {
const weekend = newTask.weekend;
if (newTask.objTime === "") throw new Error(t("请选择时间"));
if (weekend.length === 0) throw new Error(t("请选择星期"));
if (newTask.objTime === "") throw new Error(t("TXT_CODE_349edc57"));
if (weekend.length === 0) throw new Error(t("TXT_CODE_2fe0cc84"));
const time = new Date(newTask.objTime);
const h = time.getHours();
const m = time.getMinutes();
@ -74,7 +74,7 @@ const createTaskTypeCycle = async () => {
};
const createTaskTypeSpecify = async () => {
if (newTask.objTime === "") throw new Error(t("请选择时间"));
if (newTask.objTime === "") throw new Error(t("TXT_CODE_349edc57"));
const time = newTask.objTime as unknown as Dayjs;
const mm = time.month() + 1;
const dd = time.date();
@ -99,7 +99,7 @@ const createRequest = async () => {
if (state.value) {
emit("getScheduleList");
notification.success({
message: t("创建成功")
message: t("TXT_CODE_d28c05df")
});
newTask = reactive(_.cloneDeep(newTaskOrigin));
open.value = false;
@ -130,29 +130,29 @@ defineExpose({
v-model:open="open"
centered
:mask-closable="false"
:title="t('新增计划任务')"
:title="t('TXT_CODE_3502273d')"
:confirm-loading="isLoading"
:destroy-on-close="true"
:ok-text="t('保存')"
:ok-text="t('TXT_CODE_abfe9512')"
@ok="submit"
>
<a-form-item>
<a-typography-title :level="5">{{ t("计划任务名字") }}</a-typography-title>
<a-typography-title :level="5">{{ t("TXT_CODE_b290a4b0") }}</a-typography-title>
<a-typography-paragraph>
<a-typography-text type="secondary">
{{ t("必填,且必须唯一") }}
{{ t("TXT_CODE_b72d638d") }}
</a-typography-text>
</a-typography-paragraph>
<a-input v-model:value="newTask.name" />
</a-form-item>
<a-form-item>
<a-typography-title :level="5">{{ t("任务动作 / 类型") }}</a-typography-title>
<a-typography-title :level="5">{{ t("TXT_CODE_fcd641db") }}</a-typography-title>
<a-row :gutter="20">
<a-col :xs="24" :md="12" :offset="0" :class="{ 'mb-10': isPhone }">
<a-select
v-model:value="newTask.action"
:placeholder="t('请选择')"
:placeholder="t('TXT_CODE_3bb646e4')"
:dropdown-match-select-width="false"
>
<a-select-option v-for="(action, i) in ScheduleAction" :key="i" :value="i">
@ -163,7 +163,7 @@ defineExpose({
<a-col :xs="24" :md="12" :offset="0">
<a-select
v-model:value="newTask.type"
:placeholder="t('请选择')"
:placeholder="t('TXT_CODE_3bb646e4')"
:dropdown-match-select-width="false"
>
<a-select-option v-for="(type, i) in ScheduleType" :key="i" :value="i">
@ -177,44 +177,44 @@ defineExpose({
<a-form-item v-if="newTask.type === ScheduleCreateType.INTERVAL">
<a-typography-paragraph>
<a-typography-text>
{{ t("每隔一定时间将执行一次,具体间隔可以仔细设置") }}
{{ t("TXT_CODE_f17889f4") }}
</a-typography-text>
</a-typography-paragraph>
<a-row :gutter="20">
<a-col :xs="24" :md="6" :offset="0" :class="{ 'mb-10': isPhone }">
<a-input
v-model:value="newTask.cycle[2]"
:placeholder="t('不可为空,请写 0 代表每隔 0 时')"
:addon-after="t('')"
:placeholder="t('TXT_CODE_ba8ebc7')"
:addon-after="t('TXT_CODE_4e2c7f64')"
/>
</a-col>
<a-col :xs="24" :md="6" :offset="0" :class="{ 'mb-10': isPhone }">
<a-input
v-model:value="newTask.cycle[1]"
:placeholder="t('不可为空,请写 0 代表每隔 0 时')"
:addon-after="t('')"
:placeholder="t('TXT_CODE_ba8ebc7')"
:addon-after="t('TXT_CODE_a7e9ff0f')"
/>
</a-col>
<a-col :xs="24" :md="6" :offset="0" :class="{ 'mb-10': isPhone }">
<a-input
v-model:value="newTask.cycle[0]"
:placeholder="t('不可为空,请写 0 代表每隔 0 时')"
:addon-after="t('')"
:placeholder="t('TXT_CODE_ba8ebc7')"
:addon-after="t('TXT_CODE_acabc771')"
/>
</a-col>
<a-col :xs="24" :md="6" :offset="0">
<a-input v-model:value="newTask.count" :placeholder="t('执行次数,留空无限')" />
<a-input v-model:value="newTask.count" :placeholder="t('TXT_CODE_9156fbc')" />
</a-col>
</a-row>
</a-form-item>
<div v-if="newTask.type === ScheduleCreateType.CYCLE">
<a-form-item>
<a-typography-title :level="5">{{ t("触发时间") }}</a-typography-title>
<a-typography-title :level="5">{{ t("TXT_CODE_3554dac0") }}</a-typography-title>
<a-time-picker
v-model:value="newTask.objTime"
size="large"
:placeholder="$t('具体时间点')"
:placeholder="$t('TXT_CODE_38591f72')"
class="w-100"
/>
</a-form-item>
@ -223,21 +223,21 @@ defineExpose({
</a-form-item>
<a-form-item>
<a-typography-title :level="5">{{ t("执行次数") }}</a-typography-title>
<a-input v-model:value="newTask.count" :placeholder="t('留空无限')" />
<a-typography-title :level="5">{{ t("TXT_CODE_d9cfab1b") }}</a-typography-title>
<a-input v-model:value="newTask.count" :placeholder="t('TXT_CODE_a59981f4')" />
</a-form-item>
</div>
<a-form-item v-if="newTask.type === ScheduleCreateType.SPECIFY">
<a-typography-title :level="5">{{ t("请选择日期和时间") }}</a-typography-title>
<a-typography-title :level="5">{{ t("TXT_CODE_f3fe5c8e") }}</a-typography-title>
<a-date-picker v-model:value="newTask.objTime" show-time size="large" class="w-100" />
</a-form-item>
<a-form-item>
<a-typography-title :level="5">{{ t("任务有效负载") }}</a-typography-title>
<a-typography-title :level="5">{{ t("TXT_CODE_61811ac") }}</a-typography-title>
<a-typography-paragraph>
<a-typography-text type="secondary">
{{ t("比如命令,文件名或其他参数等") }}
{{ t("TXT_CODE_81297804") }}
</a-typography-text>
</a-typography-paragraph>
<a-input v-model:value="newTask.payload" />

View File

@ -48,40 +48,36 @@ defineExpose({
<a-modal
v-model:open="open"
centered
:title="t('实例状态查询协议配置')"
:title="t('TXT_CODE_23b02a65')"
:confirm-loading="isLoading"
:ok-text="t('保存')"
:ok-text="t('TXT_CODE_abfe9512')"
@ok="submit"
>
<a-form v-if="options" layout="vertical">
<a-form-item>
<a-typography-title :level="5">{{ t("更好的监控服务端状态") }}</a-typography-title>
<a-typography-title :level="5">{{ t("TXT_CODE_2498e4ed") }}</a-typography-title>
<a-typography-paragraph>
<a-typography-text type="secondary">
{{
t(
"此功能将根据管理员设置的实例类型自动选择相应协议,获取服务端进程的具体信息和参数(如:游戏人数,版本等)"
)
}}
{{ t("TXT_CODE_e7335483") }}
</a-typography-text>
</a-typography-paragraph>
</a-form-item>
<a-form-item>
<a-typography-title :level="5">{{ t("服务端访问地址") }}</a-typography-title>
<a-typography-title :level="5">{{ t("TXT_CODE_8e632796") }}</a-typography-title>
<a-typography-paragraph>
<a-typography-text type="secondary">
{{ t("必填,支持域名与 IP 地址,不填写则不会查询服务端信息,人数,版本等。") }}
{{ t("TXT_CODE_c93f32f8") }}
</a-typography-text>
</a-typography-paragraph>
<a-input v-model:value="options.config.pingConfig.ip" />
</a-form-item>
<a-form-item>
<a-typography-title :level="5">{{ t("服务端访问端口") }}</a-typography-title>
<a-typography-title :level="5">{{ t("TXT_CODE_243a463") }}</a-typography-title>
<a-typography-paragraph>
<a-typography-text type="secondary">
{{ t("必填,仅可输入数字端口号") }}
{{ t("TXT_CODE_e9935066") }}
</a-typography-text>
</a-typography-paragraph>
<a-input v-model:value="options.config.pingConfig.port" type="number" />

View File

@ -13,10 +13,10 @@ const zipCode = ref<string>();
const submit = async () => {
try {
if (!zipCode.value) throw new Error(t("请选择解压编码"));
if (!zipCode.value) throw new Error(t("TXT_CODE_97ceb743"));
emit("selectCode", zipCode.value);
open.value = false;
return message.success(t("设置成功"));
return message.success(t("TXT_CODE_f07610ed"));
} catch (err: any) {
return message.error(err.message);
}
@ -32,27 +32,27 @@ defineExpose({
v-model:open="open"
centered
:mask-closable="false"
:title="t('选择解压编码')"
:ok-text="t('保存')"
:title="t('TXT_CODE_2dc23f7a')"
:ok-text="t('TXT_CODE_abfe9512')"
@ok="submit"
>
<a-typography-paragraph>
<a-typography-text type="secondary">
{{ t("在解压/压缩文件时发现文件名存在乱码现象时,可以修改此选项解决。") }}
{{ t("TXT_CODE_b278707d") }}
<br />
{{ t("如果压缩包来源是中国大陆,一般可选 GBK;") }}
{{ t("TXT_CODE_48044fc2") }}
<br />
{{ t("如果是来自台湾香港地区可以选择BIG5如果来自其他地区可以选择 UTF-8。") }}
{{ t("TXT_CODE_76a82338") }}
</a-typography-text>
</a-typography-paragraph>
<a-select
v-model:value="zipCode"
:placeholder="t('请选择')"
:placeholder="t('TXT_CODE_3bb646e4')"
:dropdown-match-select-width="false"
>
<a-select-option value="utf-8">{{ t("面板/LinuxUTF8") }}</a-select-option>
<a-select-option value="gbk">{{ t("简体中文GBK") }}</a-select-option>
<a-select-option value="big5">{{ t("繁体中文BIG5") }}</a-select-option>
<a-select-option value="utf-8">{{ t("TXT_CODE_91bb6101") }}</a-select-option>
<a-select-option value="gbk">{{ t("TXT_CODE_4d6b06f0") }}</a-select-option>
<a-select-option value="big5">{{ t("TXT_CODE_c4dfdb26") }}</a-select-option>
</a-select>
</a-modal>
</template>

View File

@ -57,52 +57,50 @@ defineExpose({
v-model:open="open"
centered
width="auto"
:title="t('终端设置')"
:title="t('TXT_CODE_d23631cb')"
:confirm-loading="isLoading"
:ok-text="t('保存')"
:ok-text="t('TXT_CODE_abfe9512')"
@ok="submit"
>
<a-form v-if="options" layout="vertical">
<a-row :gutter="20">
<a-col :xs="24" :md="12" :offset="0">
<a-form-item>
<a-typography-title :level="5">{{ t("仿真终端") }}</a-typography-title>
<a-typography-title :level="5">{{ t("TXT_CODE_ef650d57") }}</a-typography-title>
<a-typography-paragraph>
<a-typography-text type="secondary">
{{
t("通过仿真终端转发程序来获得终端完全交互能力。\n包括使用 TabCtrl 功能键等。")
}}
{{ t("通过仿真终端转发程序来获得终端完全交互能力。包括使用 TabCtrl 功能键等。") }}
<br />
{{ t("如果使用有问题,建议关闭。") }}
{{ t("TXT_CODE_d6e7f572") }}
</a-typography-text>
</a-typography-paragraph>
<a-switch v-model:checked="options.config.terminalOption.pty" />
</a-form-item>
<a-form-item>
<a-typography-title :level="5">{{ t("网页颜色渲染") }}</a-typography-title>
<a-typography-title :level="5">{{ t("TXT_CODE_e1a3b150") }}</a-typography-title>
<a-typography-paragraph>
<a-typography-text type="secondary">
{{ t("网页自动给输出内容增加颜色渲染,渲染的颜色不一定完全正确。") }}
{{ t("TXT_CODE_6a515e35") }}
<br />
{{ t("如果颜色渲染功能与软件自带的颜色功能冲突,可以关闭此功能。") }}
{{ t("TXT_CODE_1295831e") }}
</a-typography-text>
</a-typography-paragraph>
<a-switch v-model:checked="options.config.terminalOption.haveColor" />
</a-form-item>
<a-form-item>
<a-typography-title :level="5">{{ t("命令执行回车符") }}</a-typography-title>
<a-typography-title :level="5">{{ t("TXT_CODE_b91a94f9") }}</a-typography-title>
<a-typography-paragraph>
<a-typography-text type="secondary">
{{ t("如果您输入命令按回车没有反应,可以尝试调整此选项。") }}
{{ t("TXT_CODE_5b2daea0") }}
<br />
{{ t("Windows 平台下一般是“回车换行符”Linux/MacOS 平台下一般是“换行符”。") }}
{{ t("TXT_CODE_b94f13ce") }}
</a-typography-text>
</a-typography-paragraph>
<a-select
v-model:value="options.config.crlf"
:placeholder="t('请选择')"
:placeholder="t('TXT_CODE_3bb646e4')"
:style="'width: ' + (isPhone ? '100%' : '220px')"
>
<a-select-option :value="1"> {{ t("换行符(\\n") }}</a-select-option>
@ -112,10 +110,10 @@ defineExpose({
</a-col>
<a-col :xs="24" :md="12" :offset="0">
<a-form-item>
<a-typography-title :level="5">{{ t("关闭实例命令") }}</a-typography-title>
<a-typography-title :level="5">{{ t("TXT_CODE_11cfe3a1") }}</a-typography-title>
<a-typography-paragraph>
<a-typography-text type="secondary">
{{ t("当点击“关闭实例”按钮时,会立刻执行此命令,^C 代表 Ctrl+C 信号。") }}
{{ t("TXT_CODE_7ec7ccb8") }}
</a-typography-text>
</a-typography-paragraph>
<a-input
@ -125,16 +123,16 @@ defineExpose({
</a-form-item>
<a-form-item>
<a-typography-title :level="5">{{ t("输入输出编码") }}</a-typography-title>
<a-typography-title :level="5">{{ t("TXT_CODE_449d1581") }}</a-typography-title>
<a-typography-paragraph>
<a-typography-text type="secondary">
{{ t("如果控制台中的内容出现乱码,您可以尝试修改此编码解决问题。") }}
{{ t("TXT_CODE_d16d82ab") }}
</a-typography-text>
</a-typography-paragraph>
<a-select
v-model:value="options.config.ie"
class="mr-10 mb-20"
:placeholder="t('终端输入编码')"
:placeholder="t('TXT_CODE_bd2559f3')"
:style="'width: ' + (isPhone ? '100%' : '220px')"
>
<a-select-option v-for="item in TERMINAL_CODE" :key="item" :value="item">
@ -142,7 +140,7 @@ defineExpose({
</a-select>
<a-select
v-model:value="options.config.oe"
:placeholder="t('终端输出编码')"
:placeholder="t('TXT_CODE_6e96b2a9')"
:style="'width: ' + (isPhone ? '100%' : '220px')"
>
<a-select-option v-for="item in TERMINAL_CODE" :key="item" :value="item">

View File

@ -74,14 +74,13 @@ if (props.appType === QUICKSTART_ACTION_TYPE.SteamGameServer) {
}
const rules: Record<string, Rule[]> = {
nickname: [{ required: true, message: t("请输入实例名称") }],
nickname: [{ required: true, message: t("TXT_CODE_68a504b3") }],
startCommand: [
{
required: true,
validator: async (_rule: Rule, value: string) => {
if (value === "") throw new Error(t("请输入启动命令"));
if (value.includes("\n"))
throw new Error(t("启动命令中不可包含换行,这并非脚本文件,不可执行多条命令"));
if (value === "") throw new Error(t("TXT_CODE_4e810102"));
if (value.includes("\n")) throw new Error(t("TXT_CODE_bbbda29"));
},
trigger: "change"
}
@ -94,8 +93,7 @@ const beforeUpload: UploadProps["beforeUpload"] = async (file) => {
uFile.value = file;
if (isImportMode) {
if (file.type !== "application/x-zip-compressed")
return message.error(t("只能上传zip压缩文件"));
if (file.type !== "application/x-zip-compressed") return message.error(t("TXT_CODE_808e5ad9"));
selectUnzipCodeDialog.value?.openDialog();
} else {
finalConfirm();
@ -110,29 +108,26 @@ const setUnzipCode = async (code: string) => {
finalConfirm();
};
//
const finalConfirm = async () => {
const thisModal = Modal.confirm({
title: t("最终确认"),
icon: createVNode(InfoCircleOutlined),
content: needUpload
? t("上传文件时将同时创建实例,此操作不可逆,是否继续?")
: t("实例将创建,是否继续?"),
okText: t("确定"),
content: needUpload ? t("TXT_CODE_e06841b5") : t("TXT_CODE_5deeefb5"),
okText: t("TXT_CODE_d507abff"),
async onOk() {
thisModal.destroy();
try {
await formRef.value?.validateFields();
needUpload ? await selectedFile() : await createInstance();
} catch {
return message.error(t("请先完善基本参数再进行上传文件操作"));
return message.error(t("TXT_CODE_47e21c80"));
}
},
onCancel() {}
});
};
//
//
const { state: cfg, execute: getCfg } = uploadAddress();
const { execute: uploadFile } = uploadInstanceFile();
const percentComplete = ref(0);
@ -149,7 +144,7 @@ const selectedFile = async () => {
},
data: formData
});
if (!cfg.value) throw new Error(t("获取上传地址失败"));
if (!cfg.value) throw new Error(t("TXT_CODE_e8ce38c2"));
const uploadFormData = new FormData();
uploadFormData.append("file", uFile.value as any);
@ -166,7 +161,7 @@ const selectedFile = async () => {
}
});
emit("nextStep", cfg.value.instanceUuid);
return message.success(t("创建成功"));
return message.success(t("TXT_CODE_d28c05df"));
} catch (err: any) {
console.error(err);
return message.error(err.message);
@ -189,7 +184,7 @@ const createInstance = async () => {
data: formData
});
if (newInstanceInfo.value) emit("nextStep", newInstanceInfo.value.instanceUuid);
return message.success(t("创建成功"));
return message.success(t("TXT_CODE_d28c05df"));
} catch (err: any) {
return message.error(err.message);
}
@ -201,11 +196,11 @@ const createInstance = async () => {
<a-form ref="formRef" :rules="rules" :model="formData" layout="vertical" autocomplete="off">
<a-form-item name="nickname">
<a-typography-title :level="5" class="require-field">
{{ t("实例名称") }}
{{ t("TXT_CODE_f70badb9") }}
</a-typography-title>
<a-typography-paragraph>
<a-typography-text type="secondary">
{{ t("支持中文,尽可能保证唯一性") }}
{{ t("TXT_CODE_818928ba") }}
</a-typography-text>
</a-typography-paragraph>
<a-input v-model:value="formData.nickname" />
@ -213,14 +208,14 @@ const createInstance = async () => {
<a-form-item name="startCommand">
<a-typography-title :level="5" class="require-field">
{{ t("启动命令") }}
{{ t("TXT_CODE_d12fa808") }}
</a-typography-title>
<a-typography-paragraph>
<a-typography-text type="secondary">
{{
createMethod === QUICKSTART_METHOD.IMPORT
? t("因为无法识别压缩包中的服务端文件名,请您自行填写启动命令")
: t("请您自行填写启动命令")
? t("TXT_CODE_17544b7b")
: t("TXT_CODE_8c0db3f4")
}}
</a-typography-text>
</a-typography-paragraph>
@ -228,25 +223,25 @@ const createInstance = async () => {
<a-textarea
v-model:value="formData.startCommand"
:rows="3"
:placeholder="t('如 java -jar server.jarcmd.exe 等等')"
:placeholder="t('TXT_CODE_619d74d3')"
style="min-height: 40px"
/>
<a-button
type="default"
style="height: auto; border-top-left-radius: 0; border-bottom-left-radius: 0"
>
{{ t("命令助手") }}
{{ t("TXT_CODE_2728d0d4") }}
</a-button>
</a-input-group>
</a-form-item>
<a-form-item v-if="createMethod !== QUICKSTART_METHOD.EXIST" name="cwd">
<a-typography-title :level="5">
{{ t("服务端文件目录") }}
{{ t("TXT_CODE_320f4304") }}
</a-typography-title>
<a-typography-paragraph>
<a-typography-text type="secondary">
{{ t("选填,默认自动创建与管理,如需填写请写完整绝对路径,如: C:/Servers/MyServer") }}
{{ t("TXT_CODE_877eea45") }}
</a-typography-text>
</a-typography-paragraph>
<a-input v-model:value="formData.cwd" />
@ -254,11 +249,11 @@ const createInstance = async () => {
<a-form-item v-if="createMethod === QUICKSTART_METHOD.FILE">
<a-typography-title :level="5" class="require-field">
{{ t("上传单个服务端软件") }}
{{ t("TXT_CODE_444db70f") }}
</a-typography-title>
<a-typography-paragraph>
<a-typography-text type="secondary">
{{ t("上传文件后实例将自动创建") }}
{{ t("TXT_CODE_fc4e2173") }}
</a-typography-text>
</a-typography-paragraph>
<a-upload
@ -269,20 +264,24 @@ const createInstance = async () => {
>
<a-button type="primary" :loading="percentComplete > 0">
<upload-outlined v-if="percentComplete === 0" />
{{ percentComplete > 0 ? t("正在上传:") + percentComplete + "%" : t("选择文件") }}
{{
percentComplete > 0
? t("TXT_CODE_b625dbf0") + percentComplete + "%"
: t("TXT_CODE_335ba209")
}}
</a-button>
</a-upload>
</a-form-item>
<a-form-item v-else-if="createMethod === QUICKSTART_METHOD.IMPORT">
<a-typography-title :level="5" class="require-field">
{{ t("上传服务端压缩包") }}
{{ t("TXT_CODE_f9b6e61b") }}
</a-typography-title>
<a-typography-paragraph>
<a-typography-text type="secondary">
{{ t("仅支持 ZIP 格式,上传后压缩包会自动解压到 “文件目录”") }}
{{ t("TXT_CODE_510bd294") }}
<br />
{{ t("上传文件后实例将自动创建并解压文件,可能需要一段时间才能完成解压任务") }}
{{ t("TXT_CODE_1561198c") }}
</a-typography-text>
</a-typography-paragraph>
<a-upload
@ -293,7 +292,11 @@ const createInstance = async () => {
>
<a-button type="primary" :loading="percentComplete > 0">
<upload-outlined v-if="percentComplete === 0" />
{{ percentComplete > 0 ? t("正在上传:") + percentComplete + "%" : t("选择 zip 文件") }}
{{
percentComplete > 0
? t("TXT_CODE_b625dbf0") + percentComplete + "%"
: t("TXT_CODE_c17f6488")
}}
</a-button>
</a-upload>
</a-form-item>
@ -301,7 +304,7 @@ const createInstance = async () => {
<a-form-item v-else>
<a-typography-paragraph class="mt-10">
<a-typography-text>
{{ t("填写好服务端软件文件名后,再前往文件管理上传服务端软件即可开启实例。") }}
{{ t("TXT_CODE_cbbc779f") }}
</a-typography-text>
</a-typography-paragraph>
<a-button type="primary" :loading="createInstanceLoading" @click="finalConfirm">

View File

@ -34,7 +34,7 @@ const init = async () => {
await getQuickInstallListAddr();
if (!appList.value || appList.value.length === 0) {
dialog.title = t("正在维护中");
dialog.title = t("TXT_CODE_c534ca49");
dialog.show = true;
}
} catch (err: any) {
@ -52,7 +52,7 @@ const { state: newTaskInfo, execute: executeCreateAsyncTask } = createAsyncTask(
const handleSelectTemplate = async (item: QuickStartTemplate) => {
try {
const instanceName = await openInputDialog(t("请输入新实例的名字"));
const instanceName = await openInputDialog(t("TXT_CODE_c237192c"));
await executeCreateAsyncTask({
params: {
remote_uuid: daemonId,
@ -77,7 +77,7 @@ const handleSelectTemplate = async (item: QuickStartTemplate) => {
const startDownloadTask = async () => {
if (intervalTask.value) clearInterval(intervalTask.value);
dialog.title = t("正在安装中");
dialog.title = t("TXT_CODE_f878fd4c");
dialog.show = true;
await queryStatus();
intervalTask.value = setInterval(async () => {
@ -103,7 +103,7 @@ const queryStatus = async () => {
});
if (taskInfo.value?.status === -1) {
percentage.value = 100;
dialog.title = t("安装错误");
dialog.title = t("TXT_CODE_7078fd28");
installView.value = true;
isInstalled.value = false;
clearInterval(intervalTask.value);
@ -111,7 +111,7 @@ const queryStatus = async () => {
if (taskInfo.value?.status === 0) {
percentage.value = 100;
dialog.title = t("安装完毕");
dialog.title = t("TXT_CODE_477ece61");
installView.value = false;
isInstalled.value = true;
clearInterval(intervalTask.value);
@ -156,18 +156,18 @@ onMounted(async () => {
<a-row v-else :gutter="[24, 24]" style="height: 100%">
<a-col :span="24" :md="24">
<CardPanel style="height: 100%">
<template #title>{{ t("注意事项") }}</template>
<template #title>{{ t("TXT_CODE_ef0ce2e") }}</template>
<template #body>
<a-typography-paragraph>
<a-typography-text>
{{ t("安装预设整合包将视作你已同意并阅读")
{{ t("TXT_CODE_eec3c1d7")
}}<a href="https://aka.ms/MinecraftEULA" target="_blank" rel="noopener noreferrer">
{{ t("Minecraft 最终用户协议EULA)") }}
{{ t("TXT_CODE_1e58bb5e") }}
</a>
</a-typography-text>
<br />
<a-typography-text class="color-info">
{{ t("快速安装服务由独醉科技提供文件下载支持") }}
{{ t("TXT_CODE_7153951e") }}
</a-typography-text>
</a-typography-paragraph>
</template>
@ -180,17 +180,17 @@ onMounted(async () => {
<template #body>
<div style="height: 13em">
<a-typography-paragraph
:ellipsis="{ rows: 3, expandable: true, symbol: t('查看更多') }"
:ellipsis="{ rows: 3, expandable: true, symbol: t('TXT_CODE_f4c9715b') }"
:content="item.info"
>
</a-typography-paragraph>
<a-typography-paragraph>
<a-typography-text class="color-info">
{{ t("Java版本要求") }}: {{ item.java }}
{{ t("TXT_CODE_7b92d98d") }}: {{ item.java }}
</a-typography-text>
<br />
<a-typography-text class="color-info">
{{ t("整合包大小") }}: {{ item.size }} MB
{{ t("TXT_CODE_88c990a4") }}: {{ item.size }} MB
</a-typography-text>
<br />
<a-typography-text class="color-info">
@ -203,7 +203,7 @@ onMounted(async () => {
<template #icon>
<DownloadOutlined />
</template>
{{ t("安装") }}
{{ t("TXT_CODE_1704ea49") }}
</a-button>
</template>
</CardPanel>
@ -221,9 +221,9 @@ onMounted(async () => {
>
<div v-if="!appList || appList.length === 0">
<a-typography-text>
{{ t("很抱歉,无法获取最新预设整合包列表,可能是您的网络问题或服务器正在维护中。") }}
{{ t("TXT_CODE_bcfaf14d") }}
</a-typography-text>
<a-button @click="toCreateInstancePage()">{{ t("返回手动安装") }}</a-button>
<a-button @click="toCreateInstancePage()">{{ t("TXT_CODE_bc883bbb") }}</a-button>
</div>
<div v-if="installView || isInstalled" style="text-align: center">
<a-progress
@ -235,39 +235,35 @@ onMounted(async () => {
<div v-if="installView">
<div v-if="taskInfo?.status !== -1">
<a-typography-paragraph>
<a-typography-title :level="5">{{ t("正在下载文件...") }}</a-typography-title>
<a-typography-title :level="5">{{ t("TXT_CODE_32cd41d5") }}</a-typography-title>
<a-typography-text>
{{ t("实际所需时间与网速,处理器运行速度有关,请务必耐心等待。") }}
{{ t("TXT_CODE_147a2f87") }}
</a-typography-text>
</a-typography-paragraph>
</div>
<div v-if="taskInfo?.status === -1">
<a-typography-paragraph>
<a-typography-title :level="5">{{ t("安装错误") }}</a-typography-title>
<a-typography-title :level="5">{{ t("TXT_CODE_7078fd28") }}</a-typography-title>
<a-typography-text>
{{
t(
"可能是因为网络不通畅或服务器正在维护中,请等待一段时间后再进行尝试,或使用其他安装包尝试。"
)
}}
{{ t("TXT_CODE_57cd2d04") }}
</a-typography-text>
</a-typography-paragraph>
<a-button size="" class="mr-10" @click="toCreateInstancePage()">
{{ t("返回手动安装") }}
{{ t("TXT_CODE_bc883bbb") }}
</a-button>
<a-button type="primary" size="" danger @click="dialog.show = false">
{{ t("关闭") }}
{{ t("TXT_CODE_b1dedda3") }}
</a-button>
</div>
</div>
<div v-if="isInstalled">
<a-typography-paragraph>
<a-typography-title :level="5">{{ t("安装完毕") }}</a-typography-title>
<a-typography-title :level="5">{{ t("TXT_CODE_477ece61") }}</a-typography-title>
<a-typography-text>
{{ t("大功告成!接下来您只需要进入“实例控制台”,轻点“启动实例”即可。") }}
{{ t("TXT_CODE_ce917b27") }}
</a-typography-text>
</a-typography-paragraph>
<a-button @click="toAppDetailPage()">{{ t("前往实例控制台") }}</a-button>
<a-button @click="toAppDetailPage()">{{ t("TXT_CODE_36417656") }}</a-button>
</div>
</div>
</a-modal>

View File

@ -57,7 +57,7 @@ const saveData = async () => {
uuid: <string>userUuid
}
});
return message.success(t("更新成功"));
return message.success(t("TXT_CODE_d3de39b4"));
} catch (err: any) {
console.error(err);
return message.error(err.message);
@ -92,21 +92,21 @@ const columns = computed(() => {
return arrayFilter([
{
align: "center",
title: t("所属节点"),
title: t("TXT_CODE_b26a0528"),
dataIndex: "serviceUuid",
key: "daemon",
minWidth: "200px"
},
{
align: "center",
title: t("实例名称"),
title: t("TXT_CODE_f70badb9"),
dataIndex: "nickname",
key: "name",
minWidth: "200px"
},
{
align: "center",
title: t("到期时间"),
title: t("TXT_CODE_fa920c0"),
dataIndex: "lastDatetime",
key: "limitTime",
minWidth: "200px",
@ -114,7 +114,7 @@ const columns = computed(() => {
},
{
align: "center",
title: t("实例状态"),
title: t("TXT_CODE_3d602459"),
dataIndex: "status",
key: "status",
minWidth: "200px",
@ -125,7 +125,7 @@ const columns = computed(() => {
},
{
align: "center",
title: t("操作"),
title: t("TXT_CODE_fe731dfc"),
key: "operation",
minWidth: "200px",
scopedSlots: { customRender: "operation" }
@ -146,10 +146,10 @@ const columns = computed(() => {
</template>
<template #right>
<a-button v-show="!screen.isPhone.value" class="mr-8" @click="refreshChart()">
{{ t("刷新") }}
{{ t("TXT_CODE_b76d94e0") }}
</a-button>
<a-button class="mr-8" type="primary" ghost @click="saveData()">
{{ t("保存数据") }}
{{ t("TXT_CODE_830ba3d8") }}
</a-button>
<a-button type="primary" @click="assignApp">
{{ t("TXT_CODE_a60466a1") }}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

917
package-lock.json generated
View File

@ -1,6 +1,919 @@
{
"name": "MCSManager",
"name": "mcsmanager-root",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {}
"packages": {
"": {
"name": "mcsmanager-root",
"version": "1.0.0",
"dependencies": {
"crc": "^4.3.2",
"i18next-scanner": "^4.4.0"
}
},
"node_modules/@babel/runtime": {
"version": "7.23.2",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.2.tgz",
"integrity": "sha512-mM8eg4yl5D6i3lu2QKPuPH4FArvJ8KhTofbE7jwMUv9KX5mBvwPAqnV3MlyBNqdp9RyRKP6Yck8TrfYrPvX3bg==",
"dependencies": {
"regenerator-runtime": "^0.14.0"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@gulpjs/to-absolute-glob": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/@gulpjs/to-absolute-glob/-/to-absolute-glob-4.0.0.tgz",
"integrity": "sha512-kjotm7XJrJ6v+7knhPaRgaT6q8F8K2jiafwYdNHLzmV0uGLuZY43FK6smNSHUPrhq5kX2slCUy+RGG/xGqmIKA==",
"dependencies": {
"is-negated-glob": "^1.0.0"
},
"engines": {
"node": ">=10.13.0"
}
},
"node_modules/acorn": {
"version": "8.11.2",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz",
"integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==",
"bin": {
"acorn": "bin/acorn"
},
"engines": {
"node": ">=0.4.0"
}
},
"node_modules/acorn-class-fields": {
"version": "0.3.7",
"resolved": "https://registry.npmjs.org/acorn-class-fields/-/acorn-class-fields-0.3.7.tgz",
"integrity": "sha512-jdUWSFce0fuADUljmExz4TWpPkxmRW/ZCPRqeeUzbGf0vFUcpQYbyq52l75qGd0oSwwtAepeL6hgb/naRgvcKQ==",
"dependencies": {
"acorn-private-class-elements": "^0.2.7"
},
"engines": {
"node": ">=4.8.2"
},
"peerDependencies": {
"acorn": "^6 || ^7 || ^8"
}
},
"node_modules/acorn-jsx": {
"version": "5.3.2",
"resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
"integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
"peerDependencies": {
"acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
}
},
"node_modules/acorn-private-class-elements": {
"version": "0.2.7",
"resolved": "https://registry.npmjs.org/acorn-private-class-elements/-/acorn-private-class-elements-0.2.7.tgz",
"integrity": "sha512-+GZH2wOKNZOBI4OOPmzpo4cs6mW297sn6fgIk1dUI08jGjhAaEwvC39mN2gJAg2lmAQJ1rBkFqKWonL3Zz6PVA==",
"engines": {
"node": ">=4.8.2"
},
"peerDependencies": {
"acorn": "^6.1.0 || ^7 || ^8"
}
},
"node_modules/acorn-private-methods": {
"version": "0.3.3",
"resolved": "https://registry.npmjs.org/acorn-private-methods/-/acorn-private-methods-0.3.3.tgz",
"integrity": "sha512-46oeEol3YFvLSah5m9hGMlNpxDBCEkdceJgf01AjqKYTK9r6HexKs2rgSbLK81pYjZZMonhftuUReGMlbbv05w==",
"dependencies": {
"acorn-private-class-elements": "^0.2.7"
},
"engines": {
"node": ">=4.8.2"
},
"peerDependencies": {
"acorn": "^6 || ^7 || ^8"
}
},
"node_modules/acorn-stage3": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/acorn-stage3/-/acorn-stage3-4.0.0.tgz",
"integrity": "sha512-BR+LaADtA6GTB5prkNqWmlmCLYmkyW0whvSxdHhbupTaro2qBJ95fJDEiRLPUmiACGHPaYyeH9xmNJWdGfXRQw==",
"dependencies": {
"acorn-class-fields": "^0.3.7",
"acorn-private-methods": "^0.3.3",
"acorn-static-class-features": "^0.2.4"
},
"engines": {
"node": ">=4.8.2"
},
"peerDependencies": {
"acorn": "^7.4 || ^8"
}
},
"node_modules/acorn-static-class-features": {
"version": "0.2.4",
"resolved": "https://registry.npmjs.org/acorn-static-class-features/-/acorn-static-class-features-0.2.4.tgz",
"integrity": "sha512-5X4mpYq5J3pdndLmIB0+WtFd/mKWnNYpuTlTzj32wUu/PMmEGOiayQ5UrqgwdBNiaZBtDDh5kddpP7Yg2QaQYA==",
"dependencies": {
"acorn-private-class-elements": "^0.2.7"
},
"engines": {
"node": ">=4.8.2"
},
"peerDependencies": {
"acorn": "^6.1.0 || ^7 || ^8"
}
},
"node_modules/acorn-walk": {
"version": "8.3.0",
"resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.0.tgz",
"integrity": "sha512-FS7hV565M5l1R08MXqo8odwMTB02C2UqzB17RVgu9EyuYFBqJZ3/ZY97sQD5FewVu1UyDFc1yztUDrAwT0EypA==",
"engines": {
"node": ">=0.4.0"
}
},
"node_modules/ansi-styles": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"dependencies": {
"color-convert": "^2.0.1"
},
"engines": {
"node": ">=8"
},
"funding": {
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
"node_modules/anymatch": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
"integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
"dependencies": {
"normalize-path": "^3.0.0",
"picomatch": "^2.0.4"
},
"engines": {
"node": ">= 8"
}
},
"node_modules/base64-js": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
"integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
]
},
"node_modules/bl": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/bl/-/bl-5.1.0.tgz",
"integrity": "sha512-tv1ZJHLfTDnXE6tMHv73YgSJaWR2AFuPwMntBe7XL/GBFHnT0CLnsHMogfk5+GzCDC5ZWarSCYaIGATZt9dNsQ==",
"dependencies": {
"buffer": "^6.0.3",
"inherits": "^2.0.4",
"readable-stream": "^3.4.0"
}
},
"node_modules/buffer": {
"version": "6.0.3",
"resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz",
"integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
],
"dependencies": {
"base64-js": "^1.3.1",
"ieee754": "^1.2.1"
}
},
"node_modules/chalk": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
"dependencies": {
"ansi-styles": "^4.1.0",
"supports-color": "^7.1.0"
},
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/chalk/chalk?sponsor=1"
}
},
"node_modules/clone": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz",
"integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==",
"engines": {
"node": ">=0.8"
}
},
"node_modules/clone-deep": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz",
"integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==",
"dependencies": {
"is-plain-object": "^2.0.4",
"kind-of": "^6.0.2",
"shallow-clone": "^3.0.0"
},
"engines": {
"node": ">=6"
}
},
"node_modules/clone-stats": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz",
"integrity": "sha512-au6ydSpg6nsrigcZ4m8Bc9hxjeW+GJ8xh5G3BJCMt4WXe1H10UNaVOamqQTmrx1kjVuxAHIQSNU6hY4Nsn9/ag=="
},
"node_modules/color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"dependencies": {
"color-name": "~1.1.4"
},
"engines": {
"node": ">=7.0.0"
}
},
"node_modules/color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
},
"node_modules/commander": {
"version": "9.5.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz",
"integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==",
"engines": {
"node": "^12.20.0 || >=14"
}
},
"node_modules/convert-source-map": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
"integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg=="
},
"node_modules/core-util-is": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
"integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ=="
},
"node_modules/crc": {
"version": "4.3.2",
"resolved": "https://registry.npmjs.org/crc/-/crc-4.3.2.tgz",
"integrity": "sha512-uGDHf4KLLh2zsHa8D8hIQ1H/HtFQhyHrc0uhHBcoKGol/Xnb+MPYfUMw7cvON6ze/GUESTudKayDcJC5HnJv1A==",
"engines": {
"node": ">=12"
},
"peerDependencies": {
"buffer": ">=6.0.3"
},
"peerDependenciesMeta": {
"buffer": {
"optional": true
}
}
},
"node_modules/deepmerge": {
"version": "4.3.1",
"resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz",
"integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/ensure-type": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/ensure-type/-/ensure-type-1.5.1.tgz",
"integrity": "sha512-Dxe+mVF4MupV6eueWiFa6hUd9OL9lIM2/LqR40k1P+dwG+G2il2UigXTU9aQlaw+Y/N0BKSaTofNw73htTbC5g=="
},
"node_modules/eol": {
"version": "0.9.1",
"resolved": "https://registry.npmjs.org/eol/-/eol-0.9.1.tgz",
"integrity": "sha512-Ds/TEoZjwggRoz/Q2O7SE3i4Jm66mqTDfmdHdq/7DKVk3bro9Q8h6WdXKdPqFLMoqxrDK5SVRzHVPOS6uuGtrg=="
},
"node_modules/esprima-next": {
"version": "5.8.4",
"resolved": "https://registry.npmjs.org/esprima-next/-/esprima-next-5.8.4.tgz",
"integrity": "sha512-8nYVZ4ioIH4Msjb/XmhnBdz5WRRBaYqevKa1cv9nGJdCehMbzZCPNEEnqfLCZVetUVrUPEcb5IYyu1GG4hFqgg==",
"bin": {
"esparse": "bin/esparse.js",
"esvalidate": "bin/esvalidate.js"
},
"engines": {
"node": ">=12"
}
},
"node_modules/fast-fifo": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz",
"integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ=="
},
"node_modules/fastq": {
"version": "1.15.0",
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz",
"integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==",
"dependencies": {
"reusify": "^1.0.4"
}
},
"node_modules/fs-mkdirp-stream": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/fs-mkdirp-stream/-/fs-mkdirp-stream-2.0.1.tgz",
"integrity": "sha512-UTOY+59K6IA94tec8Wjqm0FSh5OVudGNB0NL/P6fB3HiE3bYOY3VYBGijsnOHNkQSwC1FKkU77pmq7xp9CskLw==",
"dependencies": {
"graceful-fs": "^4.2.8",
"streamx": "^2.12.0"
},
"engines": {
"node": ">=10.13.0"
}
},
"node_modules/glob-parent": {
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
"integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
"dependencies": {
"is-glob": "^4.0.3"
},
"engines": {
"node": ">=10.13.0"
}
},
"node_modules/glob-stream": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-8.0.0.tgz",
"integrity": "sha512-CdIUuwOkYNv9ZadR3jJvap8CMooKziQZ/QCSPhEb7zqfsEI5YnPmvca7IvbaVE3z58ZdUYD2JsU6AUWjL8WZJA==",
"dependencies": {
"@gulpjs/to-absolute-glob": "^4.0.0",
"anymatch": "^3.1.3",
"fastq": "^1.13.0",
"glob-parent": "^6.0.2",
"is-glob": "^4.0.3",
"is-negated-glob": "^1.0.0",
"normalize-path": "^3.0.0",
"streamx": "^2.12.5"
},
"engines": {
"node": ">=10.13.0"
}
},
"node_modules/graceful-fs": {
"version": "4.2.11",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
"integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="
},
"node_modules/gulp-sort": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/gulp-sort/-/gulp-sort-2.0.0.tgz",
"integrity": "sha512-MyTel3FXOdh1qhw1yKhpimQrAmur9q1X0ZigLmCOxouQD+BD3za9/89O+HfbgBQvvh4igEbp0/PUWO+VqGYG1g==",
"dependencies": {
"through2": "^2.0.1"
}
},
"node_modules/gulp-sort/node_modules/readable-stream": {
"version": "2.3.8",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz",
"integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==",
"dependencies": {
"core-util-is": "~1.0.0",
"inherits": "~2.0.3",
"isarray": "~1.0.0",
"process-nextick-args": "~2.0.0",
"safe-buffer": "~5.1.1",
"string_decoder": "~1.1.1",
"util-deprecate": "~1.0.1"
}
},
"node_modules/gulp-sort/node_modules/safe-buffer": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
},
"node_modules/gulp-sort/node_modules/string_decoder": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
"dependencies": {
"safe-buffer": "~5.1.0"
}
},
"node_modules/gulp-sort/node_modules/through2": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz",
"integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==",
"dependencies": {
"readable-stream": "~2.3.6",
"xtend": "~4.0.1"
}
},
"node_modules/has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
"engines": {
"node": ">=8"
}
},
"node_modules/i18next": {
"version": "23.7.5",
"resolved": "https://registry.npmjs.org/i18next/-/i18next-23.7.5.tgz",
"integrity": "sha512-IKpP+vu/sU3UYZe6ajizEXiretu6YJQE0zhkPJBoiOboiR4NLzbtJP/MADCcNx9nAGYM5WTEW4MBvaDx+gK+6A==",
"funding": [
{
"type": "individual",
"url": "https://locize.com"
},
{
"type": "individual",
"url": "https://locize.com/i18next.html"
},
{
"type": "individual",
"url": "https://www.i18next.com/how-to/faq#i18next-is-awesome.-how-can-i-support-the-project"
}
],
"dependencies": {
"@babel/runtime": "^7.23.2"
}
},
"node_modules/i18next-scanner": {
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/i18next-scanner/-/i18next-scanner-4.4.0.tgz",
"integrity": "sha512-bgnVEfoFHLVxfXNQtsFFzexB/5kwgDZZkZ6+AnCmyaFKEQQbtMkgPgLHlMZ0deIIEG6KN/tYAus5ZJzng2Ac9g==",
"dependencies": {
"acorn": "^8.0.4",
"acorn-jsx": "^5.3.1",
"acorn-stage3": "^4.0.0",
"acorn-walk": "^8.0.0",
"chalk": "^4.1.0",
"clone-deep": "^4.0.0",
"commander": "^9.0.0",
"deepmerge": "^4.0.0",
"ensure-type": "^1.5.0",
"eol": "^0.9.1",
"esprima-next": "^5.7.0",
"gulp-sort": "^2.0.0",
"i18next": "*",
"lodash": "^4.0.0",
"parse5": "^6.0.0",
"sortobject": "^4.0.0",
"through2": "^4.0.0",
"vinyl": "^3.0.0",
"vinyl-fs": "^4.0.0"
},
"bin": {
"i18next-scanner": "bin/cli.js"
},
"engines": {
"node": ">=12"
}
},
"node_modules/iconv-lite": {
"version": "0.6.3",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
"integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
"dependencies": {
"safer-buffer": ">= 2.1.2 < 3.0.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/ieee754": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
"integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
]
},
"node_modules/inherits": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
},
"node_modules/is-extglob": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
"integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/is-glob": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
"integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
"dependencies": {
"is-extglob": "^2.1.1"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/is-negated-glob": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-negated-glob/-/is-negated-glob-1.0.0.tgz",
"integrity": "sha512-czXVVn/QEmgvej1f50BZ648vUI+em0xqMq2Sn+QncCLN4zj1UAxlT+kw/6ggQTOaZPd1HqKQGEqbpQVtJucWug==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/is-plain-object": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz",
"integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==",
"dependencies": {
"isobject": "^3.0.1"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/is-valid-glob": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-1.0.0.tgz",
"integrity": "sha512-AhiROmoEFDSsjx8hW+5sGwgKVIORcXnrlAx/R0ZSeaPw70Vw0CqkGBBhHGL58Uox2eXnU1AnvXJl1XlyedO5bA==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/isarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
"integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ=="
},
"node_modules/isobject": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
"integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/kind-of": {
"version": "6.0.3",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
"integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/lead": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/lead/-/lead-4.0.0.tgz",
"integrity": "sha512-DpMa59o5uGUWWjruMp71e6knmwKU3jRBBn1kjuLWN9EeIOxNeSAwvHf03WIl8g/ZMR2oSQC9ej3yeLBwdDc/pg==",
"engines": {
"node": ">=10.13.0"
}
},
"node_modules/lodash": {
"version": "4.17.21",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
},
"node_modules/normalize-path": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/now-and-later": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/now-and-later/-/now-and-later-3.0.0.tgz",
"integrity": "sha512-pGO4pzSdaxhWTGkfSfHx3hVzJVslFPwBp2Myq9MYN/ChfJZF87ochMAXnvz6/58RJSf5ik2q9tXprBBrk2cpcg==",
"dependencies": {
"once": "^1.4.0"
},
"engines": {
"node": ">= 10.13.0"
}
},
"node_modules/once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
"dependencies": {
"wrappy": "1"
}
},
"node_modules/parse5": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz",
"integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw=="
},
"node_modules/picomatch": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
"engines": {
"node": ">=8.6"
},
"funding": {
"url": "https://github.com/sponsors/jonschlinkert"
}
},
"node_modules/process-nextick-args": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="
},
"node_modules/queue-tick": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/queue-tick/-/queue-tick-1.0.1.tgz",
"integrity": "sha512-kJt5qhMxoszgU/62PLP1CJytzd2NKetjSRnyuj31fDd3Rlcz3fzlFdFLD1SItunPwyqEOkca6GbV612BWfaBag=="
},
"node_modules/readable-stream": {
"version": "3.6.2",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
"integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
"dependencies": {
"inherits": "^2.0.3",
"string_decoder": "^1.1.1",
"util-deprecate": "^1.0.1"
},
"engines": {
"node": ">= 6"
}
},
"node_modules/regenerator-runtime": {
"version": "0.14.0",
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz",
"integrity": "sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA=="
},
"node_modules/remove-trailing-separator": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz",
"integrity": "sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw=="
},
"node_modules/replace-ext": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-2.0.0.tgz",
"integrity": "sha512-UszKE5KVK6JvyD92nzMn9cDapSk6w/CaFZ96CnmDMUqH9oowfxF/ZjRITD25H4DnOQClLA4/j7jLGXXLVKxAug==",
"engines": {
"node": ">= 10"
}
},
"node_modules/resolve-options": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/resolve-options/-/resolve-options-2.0.0.tgz",
"integrity": "sha512-/FopbmmFOQCfsCx77BRFdKOniglTiHumLgwvd6IDPihy1GKkadZbgQJBcTb2lMzSR1pndzd96b1nZrreZ7+9/A==",
"dependencies": {
"value-or-function": "^4.0.0"
},
"engines": {
"node": ">= 10.13.0"
}
},
"node_modules/reusify": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
"integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
"engines": {
"iojs": ">=1.0.0",
"node": ">=0.10.0"
}
},
"node_modules/safe-buffer": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
]
},
"node_modules/safer-buffer": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
},
"node_modules/shallow-clone": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz",
"integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==",
"dependencies": {
"kind-of": "^6.0.2"
},
"engines": {
"node": ">=8"
}
},
"node_modules/sortobject": {
"version": "4.17.0",
"resolved": "https://registry.npmjs.org/sortobject/-/sortobject-4.17.0.tgz",
"integrity": "sha512-gzx7USv55AFRQ7UCWJHHauwD/ptUHF9MLXCGO3f5M9zauDPZ/4a9H6/VVbOXefdpEoI1unwB/bArHIVMbWBHmA==",
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://bevry.me/fund"
}
},
"node_modules/stream-composer": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/stream-composer/-/stream-composer-1.0.2.tgz",
"integrity": "sha512-bnBselmwfX5K10AH6L4c8+S5lgZMWI7ZYrz2rvYjCPB2DIMC4Ig8OpxGpNJSxRZ58oti7y1IcNvjBAz9vW5m4w==",
"dependencies": {
"streamx": "^2.13.2"
}
},
"node_modules/streamx": {
"version": "2.15.4",
"resolved": "https://registry.npmjs.org/streamx/-/streamx-2.15.4.tgz",
"integrity": "sha512-uSXKl88bibiUCQ1eMpItRljCzDENcDx18rsfDmV79r0e/ThfrAwxG4Y2FarQZ2G4/21xcOKmFFd1Hue+ZIDwHw==",
"dependencies": {
"fast-fifo": "^1.1.0",
"queue-tick": "^1.0.1"
}
},
"node_modules/string_decoder": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
"integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
"dependencies": {
"safe-buffer": "~5.2.0"
}
},
"node_modules/supports-color": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
"dependencies": {
"has-flag": "^4.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/teex": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/teex/-/teex-1.0.1.tgz",
"integrity": "sha512-eYE6iEI62Ni1H8oIa7KlDU6uQBtqr4Eajni3wX7rpfXD8ysFx8z0+dri+KWEPWpBsxXfxu58x/0jvTVT1ekOSg==",
"dependencies": {
"streamx": "^2.12.5"
}
},
"node_modules/through2": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz",
"integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==",
"dependencies": {
"readable-stream": "3"
}
},
"node_modules/to-through": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/to-through/-/to-through-3.0.0.tgz",
"integrity": "sha512-y8MN937s/HVhEoBU1SxfHC+wxCHkV1a9gW8eAdTadYh/bGyesZIVcbjI+mSpFbSVwQici/XjBjuUyri1dnXwBw==",
"dependencies": {
"streamx": "^2.12.5"
},
"engines": {
"node": ">=10.13.0"
}
},
"node_modules/util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
},
"node_modules/value-or-function": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/value-or-function/-/value-or-function-4.0.0.tgz",
"integrity": "sha512-aeVK81SIuT6aMJfNo9Vte8Dw0/FZINGBV8BfCraGtqVxIeLAEhJyoWs8SmvRVmXfGss2PmmOwZCuBPbZR+IYWg==",
"engines": {
"node": ">= 10.13.0"
}
},
"node_modules/vinyl": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/vinyl/-/vinyl-3.0.0.tgz",
"integrity": "sha512-rC2VRfAVVCGEgjnxHUnpIVh3AGuk62rP3tqVrn+yab0YH7UULisC085+NYH+mnqf3Wx4SpSi1RQMwudL89N03g==",
"dependencies": {
"clone": "^2.1.2",
"clone-stats": "^1.0.0",
"remove-trailing-separator": "^1.1.0",
"replace-ext": "^2.0.0",
"teex": "^1.0.1"
},
"engines": {
"node": ">=10.13.0"
}
},
"node_modules/vinyl-contents": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/vinyl-contents/-/vinyl-contents-2.0.0.tgz",
"integrity": "sha512-cHq6NnGyi2pZ7xwdHSW1v4Jfnho4TEGtxZHw01cmnc8+i7jgR6bRnED/LbrKan/Q7CvVLbnvA5OepnhbpjBZ5Q==",
"dependencies": {
"bl": "^5.0.0",
"vinyl": "^3.0.0"
},
"engines": {
"node": ">=10.13.0"
}
},
"node_modules/vinyl-fs": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-4.0.0.tgz",
"integrity": "sha512-7GbgBnYfaquMk3Qu9g22x000vbYkOex32930rBnc3qByw6HfMEAoELjCjoJv4HuEQxHAurT+nvMHm6MnJllFLw==",
"dependencies": {
"fs-mkdirp-stream": "^2.0.1",
"glob-stream": "^8.0.0",
"graceful-fs": "^4.2.11",
"iconv-lite": "^0.6.3",
"is-valid-glob": "^1.0.0",
"lead": "^4.0.0",
"normalize-path": "3.0.0",
"resolve-options": "^2.0.0",
"stream-composer": "^1.0.2",
"streamx": "^2.14.0",
"to-through": "^3.0.0",
"value-or-function": "^4.0.0",
"vinyl": "^3.0.0",
"vinyl-sourcemap": "^2.0.0"
},
"engines": {
"node": ">=10.13.0"
}
},
"node_modules/vinyl-sourcemap": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/vinyl-sourcemap/-/vinyl-sourcemap-2.0.0.tgz",
"integrity": "sha512-BAEvWxbBUXvlNoFQVFVHpybBbjW1r03WhohJzJDSfgrrK5xVYIDTan6xN14DlyImShgDRv2gl9qhM6irVMsV0Q==",
"dependencies": {
"convert-source-map": "^2.0.0",
"graceful-fs": "^4.2.10",
"now-and-later": "^3.0.0",
"streamx": "^2.12.5",
"vinyl": "^3.0.0",
"vinyl-contents": "^2.0.0"
},
"engines": {
"node": ">=10.13.0"
}
},
"node_modules/wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
},
"node_modules/xtend": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
"integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==",
"engines": {
"node": ">=0.4"
}
}
}
}

11
package.json Normal file
View File

@ -0,0 +1,11 @@
{
"name": "mcsmanager-root",
"version": "1.0.0",
"scripts": {
"i18n": "i18next-scanner --config i18-scanner.config.js"
},
"dependencies": {
"crc": "^4.3.2",
"i18next-scanner": "^4.4.0"
}
}

View File

@ -197,7 +197,7 @@ function getDefaultFrontendLayoutConfig(): IPageLayoutConfig[] {
id: getRandomId(),
meta: {},
type: "InstanceFileManager",
title: t("文件管理"),
title: t("TXT_CODE_ae533703"),
width: 12,
height: LayoutCardHeight.AUTO,
disableDelete: true
@ -219,7 +219,7 @@ function getDefaultFrontendLayoutConfig(): IPageLayoutConfig[] {
id: getRandomId(),
meta: {},
type: "InstanceServerConfigOverview",
title: t("服务端配置文件"),
title: t("TXT_CODE_d07742fe"),
width: 12,
height: LayoutCardHeight.AUTO,
disableDelete: true
@ -241,7 +241,7 @@ function getDefaultFrontendLayoutConfig(): IPageLayoutConfig[] {
id: getRandomId(),
meta: {},
type: "InstanceServerConfigFile",
title: t("编辑服务端配置文件"),
title: t("TXT_CODE_1c45f7fe"),
width: 12,
height: LayoutCardHeight.AUTO,
disableDelete: true
@ -263,7 +263,7 @@ function getDefaultFrontendLayoutConfig(): IPageLayoutConfig[] {
id: getRandomId(),
meta: {},
type: "Schedule",
title: t("计划任务"),
title: t("TXT_CODE_b7d026f8"),
width: 12,
height: LayoutCardHeight.AUTO,
disableDelete: true
@ -285,7 +285,7 @@ function getDefaultFrontendLayoutConfig(): IPageLayoutConfig[] {
id: getRandomId(),
meta: {},
type: "UserList",
title: t("用户列表"),
title: t("TXT_CODE_97d17cce"),
width: 12,
height: LayoutCardHeight.AUTO,
disableDelete: true
@ -307,7 +307,7 @@ function getDefaultFrontendLayoutConfig(): IPageLayoutConfig[] {
id: getRandomId(),
meta: {},
type: "UserAccessSettings",
title: t("用户权限设定"),
title: t("TXT_CODE_dbc9f7b2"),
width: 12,
height: LayoutCardHeight.AUTO,
disableDelete: true
@ -329,7 +329,7 @@ function getDefaultFrontendLayoutConfig(): IPageLayoutConfig[] {
id: getRandomId(),
meta: {},
type: "Settings",
title: t("系统设置"),
title: t("TXT_CODE_3fe97dcc"),
width: 8,
height: LayoutCardHeight.MEDIUM,
disableDelete: true
@ -365,7 +365,7 @@ function getDefaultFrontendLayoutConfig(): IPageLayoutConfig[] {
id: getRandomId(),
meta: {},
type: "ImageManager",
title: t("镜像管理"),
title: t("TXT_CODE_e6c30866"),
width: 12,
height: LayoutCardHeight.AUTO,
disableDelete: true
@ -387,7 +387,7 @@ function getDefaultFrontendLayoutConfig(): IPageLayoutConfig[] {
id: getRandomId(),
meta: {},
type: "NewImage",
title: t("创建镜像"),
title: t("TXT_CODE_3d09f0ac"),
width: 12,
height: LayoutCardHeight.AUTO,
disableDelete: true
@ -442,7 +442,7 @@ function getDefaultFrontendLayoutConfig(): IPageLayoutConfig[] {
{
id: getRandomId(),
type: "UserStatusBlock",
title: t("实例总计"),
title: t("TXT_CODE_7411336e"),
meta: {
type: "instance_all"
},
@ -453,7 +453,7 @@ function getDefaultFrontendLayoutConfig(): IPageLayoutConfig[] {
{
id: getRandomId(),
type: "UserStatusBlock",
title: t("正在运行"),
title: t("TXT_CODE_f912fadc"),
meta: {
type: "instance_running"
},
@ -464,7 +464,7 @@ function getDefaultFrontendLayoutConfig(): IPageLayoutConfig[] {
{
id: getRandomId(),
type: "UserStatusBlock",
title: t("未运行"),
title: t("TXT_CODE_15f2e564"),
meta: {
type: "instance_stop"
},
@ -475,7 +475,7 @@ function getDefaultFrontendLayoutConfig(): IPageLayoutConfig[] {
{
id: getRandomId(),
type: "UserStatusBlock",
title: t("维护中"),
title: t("TXT_CODE_342a04a9"),
meta: {
type: "instance_error"
},
@ -486,7 +486,7 @@ function getDefaultFrontendLayoutConfig(): IPageLayoutConfig[] {
{
id: getRandomId(),
type: "UserInstanceList",
title: t("实例列表"),
title: t("TXT_CODE_d655beec"),
meta: {
type: "instance_error"
},
@ -504,7 +504,7 @@ function getDefaultFrontendLayoutConfig(): IPageLayoutConfig[] {
id: getRandomId(),
meta: {},
type: "Page404",
title: t("页面未找到"),
title: t("TXT_CODE_6aa286df"),
width: 6,
height: LayoutCardHeight.MINI,
disableDelete: true