From 5968bae3f03db7bf520294c497ca20264b0253d2 Mon Sep 17 00:00:00 2001 From: jingyang <72259332+zjy365@users.noreply.github.com> Date: Tue, 14 May 2024 15:00:56 +0800 Subject: [PATCH] fix:cloudserver bandwidth price display (#4734) * fix:cloudserver bandwidth price display Signed-off-by: jingyang <3161362058@qq.com> * change language * fix --------- Signed-off-by: jingyang <3161362058@qq.com> --- .../cloudserver/public/locales/en/common.json | 13 +++-- .../cloudserver/public/locales/zh/common.json | 15 ++++-- .../src/components/MyTable/index.tsx | 12 +++-- .../providers/cloudserver/src/pages/_app.tsx | 1 + .../cloudserver/create/components/Form.tsx | 49 +++++++++++++++---- .../cloudserver/create/components/Header.tsx | 28 ++++++++--- .../src/pages/cloudserver/create/index.tsx | 13 +++-- .../pages/cloudservers/components/List.tsx | 6 ++- .../cloudserver/src/types/cloudserver.ts | 7 +++ 9 files changed, 105 insertions(+), 39 deletions(-) diff --git a/frontend/providers/cloudserver/public/locales/en/common.json b/frontend/providers/cloudserver/public/locales/en/common.json index ab9ab10db91..d2ea5cbf29f 100644 --- a/frontend/providers/cloudserver/public/locales/en/common.json +++ b/frontend/providers/cloudserver/public/locales/en/common.json @@ -53,8 +53,8 @@ "ReStart": "Restart", "Reference fee": "Reference fee", "Reference fee disk tips": "{{price}}/GiB/hour", - "Reference fee network tips": "When the public network bandwidth is less than 5 Mbps, the price is {{price1}}/Mbps/hour; when the public network bandwidth is greater than or equal to 5 Mbps, the price is {{price2}}/Mbps/hour.", "Reference fee tip": "{{price}}/hour", + "Reference fee bandwidth tips": "{{price}}/Mbps/hour", "Restarting": "Restarting", "Set Password": "Set Password", "Start": "Start", @@ -82,7 +82,7 @@ "delete cloud server tip": "Are you sure to delete this cloud host?", "hour": "hour", "price": "Price", - "publicIpAssigned tips": "Note: Without a dedicated public IP assigned, external communication using a public IP is not possible. The server cannot be used for record filing. Please choose carefully.", + "publicIpAssigned tips": "Please note: If an independent public IP address is not assigned, the external IP address cannot be used to communicate with each other.", "ssh port": "SSH port", "sshName": "SSH Username", "sshPassword": "SSH Password", @@ -94,7 +94,7 @@ "Architecture": "Architecture", "Instance Family": "Instance Family", "postPaidByHour": "Pay as you go", - "heterogeneous": "Heterogeneous", + "heterogeneous": "Heterogeneous (GPU)", "prePaid": "Yearly and monthly subscription", "x86_64": "x86_64", "costEffective": "Cost Effective", @@ -106,5 +106,10 @@ "Contains at least three of these": "Contains at least three of these", "Cannot start with": "Cannot start with \"/\"", "cannot contain spaces": "cannot contain spaces", - "Within 8 to 30 characters": "Within 8 to 30 characters (12 or more characters recommended)" + "Within 8 to 30 characters": "Within 8 to 30 characters (12 or more characters recommended)", + "highMemory": "High Memory", + "highPerformance": "High Performance", + "Public IP is not enabled": "Public IP is not enabled", + "interval": "Interval", + "sold out": "Sold Out" } \ No newline at end of file diff --git a/frontend/providers/cloudserver/public/locales/zh/common.json b/frontend/providers/cloudserver/public/locales/zh/common.json index e261460806e..e71aee3c755 100644 --- a/frontend/providers/cloudserver/public/locales/zh/common.json +++ b/frontend/providers/cloudserver/public/locales/zh/common.json @@ -82,11 +82,11 @@ "Public network bandwidth": "公网带宽", "Billing items": "计费项", "price": "价格", - "publicIpAssigned tips": "注意:未分配独立公网IP,无法使用外网IP对外进行互相通信,服务器无法用于备案,请慎重选择。", + "publicIpAssigned tips": "请注意:未分配独立公网IP地址的情况下无法使用外网IP地址对外进行互相通信。", "Fee inquiry in progress": "费用查询中...", "hour": "小时", "Reference fee disk tips": "{{price}}/GiB/小时", - "Reference fee network tips": "当公网带宽小于5 Mbps时,价格为{{price1}}/Mbps/小时;当公网带宽大于等于5 Mbps时,价格为{{price2}}/Mbps/小时。", + "Reference fee bandwidth tips": "{{price}}/Mbps/小时", "Billing rules": "计费规则", "The maximum number of instances is 20": "最大数量是20", "Billing model": "计费模式", @@ -94,7 +94,7 @@ "Architecture": "架构", "Instance Family": "实例族", "postPaidByHour": "按量计费", - "heterogeneous": "异构计算", + "heterogeneous": "异构计算 (GPU)", "prePaid": "包年包月", "x86_64": "x86计算", "costEffective": "实惠型", @@ -106,5 +106,10 @@ "Contains at least three of these": "至少包含其中三项", "Cannot start with": "不能以\" / \"开头", "cannot contain spaces": "不能包含空格", - "Within 8 to 30 characters": "在 8 ~ 30 位字符数以内(推荐12位以上)" -} \ No newline at end of file + "Within 8 to 30 characters": "在 8 ~ 30 位字符数以内(推荐12位以上)", + "highMemory": "内存型", + "highPerformance": "计算型", + "Public IP is not enabled": "未开启公网IP", + "interval": "区间", + "sold out": "售空" +} diff --git a/frontend/providers/cloudserver/src/components/MyTable/index.tsx b/frontend/providers/cloudserver/src/components/MyTable/index.tsx index e78b45355ba..f593e1eb324 100644 --- a/frontend/providers/cloudserver/src/components/MyTable/index.tsx +++ b/frontend/providers/cloudserver/src/components/MyTable/index.tsx @@ -12,7 +12,7 @@ interface Props extends BoxProps { columns: TableColumnsType[]; data: any[]; itemClass?: string; - openSelected?: boolean; + openSelected?: boolean; // support select item // isOptional onRowClick?: (item: any) => void; } @@ -59,13 +59,15 @@ export const MyTable = ({ _hover={{ bg: '#FBFBFC' }} - cursor={'pointer'} + cursor={!item.isOptional && openSelected ? 'not-allowed' : 'pointer'} borderBottom={'1px solid'} borderBottomColor={index1 !== data.length - 1 ? 'grayModern.150' : 'transparent'} bg={activeId == index1 && openSelected ? 'grayModern.100' : ''} onClick={() => { - setActiveId(index1); - onRowClick && onRowClick(item); + if (item.isOptional || !openSelected) { + setActiveId(index1); + onRowClick && onRowClick(item); + } }} > {columns.map((col, index2) => ( @@ -77,7 +79,7 @@ export const MyTable = ({ px={3} py={4} fontSize={'base'} - color={'grayModern.900'} + color={!item.isOptional && openSelected ? 'grayModern.500' : 'grayModern.900'} > {col.render ? col.render(item, index1, activeId) diff --git a/frontend/providers/cloudserver/src/pages/_app.tsx b/frontend/providers/cloudserver/src/pages/_app.tsx index 4383e076e67..b0172a74e5f 100644 --- a/frontend/providers/cloudserver/src/pages/_app.tsx +++ b/frontend/providers/cloudserver/src/pages/_app.tsx @@ -131,6 +131,7 @@ function App({ Component, pageProps }: AppProps) { + {/*
i18n.changeLanguage(i18n.language === 'zh' ? 'en' : 'zh')}>zh
*/}
diff --git a/frontend/providers/cloudserver/src/pages/cloudserver/create/components/Form.tsx b/frontend/providers/cloudserver/src/pages/cloudserver/create/components/Form.tsx index b2cbdb17868..ffad9be2f57 100644 --- a/frontend/providers/cloudserver/src/pages/cloudserver/create/components/Form.tsx +++ b/frontend/providers/cloudserver/src/pages/cloudserver/create/components/Form.tsx @@ -2,7 +2,7 @@ import { getCloudServerImage, getCloudServerRegion, getCloudServerType } from '@ import MyIcon from '@/components/Icon'; import { MyTable, TableColumnsType } from '@/components/MyTable'; import MyTooltip from '@/components/MyTooltip'; -import { CloudServerType, EditForm, StorageType } from '@/types/cloudserver'; +import { CloudServerStatus, CloudServerType, EditForm, StorageType } from '@/types/cloudserver'; import { CVMArchType, CVMRegionType, CVMZoneType, VirtualMachineType } from '@/types/region'; import { Box, @@ -59,7 +59,7 @@ const tabStyles: TabProps = { fontWeight: '400', color: 'grayModern.900', borderColor: 'grayModern.200', - width: '160px', + minW: '160px', css: { svg: { opacity: 0 @@ -122,7 +122,7 @@ function VirtualMachinePackageTabs({ {virtualMachinePackageFamily?.map((item) => ( - {item} + {t(item)} ))} @@ -296,6 +296,8 @@ export default function Form({ if (!formHook) return <>; const [clientRender, setClientRender] = useState(false); const { isOpen, onOpen, onClose } = useDisclosure(); + const theme = useTheme(); + const { t } = useTranslation(); const specialTips = useMemo(() => { return { @@ -310,8 +312,25 @@ export default function Form({ }, []); const { data: systemRegion } = useQuery(['getCloudServerRegion'], getCloudServerRegion, { - staleTime: 5 * 60 * 1000 + staleTime: 5 * 60 * 1000, + onSuccess(data) { + // set default form + if (data?.[0]?.chargeType) { + formHook.setValue('chargeType', data[0].chargeType); + formHook.setValue('zone', data[0].zone[0].zone); + formHook.setValue('virtualMachineArch', data[0].zone[0].arch[0].arch); + formHook.setValue( + 'virtualMachineType', + data[0].zone[0].arch[0].virtualMachineType[0].virtualMachineType + ); + formHook.setValue( + 'virtualMachinePackageFamily', + data[0].zone[0].arch[0].virtualMachineType[0].virtualMachinePackageFamily[0] + ); + } + } }); + const { data: systemImage } = useQuery(['getCloudServerImage'], getCloudServerImage, { staleTime: 5 * 60 * 1000 }); @@ -335,6 +354,7 @@ export default function Form({ }), { staleTime: 5 * 60 * 1000, + enabled: !!formHook.getValues('virtualMachinePackageFamily'), onSuccess(data) { if (data?.[0]) { formHook.setValue('virtualMachinePackageName', data[0].virtualMachinePackageName); @@ -344,9 +364,6 @@ export default function Form({ } ); - const theme = useTheme(); - const { t } = useTranslation(); - const { register, control, @@ -374,7 +391,12 @@ export default function Form({ return ( - {item.virtualMachinePackageName} + + {item.virtualMachinePackageName} + {item.status === CloudServerStatus.Unavailable && ( + {t('sold out')} + )} + ); } @@ -403,7 +425,11 @@ export default function Form({ key: 'instancePrice', render: (item: CloudServerType) => { return ( - + {t('Reference fee tip', { price: item.instancePrice })}{' '} ); @@ -555,7 +581,10 @@ export default function Form({ ({ + ...item, + isOptional: item.status === CloudServerStatus.Available ? true : false + }))} openSelected onRowClick={(item: CloudServerType) => { setValue('virtualMachinePackageName', item.virtualMachinePackageName); diff --git a/frontend/providers/cloudserver/src/pages/cloudserver/create/components/Header.tsx b/frontend/providers/cloudserver/src/pages/cloudserver/create/components/Header.tsx index cb0223d3bcf..22819bb9471 100644 --- a/frontend/providers/cloudserver/src/pages/cloudserver/create/components/Header.tsx +++ b/frontend/providers/cloudserver/src/pages/cloudserver/create/components/Header.tsx @@ -124,7 +124,7 @@ const Header = ({ {t('Storage')} - + {t('Reference fee disk tips', { price: instanceType?.diskPerG })} @@ -138,12 +138,28 @@ const Header = ({ > {t('BandWidth')} - - {t('Reference fee network tips', { - price1: instanceType?.networkSpeedUnderSpeedBoundaryPerHour, - price2: instanceType?.networkSpeedAboveSpeedBoundaryPerHour + + + {t('interval')} + {t('price')} + + {instanceType?.bandwidthPricingTiers.map((item, index) => { + return ( + + {`[${item.minBandwidth} , ${ + item.maxBandwidth === null ? '∞' : item.maxBandwidth + })`} + + {t('Reference fee bandwidth tips', { price: item.pricePerMbps })} + + + ); })} - + diff --git a/frontend/providers/cloudserver/src/pages/cloudserver/create/index.tsx b/frontend/providers/cloudserver/src/pages/cloudserver/create/index.tsx index da4d72f9841..9ec438d7717 100644 --- a/frontend/providers/cloudserver/src/pages/cloudserver/create/index.tsx +++ b/frontend/providers/cloudserver/src/pages/cloudserver/create/index.tsx @@ -4,7 +4,6 @@ import { useLoading } from '@/hooks/useLoading'; import { useToast } from '@/hooks/useToast'; import { useGlobalStore } from '@/store/global'; import { CloudServerType, EditForm } from '@/types/cloudserver'; -import { CVMChargeType } from '@/types/region'; import { serviceSideProps } from '@/utils/i18n'; import { Box, Flex } from '@chakra-ui/react'; import { useQuery } from '@tanstack/react-query'; @@ -43,12 +42,12 @@ export default function EditOrder() { amount: 1 } ], - systemImageId: '', - chargeType: CVMChargeType.postPaidByHour, - zone: 'Guangzhou-6', - virtualMachineArch: 'x86_64', - virtualMachineType: 'costEffective', - virtualMachinePackageFamily: 'A' + systemImageId: '' + // chargeType: CVMChargeType.postPaidByHour, + // zone: 'Guangzhou-6', + // virtualMachineArch: 'x86_64', + // virtualMachineType: 'costEffective', + // virtualMachinePackageFamily: 'A' } }); diff --git a/frontend/providers/cloudserver/src/pages/cloudservers/components/List.tsx b/frontend/providers/cloudserver/src/pages/cloudservers/components/List.tsx index 73df7f0373f..97c1cf347e2 100644 --- a/frontend/providers/cloudserver/src/pages/cloudservers/components/List.tsx +++ b/frontend/providers/cloudserver/src/pages/cloudservers/components/List.tsx @@ -3,7 +3,7 @@ import AppStatusTag from '@/components/AppStatusTag'; import MyIcon from '@/components/Icon'; import { CVMInstanceType, HandleEnum } from '@/types/cloudserver'; import { formatTime } from '@/utils/tools'; -import { Box, Button, Center, Flex, FlexProps, MenuButton } from '@chakra-ui/react'; +import { Box, Button, Center, Flex, FlexProps, MenuButton, Text } from '@chakra-ui/react'; import { LogoutIcon, MyTable, SealosMenu, useMessage } from '@sealos/ui'; import { useTranslation } from 'next-i18next'; import { useRouter } from 'next/router'; @@ -137,7 +137,7 @@ const OrderList = ({ apps = [], refetchApps }: { apps: any[]; refetchApps: () => {item?.privateIpAddresses?.join(',')}(内) - {item?.publicIpAddresses && ( + {item?.publicIpAddresses ? (
{item?.publicIpAddresses?.join(',')}(公)
+ ) : ( + {t('Public IP is not enabled')} )} ); diff --git a/frontend/providers/cloudserver/src/types/cloudserver.ts b/frontend/providers/cloudserver/src/types/cloudserver.ts index f2465c42fe4..dbb28b75b4d 100644 --- a/frontend/providers/cloudserver/src/types/cloudserver.ts +++ b/frontend/providers/cloudserver/src/types/cloudserver.ts @@ -23,6 +23,12 @@ export type StorageType = { use: 'SystemDisk' | 'DataDisk'; }; +export type BandwidthPricingTier = { + minBandwidth: number; + maxBandwidth: number; + pricePerMbps: number; +}; + export type CloudServerType = { cpu?: number; memory?: number; @@ -35,6 +41,7 @@ export type CloudServerType = { networkSpeedUnderSpeedBoundaryPerHour: number; networkSpeedAboveSpeedBoundaryPerHour: number; status: CloudServerStatus; + bandwidthPricingTiers: BandwidthPricingTier[]; }; export enum CloudServerStatus {