Fix: AntdvConfigProvider

This commit is contained in:
unitwk 2024-01-05 10:59:51 +08:00
parent aafcd324de
commit 8abff6590a
6 changed files with 188 additions and 146 deletions

View File

@ -36,6 +36,7 @@ declare module 'vue' {
AnyAppForm: typeof import('./src/components/fc/CmdAssistantDialog/AnyAppForm.vue')['default']
APagination: typeof import('ant-design-vue/es')['Pagination']
APopconfirm: typeof import('ant-design-vue/es')['Popconfirm']
AppConfigProvider: typeof import('./src/components/AppConfigProvider.vue')['default']
AppHeader: typeof import('./src/components/AppHeader.vue')['default']
AProgress: typeof import('ant-design-vue/es')['Progress']
ARadioButton: typeof import('ant-design-vue/es')['RadioButton']
@ -68,6 +69,7 @@ declare module 'vue' {
CopyButton: typeof import('./src/components/CopyButton.vue')['default']
DataStatistic: typeof import('./src/components/DataStatistic.vue')['default']
Editor: typeof import('./src/components/Editor.vue')['default']
Empty: typeof import('./src/components/Empty.vue')['default']
FadeUpAnimation: typeof import('./src/components/FadeUpAnimation.vue')['default']
IconBtn: typeof import('./src/components/IconBtn.vue')['default']
InnerCard: typeof import('./src/components/InnerCard.vue')['default']

View File

@ -1,49 +1,22 @@
<script setup lang="ts">
import AppConfigProvider from "./components/AppConfigProvider.vue";
import { RouterView } from "vue-router";
import AppHeader from "./components/AppHeader.vue";
import zhCN from "ant-design-vue/es/locale/zh_CN";
import enUS from "ant-design-vue/es/locale/en_US";
import dayjs from "dayjs";
import "dayjs/locale/zh-cn";
import "dayjs/locale/en";
import { onMounted, ref } from "vue";
import { onMounted } from "vue";
import { useAppConfigStore } from "@/stores/useAppConfigStore";
import { theme } from "ant-design-vue";
import InputDialogProvider from "./components/InputDialogProvider.vue";
import { Button, Select, Input, Table } from "ant-design-vue";
import MyselfInfoDialog from "./components/MyselfInfoDialog.vue";
import { closeAppLoading } from "./tools/dom";
const { getCurrentLanguage, isDarkTheme } = useAppConfigStore();
const locale = ref(enUS);
const { isDarkTheme } = useAppConfigStore();
// Ant Design Vue i18n
// This will also have to be changed if a new language is added.
if (getCurrentLanguage().toLowerCase() === "zh_cn") {
dayjs.locale("zh-cn");
locale.value = zhCN;
} else {
dayjs.locale("en-us");
}
const isDarkUI = isDarkTheme();
const appTheme = {
algorithm: theme.defaultAlgorithm,
token: {
fontSizeLG: 14,
fontSizeSM: 12,
fontSizeXL: 18
}
};
if (isDarkUI) {
if (isDarkTheme()) {
document.body.classList.add("app-dark-theme");
appTheme.algorithm = theme.darkAlgorithm;
} else {
document.body.classList.add("app-light-theme");
}
import { Button, Select, Input, Table, ConfigProvider } from "ant-design-vue";
import MyselfInfoDialog from "./components/MyselfInfoDialog.vue";
import { closeAppLoading } from "./tools/dom";
[Button, Select, Input, Table].forEach((element) => {
element.props.size.default = "large";
});
@ -54,7 +27,7 @@ onMounted(async () => {
</script>
<template>
<ConfigProvider :theme="appTheme" :locale="locale">
<AppConfigProvider>
<div class="global-app-container">
<AppHeader></AppHeader>
<RouterView :key="$route.fullPath" />
@ -63,5 +36,5 @@ onMounted(async () => {
<!-- Global Components -->
<InputDialogProvider></InputDialogProvider>
<MyselfInfoDialog></MyselfInfoDialog>
</ConfigProvider>
</AppConfigProvider>
</template>

View File

@ -0,0 +1,42 @@
<script setup lang="ts">
import zhCN from "ant-design-vue/es/locale/zh_CN";
import enUS from "ant-design-vue/es/locale/en_US";
import "dayjs/locale/zh-cn";
import "dayjs/locale/en";
import dayjs from "dayjs";
import { ref } from "vue";
import { useAppConfigStore } from "@/stores/useAppConfigStore";
import { theme } from "ant-design-vue";
import { ConfigProvider } from "ant-design-vue";
const { getCurrentLanguage, isDarkTheme } = useAppConfigStore();
const locale = ref(enUS);
// init language with lib
if (getCurrentLanguage().toLowerCase() === "zh_cn") {
dayjs.locale("zh-cn");
locale.value = zhCN;
} else {
dayjs.locale("en-us");
}
const isDarkUI = isDarkTheme();
const appTheme = {
algorithm: theme.defaultAlgorithm,
token: {
fontSizeLG: 14,
fontSizeSM: 12,
fontSizeXL: 18
}
};
if (isDarkUI) {
appTheme.algorithm = theme.darkAlgorithm;
}
</script>
<template>
<ConfigProvider :theme="appTheme" :locale="locale">
<slot></slot>
</ConfigProvider>
</template>

View File

@ -0,0 +1,13 @@
<script lang="ts" setup>
defineProps<{
description?: string;
}>();
</script>
<template>
<a-empty>
<template #description>
<span class="color-info">{{ description }}</span>
</template>
<!-- <a-button type="primary">Create Now</a-button> -->
</a-empty>
</template>

View File

@ -18,6 +18,7 @@ import { throttle } from "lodash";
import { useScreen } from "@/hooks/useScreen";
import type { ColumnsType } from "ant-design-vue/es/table";
import type { AntTableCell } from "../../types/ant";
import AppConfigProvider from "../AppConfigProvider.vue";
const props = defineProps<MountComponent>();
const { isPhone } = useScreen();
@ -140,114 +141,121 @@ const handleChangeNode = async (item: NodeStatus) => {
</script>
<template>
<a-modal
v-model:open="open"
centered
:mask-closable="false"
: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("TXT_CODE_50697989") }}
</a-typography-text>
</a-typography-paragraph>
<a-row :gutter="[24, 24]" style="height: 100%">
<a-col :span="24">
<BetweenMenus>
<template #left>
<a-dropdown>
<template #overlay>
<a-menu>
<a-menu-item
v-for="item in nodes"
:key="item.uuid"
:disabled="!item.available"
@click="handleChangeNode(item)"
>
<DatabaseOutlined v-if="item.available" />
<FrownOutlined v-else />
{{ computeNodeName(item.ip, item.available, item.remarks) }}
</a-menu-item>
<a-menu-divider />
<a-menu-item key="toNodesPage">
<FormOutlined />
{{ t("TXT_CODE_28e53fed") }}
</a-menu-item>
</a-menu>
</template>
<a-button :class="isPhone && 'mb-10 w-100'">
{{
computeNodeName(
currentRemoteNode?.ip || "",
currentRemoteNode?.available || true,
currentRemoteNode?.remarks
)
}}
<DownOutlined />
</a-button>
</a-dropdown>
</template>
<template #right>
<div class="search-input" :class="isPhone && 'w-100'">
<a-input
v-model:value="operationForm.instanceName"
:placeholder="t('TXT_CODE_ce132192')"
@press-enter="handleQueryInstance"
@change="handleQueryInstance"
>
<template #prefix>
<search-outlined />
</template>
</a-input>
</div>
</template>
</BetweenMenus>
</a-col>
<a-col :span="24">
<div v-if="instances" class="flex-between align-center">
<a-typography-text>
{{ t("TXT_CODE_379fa48a") }} {{ selectedItems.length }} {{ t("TXT_CODE_5cd3b4bd") }}
</a-typography-text>
<a-pagination
v-model:current="operationForm.currentPage"
v-model:pageSize="operationForm.pageSize"
:total="instances.maxPage * operationForm.pageSize"
show-size-changer
@change="initInstancesData"
/>
</div>
</a-col>
<template v-if="instancesList">
<AppConfigProvider>
<a-modal
v-model:open="open"
centered
:mask-closable="false"
: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("TXT_CODE_50697989") }}
</a-typography-text>
</a-typography-paragraph>
<a-row :gutter="[24, 24]" style="height: 100%">
<a-col :span="24">
<a-table
:loading="isLoading"
:data-source="instancesList"
:columns="columns"
:pagination="false"
size="small"
:scroll="{
x: 'max-content'
}"
>
<template #bodyCell="{ column, record }: AntTableCell">
<template v-if="column.key === 'operation'">
<a-button v-if="findItem(record)" danger size="middle" @click="removeItem(record)">
{{ t("TXT_CODE_65fcbd09") }}
<BetweenMenus>
<template #left>
<a-dropdown>
<template #overlay>
<a-menu>
<a-menu-item
v-for="item in nodes"
:key="item.uuid"
:disabled="!item.available"
@click="handleChangeNode(item)"
>
<DatabaseOutlined v-if="item.available" />
<FrownOutlined v-else />
{{ computeNodeName(item.ip, item.available, item.remarks) }}
</a-menu-item>
<a-menu-divider />
<a-menu-item key="toNodesPage">
<FormOutlined />
{{ t("TXT_CODE_28e53fed") }}
</a-menu-item>
</a-menu>
</template>
<a-button :class="isPhone && 'mb-10 w-100'">
{{
computeNodeName(
currentRemoteNode?.ip || "",
currentRemoteNode?.available || true,
currentRemoteNode?.remarks
)
}}
<DownOutlined />
</a-button>
<a-button v-else size="middle" @click="selectItem(record)">
{{ t("TXT_CODE_7b2c5414") }}
</a-button>
</template>
</a-dropdown>
</template>
</a-table>
<template #right>
<div class="search-input" :class="isPhone && 'w-100'">
<a-input
v-model:value="operationForm.instanceName"
:placeholder="t('TXT_CODE_ce132192')"
@press-enter="handleQueryInstance"
@change="handleQueryInstance"
>
<template #prefix>
<search-outlined />
</template>
</a-input>
</div>
</template>
</BetweenMenus>
</a-col>
</template>
</a-row>
</a-modal>
<a-col :span="24">
<div v-if="instances" class="flex-between align-center">
<a-typography-text>
{{ t("TXT_CODE_379fa48a") }} {{ selectedItems.length }} {{ t("TXT_CODE_5cd3b4bd") }}
</a-typography-text>
<a-pagination
v-model:current="operationForm.currentPage"
v-model:pageSize="operationForm.pageSize"
:total="instances.maxPage * operationForm.pageSize"
show-size-changer
@change="initInstancesData"
/>
</div>
</a-col>
<template v-if="instancesList">
<a-col :span="24">
<a-table
:loading="isLoading"
:data-source="instancesList"
:columns="columns"
:pagination="false"
size="small"
:scroll="{
x: 'max-content'
}"
>
<template #bodyCell="{ column, record }: AntTableCell">
<template v-if="column.key === 'operation'">
<a-button
v-if="findItem(record)"
danger
size="middle"
@click="removeItem(record)"
>
{{ t("TXT_CODE_65fcbd09") }}
</a-button>
<a-button v-else size="middle" @click="selectItem(record)">
{{ t("TXT_CODE_7b2c5414") }}
</a-button>
</template>
</template>
</a-table>
</a-col>
</template>
</a-row>
</a-modal>
</AppConfigProvider>
</template>
<style lang="scss" scoped>

View File

@ -24,7 +24,7 @@ import { router } from "@/config/router";
import { remoteInstances, remoteNodeList } from "@/services/apis";
import { batchStart, batchStop, batchKill, batchDelete } from "@/services/apis/instance";
import type { NodeStatus } from "../types/index";
import { message, notification, Modal } from "ant-design-vue";
import { notification, Modal } from "ant-design-vue";
import { computeNodeName } from "../tools/nodes";
import type { InstanceMoreDetail } from "../hooks/useInstance";
import { useInstanceMoreDetail } from "../hooks/useInstance";
@ -55,7 +55,7 @@ const instancesMoreInfo = computed(() => {
const instanceMoreInfo = useInstanceMoreDetail(instance);
newInstances.push(instanceMoreInfo);
}
return newInstances;
return newInstances || [];
});
const initNodes = async () => {
@ -324,7 +324,11 @@ onMounted(async () => {
<DownOutlined />
</a-button>
</a-dropdown>
<a-button type="primary" @click="toCreateAppPage">
<a-button
type="primary"
:disabled="!currentRemoteNode?.available"
@click="toCreateAppPage"
>
{{ t("TXT_CODE_53408064") }}
</a-button>
</template>
@ -410,7 +414,7 @@ onMounted(async () => {
<template v-if="isLoading">
<Loading></Loading>
</template>
<template v-if="instancesMoreInfo">
<template v-else-if="instancesMoreInfo.length > 0">
<a-col v-for="item in instancesMoreInfo" :key="item.instanceUuid" :span="24" :md="6">
<CardPanel
class="instance-card"
@ -455,10 +459,10 @@ onMounted(async () => {
</a-col>
</template>
<div
v-if="!instancesMoreInfo || instancesMoreInfo.length === 0"
v-else-if="instancesMoreInfo.length === 0"
class="flex align-center justify-center h-100 w-100"
>
<a-empty :description="t('无内容,请在右上角下拉框选择节点')" />
<Empty :description="t('无内容,请在右上角下拉框选择节点,或点击新建应用')" />
</div>
</a-row>
</div>