Commit 5c916b48 authored by 熊洋洋's avatar 熊洋洋

feat: add data handle

parent 92794da9
...@@ -11,10 +11,10 @@ export interface View { ...@@ -11,10 +11,10 @@ export interface View {
} }
export default class getView { export default class getView {
static getViewComponent(params: { static getViewComponent(params: { props: Record<string, any>; need: string }) {
props: Record<string, any>,
need: string
}) {
return backendApi.post('/openAi/api/reactLive', params); return backendApi.post('/openAi/api/reactLive', params);
} }
static getViewFunction(params: { data: Record<string, any>; need: string }) {
return backendApi.post('/openAi/api/code', params);
}
} }
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
"@arco-design/web-react": "^2.45.0", "@arco-design/web-react": "^2.45.0",
"@dbml/core": "^2.5.1", "@dbml/core": "^2.5.1",
"@digitalocean/do-markdownit": "^1.9.0", "@digitalocean/do-markdownit": "^1.9.0",
"@koale/useworker": "^4.0.2",
"@microsoft/fetch-event-source": "^2.0.1", "@microsoft/fetch-event-source": "^2.0.1",
"@monaco-editor/react": "^4.4.5", "@monaco-editor/react": "^4.4.5",
"@next/font": "13.1.6", "@next/font": "13.1.6",
...@@ -45,6 +46,7 @@ ...@@ -45,6 +46,7 @@
"react-hook-speech-to-text": "^0.8.0", "react-hook-speech-to-text": "^0.8.0",
"react-hotkeys-hook": "^4.3.7", "react-hotkeys-hook": "^4.3.7",
"react-i18next": "^12.3.1", "react-i18next": "^12.3.1",
"react-json-view": "^1.21.3",
"react-live-runner": "^1.0.5", "react-live-runner": "^1.0.5",
"reactflow": "^11.5.6", "reactflow": "^11.5.6",
"redaxios": "^0.5.1", "redaxios": "^0.5.1",
...@@ -53,8 +55,7 @@ ...@@ -53,8 +55,7 @@
"swr": "^2.0.3", "swr": "^2.0.3",
"tailwindcss": "^3.2.7", "tailwindcss": "^3.2.7",
"typescript": "4.9.5", "typescript": "4.9.5",
"unstated-next": "^1.1.0", "unstated-next": "^1.1.0"
"wasm-jseval": "^0.1.2"
}, },
"resolutions": { "resolutions": {
"postcss": "^8.4.14" "postcss": "^8.4.14"
...@@ -65,5 +66,10 @@ ...@@ -65,5 +66,10 @@
}, },
"engines": { "engines": {
"node": "18" "node": "18"
},
"browser": {
"fs": false,
"os": false,
"path": false
} }
} }
\ No newline at end of file
import { Button, Card, Spin } from '@arco-design/web-react'; import { Button, Card, Collapse, Spin } from '@arco-design/web-react';
import { IconCode, IconEye, IconRefresh, IconSend, IconSwap } from '@arco-design/web-react/icon'; import { IconCode, IconEye, IconRefresh, IconSend, IconSwap } from '@arco-design/web-react/icon';
import React, { ReactElement, memo, useCallback, useMemo, useRef, useState } from 'react'; import React, {
ReactElement,
memo,
useCallback,
useEffect,
useMemo,
useRef,
useState,
} from 'react';
import { import {
LiveEditor, LiveEditor,
LiveError, LiveError,
...@@ -16,8 +24,17 @@ import AI from '@/components/AITool'; ...@@ -16,8 +24,17 @@ import AI from '@/components/AITool';
import useSWRMutation from 'swr/mutation'; import useSWRMutation from 'swr/mutation';
import getView from '@/client/api/getView'; import getView from '@/client/api/getView';
import { nanoid } from 'nanoid'; import { nanoid } from 'nanoid';
import { get } from 'lodash'; import { get, isEqual } from 'lodash';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import Editor, { Monaco, useMonaco, OnMount } from '@monaco-editor/react';
import { XML } from '@/utils/getXMLContent';
import { useWorker } from '@koale/useworker';
import dynamic from 'next/dynamic';
const ReactJson = dynamic(() => import('react-json-view'), { ssr: false });
const CollapseItem = Collapse.Item;
type MonacoEditor = Parameters<OnMount>[0];
function Error() { function Error() {
const { error } = useLiveContext(); const { error } = useLiveContext();
...@@ -27,7 +44,7 @@ function Error() { ...@@ -27,7 +44,7 @@ function Error() {
export function ChatView({ export function ChatView({
defaultNode, defaultNode,
props, props: propsRaw,
}: { }: {
defaultNode?: ReactElement; defaultNode?: ReactElement;
props: Record<string, any>; props: Record<string, any>;
...@@ -35,6 +52,12 @@ export function ChatView({ ...@@ -35,6 +52,12 @@ export function ChatView({
const [showCode, setShowCode] = useState(true); const [showCode, setShowCode] = useState(true);
const reqRef = useRef(nanoid()); const reqRef = useRef(nanoid());
const [showTable, setShowTable] = useState(false); const [showTable, setShowTable] = useState(false);
const [props, setProps] = useState(propsRaw);
useEffect(() => {
setProps(propsRaw);
}, [propsRaw]);
const { trigger, data, isMutating } = useSWRMutation(reqRef.current, (_, { arg: { need } }) => { const { trigger, data, isMutating } = useSWRMutation(reqRef.current, (_, { arg: { need } }) => {
return getView.getViewComponent({ return getView.getViewComponent({
props, props,
...@@ -100,8 +123,122 @@ export function ChatView({ ...@@ -100,8 +123,122 @@ export function ChatView({
); );
}, [example, props, showCode]); }, [example, props, showCode]);
const [editor, setEditor] = useState<MonacoEditor>();
const monaco = useMonaco();
const [workerFn, { status: workerStatus, kill: workerTerminate }] = useWorker(
(data, code) => {
return new Function('data', code)(data);
},
{
autoTerminate: false,
}
);
console.log(workerStatus, 'workerStatus');
const onKeyDown = editor?.onKeyDown!;
const KeyDownEvent = useRef<ReturnType<typeof onKeyDown>>();
useEffect(() => {
if (editor) {
if (KeyDownEvent.current) {
KeyDownEvent.current.dispose();
}
KeyDownEvent.current = editor.onKeyDown(function (event: any) {
if (event.keyCode === 2 && monaco) {
const position = editor.getPosition();
const line = editor.getModel()?.getLineContent(position!.lineNumber) || '';
const flag = /^\/\//;
if (flag.test(line)) {
// 在当前行后面提示“生成中”占位符
const position = editor.getPosition()!;
const lineNumber = position.lineNumber;
const column = position.column;
const insertText = ' 代码生成中,请稍后...';
const op = {
range: new monaco.Range(lineNumber, column, lineNumber, column),
text: insertText,
};
editor.executeEdits('insertSnippet', [op]);
getView
.getViewFunction({
data: props,
need: line.replace(flag, ''),
})
.then((data: any) => {
const code = get(data, 'data.code');
const xml = new XML(code);
const insertText = xml.get('FunctionCode');
const nextLineNumber = lineNumber + 1;
console.log(insertText);
const op1 = {
range: new monaco.Range(
lineNumber,
0,
lineNumber,
column + insertText.length
),
text: line,
};
const op2 = {
range: new monaco.Range(nextLineNumber, 1, nextLineNumber, 1),
text: insertText.trim() + '\n\n',
};
editor.executeEdits('insertSnippet', [op1, op2]);
});
}
}
});
}
}, [editor, props]);
return ( return (
<div> <div>
<div className="w-full mb-[20px]">
<Collapse style={{ maxWidth: 1180 }}>
<CollapseItem
header="数据处理"
name="1"
extra={
<Button
onClick={async () => {
const data = await workerFn(
propsRaw,
`${editor.getValue()};\n return handler(data);`
);
console.log(data);
setProps(data);
}}
type="primary"
size="mini"
>
Run
</Button>
}
>
<Editor
onMount={(instance, monaco) => {
console.log(instance);
setEditor(instance);
}}
height="300px"
defaultLanguage="javascript"
defaultValue={`/**
* @description 处理数据的函数
* @param record<string,any> data
*/
function handler(data){
return data
}
`}
/>
</CollapseItem>
</Collapse>
</div>
<div className="flex justify-between items-center mb-[20px]"> <div className="flex justify-between items-center mb-[20px]">
<AI <AI
simpleMode="input" simpleMode="input"
...@@ -137,8 +274,10 @@ export function ChatView({ ...@@ -137,8 +274,10 @@ export function ChatView({
</div> </div>
<div className="overflow-hidden">{Live}</div> <div className="overflow-hidden">{Live}</div>
</div> </div>
) : ( ) : isEqual(props, propsRaw) ? (
defaultNode || null defaultNode || null
) : (
<ReactJson src={props} />
)} )}
</Spin> </Spin>
</div> </div>
......
...@@ -10,7 +10,6 @@ import Link from 'next/link'; ...@@ -10,7 +10,6 @@ import Link from 'next/link';
import { useTranslation, Trans } from 'react-i18next'; import { useTranslation, Trans } from 'react-i18next';
function Home() { function Home() {
const { data } = useSWR('getTableList', () => getSchema.getTableList({ type: 'schema' }));
const { t } = useTranslation(); const { t } = useTranslation();
return ( return (
<> <>
......
This diff is collapsed.
...@@ -89,7 +89,11 @@ body[arco-theme=dark] { ...@@ -89,7 +89,11 @@ body[arco-theme=dark] {
.view-lines, .view-lines,
.decorationsOverviewRuler, .decorationsOverviewRuler,
.invisible { .invisible {
background: rgb(233, 242, 241); background: rgb(233, 242, 241,0.4);
}
.selected-text{
background:rgba(255, 166, 0, 0.53) !important;
} }
.slider.slider { .slider.slider {
......
export class XML {
private root: HTMLDivElement;
constructor(code: string) {
this.root = document.createElement('div');
this.root.innerHTML = code;
}
get(code: string): string {
const insertText =
(this.root.querySelector('FunctionCode') as HTMLElement)?.outerText || '';
return insertText;
}
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment