更新底部服务保障跳转链接 & 购买套餐添加折扣字段 & 用户总览添加长效动态图表

This commit is contained in:
Eamon-meng
2025-12-18 17:11:19 +08:00
parent 375a6f30c0
commit fa942d4b99
5 changed files with 163 additions and 48 deletions

View File

@@ -19,7 +19,7 @@ export default function Footer(props: FooterProps) {
<p className="text-sm text-gray-400">QQ 70177252</p>
<h3 className="hidden sm:block"></h3>
<a
href="https://weixin.qq.com/r/mp/AxYMFAzErFHTrUh390MR"
href="https://work.weixin.qq.com/kfid/kfc458bc58e79e5093f"
target="_blank"
rel="noopener noreferrer"
className="text-sm text-gray-400 hidden sm:block cursor-pointer hover:text-white transition-colors"
@@ -27,7 +27,7 @@ export default function Footer(props: FooterProps) {
</a>
<a
href="https://weixin.qq.com/r/mp/AxYMFAzErFHTrUh390MR"
href="https://work.weixin.qq.com/kfid/kfc458bc58e79e5093f"
target="_blank"
rel="noopener noreferrer"
className="text-sm text-gray-400 hidden sm:block cursor-pointer hover:text-white transition-colors"
@@ -41,7 +41,7 @@ export default function Footer(props: FooterProps) {
items={[
{name: `产品订购`, href: `/product`},
{name: `获取代理`, href: `/collect`},
{name: `帮助中心`, href: `/docs`},
{name: `帮助中心`, href: `/docs/faq-general`},
{name: `企业服务`, href: `/custom`},
]}
/>
@@ -56,14 +56,14 @@ export default function Footer(props: FooterProps) {
<SiteNavList
title="使用案例"
items={[
{name: `数据抓取`, href: `/data-capture`},
{name: `媒体矩阵`, href: `#`},
{name: `广告验证`, href: `#`},
{name: `价格监控`, href: `#`},
{name: `市场调研`, href: `#`},
{name: `金融数据`, href: `#`},
{name: `SEO优化`, href: `#`},
{name: `测试`, href: `#`},
{name: `数据采集`, href: `/data-capture`},
{name: `电商运营`, href: `/e-commerce`},
{name: `市场调研`, href: `/market-research`},
{name: `SEO优化`, href: `/seo-optimization`},
{name: `社交媒体`, href: `/social-media`},
{name: `广告投放`, href: `/advertising`},
{name: `账号管理`, href: `/account-management`},
{name: `测试`, href: `/network-testing`},
]}
/>
<SiteNavList

View File

@@ -123,8 +123,7 @@ export default function Charts({initialData}: ChartsProps) {
{submittedData && <DashboardChart data={submittedData}/>}
</TabsContent>
<TabsContent value="static" className="flex flex-col items-center justify-center gap-2">
<Image alt="coming soon" src={soon}/>
<p></p>
<LongChart/>
</TabsContent>
</Tabs>
</CardContent>
@@ -184,3 +183,33 @@ function DashboardChart(props: DashboardChartProps) {
</ChartContainer>
)
}
function LongChart() {
return (
<ChartContainer config={config} className="w-full h-full">
<AreaChart margin={{top: 0, right: 20, left: 0, bottom: 0}}>
<CartesianGrid vertical={false}/>
<XAxis
dataKey="formattedTime"
tickLine={false}
/>
<YAxis tickLine={false}/>
<Tooltip
animationDuration={100}
// labelFormatter={value => `日期: ${chartData.find(item => item.formattedTime === value)?.fullDate || value}`}
formatter={value => [`${value}`, '套餐使用量']}
/>
<Area
type="monotone"
dataKey="count"
stroke="#8884d8"
fill="#8884d8"
fillOpacity={0.2}
strokeWidth={2}
name="套餐使用量"
/>
<Legend/>
</AreaChart>
</ChartContainer>
)
}

View File

@@ -4,8 +4,6 @@ import {merge} from '@/lib/utils'
import {Tabs, TabsContent, TabsList, TabsTrigger} from '@/components/ui/tabs'
import LongForm from '@/components/composites/purchase/long/form'
import ShortForm from '@/components/composites/purchase/short/form'
import FixedForm from '@/components/composites/purchase/fixed/form'
import Custom from '@/components/composites/purchase/custom/page'
import {usePathname, useRouter, useSearchParams} from 'next/navigation'
import SelfDesc from '@/components/features/self-desc'
export type TabType = 'short' | 'long' | 'fixed' | 'custom'

View File

@@ -19,6 +19,12 @@ import {Schema} from '@/components/composites/purchase/long/form'
import {Card} from '@/components/ui/card'
import {getPrice, CreateResourceReq} from '@/actions/resource'
interface PriceData {
price: string
discounted_price?: string
discounted?: number
}
export default function Right() {
const {control} = useFormContext<Schema>()
const method = useWatch({control, name: 'pay_type'})
@@ -27,7 +33,11 @@ export default function Right() {
const quota = useWatch({control, name: 'quota'})
const expire = useWatch({control, name: 'expire'})
const dailyLimit = useWatch({control, name: 'daily_limit'})
const [price, setPrice] = useState<string>('')
const [priceData, setPriceData] = useState<PriceData>({
price: '0.00',
discounted_price: '0.00',
discounted: 0,
})
useEffect(() => {
const price = async () => {
@@ -42,17 +52,31 @@ export default function Right() {
}
try {
const priceValue = await getPrice(params)
console.log(priceValue, 'priceValue')
if (priceValue.success && priceValue.data?.price) {
setPrice(priceValue.data.price)
const data: PriceData = priceValue.data
setPriceData({
price: data.price,
discounted_price: data.discounted_price ?? data.price ?? '',
discounted: data.discounted,
})
}
}
catch (error) {
console.error('获取价格失败:', error)
setPrice('0.00')
setPriceData({
price: '0.00',
discounted_price: '0.00',
discounted: 0,
})
}
}
price()
}, [dailyLimit, expire, live, quota, mode])
const {price, discounted_price: discountedPrice = '', discounted} = priceData
return (
<Card className={merge(
`flex-none basis-90 p-6 flex flex-col gap-6 relative`,
@@ -74,13 +98,21 @@ export default function Right() {
</span>
</li>
{mode === '2' ? (
<li className="flex justify-between items-center">
<span className="text-sm text-gray-500"> IP </span>
<span className="text-sm">
{quota}
</span>
</li>
<>
<li className="flex justify-between items-center">
<span className="text-sm text-gray-500"> IP </span>
<span className="text-sm">
{quota}
</span>
</li>
<li className="flex justify-between items-center">
<span className="text-sm text-gray-500"></span>
<span className="text-sm">
{price}
</span>
</li>
</>
) : (
<>
<li className="flex justify-between items-center">
@@ -97,19 +129,30 @@ export default function Right() {
</span>
</li>
<li className="flex justify-between items-center">
<span className="text-sm text-gray-500"></span>
<span className="text-sm">
{price}
</span>
</li>
<li className="flex justify-between items-center">
<span className="text-sm text-gray-500"></span>
<span className="text-sm">
-{discounted}
</span>
</li>
</>
)}
</ul>
<div className="border-b border-gray-200"></div>
<p className="flex justify-between items-center">
<span></span>
<span></span>
<span className="text-xl text-orange-500">
{price}
{discountedPrice}
</span>
</p>
<Suspense>
<BalanceOrLogin {...{method, price, mode, live, quota, expire, dailyLimit}}/>
<BalanceOrLogin {...{method, discountedPrice, mode, live, quota, expire, dailyLimit}}/>
</Suspense>
</Card>
)
@@ -117,7 +160,7 @@ export default function Right() {
function BalanceOrLogin(props: {
method: 'wechat' | 'alipay' | 'balance'
price: string
discountedPrice: string
mode: string
live: string
quota: number
@@ -176,7 +219,7 @@ function BalanceOrLogin(props: {
<Pay
method={props.method}
balance={profile.balance}
amount={props.price}
amount={props.discountedPrice}
resource={{
type: 2,
long: {

View File

@@ -17,6 +17,13 @@ import Pay from '@/components/composites/purchase/pay'
import {useFormContext, useWatch} from 'react-hook-form'
import {Card} from '@/components/ui/card'
import {CreateResourceReq, getPrice} from '@/actions/resource'
interface PriceData {
price: string
discounted_price?: string
discounted?: number
}
export default function Right() {
const {control} = useFormContext<Schema>()
const method = useWatch({control, name: 'pay_type'})
@@ -25,7 +32,11 @@ export default function Right() {
const expire = useWatch({control, name: 'expire'})
const quota = useWatch({control, name: 'quota'})
const dailyLimit = useWatch({control, name: 'daily_limit'})
const [price, setPrice] = useState<string>('')
const [priceData, setPriceData] = useState<PriceData>({
price: '0.00',
discounted_price: '0.00',
discounted: 0,
})
useEffect(() => {
const price = async () => {
@@ -40,18 +51,31 @@ export default function Right() {
}
try {
const priceResponse = await getPrice(params)
if (priceResponse.success && priceResponse.data?.price) {
setPrice(priceResponse.data.price)
console.log(priceResponse, 'priceResponse')
if (priceResponse.success && priceResponse.data) {
const data: PriceData = priceResponse.data
setPriceData({
price: data.price,
discounted_price: data.discounted_price ?? data.price ?? '',
discounted: data.discounted,
})
}
}
catch (error) {
console.error('获取价格失败:', error)
setPrice('0.00')
setPriceData({
price: '0.00',
discounted_price: '0.00',
discounted: 0,
})
}
}
price()
}, [expire, live, quota, mode, dailyLimit])
const {price, discounted_price: discountedPrice = '', discounted} = priceData
return (
<Card className={merge(
`flex-none basis-90 p-6 flex flex-col gap-6 relative`,
@@ -73,13 +97,21 @@ export default function Right() {
</span>
</li>
{mode === '2' ? (
<li className="flex justify-between items-center">
<span className="text-sm text-gray-500"> IP </span>
<span className="text-sm">
{quota}
</span>
</li>
<>
<li className="flex justify-between items-center">
<span className="text-sm text-gray-500"> IP </span>
<span className="text-sm">
{quota}
</span>
</li>
<li className="flex justify-between items-center">
<span className="text-sm text-gray-500"></span>
<span className="text-sm">
{price}
</span>
</li>
</>
) : (
<>
<li className="flex justify-between items-center">
@@ -96,19 +128,32 @@ export default function Right() {
</span>
</li>
<li className="flex justify-between items-center">
<span className="text-sm text-gray-500"></span>
<span className="text-sm">
{price}
</span>
</li>
{discounted === 1 ? '' : (
<li className="flex justify-between items-center">
<span className="text-sm text-gray-500"></span>
<span className="text-sm">
-{discounted === 1 ? '' : discounted}
</span>
</li>
)}
</>
)}
</ul>
<div className="border-b border-gray-200"></div>
<p className="flex justify-between items-center">
<span></span>
<span></span>
<span className="text-xl text-orange-500">
{price}
{discountedPrice}
</span>
</p>
<Suspense>
<BalanceOrLogin {...{method, price, mode, live, quota, expire, dailyLimit}}/>
<BalanceOrLogin {...{method, discountedPrice, mode, live, quota, expire, dailyLimit}}/>
</Suspense>
</Card>
)
@@ -116,7 +161,7 @@ export default function Right() {
function BalanceOrLogin(props: {
method: 'wechat' | 'alipay' | 'balance'
price: string
discountedPrice: string
mode: string
live: string
quota: number
@@ -175,7 +220,7 @@ function BalanceOrLogin(props: {
<Pay
method={props.method}
balance={profile.balance}
amount={props.price}
amount={props.discountedPrice}
resource={{
type: 1,
short: {