mirror of
https://github.com/MCSManager/MCSManager.git
synced 2025-04-06 17:10:29 +08:00
Feat: create card support instance selector
This commit is contained in:
parent
ee47fda7d3
commit
5713d6caf2
2
common/global.d.ts
vendored
2
common/global.d.ts
vendored
@ -148,7 +148,7 @@ export interface IPageLayoutConfig {
|
||||
export interface ILayoutCardParams {
|
||||
field: string;
|
||||
label: string;
|
||||
type: "string" | "number" | "boolean" | "instanceId";
|
||||
type: "string" | "number" | "boolean" | "instance";
|
||||
}
|
||||
|
||||
export interface ILayoutCard {
|
||||
|
1
frontend/components.d.ts
vendored
1
frontend/components.d.ts
vendored
@ -82,6 +82,5 @@ declare module 'vue' {
|
||||
RouterLink: typeof import('vue-router')['RouterLink']
|
||||
RouterView: typeof import('vue-router')['RouterView']
|
||||
SelectInstances: typeof import('./src/components/SelectInstances.vue')['default']
|
||||
Spin: typeof import('./src/components/Spin.vue')['default']
|
||||
}
|
||||
}
|
||||
|
41
frontend/package-lock.json
generated
41
frontend/package-lock.json
generated
@ -18,7 +18,7 @@
|
||||
"@codemirror/legacy-modes": "^6.3.3",
|
||||
"@codemirror/stream-parser": "^0.19.9",
|
||||
"@vueuse/core": "^10.3.0",
|
||||
"ant-design-vue": "^4.0.0",
|
||||
"ant-design-vue": "^4.0.7",
|
||||
"axios": "^1.4.0",
|
||||
"codemirror": "^6.0.1",
|
||||
"crc": "^4.3.2",
|
||||
@ -2880,12 +2880,12 @@
|
||||
}
|
||||
},
|
||||
"node_modules/ant-design-vue": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ant-design-vue/-/ant-design-vue-4.0.0.tgz",
|
||||
"integrity": "sha512-6V8DxHPv3HJYDdv48W/KFOUjeZDsYJhFlk13HFSKCJSR2MQs4YnPIAC+rWie9vYcVEKbO+cQDqiOM3cBoHMNUQ==",
|
||||
"version": "4.0.7",
|
||||
"resolved": "https://registry.npmjs.org/ant-design-vue/-/ant-design-vue-4.0.7.tgz",
|
||||
"integrity": "sha512-oHTtc1GZkfENZTkt2aDvjaD4yoRsowYvCOmxA6+5AGqm5uz/datdJOXsq9nokIhC+vrAMhk6JQVFZ2hh7eU6Pw==",
|
||||
"dependencies": {
|
||||
"@ant-design/colors": "^6.0.0",
|
||||
"@ant-design/icons-vue": "^6.1.0",
|
||||
"@ant-design/icons-vue": "^7.0.0",
|
||||
"@babel/runtime": "^7.10.5",
|
||||
"@ctrl/tinycolor": "^3.5.0",
|
||||
"@emotion/hash": "^0.9.0",
|
||||
@ -2918,6 +2918,18 @@
|
||||
"vue": ">=3.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/ant-design-vue/node_modules/@ant-design/icons-vue": {
|
||||
"version": "7.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@ant-design/icons-vue/-/icons-vue-7.0.1.tgz",
|
||||
"integrity": "sha512-eCqY2unfZK6Fe02AwFlDHLfoyEFreP6rBwAZMIJ1LugmfMiVgwWDYlp1YsRugaPtICYOabV1iWxXdP12u9U43Q==",
|
||||
"dependencies": {
|
||||
"@ant-design/colors": "^6.0.0",
|
||||
"@ant-design/icons-svg": "^4.2.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"vue": ">=3.0.3"
|
||||
}
|
||||
},
|
||||
"node_modules/anymatch": {
|
||||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
|
||||
@ -11547,12 +11559,12 @@
|
||||
}
|
||||
},
|
||||
"ant-design-vue": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ant-design-vue/-/ant-design-vue-4.0.0.tgz",
|
||||
"integrity": "sha512-6V8DxHPv3HJYDdv48W/KFOUjeZDsYJhFlk13HFSKCJSR2MQs4YnPIAC+rWie9vYcVEKbO+cQDqiOM3cBoHMNUQ==",
|
||||
"version": "4.0.7",
|
||||
"resolved": "https://registry.npmjs.org/ant-design-vue/-/ant-design-vue-4.0.7.tgz",
|
||||
"integrity": "sha512-oHTtc1GZkfENZTkt2aDvjaD4yoRsowYvCOmxA6+5AGqm5uz/datdJOXsq9nokIhC+vrAMhk6JQVFZ2hh7eU6Pw==",
|
||||
"requires": {
|
||||
"@ant-design/colors": "^6.0.0",
|
||||
"@ant-design/icons-vue": "^6.1.0",
|
||||
"@ant-design/icons-vue": "^7.0.0",
|
||||
"@babel/runtime": "^7.10.5",
|
||||
"@ctrl/tinycolor": "^3.5.0",
|
||||
"@emotion/hash": "^0.9.0",
|
||||
@ -11573,6 +11585,17 @@
|
||||
"throttle-debounce": "^5.0.0",
|
||||
"vue-types": "^3.0.0",
|
||||
"warning": "^4.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@ant-design/icons-vue": {
|
||||
"version": "7.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@ant-design/icons-vue/-/icons-vue-7.0.1.tgz",
|
||||
"integrity": "sha512-eCqY2unfZK6Fe02AwFlDHLfoyEFreP6rBwAZMIJ1LugmfMiVgwWDYlp1YsRugaPtICYOabV1iWxXdP12u9U43Q==",
|
||||
"requires": {
|
||||
"@ant-design/colors": "^6.0.0",
|
||||
"@ant-design/icons-svg": "^4.2.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"anymatch": {
|
||||
|
@ -23,7 +23,7 @@
|
||||
"@codemirror/legacy-modes": "^6.3.3",
|
||||
"@codemirror/stream-parser": "^0.19.9",
|
||||
"@vueuse/core": "^10.3.0",
|
||||
"ant-design-vue": "^4.0.0",
|
||||
"ant-design-vue": "^4.0.7",
|
||||
"axios": "^1.4.0",
|
||||
"codemirror": "^6.0.1",
|
||||
"crc": "^4.3.2",
|
||||
|
@ -25,6 +25,7 @@ import { message } from "ant-design-vue";
|
||||
import { useAppToolsStore } from "@/stores/useAppToolsStore";
|
||||
import { useAppStateStore } from "@/stores/useAppStateStore";
|
||||
import { useLayoutConfigStore } from "../stores/useLayoutConfig";
|
||||
import { Modal } from "ant-design-vue";
|
||||
|
||||
const { saveGlobalLayoutConfig } = useLayoutConfigStore();
|
||||
const { containerState, changeDesignMode } = useLayoutContainerStore();
|
||||
@ -119,12 +120,25 @@ const appMenus = computed(() => {
|
||||
title: t("TXT_CODE_8145d82"),
|
||||
icon: SaveOutlined,
|
||||
click: async () => {
|
||||
changeDesignMode(false);
|
||||
await saveGlobalLayoutConfig();
|
||||
notification.success({
|
||||
placement: "top",
|
||||
message: t("TXT_CODE_47c35915"),
|
||||
description: t("TXT_CODE_e10c992a")
|
||||
Modal.confirm({
|
||||
title: "确定要保存布局吗?",
|
||||
content:
|
||||
"由于界面的高度可定制化,一旦保存布局后整个界面的语言将会被锁定,除非重置布局否则切换语言将无法很好的工作。如果您没有切换语言的需求,可以忽略这条建议。",
|
||||
async onOk() {
|
||||
changeDesignMode(false);
|
||||
await saveGlobalLayoutConfig();
|
||||
notification.success({
|
||||
placement: "top",
|
||||
message: t("TXT_CODE_47c35915"),
|
||||
description: t("TXT_CODE_e10c992a")
|
||||
});
|
||||
setTimeout(() => {
|
||||
window.location.reload();
|
||||
}, 1000);
|
||||
},
|
||||
onCancel() {
|
||||
window.location.reload();
|
||||
}
|
||||
});
|
||||
},
|
||||
conditions: containerState.isDesignMode,
|
||||
|
@ -81,29 +81,19 @@ const handleTabClick = (value: string) => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Transition name="global-action-float">
|
||||
<div v-if="display" class="new-card-list-tabs">
|
||||
<a-tabs
|
||||
v-model:activeKey="currentCardCategory"
|
||||
:tab-bar-gutter="0"
|
||||
size="small"
|
||||
tab-position="right"
|
||||
animated
|
||||
@change="handleTabClick"
|
||||
>
|
||||
<a-tab-pane v-for="item in cardCategoryList" :key="item.value" :tab="item.label" />
|
||||
|
||||
<a-tab-pane
|
||||
key="EXIT"
|
||||
:tab="t('TXT_CODE_b1dedda3')"
|
||||
@click="() => (containerState.showNewCardDialog = false)"
|
||||
/>
|
||||
</a-tabs>
|
||||
</div>
|
||||
</Transition>
|
||||
<Transition name="global-action-float">
|
||||
<div v-if="display" class="new-card-list-container">
|
||||
<div class="new-card-list">
|
||||
<div class="mb-24">
|
||||
<a-radio-group v-model:value="currentCardCategory" size="large">
|
||||
<a-radio-button v-for="item in cardCategoryList" :key="item.value" :value="item.value">
|
||||
{{ item.label }}
|
||||
</a-radio-button>
|
||||
<a-radio-button value="EXIT" @click="() => (containerState.showNewCardDialog = false)">
|
||||
{{ t("TXT_CODE_b1dedda3") }}
|
||||
</a-radio-button>
|
||||
</a-radio-group>
|
||||
</div>
|
||||
<div v-for="card in cardPool" :key="card.id + currentCardCategory">
|
||||
<a-row v-if="card.category === currentCardCategory" style="margin-bottom: 20px">
|
||||
<a-col span="24">
|
||||
|
@ -5,6 +5,7 @@ import type { MapData } from "@/types/index";
|
||||
import type { FormInstance } from "ant-design-vue";
|
||||
import { BulbOutlined } from "@ant-design/icons-vue";
|
||||
import { $t as t } from "@/lang/i18n";
|
||||
import { useSelectInstances } from "@/hooks/useSelectInstances";
|
||||
|
||||
const open = ref(false);
|
||||
const card = ref<LayoutCard>();
|
||||
@ -13,6 +14,18 @@ let resolveFn: (value: unknown) => void;
|
||||
const formData = ref<MapData<string>>({});
|
||||
const formRef = ref<FormInstance>();
|
||||
|
||||
const openInstanceSelectDialog = async () => {
|
||||
try {
|
||||
const selectedInstances = await useSelectInstances();
|
||||
if (selectedInstances) {
|
||||
formData.value.instanceId = selectedInstances[0].instanceUuid;
|
||||
formData.value.daemonId = selectedInstances[0].serviceUuid;
|
||||
}
|
||||
} catch (err: any) {
|
||||
console.error(err);
|
||||
}
|
||||
};
|
||||
|
||||
const onClose = () => {
|
||||
open.value = false;
|
||||
resolveFn(false);
|
||||
@ -62,13 +75,20 @@ defineExpose({
|
||||
<a-col v-for="item in card.params" :key="item.field" :span="24" :md="12">
|
||||
<a-form-item :label="item.label" :name="item.field">
|
||||
<a-input v-if="item.type === 'string'" v-model:value="formData[item.field]" />
|
||||
<a-button
|
||||
v-if="item.type === 'instance'"
|
||||
type="primary"
|
||||
@click="openInstanceSelectDialog"
|
||||
>
|
||||
{{ t("选择实例") }}
|
||||
</a-button>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-form>
|
||||
<p>
|
||||
<BulbOutlined />
|
||||
<span>
|
||||
<span class="ml-4">
|
||||
{{ t("TXT_CODE_e29b79df") }}
|
||||
</span>
|
||||
</p>
|
||||
|
@ -111,6 +111,11 @@ export function getLayoutCardPool() {
|
||||
field: "daemonId",
|
||||
label: t("节点 ID"),
|
||||
type: "string"
|
||||
},
|
||||
{
|
||||
field: "instance",
|
||||
label: t("实例"),
|
||||
type: "instance"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -12,7 +12,6 @@ export enum LayoutCardHeight {
|
||||
export let ORIGIN_LAYOUT_CONFIG: IPageLayoutConfig[] = [];
|
||||
|
||||
export function setAllLayoutConfig(cfg: IPageLayoutConfig[]) {
|
||||
console.debug("设置布局配置:", cfg);
|
||||
ORIGIN_LAYOUT_CONFIG = cfg;
|
||||
}
|
||||
|
||||
|
@ -4,5 +4,5 @@ import type { UserInstance } from "@/types";
|
||||
|
||||
export function useSelectInstances() {
|
||||
const { mount } = useMountComponent();
|
||||
return mount<UserInstance>(SelectInstances);
|
||||
return mount<UserInstance[]>(SelectInstances);
|
||||
}
|
||||
|
@ -24,11 +24,13 @@ import { GLOBAL_INSTANCE_NAME } from "../../config/const";
|
||||
import { INSTANCE_STATUS_TEXT } from "../../hooks/useInstance";
|
||||
import { message } from "ant-design-vue";
|
||||
import connectErrorImage from "@/assets/daemon_connection_error.png";
|
||||
import { useLayoutContainerStore } from "@/stores/useLayoutContainerStore";
|
||||
|
||||
const props = defineProps<{
|
||||
card: LayoutCard;
|
||||
}>();
|
||||
|
||||
const { containerState } = useLayoutContainerStore();
|
||||
const { getMetaOrRouteValue } = useLayoutCardTools(props.card);
|
||||
const {
|
||||
execute,
|
||||
@ -239,7 +241,7 @@ const innerTerminalType = viewType === "inner";
|
||||
</BetweenMenus>
|
||||
</div>
|
||||
<a-spin :spinning="!isConnect" tip="正在连接终端中...">
|
||||
<div class="console-wrapper">
|
||||
<div v-if="!containerState.isDesignMode" class="console-wrapper">
|
||||
<div class="terminal-wrapper global-card-container-shadow">
|
||||
<div class="terminal-container">
|
||||
<div :id="terminalDomId"></div>
|
||||
@ -257,12 +259,20 @@ const innerTerminalType = viewType === "inner";
|
||||
</a-input>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else>
|
||||
<a-skeleton :paragraph="{ rows: 8 }" />
|
||||
</div>
|
||||
</a-spin>
|
||||
</div>
|
||||
|
||||
<!-- Other Page View -->
|
||||
<CardPanel v-else class="containerWrapper" style="height: 100%">
|
||||
<template #title>{{ card.title }}</template>
|
||||
<template #title>
|
||||
<CloudServerOutlined />
|
||||
<span class="ml-8">
|
||||
{{ getInstanceName }}
|
||||
</span>
|
||||
</template>
|
||||
<template #operator>
|
||||
<span
|
||||
v-for="item in quickOperations"
|
||||
@ -288,7 +298,7 @@ const innerTerminalType = viewType === "inner";
|
||||
</a-dropdown>
|
||||
</template>
|
||||
<template #body>
|
||||
<div class="console-wrapper">
|
||||
<div v-if="!containerState.isDesignMode" class="console-wrapper">
|
||||
<div class="terminal-wrapper">
|
||||
<div class="terminal-container">
|
||||
<div :id="terminalDomId"></div>
|
||||
@ -306,6 +316,9 @@ const innerTerminalType = viewType === "inner";
|
||||
</a-input>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else>
|
||||
<a-skeleton :paragraph="{ rows: 8 }" />
|
||||
</div>
|
||||
</template>
|
||||
</CardPanel>
|
||||
</template>
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"TXT_CODE_00000001": "欢迎使用 MCSManager 管理面板",
|
||||
"TXT_CODE_108ce2e4": "宽度:",
|
||||
"TXT_CODE_13663120": "列如:在不填写参数的情况下, “终端卡片” 只能在 “实例详情” 页使用。",
|
||||
"TXT_CODE_13663120": "比如:在不填写参数的情况下, “终端卡片” 只能在 “实例详情” 页使用。",
|
||||
"TXT_CODE_153f705d": "删除卡片",
|
||||
"TXT_CODE_16d71239": "仪表盘",
|
||||
"TXT_CODE_18cdc17f": "修改标题",
|
||||
|
6
package-lock.json
generated
Normal file
6
package-lock.json
generated
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"name": "MCSManager",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user