mirror of
https://github.com/MCSManager/MCSManager.git
synced 2025-03-07 16:26:45 +08:00
commit
bf8791893a
@ -3,7 +3,7 @@ import { router, type RouterMetaInfo } from "@/config/router";
|
||||
import logo from "@/assets/logo.png";
|
||||
import { useLayoutContainerStore } from "@/stores/useLayoutContainerStore";
|
||||
import { useRoute } from "vue-router";
|
||||
import { computed, h, reactive } from "vue";
|
||||
import { computed, h } from "vue";
|
||||
import { useAppRouters } from "@/hooks/useAppRouters";
|
||||
import { notification } from "ant-design-vue";
|
||||
import {
|
||||
@ -14,25 +14,26 @@ import {
|
||||
UserOutlined,
|
||||
MenuUnfoldOutlined,
|
||||
FormatPainterOutlined,
|
||||
FormatPainterFilled,
|
||||
TranslationOutlined
|
||||
} from "@ant-design/icons-vue";
|
||||
import { useScreen } from "@/hooks/useScreen";
|
||||
import CardPanel from "./CardPanel.vue";
|
||||
import { $t, setLanguage, $t as t } from "@/lang/i18n";
|
||||
import { THEME, useAppConfigStore } from "@/stores/useAppConfigStore";
|
||||
|
||||
import { logoutUser } from "@/services/apis/index";
|
||||
import { message } from "ant-design-vue";
|
||||
import { useAppToolsStore } from "@/stores/useAppToolsStore";
|
||||
const [messageApi] = message.useMessage();
|
||||
// const [messageApi] = message.useMessage();
|
||||
const { containerState, changeDesignMode } = useLayoutContainerStore();
|
||||
const { getRouteParamsUrl, toPage } = useAppRouters();
|
||||
const { setTheme, isDarkTheme } = useAppConfigStore();
|
||||
const { setTheme } = useAppConfigStore();
|
||||
const { state: appTools } = useAppToolsStore();
|
||||
const openNewCardDialog = () => {
|
||||
containerState.showNewCardDialog = true;
|
||||
};
|
||||
|
||||
const { execute } = logoutUser();
|
||||
|
||||
const handleToPage = (url: string) => {
|
||||
containerState.showPhoneMenu = false;
|
||||
toPage({
|
||||
@ -170,9 +171,7 @@ const appMenus = computed(() => {
|
||||
notification.info({
|
||||
placement: "top",
|
||||
message: t("TXT_CODE_7b1adf35"),
|
||||
description: t(
|
||||
"TXT_CODE_6b6f1d3"
|
||||
)
|
||||
description: t("TXT_CODE_6b6f1d3")
|
||||
});
|
||||
},
|
||||
conditions: !containerState.isDesignMode,
|
||||
@ -190,9 +189,12 @@ const appMenus = computed(() => {
|
||||
{
|
||||
title: t("TXT_CODE_2c69ab15"),
|
||||
icon: LogoutOutlined,
|
||||
click: () => {
|
||||
toPage({ path: "/" });
|
||||
messageApi.success(t("TXT_CODE_e6856d81"));
|
||||
click: async () => {
|
||||
await execute();
|
||||
message.success(t("成功退出登录"));
|
||||
router.go(0);
|
||||
// toPage({ path: "/" });
|
||||
// messageApi.success(t("TXT_CODE_e6856d81"));
|
||||
},
|
||||
conditions: !containerState.isDesignMode,
|
||||
onlyPC: false
|
||||
|
@ -24,6 +24,12 @@ export const loginUser = useDefineApi<
|
||||
method: "POST"
|
||||
});
|
||||
|
||||
// 用户登出
|
||||
export const logoutUser = useDefineApi<any, any>({
|
||||
url: "/api/auth/logout",
|
||||
method: "GET"
|
||||
});
|
||||
|
||||
// 获取当前登录的用户信息
|
||||
export const userInfoApi = useDefineApi<any, BaseUserInfo>({
|
||||
url: "/api/auth/"
|
||||
@ -119,3 +125,52 @@ export const addUser = useDefineApi<
|
||||
export const overviewInfo = useDefineApi<any, IPanelOverviewResponse>({
|
||||
url: "/api/overview"
|
||||
});
|
||||
|
||||
// 节点管理
|
||||
// 修改秘钥
|
||||
export const editNode = useDefineApi<
|
||||
{
|
||||
params: {
|
||||
uuid: string;
|
||||
};
|
||||
data: {
|
||||
apiKey?: string;
|
||||
ip?: string;
|
||||
port?: number;
|
||||
remarks?: string;
|
||||
};
|
||||
},
|
||||
any
|
||||
>({
|
||||
url: "/api/service/remote_service",
|
||||
method: "PUT"
|
||||
});
|
||||
|
||||
// 新建节点
|
||||
export const addNode = useDefineApi<
|
||||
{
|
||||
data: {
|
||||
ip: string;
|
||||
port: number;
|
||||
remarks: string;
|
||||
apiKey: string;
|
||||
};
|
||||
},
|
||||
any
|
||||
>({
|
||||
url: "/api/service/remote_service",
|
||||
method: "POST"
|
||||
});
|
||||
|
||||
// 删除节点
|
||||
export const deleteNode = useDefineApi<
|
||||
{
|
||||
params: {
|
||||
uuid: string;
|
||||
};
|
||||
},
|
||||
any
|
||||
>({
|
||||
url: "/api/service/remote_service",
|
||||
method: "DELETE"
|
||||
});
|
||||
|
@ -1,7 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import CardPanel from "@/components/CardPanel.vue";
|
||||
import type { LayoutCard } from "@/types/index";
|
||||
import { ref } from "vue";
|
||||
import { ref, computed } from "vue";
|
||||
import { t } from "@/lang/i18n";
|
||||
import {
|
||||
ProfileOutlined,
|
||||
@ -16,8 +16,14 @@ import BetweenMenus from "@/components/BetweenMenus.vue";
|
||||
import { useOverviewInfo, type ComputedNodeInfo } from "@/hooks/useOverviewInfo";
|
||||
import IconBtn from "@/components/IconBtn.vue";
|
||||
import NodeSimpleChart from "@/components/NodeSimpleChart.vue";
|
||||
import {
|
||||
editNode as editNodeApi,
|
||||
addNode as addNodeApi,
|
||||
deleteNode as deleteNodeApi
|
||||
} from "@/services/apis";
|
||||
import { message } from "ant-design-vue";
|
||||
|
||||
const props = defineProps<{
|
||||
defineProps<{
|
||||
card: LayoutCard;
|
||||
}>();
|
||||
|
||||
@ -85,11 +91,124 @@ const nodeOperations = [
|
||||
{
|
||||
title: t("TXT_CODE_b5c7b82d"),
|
||||
icon: SettingOutlined,
|
||||
click: () => {
|
||||
console.log(3);
|
||||
click: (node: ComputedNodeInfo) => {
|
||||
editDialog.value.uuid = node.uuid;
|
||||
editDialog.value.data.ip = node.ip;
|
||||
editDialog.value.data.port = node.port;
|
||||
editDialog.value.data.remarks = node.remarks;
|
||||
editDialog.value.showEdit();
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
const addNode = async () => {
|
||||
const { execute } = addNodeApi();
|
||||
try {
|
||||
await execute({
|
||||
data: {
|
||||
...editDialog.value.data
|
||||
}
|
||||
});
|
||||
editDialog.value.hidden();
|
||||
message.success(t("添加节点成功"));
|
||||
} catch (error: any) {
|
||||
message.error(t("添加节点失败"));
|
||||
}
|
||||
editDialog.value.loading = false;
|
||||
};
|
||||
|
||||
const deleteNode = async () => {
|
||||
const { execute } = deleteNodeApi();
|
||||
try {
|
||||
await execute({
|
||||
params: {
|
||||
uuid: editDialog.value.uuid
|
||||
}
|
||||
});
|
||||
message.success(t("删除节点成功"));
|
||||
editDialog.value.hidden();
|
||||
} catch (error) {
|
||||
message.error(t("删除节点失败"));
|
||||
}
|
||||
editDialog.value.loading = false;
|
||||
};
|
||||
|
||||
const editNode = async () => {
|
||||
const { apiKey, ...outherData } = editDialog.value.data;
|
||||
|
||||
const updatedData = apiKey == "" ? { ...outherData } : editDialog.value.data;
|
||||
const { execute } = editNodeApi();
|
||||
try {
|
||||
await execute({
|
||||
params: {
|
||||
uuid: editDialog.value.uuid
|
||||
},
|
||||
data: {
|
||||
...updatedData
|
||||
}
|
||||
});
|
||||
message.success(t("保存成功"));
|
||||
editDialog.value.loading = false;
|
||||
editDialog.value.hidden();
|
||||
} catch (error) {
|
||||
message.error(t("编辑节点失败"));
|
||||
}
|
||||
};
|
||||
|
||||
const editMode = ref(false);
|
||||
const editDialog = ref({
|
||||
status: false,
|
||||
loading: false,
|
||||
title: computed(() => (editMode.value ? t("编辑节点信息") : t("新增节点"))),
|
||||
data: {
|
||||
ip: "",
|
||||
port: 24444,
|
||||
remarks: "",
|
||||
apiKey: ""
|
||||
},
|
||||
uuid: "",
|
||||
check: () => {
|
||||
if (!editMode.value) {
|
||||
if (!editDialog.value.data.apiKey) return false;
|
||||
}
|
||||
if (!editDialog.value.data.ip || !editDialog.value.data.port) return false;
|
||||
},
|
||||
show: () => {
|
||||
editMode.value = false;
|
||||
editDialog.value.status = true;
|
||||
},
|
||||
showEdit: () => {
|
||||
editMode.value = true;
|
||||
editDialog.value.status = true;
|
||||
},
|
||||
clear: () => {
|
||||
editDialog.value.data = {
|
||||
ip: "",
|
||||
port: 24444,
|
||||
remarks: "",
|
||||
apiKey: ""
|
||||
};
|
||||
},
|
||||
delete: () => {
|
||||
editDialog.value.loading = true;
|
||||
deleteNode();
|
||||
},
|
||||
submit: () => {
|
||||
if (editDialog.value.check() === false) {
|
||||
return message.error(t("请正确填写表单"));
|
||||
}
|
||||
editDialog.value.loading = true;
|
||||
if (editMode.value) {
|
||||
editNode();
|
||||
} else {
|
||||
addNode();
|
||||
}
|
||||
},
|
||||
hidden: () => {
|
||||
editDialog.value.status = false;
|
||||
editDialog.value.clear();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@ -104,8 +223,12 @@ const nodeOperations = [
|
||||
</a-typography-title>
|
||||
</template>
|
||||
<template #right>
|
||||
<a-button class="mr-12" type="primary">{{ t("TXT_CODE_15a381d5") }}</a-button>
|
||||
<a-button>{{ t("TXT_CODE_3a302f23") }}</a-button>
|
||||
<a-button class="mr-12" type="primary" @click="editDialog.show">
|
||||
{{ t("TXT_CODE_15a381d5") }}
|
||||
</a-button>
|
||||
<a-button href="https://docs.mcsmanager.com/" target="_black">
|
||||
{{ t("TXT_CODE_3a302f23") }}
|
||||
</a-button>
|
||||
</template>
|
||||
<template #center>
|
||||
<div class="search-input">
|
||||
@ -121,13 +244,9 @@ const nodeOperations = [
|
||||
|
||||
<a-col :span="24">
|
||||
<a-typography-text type="secondary">
|
||||
{{
|
||||
t("TXT_CODE_f9a92e38")
|
||||
}}
|
||||
{{ t("TXT_CODE_f9a92e38") }}
|
||||
<br />
|
||||
{{
|
||||
t("TXT_CODE_a65c65c2")
|
||||
}}
|
||||
{{ t("TXT_CODE_a65c65c2") }}
|
||||
</a-typography-text>
|
||||
</a-col>
|
||||
|
||||
@ -147,7 +266,7 @@ const nodeOperations = [
|
||||
<IconBtn
|
||||
:icon="operation.icon"
|
||||
:title="operation.title"
|
||||
@click="operation.click"
|
||||
@click="operation.click(item)"
|
||||
></IconBtn>
|
||||
</span>
|
||||
</template>
|
||||
@ -178,6 +297,83 @@ const nodeOperations = [
|
||||
</a-col>
|
||||
</a-row>
|
||||
</div>
|
||||
<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-paragraph>
|
||||
<a-typography-text type="secondary">
|
||||
{{ t("必填,支持中文,用于填写相关备注信息") }}
|
||||
</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-paragraph>
|
||||
<a-typography-text type="secondary">
|
||||
{{ t("必须使用外网地址或 localhost 地址,否则将导致远程实例无法连接") }}
|
||||
<br />
|
||||
{{ t("必填,例如 mcsmanager.com,43.123.211.12") }}
|
||||
</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-paragraph>
|
||||
<a-typography-text type="secondary">
|
||||
{{ t("必填,例如 24444") }}
|
||||
</a-typography-text>
|
||||
</a-typography-paragraph>
|
||||
<a-input v-model:value="editDialog.data.port" />
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item>
|
||||
<a-typography-title class="flex" :level="5">
|
||||
{{ t("验证密钥") }}
|
||||
<div v-if="editMode">{{ t("(留空则不修改)") }}</div>
|
||||
</a-typography-title>
|
||||
<a-typography-paragraph>
|
||||
<a-typography-text type="secondary">
|
||||
{{ t("在远程节点启动时控制台上会输出显示,务必确保密钥安全") }}
|
||||
<br />
|
||||
{{ t("在 Linux 下,密钥一般在 /opt/mcsmanager/daemon/data/Config/global.json 中") }}
|
||||
<br />
|
||||
{{ t("必填,例如 6ff0fa1ef9a943f3c6f2fe0e4564a2fa383d35c4b78ccb5") }}
|
||||
<br />
|
||||
<a href="https://docs.mcsmanager.com/" target="_blank">{{ t("如何获取密钥?") }}</a>
|
||||
</a-typography-text>
|
||||
</a-typography-paragraph>
|
||||
<a-input v-model:value="editDialog.data.apiKey" />
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
<template #footer>
|
||||
<div class="justify-space-between">
|
||||
<a-popconfirm
|
||||
:title="t('确定要永久删除该节点吗?')"
|
||||
ok-text="Yes"
|
||||
cancel-text="No"
|
||||
@confirm="deleteNode()"
|
||||
>
|
||||
<a-button v-if="editMode" key="delete">{{ t("删除节点") }}</a-button>
|
||||
</a-popconfirm>
|
||||
<div class="right">
|
||||
<a-button key="back" @click="editDialog.hidden()">{{ t("取消") }}</a-button>
|
||||
<a-button
|
||||
key="submit"
|
||||
type="primary"
|
||||
:loading="editDialog.loading"
|
||||
@click="editDialog.submit()"
|
||||
>
|
||||
{{ t("确定") }}
|
||||
</a-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</a-modal>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
Loading…
Reference in New Issue
Block a user