This commit is contained in:
rustdesk 2024-10-12 01:43:25 +08:00
parent 13b9da4121
commit 0b733ca594
3 changed files with 137 additions and 13 deletions

View File

@ -21,7 +21,14 @@ const {
<WidgetWrapper id={id} isDark={isDark} containerClass={`max-w-7xl mx-auto ${classes?.container ?? ''}`} bg={bg}> <WidgetWrapper id={id} isDark={isDark} containerClass={`max-w-7xl mx-auto ${classes?.container ?? ''}`} bg={bg}>
<Headline title={title} subtitle={subtitle} tagline={tagline} /> <Headline title={title} subtitle={subtitle} tagline={tagline} />
<div class="flex items-stretch justify-center"> <div class="flex items-stretch justify-center">
<div class="grid grid-cols-4 gap-4 dark:text-white sm:grid-cols-2 md:grid-cols-2 lg:grid-cols-4 xl:grid-cols-4"> <div
class={`grid grid-cols-` +
prices.length +
` gap-4 dark:text-white sm:grid-cols-2 md:grid-cols-2 lg:grid-cols-` +
prices.length +
` xl:grid-cols-` +
prices.length}
>
{ {
prices && prices &&
prices.map( prices.map(
@ -35,11 +42,16 @@ const {
callToAction2, callToAction2,
hasRibbon = false, hasRibbon = false,
content, content,
id,
ribbonTitle, ribbonTitle,
}) => ( }) => (
<div class="col-span-3 mx-auto flex w-full sm:col-span-1 md:col-span-1 lg:col-span-1 xl:col-span-1"> <div
class="col-span-3 mx-auto flex w-full sm:col-span-1 md:col-span-1 lg:col-span-1 xl:col-span-1"
id={id || ''}
>
{id && <a name={id} />}
{price && period && ( {price && period && (
<div class="rounded-lg backdrop-blur border border-gray-200 dark:border-gray-700 bg-white dark:bg-slate-900 shadow px-3 py-6 flex w-full max-w-sm flex-col justify-between text-center"> <div class="rounded-lg backdrop-blur border border-gray-200 dark:border-gray-700 bg-white dark:bg-slate-900 shadow px-3 py-6 flex w-full flex-col justify-between text-center">
{hasRibbon && ribbonTitle && ( {hasRibbon && ribbonTitle && (
<div class="absolute right-[-5px] 2xl:right-[-8px] rtl:right-auto rtl:left-[-8px] rtl:2xl:left-[-10px] top-[-5px] 2xl:top-[-10px] z-[1] h-[100px] w-[100px] overflow-hidden text-right"> <div class="absolute right-[-5px] 2xl:right-[-8px] rtl:right-auto rtl:left-[-8px] rtl:2xl:left-[-10px] top-[-5px] 2xl:top-[-10px] z-[1] h-[100px] w-[100px] overflow-hidden text-right">
<span class="absolute top-[19px] right-[-21px] rtl:right-auto rtl:left-[-21px] block w-full rotate-45 rtl:-rotate-45 bg-green-700 text-center text-[10px] font-bold uppercase leading-5 text-white shadow-[0_3px_10px_-5px_rgba(0,0,0,0.3)] before:absolute before:left-0 before:top-full before:z-[-1] before:border-[3px] before:border-r-transparent before:border-b-transparent before:border-l-green-800 before:border-t-green-800 before:content-[''] after:absolute after:right-0 after:top-full after:z-[-1] after:border-[3px] after:border-l-transparent after:border-b-transparent after:border-r-green-800 after:border-t-green-800 after:content-['']"> <span class="absolute top-[19px] right-[-21px] rtl:right-auto rtl:left-[-21px] block w-full rotate-45 rtl:-rotate-45 bg-green-700 text-center text-[10px] font-bold uppercase leading-5 text-white shadow-[0_3px_10px_-5px_rgba(0,0,0,0.3)] before:absolute before:left-0 before:top-full before:z-[-1] before:border-[3px] before:border-r-transparent before:border-b-transparent before:border-l-green-800 before:border-t-green-800 before:content-[''] after:absolute after:right-0 after:top-full after:z-[-1] after:border-[3px] after:border-l-transparent after:border-b-transparent after:border-r-green-800 after:border-t-green-800 after:content-['']">
@ -53,8 +65,12 @@ const {
{title} {title}
</h3> </h3>
)} )}
{subtitle && <p class="font-light sm:text-lg text-gray-600 dark:text-slate-400">{subtitle}</p>} {subtitle && (
<div class="my-8"> <p class="font-light sm:text-lg text-gray-600 dark:text-slate-400">
<Fragment set:html={subtitle} />
</p>
)}
<div class="my-6">
<div class="flex items-center justify-center text-center mb-1"> <div class="flex items-center justify-center text-center mb-1">
<span class="text-5xl">$</span> <span class="text-5xl">$</span>
<span class="text-5xl font-extrabold"> <span class="text-5xl font-extrabold">
@ -64,12 +80,12 @@ const {
<span class="text-base leading-6 lowercase text-gray-600 dark:text-slate-400">{period}</span> <span class="text-base leading-6 lowercase text-gray-600 dark:text-slate-400">{period}</span>
</div> </div>
{items && ( {items && (
<ul class="my-8 md:my-10 space-y-2 text-left"> <ul class="my-4 space-y-2 text-left">
{items.map( {items.map(
({ description, icon }) => ({ description, icon }) =>
description && ( description && (
<li class="mb-1.5 flex items-start space-x-3 leading-7 text-sm"> <li class="flex items-start space-x-3 text-sm">
<div class="mt-1.5"> <div class="">
<Icon name={icon ? icon : 'tabler:check'} class="size-4 text-blue-500" /> <Icon name={icon ? icon : 'tabler:check'} class="size-4 text-blue-500" />
</div> </div>
<span> <span>

View File

@ -54,7 +54,7 @@ const metadata = {
prices={[ prices={[
{ {
title: 'Free', title: 'Free',
subtitle: 'Free Self-hosting Plan', subtitle: 'Free self-hosting plan',
price: '0 <span class="text-sm">/month</span>', price: '0 <span class="text-sm">/month</span>',
period: 'Open source and free', period: 'Open source and free',
items: [ items: [
@ -73,7 +73,7 @@ const metadata = {
}, },
{ {
title: 'Individual', title: 'Individual',
subtitle: 'Individual Self-hosting Pro Plan', subtitle: 'Individual self-hosting <span class="font-bold">Pro</span> plan',
price: '9.90 <span class="text-sm">/month</span>', price: '9.90 <span class="text-sm">/month</span>',
period: 'billed annually', period: 'billed annually',
items: [ items: [
@ -127,7 +127,7 @@ const metadata = {
}, },
{ {
title: 'Basic', title: 'Basic',
subtitle: 'Basic Self-hosting Pro Plan', subtitle: 'Basic self-hosting <span class="font-bold">Pro</span> plan',
price: '19.90 <span class="text-sm">/month</span>', price: '19.90 <span class="text-sm">/month</span>',
period: 'billed annually', period: 'billed annually',
items: [ items: [
@ -169,7 +169,7 @@ const metadata = {
}, },
{ {
title: 'Customized', title: 'Customized',
subtitle: 'Customized Pro Plan', subtitle: 'Customized <span class="font-bold">Pro</span> plan',
price: '<span id="cprice">19.90</span> <span class="text-sm">/month</span>', price: '<span id="cprice">19.90</span> <span class="text-sm">/month</span>',
period: 'billed annually', period: 'billed annually',
items: [ items: [
@ -185,7 +185,7 @@ const metadata = {
}, },
], ],
content: ` content: `
<form class="flex flex-col space-y-4 mx-3"> <form class="flex flex-col space-y-3 mx-3">
<label for="users" class="text-left font-bold">Number of Licensed Users:</label> <label for="users" class="text-left font-bold">Number of Licensed Users:</label>
<input class="bg-white text-black rounded-md border border-gray-300 py-1 px-2 w-24 h-10" type="number" id="users" name="users" value="10" min="10" max="500" step="10"> <input class="bg-white text-black rounded-md border border-gray-300 py-1 px-2 w-24 h-10" type="number" id="users" name="users" value="10" min="10" max="500" step="10">
<input type="range" id="usersSlider" class="slider" name="usersRange" value="10" min="10" max="500" step="10"> <input type="range" id="usersSlider" class="slider" name="usersRange" value="10" min="10" max="500" step="10">
@ -193,6 +193,7 @@ const metadata = {
<input class="bg-white text-black rounded-md border border-gray-300 py-1 px-2 w-24 h-10" type="number" id="devices" name="devices" value="100" min="100" max="5000" step="100"> <input class="bg-white text-black rounded-md border border-gray-300 py-1 px-2 w-24 h-10" type="number" id="devices" name="devices" value="100" min="100" max="5000" step="100">
<input type="range" id="devicesSlider" class="slider" name="devicesRange" value="100" min="100" max="5000" step="100"> <input type="range" id="devicesSlider" class="slider" name="devicesRange" value="100" min="100" max="5000" step="100">
</form> </form>
<br>
<script> <script>
var users = 10; var users = 10;
var devices = 100; var devices = 100;
@ -239,6 +240,112 @@ const metadata = {
]} ]}
/> />
<Prices
prices={[
{
title: 'Customized V2',
subtitle: 'Customized <span class="font-bold">Pro</span> plan with limited concurrent connections',
price: '<span id="cprice2">19.90</span> <span class="text-sm">/month</span>',
period: 'billed annually',
items: [
{
description:
'<span class="font-bold">Everything in the basic self-hosting plan <span class="underline font-normal">but with limited concurrent connections, excessive managed devices won\'t be disabled</span></span>',
icon: 'tabler:checks',
},
{
description: 'Unlimited concurrent sessions (in tabs or seperate windows) per concurrent connection',
},
{
description: '$1 for each additional user',
},
{
description: '$0.1 for each additional device',
},
{
description: '$20 for each additional concurrent connection',
},
],
id: 'custom2',
content: `
<form class="flex flex-col space-y-3 mx-3">
<label for="users2" class="text-left font-bold">Number of Licensed Users:</label>
<input class="bg-white text-black rounded-md border border-gray-300 py-1 px-2 w-24 h-10" type="number" id="users2" name="users2" value="10" min="10" max="500" step="10">
<input type="range" id="usersSlider2" class="slider" name="usersRange2" value="10" min="10" max="500" step="10">
<label for="devices2" class="text-left font-bold">Number of Managed Devices:</label>
<input class="bg-white text-black rounded-md border border-gray-300 py-1 px-2 w-24 h-10" type="number" id="devices2" name="devices2" value="100" min="100" max="5000" step="100">
<input type="range" id="devicesSlider2" class="slider" name="devicesRange2" value="100" min="100" max="5000" step="100">
<label for="conns" class="text-left font-bold">Number of Concurrent Connections:</label>
<input class="bg-white text-black rounded-md border border-gray-300 py-1 px-2 w-24 h-10" type="number" id="conns" name="conns" value="1" min="1" max="50" step="1">
<input type="range" id="connsSlider" class="slider" name="connsRange" value="1" min="1" max="50" step="1">
</form>
<br>
<script>
var users2 = 10;
var devices2 = 100;
var conns = 1;
function submit2() {
redirectUrl = "https://rustdesk.com/api/lic/stripe/checkout?type=Customized&users=" + users2 + "&devices=" + devices2 + "&conns=" + conns;
gotoBuy(redirectUrl);
}
function calculatePrice2() {
users2 = parseInt(document.getElementById("users2").value);
devices2 = parseInt(document.getElementById("devices2").value);
conns = parseInt(document.getElementById("conns").value);
if (!users2 || users2 < 10) users2 = 10;
if (devices2 < 100) devices2 = 100;
if (conns < 1) conns = 1;
var price = 19.9 + (users2 - 10) + (devices2 - 100) * 0.1 + (conns - 1) * 20;
document.getElementById("cprice2").innerText = price.toFixed(price >= 100 ? 1 : 2);
}
if (window.location.href.indexOf("custom2") > 0) {
document.getElementById("custom2").style.display = 'block';
setTimeout(function() { window.location = "#custom2"; }, 150);
} else {
document.getElementById("custom2").style.display = 'none';
}
document.getElementById("users2").oninput = function() {
document.getElementById("usersSlider2").value = this.value;
calculatePrice2();
}
document.getElementById("devices2").oninput = function() {
document.getElementById("devicesSlider2").value = this.value;
calculatePrice2();
}
document.getElementById("conns").oninput = function() {
document.getElementById("connsSlider").value = this.value;
calculatePrice2();
}
document.getElementById("usersSlider2").oninput = function() {
document.getElementById("users2").value = this.value;
calculatePrice2();
}
document.getElementById("devicesSlider2").oninput = function() {
document.getElementById("devices2").value = this.value;
calculatePrice2();
}
document.getElementById("connsSlider").oninput = function() {
document.getElementById("conns").value = this.value;
calculatePrice2();
}
</script>
`,
callToAction: {
text: 'Buy now',
onclick: 'submit2()',
variant: 'primary',
},
},
]}
/>
<CallToAction <CallToAction
actions={[ actions={[
{ {

1
v3/src/types.d.ts vendored
View File

@ -153,6 +153,7 @@ export interface Price {
hasRibbon?: boolean; hasRibbon?: boolean;
ribbonTitle?: string; ribbonTitle?: string;
content?: string; content?: string;
id?: string;
} }
export interface Testimonial { export interface Testimonial {