mirror of
https://github.com/csunny/DB-GPT.git
synced 2025-08-22 02:04:37 +00:00
feat: chat add chart mode
This commit is contained in:
parent
74deb4d9c2
commit
49a86fae6e
@ -1,13 +0,0 @@
|
||||
import { Box } from '@/lib/mui';
|
||||
|
||||
export default function RootLayout({
|
||||
children,
|
||||
}: {
|
||||
children: React.ReactNode
|
||||
}) {
|
||||
return (
|
||||
<>
|
||||
{children}
|
||||
</>
|
||||
)
|
||||
}
|
@ -1,214 +0,0 @@
|
||||
"use client"
|
||||
import ChatBoxComp from '@/components/chatBox';
|
||||
import { Chart, LineAdvance, Interval, Tooltip, getTheme } from 'bizcharts';
|
||||
import { Card, CardContent, Typography, Grid, styled, Sheet } from '@/lib/mui';
|
||||
import { Stack } from '@mui/material';
|
||||
import useAgentChat from '@/hooks/useAgentChat';
|
||||
|
||||
|
||||
const Item = styled(Sheet)(({ theme }) => ({
|
||||
...theme.typography.body2,
|
||||
padding: theme.spacing(1),
|
||||
textAlign: 'center',
|
||||
borderRadius: 4,
|
||||
color: theme.vars.palette.text.secondary,
|
||||
}));
|
||||
|
||||
const Agents = () => {
|
||||
const { handleChatSubmit, history } = useAgentChat({
|
||||
queryAgentURL: `/v1/chat/completions`,
|
||||
});
|
||||
|
||||
const data = [
|
||||
{
|
||||
month: "Jan",
|
||||
city: "Tokyo",
|
||||
temperature: 7
|
||||
},
|
||||
{
|
||||
month: "Feb",
|
||||
city: "Tokyo",
|
||||
temperature: 13
|
||||
},
|
||||
{
|
||||
month: "Mar",
|
||||
city: "Tokyo",
|
||||
temperature: 16.5
|
||||
},
|
||||
{
|
||||
month: "Apr",
|
||||
city: "Tokyo",
|
||||
temperature: 14.5
|
||||
},
|
||||
{
|
||||
month: "May",
|
||||
city: "Tokyo",
|
||||
temperature: 10
|
||||
},
|
||||
{
|
||||
month: "Jun",
|
||||
city: "Tokyo",
|
||||
temperature: 7.5
|
||||
},
|
||||
{
|
||||
month: "Jul",
|
||||
city: "Tokyo",
|
||||
temperature: 9.2
|
||||
},
|
||||
{
|
||||
month: "Aug",
|
||||
city: "Tokyo",
|
||||
temperature: 14.5
|
||||
},
|
||||
{
|
||||
month: "Sep",
|
||||
city: "Tokyo",
|
||||
temperature: 9.3
|
||||
},
|
||||
{
|
||||
month: "Oct",
|
||||
city: "Tokyo",
|
||||
temperature: 8.3
|
||||
},
|
||||
{
|
||||
month: "Nov",
|
||||
city: "Tokyo",
|
||||
temperature: 8.9
|
||||
},
|
||||
{
|
||||
month: "Dec",
|
||||
city: "Tokyo",
|
||||
temperature: 5.6
|
||||
},
|
||||
];
|
||||
|
||||
const d1 = [
|
||||
{ year: '1951 年', sales: 0 },
|
||||
{ year: '1952 年', sales: 52 },
|
||||
{ year: '1956 年', sales: 61 },
|
||||
{ year: '1957 年', sales: 45 },
|
||||
{ year: '1958 年', sales: 48 },
|
||||
{ year: '1959 年', sales: 38 },
|
||||
{ year: '1960 年', sales: 38 },
|
||||
{ year: '1962 年', sales: 38 },
|
||||
];
|
||||
|
||||
const topCard = [{
|
||||
label: 'Revenue Won',
|
||||
value: '$7,811,851'
|
||||
}, {
|
||||
label: 'Close %',
|
||||
value: '37.7%'
|
||||
}, {
|
||||
label: 'AVG Days to Close',
|
||||
value: '121'
|
||||
}, {
|
||||
label: 'Opportunities Won',
|
||||
value: '526'
|
||||
}];
|
||||
|
||||
return (
|
||||
<div className='p-4 flex flex-row gap-6 min-h-full w-full'>
|
||||
<div className='flex w-full'>
|
||||
<Grid container spacing={2} sx={{ flexGrow: 1 }}>
|
||||
<Grid xs={8}>
|
||||
<Stack spacing={2} className='h-full'>
|
||||
<Item>
|
||||
<Grid container spacing={2}>
|
||||
{topCard.map((item) => (
|
||||
<Grid key={item.label} xs={3}>
|
||||
<Card className="flex-1 h-full">
|
||||
<CardContent className="justify-around">
|
||||
<Typography gutterBottom component="div">
|
||||
{item.label}
|
||||
</Typography>
|
||||
<Typography>
|
||||
{item.value}
|
||||
</Typography>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</Grid>
|
||||
))}
|
||||
</Grid>
|
||||
</Item>
|
||||
<Item className='flex-1'>
|
||||
<Card className='h-full'>
|
||||
<CardContent className='h-full'>
|
||||
<Typography gutterBottom component="div">
|
||||
Revenue Won by Month
|
||||
</Typography>
|
||||
<div className='flex-1'>
|
||||
<Chart padding={[10, 20, 50, 40]} autoFit data={data} >
|
||||
<LineAdvance
|
||||
shape="smooth"
|
||||
point
|
||||
area
|
||||
position="month*temperature"
|
||||
color="city"
|
||||
/>
|
||||
</Chart>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</Item>
|
||||
<Item className='flex-1'>
|
||||
<Grid container spacing={2} className='h-full'>
|
||||
<Grid xs={4} className='h-full'>
|
||||
<Card className='flex-1 h-full'>
|
||||
<CardContent className='h-full'>
|
||||
<Typography gutterBottom component="div">
|
||||
Close % by Month
|
||||
</Typography>
|
||||
<div className='flex-1'>
|
||||
<Chart autoFit data={d1} >
|
||||
<Interval position="year*sales" style={{ lineWidth: 3, stroke: getTheme().colors10[0] }} />
|
||||
<Tooltip shared />
|
||||
</Chart>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</Grid>
|
||||
<Grid xs={4} className='h-full'>
|
||||
<Card className='flex-1 h-full'>
|
||||
<CardContent className='h-full'>
|
||||
<Typography gutterBottom component="div">
|
||||
Close % by Month
|
||||
</Typography>
|
||||
<div className='flex-1'>
|
||||
<Chart autoFit data={d1} >
|
||||
<Interval position="year*sales" style={{ lineWidth: 3, stroke: getTheme().colors10[0] }} />
|
||||
<Tooltip shared />
|
||||
</Chart>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</Grid>
|
||||
<Grid xs={4} className='h-full'>
|
||||
<Card className='flex-1 h-full'>
|
||||
<CardContent className='h-full'>
|
||||
<Typography gutterBottom component="div">
|
||||
Close % by Month
|
||||
</Typography>
|
||||
<div className='flex-1'>
|
||||
<Chart autoFit data={d1} >
|
||||
<Interval position="year*sales" style={{ lineWidth: 3, stroke: getTheme().colors10[0] }} />
|
||||
<Tooltip shared />
|
||||
</Chart>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Item>
|
||||
</Stack>
|
||||
</Grid>
|
||||
<Grid xs={4}>
|
||||
<ChatBoxComp messages={history} onSubmit={handleChatSubmit}/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Agents;
|
@ -1,10 +1,14 @@
|
||||
"use client"
|
||||
import { useRequest } from 'ahooks';
|
||||
import { sendGetRequest, sendPostRequest } from '@/utils/request';
|
||||
import { Card, CardContent, Typography, Grid, Table } from "@/lib/mui";
|
||||
import useAgentChat from '@/hooks/useAgentChat';
|
||||
import ChatBoxComp from '@/components/chatBoxTemp';
|
||||
import { useDialogueContext } from '@/app/context/dialogue';
|
||||
import { useSearchParams } from 'next/navigation';
|
||||
import { useMemo } from 'react';
|
||||
import { Chart, LineAdvance, Interval, Tooltip, getTheme } from "bizcharts";
|
||||
import lodash from 'lodash';
|
||||
|
||||
const AgentPage = () => {
|
||||
const searchParams = useSearchParams();
|
||||
@ -33,8 +37,197 @@ const AgentPage = () => {
|
||||
initHistory: historyList?.data
|
||||
});
|
||||
|
||||
const chartsData = useMemo(() => {
|
||||
try {
|
||||
const contextTemp = history?.[history.length - 1]?.context;
|
||||
const contextObj = JSON.parse(contextTemp);
|
||||
return contextObj?.template_name === 'sales_report' ? contextObj?.charts : undefined;
|
||||
} catch (e) {
|
||||
return undefined;
|
||||
}
|
||||
}, [history]);
|
||||
|
||||
const chartRows = useMemo(() => {
|
||||
if (chartsData) {
|
||||
let res = [];
|
||||
// 若是有类型为 IndicatorValue 的,提出去,独占一行
|
||||
const chartCalc = chartsData?.filter(
|
||||
(item) => item.chart_type === "IndicatorValue"
|
||||
);
|
||||
if (chartCalc.length > 0) {
|
||||
res.push({
|
||||
rowIndex: res.length,
|
||||
cols: chartCalc,
|
||||
type: "IndicatorValue",
|
||||
});
|
||||
}
|
||||
let otherCharts = chartsData?.filter(
|
||||
(item) => item.chart_type !== "IndicatorValue"
|
||||
);
|
||||
let otherLength = otherCharts.length;
|
||||
let curIndex = 0;
|
||||
// charts 数量 3~8个,暂定每行排序
|
||||
let chartLengthMap = [
|
||||
[0],
|
||||
[1],
|
||||
[2],
|
||||
[1, 2],
|
||||
[1, 3],
|
||||
[2, 1, 2],
|
||||
[2, 1, 3],
|
||||
[3, 1, 3],
|
||||
[3, 2, 3],
|
||||
];
|
||||
let currentRowsSort = chartLengthMap[otherLength];
|
||||
currentRowsSort.forEach((item) => {
|
||||
if (item > 0) {
|
||||
const rowsItem = otherCharts.slice(curIndex, curIndex + item);
|
||||
curIndex = curIndex + item;
|
||||
res.push({
|
||||
rowIndex: res.length,
|
||||
cols: rowsItem,
|
||||
});
|
||||
}
|
||||
});
|
||||
return res;
|
||||
}
|
||||
return undefined;
|
||||
}, [chartsData]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Grid container spacing={2} className="h-full" sx={{ flexGrow: 1 }}>
|
||||
{chartsData && (
|
||||
<Grid xs={8} className="max-h-full">
|
||||
<div className="flex flex-col gap-3 h-full">
|
||||
{chartRows?.map((chartRow) => (
|
||||
<div
|
||||
key={chartRow.rowIndex}
|
||||
className={`${
|
||||
chartRow?.type !== "IndicatorValue"
|
||||
? "flex flex-1 gap-3 overflow-hidden"
|
||||
: ""
|
||||
}`}
|
||||
>
|
||||
{chartRow.cols.map((col) => {
|
||||
if (col.chart_type === "IndicatorValue") {
|
||||
return (
|
||||
<div
|
||||
key={col.chart_uid}
|
||||
className="flex flex-row gap-3"
|
||||
>
|
||||
{col.values.map((item) => (
|
||||
<div key={item.name} className="flex-1">
|
||||
<Card>
|
||||
<CardContent className="justify-around">
|
||||
<Typography gutterBottom component="div">
|
||||
{item.name}
|
||||
</Typography>
|
||||
<Typography>{item.value}</Typography>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
} else if (col.chart_type === "LineChart") {
|
||||
return (
|
||||
<div className="flex-1 overflow-hidden" key={col.chart_uid}>
|
||||
<Card className="h-full">
|
||||
<CardContent className="h-full">
|
||||
<Typography gutterBottom component="div">
|
||||
{col.chart_name}
|
||||
</Typography>
|
||||
<div className="flex-1 h-full">
|
||||
<Chart
|
||||
padding={[10, 20, 50, 40]}
|
||||
autoFit
|
||||
data={col.values}
|
||||
>
|
||||
<LineAdvance
|
||||
shape="smooth"
|
||||
point
|
||||
area
|
||||
position="name*value"
|
||||
color="type"
|
||||
/>
|
||||
</Chart>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
);
|
||||
} else if (col.chart_type === "BarChart") {
|
||||
return (
|
||||
<div className="flex-1" key={col.chart_uid}>
|
||||
<Card className="h-full">
|
||||
<CardContent className="h-full">
|
||||
<Typography gutterBottom component="div">
|
||||
{col.chart_name}
|
||||
</Typography>
|
||||
<div className="flex-1">
|
||||
<Chart autoFit data={col.values}>
|
||||
<Interval
|
||||
position="name*value"
|
||||
style={{
|
||||
lineWidth: 3,
|
||||
stroke: getTheme().colors10[0],
|
||||
}}
|
||||
/>
|
||||
<Tooltip shared />
|
||||
</Chart>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
);
|
||||
} else if (col.chart_type === 'Table') {
|
||||
const data = lodash.groupBy(col.values, 'type');
|
||||
return (
|
||||
<div className="flex-1" key={col.chart_uid}>
|
||||
<Card className="h-full overflow-auto">
|
||||
|
||||
<CardContent className="h-full">
|
||||
<Typography gutterBottom component="div">
|
||||
{col.chart_name}
|
||||
</Typography>
|
||||
<div className="flex-1">
|
||||
<Table
|
||||
aria-label="basic table"
|
||||
stripe="odd"
|
||||
hoverRow
|
||||
borderAxis="bothBetween"
|
||||
>
|
||||
<thead>
|
||||
<tr>
|
||||
{Object.keys(data).map(key => (
|
||||
<th key={key}>{key}</th>
|
||||
))}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{Object.values(data)?.[0]?.map((value, i) => (
|
||||
<tr key={i}>
|
||||
{Object.keys(data)?.map(k => (
|
||||
<td key={k}>{data?.[k]?.[i].value || ''}</td>
|
||||
))}
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</Table>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
})}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</Grid>
|
||||
)}
|
||||
<Grid xs={chartsData ? 4 : 12} className="h-full max-h-full">
|
||||
<div className='h-full' style={{ boxShadow: chartsData ? '0px 0px 9px 0px #c1c0c080' : 'unset' }}>
|
||||
<ChatBoxComp
|
||||
clearIntialMessage={async () => {
|
||||
await refreshDialogList();
|
||||
@ -43,7 +236,10 @@ const AgentPage = () => {
|
||||
onSubmit={handleChatSubmit}
|
||||
paramsList={paramsList?.data}
|
||||
/>
|
||||
</>
|
||||
</div>
|
||||
</Grid>
|
||||
|
||||
</Grid>
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -96,7 +96,6 @@ import { useDialogueContext } from '@/app/context/dialogue';
|
||||
throw new Error(err);
|
||||
},
|
||||
onmessage: (event) => {
|
||||
console.log(event, 'e');
|
||||
event.data = event.data.replaceAll('\\n', '\n');
|
||||
|
||||
if (event.data === '[DONE]') {
|
||||
@ -129,7 +128,7 @@ import { useDialogueContext } from '@/app/context/dialogue';
|
||||
},
|
||||
});
|
||||
} catch (err) {
|
||||
console.log('---e', err);
|
||||
console.log(err);
|
||||
|
||||
setState({
|
||||
history: [
|
||||
|
Loading…
Reference in New Issue
Block a user