diff --git a/docs/website/src/pages/pricing/plan/index.tsx b/docs/website/src/pages/pricing/plan/index.tsx index 1ebbab695e2..d651e177fe4 100644 --- a/docs/website/src/pages/pricing/plan/index.tsx +++ b/docs/website/src/pages/pricing/plan/index.tsx @@ -127,14 +127,14 @@ export default function Plan() { {select === 'month' && (
如集群中运行一个容器,配额是 CPU 1核 x 内存1G x 存储卷 100G x 网络 10G, - 则一年消耗的费用为 1.61 + 0.80 + 0 + 0 = 2.41元 + 则一月消耗的费用为 1.61 + 0.80 + 0 + 0 = 2.41元
)} {select === 'day' && (
如集群中运行一个容器,配额是 CPU 1核 x 内存1G x 存储卷 100G x 网络 10G, - 则一年消耗的费用为 0.05 + 0.03 + 0 + 0 = 0.08元 + 则一天消耗的费用为 0.05 + 0.03 + 0 + 0 = 0.08元
)}
+
Sealos 私有云
diff --git a/service/license/public/images/avatar.svg b/service/license/public/images/avatar.svg new file mode 100644 index 00000000000..41d77596d76 --- /dev/null +++ b/service/license/public/images/avatar.svg @@ -0,0 +1,4 @@ + + + + diff --git a/service/license/src/components/Account/index.tsx b/service/license/src/components/Account/index.tsx index c2b50fa4403..b9429385b43 100644 --- a/service/license/src/components/Account/index.tsx +++ b/service/license/src/components/Account/index.tsx @@ -29,23 +29,15 @@ export default function Account() { position={'relative'} onClick={accountDisclosure.onOpen} > - {userInfo?.user?.avatar ? ( - user avator - ) : ( - - )} + user avator {accountDisclosure.isOpen && ( <> @@ -75,7 +67,7 @@ export default function Account() { height={'36px'} borderRadius="full" src={userInfo?.user?.avatar || ''} - fallbackSrc="/images/sealos.svg" + fallbackSrc={'/images/avatar.svg'} alt="user avator" /> {userInfo?.user?.name} diff --git a/service/license/src/components/CodeBlock/index.tsx b/service/license/src/components/CodeBlock/index.tsx index 970a180dc00..9eac45d20c0 100644 --- a/service/license/src/components/CodeBlock/index.tsx +++ b/service/license/src/components/CodeBlock/index.tsx @@ -1,17 +1,24 @@ import { useCopyData } from '@/hooks/useCopyData'; -import { Center, Flex, FlexProps, Text } from '@chakra-ui/react'; +import { Box, Center, Flex, FlexProps, Text } from '@chakra-ui/react'; import { CSSProperties } from 'react'; import { PrismAsyncLight as SyntaxHighlighter } from 'react-syntax-highlighter'; import { CopyIcon } from '@/components/Icon'; type CodeBlockProps = { code: string; + copyValue?: string; language: string; customStyle?: CSSProperties | undefined; flexStyle?: FlexProps; }; -export default function CodeBlock({ code, language, customStyle, flexStyle }: CodeBlockProps) { +export default function CodeBlock({ + code, + language, + customStyle, + flexStyle, + copyValue +}: CodeBlockProps) { const { copyData } = useCopyData(); return ( @@ -25,14 +32,14 @@ export default function CodeBlock({ code, language, customStyle, flexStyle }: Co px="20px" fontSize={'14px'} > - + $ - + {code} -
copyData(code)}> +
copyData(copyValue ? copyValue : code)}>
diff --git a/service/license/src/components/Signin/index.tsx b/service/license/src/components/Signin/index.tsx index 214ecc35a41..13e6040edff 100644 --- a/service/license/src/components/Signin/index.tsx +++ b/service/license/src/components/Signin/index.tsx @@ -55,14 +55,13 @@ export default function SigninComponent() { isLoading: passwordLoading } = usePassword({ showError }); const isLoading = useMemo(() => passwordLoading || smsLoading, [passwordLoading, smsLoading]); - const isSignIn = useSessionStore((s) => s.isUserLogin); - const router = useRouter(); - - useEffect(() => { - if (isSignIn()) { - router.push('/pricing'); - } - }, [isSignIn, router]); + // const isSignIn = useSessionStore((s) => s.isUserLogin); + // const router = useRouter(); + // useEffect(() => { + // if (isSignIn()) { + // router.push('/pricing'); + // } + // }, [isSignIn, router]); const { AuthList } = useAuthList(); diff --git a/service/license/src/components/account/index.tsx b/service/license/src/components/account/index.tsx index c2b50fa4403..b9429385b43 100644 --- a/service/license/src/components/account/index.tsx +++ b/service/license/src/components/account/index.tsx @@ -29,23 +29,15 @@ export default function Account() { position={'relative'} onClick={accountDisclosure.onOpen} > - {userInfo?.user?.avatar ? ( - user avator - ) : ( - - )} + user avator {accountDisclosure.isOpen && ( <> @@ -75,7 +67,7 @@ export default function Account() { height={'36px'} borderRadius="full" src={userInfo?.user?.avatar || ''} - fallbackSrc="/images/sealos.svg" + fallbackSrc={'/images/avatar.svg'} alt="user avator" /> {userInfo?.user?.name} diff --git a/service/license/src/components/signin/index.tsx b/service/license/src/components/signin/index.tsx index 214ecc35a41..13e6040edff 100644 --- a/service/license/src/components/signin/index.tsx +++ b/service/license/src/components/signin/index.tsx @@ -55,14 +55,13 @@ export default function SigninComponent() { isLoading: passwordLoading } = usePassword({ showError }); const isLoading = useMemo(() => passwordLoading || smsLoading, [passwordLoading, smsLoading]); - const isSignIn = useSessionStore((s) => s.isUserLogin); - const router = useRouter(); - - useEffect(() => { - if (isSignIn()) { - router.push('/pricing'); - } - }, [isSignIn, router]); + // const isSignIn = useSessionStore((s) => s.isUserLogin); + // const router = useRouter(); + // useEffect(() => { + // if (isSignIn()) { + // router.push('/pricing'); + // } + // }, [isSignIn, router]); const { AuthList } = useAuthList(); diff --git a/service/license/src/pages/api/payment/create.ts b/service/license/src/pages/api/payment/create.ts index 86b5f1f772c..23e4b43b167 100644 --- a/service/license/src/pages/api/payment/create.ts +++ b/service/license/src/pages/api/payment/create.ts @@ -1,4 +1,5 @@ import { authSession } from '@/services/backend/auth'; +import { generateLicenseToken } from '@/services/backend/db/license'; import { createPaymentRecord } from '@/services/backend/db/payment'; import { jsonRes } from '@/services/backend/response'; import { getSealosPay } from '@/services/pay'; diff --git a/service/license/src/pages/cluster/components/Tutorial.tsx b/service/license/src/pages/cluster/components/Tutorial.tsx index 2c94cdc5c39..3a19b19a4ac 100644 --- a/service/license/src/pages/cluster/components/Tutorial.tsx +++ b/service/license/src/pages/cluster/components/Tutorial.tsx @@ -29,7 +29,22 @@ export default function Tutorial({ clusterId: string; ossFileName: string; }) { - let fileName = useMemo(() => ossFileName.replace('/cloud/', ''), [ossFileName]); + let { fileNameParams, bashParams } = useMemo(() => { + if (ossFileName) { + let match = /cloud-(.*?)\.tar/g.exec(ossFileName); + return { + fileNameParams: ossFileName?.replace('/cloud/', ''), + bashParams: match ? `--cloud-version=${match[1]}` : '--cloud-version v5.0.0-beta1' + }; + } else { + return { + fileNameParams: '', + bashParams: '' + }; + } + }, [ossFileName]); + // console.log(ossFileName, fileNameParams, bashParams); + const { t } = useTranslation(); const { copyData } = useCopyData(); const [ossLink, setOssLink] = useState(''); @@ -239,14 +254,15 @@ export default function Tutorial({ 服务器上下载 - + 部署集群 @@ -263,7 +279,7 @@ export default function Tutorial({ diff --git a/service/license/src/pages/license/components/Recharge.tsx b/service/license/src/pages/license/components/Recharge.tsx index 1e8c296672d..8b013922498 100644 --- a/service/license/src/pages/license/components/Recharge.tsx +++ b/service/license/src/pages/license/components/Recharge.tsx @@ -32,7 +32,7 @@ export default function RechargeComponent() { const queryClient = useQueryClient(); const toast = useToast({ position: 'top', duration: 2000 }); const { t } = useTranslation(); - const [isAgree, setIsAgree] = useState(true); + const [isAgree, setIsAgree] = useState(false); const [isInvalid, setIsInvalid] = useState(false); const { BonusBox, selectAmount } = useBonusBox(); const { isOpen, onOpen, onClose } = useDisclosure(); diff --git a/service/license/src/pages/pricing/components/Product.tsx b/service/license/src/pages/pricing/components/Product.tsx index e903d786d4e..07deb94d839 100644 --- a/service/license/src/pages/pricing/components/Product.tsx +++ b/service/license/src/pages/pricing/components/Product.tsx @@ -46,7 +46,7 @@ export default function Product() { const [orderID, setOrderID] = useState(''); const [wechatData, setWechatData] = useState(); const { data: platformEnv } = useQuery(['getPlatformEnv'], getSystemEnv); - const [remainingSeconds, setRemainingSeconds] = useState(2); // 初始值为2秒 + const [remainingSeconds, setRemainingSeconds] = useState(1); // 初始值为2秒 const { data: routeParams, setRouteParams, clearRouteParams } = useRouteParamsStore(); const { isUserLogin } = useSessionStore(); const { paymentData, setPaymentData, deletePaymentData, isExpired } = usePaymentDataStore(); @@ -221,7 +221,7 @@ export default function Product() { status: 'success', title: t('Checking Payment Results'), // 这里改为license 签发成功 isClosable: true, - duration: 9000, + duration: 3500, position: 'top' }); setComplete(2); @@ -262,18 +262,11 @@ export default function Product() { // handle Jump link useEffect(() => { - const { clusterType, external } = router.query; - const isLogin = isUserLogin(); - console.log(clusterType, external); - - if (!isLogin) { - setRouteParams(external as string, clusterType as ClusterType); - } else if (routeParams.clusterType) { + const { clusterType, external } = routeParams; + console.log(clusterType, external, 'pricing'); + if (clusterType && external) { handleProductByType(routeParams.clusterType as ClusterType); clearRouteParams(); - } else { - console.log(11); - handleProductByType(clusterType as ClusterType); } // eslint-disable-next-line react-hooks/exhaustive-deps }, []); @@ -281,8 +274,8 @@ export default function Product() { return ( {children} diff --git a/service/license/src/pages/signin.tsx b/service/license/src/pages/signin.tsx index 235dd488fdb..e6634721a63 100644 --- a/service/license/src/pages/signin.tsx +++ b/service/license/src/pages/signin.tsx @@ -1,8 +1,29 @@ import SigninComponent from '@/components/Signin'; +import useRouteParamsStore from '@/stores/routeParams'; +import useSessionStore from '@/stores/session'; +import { ClusterType } from '@/types'; import { compareFirstLanguages } from '@/utils/tools'; import { serverSideTranslations } from 'next-i18next/serverSideTranslations'; +import { useRouter } from 'next/router'; +import { useEffect } from 'react'; export default function SigninPage() { + const router = useRouter(); + const { data: routeParams, setRouteParams, clearRouteParams } = useRouteParamsStore(); + const { isUserLogin } = useSessionStore(); + + useEffect(() => { + const { clusterType, external } = router.query; + console.log(clusterType, external, '--------'); + if (external && clusterType) { + setRouteParams(external as string, clusterType as ClusterType); + } + if (isUserLogin()) { + router.push('/pricing'); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + return ; } diff --git a/service/license/src/services/backend/db/license.ts b/service/license/src/services/backend/db/license.ts index aa033e69614..39327f0e5f7 100644 --- a/service/license/src/services/backend/db/license.ts +++ b/service/license/src/services/backend/db/license.ts @@ -3,6 +3,8 @@ import { base64Decode } from '@/utils/tools'; import { sign } from 'jsonwebtoken'; import { connectToDatabase } from './mongodb'; +const ExpiredTime = 30 * 24 * 60 * 60; + async function connectLicenseCollection() { const client = await connectToDatabase(); const collection = client.db().collection('license'); @@ -21,7 +23,6 @@ export async function createLicenseRecord({ const collection = await connectLicenseCollection(); const now = Math.floor(Date.now() / 1000); // Get current timestamp in seconds - const oneDayInSeconds = 3 * 24 * 60 * 60; const record: LicenseDB = { uid: uid, @@ -32,7 +33,7 @@ export async function createLicenseRecord({ quota: quota }, iat: now, // Store the current timestamp as iat - exp: now + oneDayInSeconds, // Set expiration to one day from now (in seconds) + exp: now + ExpiredTime, // Set expiration to one day from now (in seconds) amount: amount, type: type, createdAt: new Date(), @@ -96,13 +97,13 @@ export async function getLicenseRecordsByUid({ return result; } -export function generateLicenseToken(payload: LicenseToken) { +export function generateLicenseToken(payload: LicenseToken, time = ExpiredTime) { const privateKey = process.env.LICENSE_PRIVATE_KEY; if (!privateKey) { throw new Error('LICENSE PRIVATE KEY IS MISSING'); } const nowInSeconds = Math.floor(Date.now() / 1000); - const expirationTime = nowInSeconds + 3 * 24 * 60 * 60; //默认三天有效时间 + const expirationTime = nowInSeconds + time; // Valid for three days by default const _payload = { iss: 'Sealos', diff --git a/service/license/src/utils/tools.ts b/service/license/src/utils/tools.ts index 6da6b7f9ef3..9f78d0df764 100644 --- a/service/license/src/utils/tools.ts +++ b/service/license/src/utils/tools.ts @@ -12,11 +12,28 @@ export const getRemainingTime = (expirationTime: number) => { } const remainingTimeInSeconds = expirationTime - currentTime; - const hours = Math.floor(remainingTimeInSeconds / 3600); + const days = Math.floor(remainingTimeInSeconds / 86400); + const hours = Math.floor((remainingTimeInSeconds % 86400) / 3600); const minutes = Math.floor((remainingTimeInSeconds % 3600) / 60); - const seconds = remainingTimeInSeconds % 60; - const formattedTime = `${hours}小时${minutes}分钟`; + let formattedTime = ''; + + if (days > 0) { + formattedTime += `${days}天`; + } + + if (hours > 0) { + formattedTime += `${hours}小时`; + } + + if (minutes > 0 && (days === 0 || hours === 0)) { + formattedTime += `${minutes}分钟`; + } + + if (formattedTime === '') { + return '不足一分钟'; + } + return formattedTime; };