Feat: create card support instance selector

This commit is contained in:
unitwk 2023-11-11 22:41:16 +08:00
parent ee47fda7d3
commit 5713d6caf2
13 changed files with 114 additions and 45 deletions

2
common/global.d.ts vendored
View File

@ -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 {

View File

@ -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']
}
}

View File

@ -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": {

View File

@ -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",

View File

@ -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,

View File

@ -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">

View File

@ -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>

View File

@ -111,6 +111,11 @@ export function getLayoutCardPool() {
field: "daemonId",
label: t("节点 ID"),
type: "string"
},
{
field: "instance",
label: t("实例"),
type: "instance"
}
]
},

View File

@ -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;
}

View File

@ -4,5 +4,5 @@ import type { UserInstance } from "@/types";
export function useSelectInstances() {
const { mount } = useMountComponent();
return mount<UserInstance>(SelectInstances);
return mount<UserInstance[]>(SelectInstances);
}

View File

@ -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>

View File

@ -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
View File

@ -0,0 +1,6 @@
{
"name": "MCSManager",
"lockfileVersion": 3,
"requires": true,
"packages": {}
}