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 ? (
-
- ) : (
-
- )}
+
{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 ? (
-
- ) : (
-
- )}
+
{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;
};