mirror of
https://github.com/MCSManager/MCSManager.git
synced 2025-02-23 16:09:37 +08:00
Fix: Warning Alert
This commit is contained in:
parent
80884524c6
commit
6b1eb6c084
2
frontend/components.d.ts
vendored
2
frontend/components.d.ts
vendored
@ -94,11 +94,13 @@ declare module 'vue' {
|
||||
RightMenu: typeof import('./src/components/fc/RightMenu.vue')['default']
|
||||
RouterLink: typeof import('vue-router')['RouterLink']
|
||||
RouterView: typeof import('vue-router')['RouterView']
|
||||
SafeWarning: typeof import('./src/components/fc/SafeWarning.vue')['default']
|
||||
SelectInstances: typeof import('./src/components/fc/SelectInstances.vue')['default']
|
||||
Style1: typeof import('./src/components/time/Style1.vue')['default']
|
||||
Style2: typeof import('./src/components/time/Style2.vue')['default']
|
||||
TaskLoadingDialog: typeof import('./src/components/fc/TaskLoadingDialog.vue')['default']
|
||||
TerminalCore: typeof import('./src/components/TerminalCore.vue')['default']
|
||||
UploadFileDialog: typeof import('./src/components/fc/UploadFileDialog.vue')['default']
|
||||
WarningDialog: typeof import('./src/components/fc/WarningDialog.vue')['default']
|
||||
}
|
||||
}
|
||||
|
@ -58,7 +58,8 @@ const instancesList = computed(() => {
|
||||
daemonId: currentRemoteNode.value?.uuid ?? "",
|
||||
nickname: instance.config.nickname,
|
||||
status: instance.status,
|
||||
hostIp: `${currentRemoteNode.value?.ip}:${currentRemoteNode.value?.port}`
|
||||
hostIp: `${currentRemoteNode.value?.ip}:${currentRemoteNode.value?.port}`,
|
||||
config: instance.config
|
||||
});
|
||||
}
|
||||
return newInstances;
|
||||
@ -242,6 +243,12 @@ const handleChangeNode = async (item: NodeStatus) => {
|
||||
}"
|
||||
>
|
||||
<template #bodyCell="{ column, record }: AntTableCell">
|
||||
<template v-if="column.key === 'safe'">
|
||||
<span v-if="record?.config?.docker?.image" style="color: var(--color-green-6)">
|
||||
{{ t("容器保护") }}
|
||||
</span>
|
||||
<span v-else class="color-danger">{{ t("无保护") }}</span>
|
||||
</template>
|
||||
<template v-if="column.key === 'operation'">
|
||||
<a-button
|
||||
v-if="findItem(record)"
|
||||
|
@ -32,6 +32,7 @@ defineExpose({
|
||||
:mask-closable="false"
|
||||
:closable="false"
|
||||
:footer="null"
|
||||
@cancel="cancel"
|
||||
>
|
||||
<div class="dialog-overflow-container">
|
||||
<div class="flex flex-center">
|
||||
|
84
frontend/src/components/fc/WarningDialog.vue
Normal file
84
frontend/src/components/fc/WarningDialog.vue
Normal file
@ -0,0 +1,84 @@
|
||||
<script setup lang="ts">
|
||||
import { ref } from "vue";
|
||||
import type { MountComponent } from "@/types";
|
||||
import { t } from "@/lang/i18n";
|
||||
|
||||
interface Props extends MountComponent {
|
||||
title: string;
|
||||
subTitle: string;
|
||||
checkText: string;
|
||||
}
|
||||
|
||||
const props = defineProps<Props>();
|
||||
const open = ref(false);
|
||||
const checkbox = ref(false);
|
||||
let resolve: Function;
|
||||
let reject: Function;
|
||||
|
||||
const openDialog = () => {
|
||||
open.value = true;
|
||||
return new Promise<void>((y, n) => {
|
||||
resolve = y;
|
||||
reject = n;
|
||||
});
|
||||
};
|
||||
|
||||
const cancel = () => {
|
||||
open.value = false;
|
||||
reject(new Error(t("已取消操作!")));
|
||||
if (props.destroyComponent) props.destroyComponent();
|
||||
};
|
||||
|
||||
const confirm = () => {
|
||||
open.value = false;
|
||||
resolve();
|
||||
if (props.destroyComponent) props.destroyComponent();
|
||||
};
|
||||
|
||||
defineExpose({
|
||||
cancel,
|
||||
confirm,
|
||||
openDialog
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<a-modal
|
||||
v-model:open="open"
|
||||
centered
|
||||
width="600px"
|
||||
title=""
|
||||
:mask-closable="false"
|
||||
:closable="false"
|
||||
:footer="null"
|
||||
@cancel="cancel"
|
||||
>
|
||||
<div class="dialog-overflow-container">
|
||||
<div class="flex flex-center">
|
||||
<div>
|
||||
<a-typography-paragraph>
|
||||
<a-typography-title :level="4">
|
||||
<div class="flex flex-center mb-24">
|
||||
{{ props.title }}
|
||||
</div>
|
||||
</a-typography-title>
|
||||
<a-typography-text>
|
||||
<div class="flex flex-center" style="gap: 10px">
|
||||
<pre>{{ props.subTitle }}</pre>
|
||||
</div>
|
||||
</a-typography-text>
|
||||
</a-typography-paragraph>
|
||||
<div class="justify-center mb-24">
|
||||
<a-checkbox v-model:checked="checkbox">{{ props.checkText }}</a-checkbox>
|
||||
</div>
|
||||
<div class="flex justify-center">
|
||||
<a-button class="mr-12" danger :disabled="!checkbox" @click="confirm">
|
||||
{{ t("确定") }}
|
||||
</a-button>
|
||||
<a-button @click="cancel">{{ t("取消") }}</a-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</a-modal>
|
||||
</template>
|
@ -37,6 +37,11 @@ export async function useSelectInstances(data: UserInstance[] = []) {
|
||||
dataIndex: "nickname",
|
||||
key: "instanceUuid"
|
||||
},
|
||||
{
|
||||
align: "center",
|
||||
title: t("安全性"),
|
||||
key: "safe"
|
||||
},
|
||||
{
|
||||
align: "center",
|
||||
title: t("TXT_CODE_fe731dfc"),
|
||||
|
@ -1,9 +1,12 @@
|
||||
import type { IGlobalInstanceConfig } from "../../../common/global.d.ts";
|
||||
|
||||
export interface UserInstance {
|
||||
hostIp: string;
|
||||
instanceUuid: string;
|
||||
nickname: string;
|
||||
daemonId: string;
|
||||
status: number;
|
||||
config?: IGlobalInstanceConfig;
|
||||
}
|
||||
|
||||
export interface BaseUserInfo {
|
||||
|
@ -16,6 +16,8 @@ import { reportErrorMsg } from "@/tools/validator";
|
||||
import { INSTANCE_STATUS } from "@/types/const";
|
||||
import type { AntColumnsType, AntTableCell } from "@/types/ant";
|
||||
import dayjs from "dayjs";
|
||||
import WarningDialog from "@/components/fc/WarningDialog.vue";
|
||||
import { useMountComponent } from "@/hooks/useMountComponent";
|
||||
|
||||
const props = defineProps<{
|
||||
card: LayoutCard;
|
||||
@ -49,6 +51,24 @@ const handleDelete = async (deletedInstance: UserInstance) => {
|
||||
const assignApp = async () => {
|
||||
try {
|
||||
const selectedInstances = await useSelectInstances(dataSource.value);
|
||||
let warningInstances: string[] = [];
|
||||
for (const instance of selectedInstances || []) {
|
||||
if (typeof instance.config?.docker?.image == "string" && !instance.config?.docker?.image)
|
||||
warningInstances.push(instance.nickname);
|
||||
}
|
||||
if (warningInstances.length > 0) {
|
||||
const component = (
|
||||
await useMountComponent({
|
||||
title: t("安全警告"),
|
||||
subTitle:
|
||||
t(
|
||||
"你所分配的实例中包含一些没有启用 “容器保护” 的实例,MCSManager 将无法控制此用户的行为,被分配的用户可以通过这些实例上传恶意软件入侵你的主机,请确保子用户是您信任的人。\n\n有安全风险的实例名字如下:"
|
||||
) + warningInstances.join(", "),
|
||||
checkText: t("我已知晓我可能会被入侵!忽略风险!")
|
||||
})
|
||||
).load<InstanceType<typeof WarningDialog>>(WarningDialog);
|
||||
await component.openDialog();
|
||||
}
|
||||
if (selectedInstances) dataSource.value = selectedInstances;
|
||||
await saveData();
|
||||
} catch (err: any) {
|
||||
|
Loading…
Reference in New Issue
Block a user