feat: chat add chart mode

This commit is contained in:
changhuiping.chp 2023-07-07 15:55:28 +08:00
parent 74deb4d9c2
commit 49a86fae6e
4 changed files with 207 additions and 239 deletions

View File

@ -1,13 +0,0 @@
import { Box } from '@/lib/mui';
export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<>
{children}
</>
)
}

View File

@ -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;

View File

@ -1,10 +1,14 @@
"use client" "use client"
import { useRequest } from 'ahooks'; import { useRequest } from 'ahooks';
import { sendGetRequest, sendPostRequest } from '@/utils/request'; import { sendGetRequest, sendPostRequest } from '@/utils/request';
import { Card, CardContent, Typography, Grid, Table } from "@/lib/mui";
import useAgentChat from '@/hooks/useAgentChat'; import useAgentChat from '@/hooks/useAgentChat';
import ChatBoxComp from '@/components/chatBoxTemp'; import ChatBoxComp from '@/components/chatBoxTemp';
import { useDialogueContext } from '@/app/context/dialogue'; import { useDialogueContext } from '@/app/context/dialogue';
import { useSearchParams } from 'next/navigation'; import { useSearchParams } from 'next/navigation';
import { useMemo } from 'react';
import { Chart, LineAdvance, Interval, Tooltip, getTheme } from "bizcharts";
import lodash from 'lodash';
const AgentPage = () => { const AgentPage = () => {
const searchParams = useSearchParams(); const searchParams = useSearchParams();
@ -33,8 +37,197 @@ const AgentPage = () => {
initHistory: historyList?.data 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 数量 38个暂定每行排序
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 ( 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 <ChatBoxComp
clearIntialMessage={async () => { clearIntialMessage={async () => {
await refreshDialogList(); await refreshDialogList();
@ -43,7 +236,10 @@ const AgentPage = () => {
onSubmit={handleChatSubmit} onSubmit={handleChatSubmit}
paramsList={paramsList?.data} paramsList={paramsList?.data}
/> />
</> </div>
</Grid>
</Grid>
) )
} }

View File

@ -96,7 +96,6 @@ import { useDialogueContext } from '@/app/context/dialogue';
throw new Error(err); throw new Error(err);
}, },
onmessage: (event) => { onmessage: (event) => {
console.log(event, 'e');
event.data = event.data.replaceAll('\\n', '\n'); event.data = event.data.replaceAll('\\n', '\n');
if (event.data === '[DONE]') { if (event.data === '[DONE]') {
@ -129,7 +128,7 @@ import { useDialogueContext } from '@/app/context/dialogue';
}, },
}); });
} catch (err) { } catch (err) {
console.log('---e', err); console.log(err);
setState({ setState({
history: [ history: [