选择套餐配置链接&更新账户总览数据展示
This commit is contained in:
@@ -6,12 +6,12 @@ import {listAnnouncements} from './announcement'
|
|||||||
|
|
||||||
type listAccountReq = {
|
type listAccountReq = {
|
||||||
resource_no?: string
|
resource_no?: string
|
||||||
create_after: Date
|
create_after?: Date
|
||||||
create_before: Date
|
create_before?: Date
|
||||||
}
|
}
|
||||||
|
|
||||||
type listAccountResp = {
|
type listAccountResp = {
|
||||||
time: Date
|
date: string
|
||||||
count: number
|
count: number
|
||||||
}[]
|
}[]
|
||||||
|
|
||||||
@@ -81,11 +81,3 @@ export async function listInitialization(): Promise<ApiResponse<listInitializati
|
|||||||
data: data,
|
data: data,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ChartDataItem = {
|
|
||||||
time: Date
|
|
||||||
count: number
|
|
||||||
count2: number
|
|
||||||
}
|
|
||||||
|
|
||||||
export type ChartData = ChartDataItem[]
|
|
||||||
|
|||||||
@@ -12,18 +12,21 @@ import Image from 'next/image'
|
|||||||
import check from './_assets/check.svg'
|
import check from './_assets/check.svg'
|
||||||
import banner from './_assets/Mask-group.webp'
|
import banner from './_assets/Mask-group.webp'
|
||||||
import group from './_assets/Group.svg'
|
import group from './_assets/Group.svg'
|
||||||
|
import {merge} from '@/lib/utils'
|
||||||
|
import {useRouter} from 'next/navigation'
|
||||||
|
|
||||||
const formSchema = z.object({
|
const formSchema = z.object({
|
||||||
companyName: z.string().min(2, '企业名称至少2个字符'),
|
companyName: z.string().min(2, '企业名称至少2个字符'),
|
||||||
contactName: z.string().min(2, '联系人姓名至少2个字符'),
|
contactName: z.string().min(2, '联系人姓名至少2个字符'),
|
||||||
phone: z.string().min(11, '请输入11位手机号码').max(11, '手机号码长度不正确'),
|
phone: z.string().min(11, '请输入11位手机号码').max(11, '手机号码长度不正确'),
|
||||||
monthlyUsage: z.string().min(1, '请选择每月需求量'),
|
monthlyUsage: z.string().min(1, '请选择您需要的用量'),
|
||||||
purpose: z.string().min(1, '输入用途'),
|
purpose: z.string().min(1, '输入用途'),
|
||||||
})
|
})
|
||||||
|
|
||||||
type FormValues = z.infer<typeof formSchema>
|
type FormValues = z.infer<typeof formSchema>
|
||||||
|
|
||||||
export default function CollectPage() {
|
export default function CollectPage() {
|
||||||
|
const router = useRouter()
|
||||||
const form = useForm<FormValues>({
|
const form = useForm<FormValues>({
|
||||||
resolver: zodResolver(formSchema),
|
resolver: zodResolver(formSchema),
|
||||||
defaultValues: {
|
defaultValues: {
|
||||||
@@ -161,7 +164,7 @@ export default function CollectPage() {
|
|||||||
<div className="flex items-center justify-between gap-4">
|
<div className="flex items-center justify-between gap-4">
|
||||||
<label htmlFor={id} className="text-sm flex items-center gap-1">
|
<label htmlFor={id} className="text-sm flex items-center gap-1">
|
||||||
<span className="text-red-500">*</span>
|
<span className="text-red-500">*</span>
|
||||||
<span>每日需求用量</span>
|
<span>每月需求用量</span>
|
||||||
</label>
|
</label>
|
||||||
<Select onValueChange={field.onChange} value={field.value}>
|
<Select onValueChange={field.onChange} value={field.value}>
|
||||||
<SelectTrigger id={id} className="flex-1 max-w-xs">
|
<SelectTrigger id={id} className="flex-1 max-w-xs">
|
||||||
@@ -194,7 +197,7 @@ export default function CollectPage() {
|
|||||||
)}
|
)}
|
||||||
</FormField>
|
</FormField>
|
||||||
<div className="pt-4 flex justify-center">
|
<div className="pt-4 flex justify-center">
|
||||||
<Button type="submit" className="bg-blue-600 hover:bg-blue-600 px-8">
|
<Button type="submit" className="bg-blue-600 hover:bg-blue-700 px-8">
|
||||||
提交
|
提交
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
@@ -211,9 +214,12 @@ export default function CollectPage() {
|
|||||||
priority
|
priority
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="relative z-10 h-full flex items-center justify-end">
|
<div className={merge('relative h-full flex items-center justify-center pl-150')}>
|
||||||
<div className="flex items-center gap-8">
|
<div className="flex items-center gap-4">
|
||||||
<Button className="bg-blue-600 hover:bg-blue-700 text-white px-6 py-2 rounded-md whitespace-nowrap">
|
<Button
|
||||||
|
className={merge('bg-blue-600 hover:bg-blue-700 text-white px-6 py-2 rounded-md whitespace-nowrap')}
|
||||||
|
onClick={() => router.push('/login')}
|
||||||
|
>
|
||||||
免费试用
|
免费试用
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ export default function CollectPage(props: CollectPageProps) {
|
|||||||
`mt-32 max-md:mt-20 w-96 max-md:w-full h-16 md:h-24 rounded-lg shadow-lg`,
|
`mt-32 max-md:mt-20 w-96 max-md:w-full h-16 md:h-24 rounded-lg shadow-lg`,
|
||||||
`bg-gradient-to-r from-blue-500 to-cyan-400 text-white text-xl lg:text-4xl`,
|
`bg-gradient-to-r from-blue-500 to-cyan-400 text-white text-xl lg:text-4xl`,
|
||||||
].join(' ')}
|
].join(' ')}
|
||||||
onClick={() => router.push('/login')}
|
onClick={() => router.push('/product?type=short')}
|
||||||
>
|
>
|
||||||
选择套餐
|
选择套餐
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
@@ -21,28 +21,20 @@ import {ChartConfig, ChartContainer} from '@/components/ui/chart'
|
|||||||
import {CartesianGrid, XAxis, YAxis, Tooltip, Area, AreaChart, Legend} from 'recharts'
|
import {CartesianGrid, XAxis, YAxis, Tooltip, Area, AreaChart, Legend} from 'recharts'
|
||||||
|
|
||||||
type ChartDataItem = {
|
type ChartDataItem = {
|
||||||
time: Date
|
date: string
|
||||||
count: number
|
count: number
|
||||||
count2: number
|
count2?: number
|
||||||
}
|
}
|
||||||
|
|
||||||
type ChartData = ChartDataItem[]
|
|
||||||
|
|
||||||
type ChartsProps = {
|
type ChartsProps = {
|
||||||
initialData?: ExtraResp<typeof listAccount>
|
initialData?: ExtraResp<typeof listAccount>
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function Charts({initialData}: ChartsProps) {
|
export default function Charts({initialData}: ChartsProps) {
|
||||||
// const [submittedData, setSubmittedData] = useState<ExtraReq<typeof listAccount>>()
|
// const [submittedData, setSubmittedData] = useState<ExtraReq<typeof listAccount>>()
|
||||||
const [submittedData, setSubmittedData] = useState<ExtraResp<typeof listAccount>>(
|
const [submittedData, setSubmittedData] = useState<ExtraResp<typeof listAccount>>(initialData || [])
|
||||||
initialData || [
|
|
||||||
{time: new Date(), count: 80, count2: 64},
|
|
||||||
{time: new Date('2025-03-05'), count: 100, count2: 80},
|
|
||||||
{time: new Date('2024-03-05'), count: 50, count2: 40},
|
|
||||||
],
|
|
||||||
)
|
|
||||||
const formSchema = zod.object({
|
const formSchema = zod.object({
|
||||||
resource_no: zod.string().min(11, '请输入正确的套餐编号').max(11, '请输入正确的套餐编号').optional(),
|
resource_no: zod.string().optional(),
|
||||||
create_after: zod.date().optional(),
|
create_after: zod.date().optional(),
|
||||||
create_before: zod.date().optional(),
|
create_before: zod.date().optional(),
|
||||||
})
|
})
|
||||||
@@ -55,26 +47,34 @@ export default function Charts({initialData}: ChartsProps) {
|
|||||||
})
|
})
|
||||||
const handler = form.handleSubmit(
|
const handler = form.handleSubmit(
|
||||||
async (value) => {
|
async (value) => {
|
||||||
console.log(value, 'value')
|
// 获取当前日期
|
||||||
|
const today = new Date()
|
||||||
|
// 计算7天前的日期
|
||||||
|
const sevenDaysAgo = new Date()
|
||||||
|
sevenDaysAgo.setDate(today.getDate() - 3)
|
||||||
const res = {
|
const res = {
|
||||||
resource_no: value.resource_no ?? '',
|
resource_no: value.resource_no ?? '',
|
||||||
create_after: value.create_after ?? new Date(),
|
create_after: value.create_after ?? sevenDaysAgo,
|
||||||
create_before: value.create_before ?? new Date(),
|
create_before: value.create_before ?? today,
|
||||||
}
|
}
|
||||||
|
|
||||||
const resp = await listAccount(res)
|
const resp = await listAccount(res)
|
||||||
if (!resp.success) {
|
if (!resp.success) {
|
||||||
toast.error('接口请求失败:' + resp.message)
|
toast.error('接口请求失败:' + resp.message)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
resp.data.map((_, i) => {
|
if (!resp.data || resp.data.length === 0) {
|
||||||
let time = new Date()
|
toast.info('没有查询到相关数据')
|
||||||
time = addDays(time, i)
|
setSubmittedData([])
|
||||||
return {
|
return
|
||||||
time: format(time, `YYYY年-MM月-dd日`),
|
}
|
||||||
count: Math.floor(Math.random() * 100) + 1,
|
const formattedData = resp.data.map(item => ({
|
||||||
}
|
...item,
|
||||||
})
|
date: item.date,
|
||||||
setSubmittedData(resp.data)
|
count: item.count,
|
||||||
|
}))
|
||||||
|
|
||||||
|
setSubmittedData(formattedData)
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -146,10 +146,6 @@ const config = {
|
|||||||
label: `套餐使用量`,
|
label: `套餐使用量`,
|
||||||
color: `var(--color-primary)`,
|
color: `var(--color-primary)`,
|
||||||
},
|
},
|
||||||
count2: {
|
|
||||||
label: `次套餐使用量`,
|
|
||||||
color: `#82ca9d`,
|
|
||||||
},
|
|
||||||
} satisfies ChartConfig
|
} satisfies ChartConfig
|
||||||
|
|
||||||
type DashboardChartProps = {
|
type DashboardChartProps = {
|
||||||
@@ -157,26 +153,27 @@ type DashboardChartProps = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function DashboardChart(props: DashboardChartProps) {
|
function DashboardChart(props: DashboardChartProps) {
|
||||||
const chartData = props.data.map(item => ({
|
const chartData = props.data.map((item) => {
|
||||||
...item,
|
const date = new Date(item.date.split('T')[0])
|
||||||
formattedTime: format(new Date(item.time), 'MM-dd'),
|
return {
|
||||||
}))
|
...item,
|
||||||
|
formattedTime: format(date, 'MM-dd'),
|
||||||
|
fullDate: format(date, 'yyyy-MM-dd'),
|
||||||
|
}
|
||||||
|
})
|
||||||
return (
|
return (
|
||||||
<ChartContainer config={config} className="w-full h-full">
|
<ChartContainer config={config} className="w-full h-full">
|
||||||
<AreaChart data={chartData} margin={{top: 0, right: 20, left: 0, bottom: 0}}>
|
<AreaChart data={chartData} margin={{top: 0, right: 20, left: 0, bottom: 0}}>
|
||||||
<CartesianGrid vertical={false}/>
|
<CartesianGrid vertical={false}/>
|
||||||
<XAxis
|
<XAxis
|
||||||
dataKey="formattedTime" // 使用预处理后的字段
|
dataKey="formattedTime"
|
||||||
tickLine={false}
|
tickLine={false}
|
||||||
/>
|
/>
|
||||||
<YAxis tickLine={false}/>
|
<YAxis tickLine={false}/>
|
||||||
<Tooltip
|
<Tooltip
|
||||||
animationDuration={100}
|
animationDuration={100}
|
||||||
labelFormatter={value => `日期: ${format(new Date(value), 'yyyy-MM-dd')}`}
|
labelFormatter={value => `日期: ${chartData.find(item => item.formattedTime === value)?.fullDate || value}`}
|
||||||
formatter={(value, name) => {
|
formatter={value => [`${value}`, '套餐使用量']}
|
||||||
const displayName = name === 'count' ? '主套餐使用量' : '次套餐使用量'
|
|
||||||
return [`${value}`, displayName]
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
<Area
|
<Area
|
||||||
type="monotone"
|
type="monotone"
|
||||||
@@ -185,16 +182,7 @@ function DashboardChart(props: DashboardChartProps) {
|
|||||||
fill="#8884d8"
|
fill="#8884d8"
|
||||||
fillOpacity={0.2}
|
fillOpacity={0.2}
|
||||||
strokeWidth={2}
|
strokeWidth={2}
|
||||||
name="主套餐使用量"
|
name="套餐使用量"
|
||||||
/>
|
|
||||||
<Area
|
|
||||||
type="monotone"
|
|
||||||
dataKey="count2"
|
|
||||||
stroke="#82ca9d"
|
|
||||||
fill="#82ca9d"
|
|
||||||
fillOpacity={0.2}
|
|
||||||
strokeWidth={2}
|
|
||||||
name="次套餐使用量"
|
|
||||||
/>
|
/>
|
||||||
<Legend/>
|
<Legend/>
|
||||||
</AreaChart>
|
</AreaChart>
|
||||||
|
|||||||
@@ -9,12 +9,12 @@ import Charts from './_client/charts'
|
|||||||
import UserCenter from './_client/userCenter'
|
import UserCenter from './_client/userCenter'
|
||||||
import soon from './_assets/coming-soon.svg'
|
import soon from './_assets/coming-soon.svg'
|
||||||
import mask from './_assets/Mask group.webp'
|
import mask from './_assets/Mask group.webp'
|
||||||
|
import {Button} from '@/components/ui/button'
|
||||||
|
|
||||||
export type DashboardPageProps = {}
|
export type DashboardPageProps = {}
|
||||||
|
|
||||||
export default async function DashboardPage(props: DashboardPageProps) {
|
export default async function DashboardPage(props: DashboardPageProps) {
|
||||||
const resp = await listInitialization()
|
const resp = await listInitialization()
|
||||||
console.log(resp, 'respresprespresprespresp')
|
|
||||||
if (!resp.success) {
|
if (!resp.success) {
|
||||||
return (
|
return (
|
||||||
<div className="col-start-4 row-start-3 row-span-2 flex justify-center items-center">
|
<div className="col-start-4 row-start-3 row-span-2 flex justify-center items-center">
|
||||||
@@ -23,16 +23,7 @@ export default async function DashboardPage(props: DashboardPageProps) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
const initData = resp.data
|
const initData = resp.data
|
||||||
// 添加模拟的 usage 数据(如果 API 返回的 usage 为 null)
|
|
||||||
// if (!initData.usage) {
|
|
||||||
// initData.usage = [
|
|
||||||
// {time: new Date('2025-03-01'), count: 100, count2: 80},
|
|
||||||
// {time: new Date('2025-03-02'), count: 150, count2: 120},
|
|
||||||
// {time: new Date('2025-03-03'), count: 80, count2: 64},
|
|
||||||
// {time: new Date('2025-03-04'), count: 200, count2: 160},
|
|
||||||
// {time: new Date('2025-03-05'), count: 120, count2: 96},
|
|
||||||
// ]
|
|
||||||
// }
|
|
||||||
return (
|
return (
|
||||||
<Page className={merge(
|
<Page className={merge(
|
||||||
`flex-auto grid`,
|
`flex-auto grid`,
|
||||||
@@ -169,7 +160,12 @@ function Announcements(props: Props) {
|
|||||||
<CardHeader>
|
<CardHeader>
|
||||||
<div className="flex justify-between gap-2">
|
<div className="flex justify-between gap-2">
|
||||||
<CardTitle>公告</CardTitle>
|
<CardTitle>公告</CardTitle>
|
||||||
<span className="text-sm text-primary font-medium">查看更多</span>
|
{/* <Button
|
||||||
|
theme="text"
|
||||||
|
className="text-sm text-primary font-medium hover:text-primary bg-transparent border-none p-0 cursor-pointer"
|
||||||
|
>
|
||||||
|
查看更多
|
||||||
|
</Button> */}
|
||||||
</div>
|
</div>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent className="flex-auto p-0">
|
<CardContent className="flex-auto p-0">
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ export default function BillsPage(props: BillsPageProps) {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Form form={form} onSubmit={onSubmit} className="flex items-end gap-4 flex-wrap">
|
<Form form={form} onSubmit={onSubmit} className="flex items-end gap-4 flex-wrap">
|
||||||
<FormField name="trade_id" label={<span className="text-sm">订单号</span>}>
|
{/* <FormField name="trade_id" label={<span className="text-sm">订单号</span>}>
|
||||||
{({id, field}) => (
|
{({id, field}) => (
|
||||||
<Input
|
<Input
|
||||||
{...field}
|
{...field}
|
||||||
@@ -100,7 +100,7 @@ export default function BillsPage(props: BillsPageProps) {
|
|||||||
placeholder="输入订单号"
|
placeholder="输入订单号"
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</FormField>
|
</FormField> */}
|
||||||
<FormField name="type" label={<span className="text-sm">账单类型</span>}>
|
<FormField name="type" label={<span className="text-sm">账单类型</span>}>
|
||||||
{({id, field}) => (
|
{({id, field}) => (
|
||||||
<Select value={field.value} onValueChange={field.onChange}>
|
<Select value={field.value} onValueChange={field.onChange}>
|
||||||
|
|||||||
@@ -62,8 +62,7 @@ export default function IdentifyPage(props: IdentifyPageProps) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
console.log(resp.message)
|
toast.error(resp.message || `认证失败:请稍后重试`)
|
||||||
toast.error(`认证信息提交失败:请稍后重试`)
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@@ -169,12 +168,12 @@ export default function IdentifyPage(props: IdentifyPageProps) {
|
|||||||
<div className="flex flex-col gap-4 items-center">
|
<div className="flex flex-col gap-4 items-center">
|
||||||
<canvas ref={canvas} width={256} height={256}/>
|
<canvas ref={canvas} width={256} height={256}/>
|
||||||
<p className="text-sm text-gray-600">请扫码完成认证</p>
|
<p className="text-sm text-gray-600">请扫码完成认证</p>
|
||||||
<Button onClick={async () => {
|
{/* <Button onClick={async () => {
|
||||||
await refreshProfile()
|
await refreshProfile()
|
||||||
setOpenDialog(false)
|
setOpenDialog(false)
|
||||||
}}>
|
}}>
|
||||||
已完成认证
|
已完成认证
|
||||||
</Button>
|
</Button> */}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
|
|||||||
Reference in New Issue
Block a user