add prompt js page
This commit is contained in:
parent
d53c18606e
commit
3da62fd254
@ -4,6 +4,9 @@ import { App as ContainerApp } from './pages/container';
|
|||||||
import { App as PanelApp } from './pages/panel';
|
import { App as PanelApp } from './pages/panel';
|
||||||
import { App as PublishApp } from './pages/publish';
|
import { App as PublishApp } from './pages/publish';
|
||||||
import { App as CodeEditorApp } from './pages/code-editor';
|
import { App as CodeEditorApp } from './pages/code-editor';
|
||||||
|
import { App as MapApp } from './pages/map';
|
||||||
|
import { App as PromptApp } from './pages/prompt';
|
||||||
|
|
||||||
import '@abearxiong/container/dist/container.css';
|
import '@abearxiong/container/dist/container.css';
|
||||||
|
|
||||||
export const App = () => {
|
export const App = () => {
|
||||||
@ -20,6 +23,8 @@ export const App = () => {
|
|||||||
<Route path='/panel/*' element={<PanelApp />} />
|
<Route path='/panel/*' element={<PanelApp />} />
|
||||||
<Route path='/publish/*' element={<PublishApp />} />
|
<Route path='/publish/*' element={<PublishApp />} />
|
||||||
<Route path='/code-editor' element={<CodeEditorApp />} />
|
<Route path='/code-editor' element={<CodeEditorApp />} />
|
||||||
|
<Route path='/map/*' element={<MapApp />} />
|
||||||
|
<Route path='/prompt/*' element={<PromptApp />} />
|
||||||
<Route path='/404' element={<div>404</div>} />
|
<Route path='/404' element={<div>404</div>} />
|
||||||
<Route path='*' element={<div>404</div>} />
|
<Route path='*' element={<div>404</div>} />
|
||||||
</Routes>
|
</Routes>
|
||||||
|
BIN
src/assets/fonts/D-DIN/D-DIN-Bold.woff
Normal file
BIN
src/assets/fonts/D-DIN/D-DIN-Bold.woff
Normal file
Binary file not shown.
BIN
src/assets/fonts/D-DIN/D-DIN-Italic.woff
Normal file
BIN
src/assets/fonts/D-DIN/D-DIN-Italic.woff
Normal file
Binary file not shown.
BIN
src/assets/fonts/D-DIN/D-DIN.woff
Normal file
BIN
src/assets/fonts/D-DIN/D-DIN.woff
Normal file
Binary file not shown.
BIN
src/assets/fonts/D-DIN/D-DINCondensed-Bold.woff
Normal file
BIN
src/assets/fonts/D-DIN/D-DINCondensed-Bold.woff
Normal file
Binary file not shown.
BIN
src/assets/fonts/D-DIN/D-DINCondensed.woff
Normal file
BIN
src/assets/fonts/D-DIN/D-DINCondensed.woff
Normal file
Binary file not shown.
BIN
src/assets/fonts/D-DIN/D-DINExp-Bold.woff
Normal file
BIN
src/assets/fonts/D-DIN/D-DINExp-Bold.woff
Normal file
Binary file not shown.
BIN
src/assets/fonts/D-DIN/D-DINExp-Italic.woff
Normal file
BIN
src/assets/fonts/D-DIN/D-DINExp-Italic.woff
Normal file
Binary file not shown.
BIN
src/assets/fonts/D-DIN/D-DINExp.woff
Normal file
BIN
src/assets/fonts/D-DIN/D-DINExp.woff
Normal file
Binary file not shown.
64
src/assets/fonts/D-DIN/font.css
Normal file
64
src/assets/fonts/D-DIN/font.css
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
/* #### Generated By: http://www.cufonfonts.com #### */
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: 'D-DIN';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: normal;
|
||||||
|
src: url('D-DIN.woff') format('woff');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: 'D-DIN-Italic';
|
||||||
|
font-style: italic;
|
||||||
|
font-weight: normal;
|
||||||
|
src: url('D-DIN-Italic.woff') format('woff');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: 'D-DIN-Bold';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: bold;
|
||||||
|
src: url('D-DIN-Bold.woff') format('woff');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: 'D-DIN Condensed';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: normal;
|
||||||
|
src: url('D-DINCondensed.woff') format('woff');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: 'D-DIN Exp';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: normal;
|
||||||
|
src: url('D-DINExp.woff') format('woff');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: 'D-DIN Exp-Italic';
|
||||||
|
font-style: italic;
|
||||||
|
font-weight: normal;
|
||||||
|
src: url('D-DINExp-Italic.woff') format('woff');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: 'D-DIN Condensed-Bold';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: bold;
|
||||||
|
src: url('D-DINCondensed-Bold.woff') format('woff');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: 'D-DIN Exp-Bold';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: bold;
|
||||||
|
src: url('D-DINExp-Bold.woff') format('woff');
|
||||||
|
}
|
Binary file not shown.
BIN
src/assets/fonts/Montserrat/Montserrat-VariableFont_wght.ttf
Normal file
BIN
src/assets/fonts/Montserrat/Montserrat-VariableFont_wght.ttf
Normal file
Binary file not shown.
16
src/assets/fonts/Montserrat/font.css
Normal file
16
src/assets/fonts/Montserrat/font.css
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
/* #### Generated By: http://www.cufonfonts.com #### */
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Montserrat';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 100 900;
|
||||||
|
src: url('Montserrat-VariableFont_wght.ttf') format('truetype');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Montserrat-Italic';
|
||||||
|
font-style: italic;
|
||||||
|
font-weight: 100 900;
|
||||||
|
src: url('Montserrat-Italic-VariableFont_wght.ttf') format('truetype');
|
||||||
|
}
|
BIN
src/assets/fonts/Orbitron/Orbitron-VariableFont_wght.ttf
Normal file
BIN
src/assets/fonts/Orbitron/Orbitron-VariableFont_wght.ttf
Normal file
Binary file not shown.
6
src/assets/fonts/Orbitron/font.css
Normal file
6
src/assets/fonts/Orbitron/font.css
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
@font-face {
|
||||||
|
font-family: 'Orbitron';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 400 900;
|
||||||
|
src: url('Orbitron-VariableFont_wght.ttf') format('truetype');
|
||||||
|
}
|
3
src/assets/fonts/font.css
Normal file
3
src/assets/fonts/font.css
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
@import "./D-DIN/font.css";
|
||||||
|
@import "./Montserrat/font.css";
|
||||||
|
@import "./Orbitron/font.css";
|
@ -1,3 +1,5 @@
|
|||||||
|
@import './fonts/font.css';
|
||||||
|
|
||||||
.scrollbar {
|
.scrollbar {
|
||||||
/* 整个滚动条 */
|
/* 整个滚动条 */
|
||||||
&::-webkit-scrollbar {
|
&::-webkit-scrollbar {
|
||||||
@ -14,7 +16,7 @@
|
|||||||
/* 滚动条滑块(竖向:vertical 横向:horizontal) */
|
/* 滚动条滑块(竖向:vertical 横向:horizontal) */
|
||||||
&::-webkit-scrollbar-thumb {
|
&::-webkit-scrollbar-thumb {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
background-color: black;
|
background-color: #c1c1c1;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,4 +12,7 @@
|
|||||||
h3 {
|
h3 {
|
||||||
@apply text-lg font-bold;
|
@apply text-lg font-bold;
|
||||||
}
|
}
|
||||||
|
.layout-menu {
|
||||||
|
@apply bg-gray-900 p-2 text-white flex justify-between h-12;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,3 +10,34 @@ body {
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.w-tc-editor, .w-tc-editor > textarea {
|
||||||
|
/* 整个滚动条 */
|
||||||
|
&::-webkit-scrollbar {
|
||||||
|
width: 3px;
|
||||||
|
height: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 滚动条有滑块的轨道部分 */
|
||||||
|
&::-webkit-scrollbar-track-piece {
|
||||||
|
background-color: transparent;
|
||||||
|
border-radius: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 滚动条滑块(竖向:vertical 横向:horizontal) */
|
||||||
|
&::-webkit-scrollbar-thumb {
|
||||||
|
cursor: pointer;
|
||||||
|
background-color: #c1c1c1;
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 滚动条滑块hover */
|
||||||
|
&::-webkit-scrollbar-thumb:hover {
|
||||||
|
background-color: #999999;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 同时有垂直和水平滚动条时交汇的部分 */
|
||||||
|
&::-webkit-scrollbar-corner {
|
||||||
|
display: block; /* 修复交汇时出现的白块 */
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,5 @@
|
|||||||
import CodeEditor from '@uiw/react-textarea-code-editor';
|
import CodeEditor from '@uiw/react-textarea-code-editor';
|
||||||
|
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { clsx } from 'clsx';
|
import { clsx } from 'clsx';
|
||||||
|
|
||||||
@ -7,29 +8,35 @@ type Props = {
|
|||||||
onChange?: (data: string) => void;
|
onChange?: (data: string) => void;
|
||||||
readonly?: boolean;
|
readonly?: boolean;
|
||||||
className?: string;
|
className?: string;
|
||||||
|
style?: React.CSSProperties;
|
||||||
|
language?: string;
|
||||||
|
listen?: boolean;
|
||||||
};
|
};
|
||||||
export const TextArea = (props: Props) => {
|
export const TextArea = (props: Props) => {
|
||||||
const [code, setCode] = useState<string>('');
|
const [code, setCode] = useState<string>('');
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setCode(props.value || '');
|
setCode(props.value || '');
|
||||||
}, []);
|
}, [props.value]);
|
||||||
const _onChange = (value: string) => {
|
const _onChange = (value: string) => {
|
||||||
setCode(value);
|
setCode(value);
|
||||||
props.onChange && props.onChange(value);
|
if (props.onChange) {
|
||||||
|
props.onChange(value);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<div className={clsx('min-h-16 max-h-52 overflow-scroll p-1 ', props.className)}>
|
<div className={clsx('min-h-16 max-h-52 overflow-scroll scrollbar p-1 ', props.className)}>
|
||||||
<CodeEditor
|
<CodeEditor
|
||||||
value={code}
|
value={code}
|
||||||
language='js'
|
language='js'
|
||||||
className='border rounded-sm'
|
className='border rounded-sm '
|
||||||
readOnly={props.readonly}
|
readOnly={props.readonly}
|
||||||
placeholder='Please enter JS code.'
|
placeholder='Please enter JS code.'
|
||||||
onChange={(evn) => _onChange(evn.target.value)}
|
onChange={(evn) => _onChange(evn.target.value)}
|
||||||
padding={10}
|
padding={10}
|
||||||
style={{
|
style={{
|
||||||
backgroundColor: '#f5f5f5',
|
// backgroundColor: '#f5f5f5',
|
||||||
fontFamily: 'ui-monospace,SFMono-Regular,SF Mono,Consolas,Liberation Mono,Menlo,monospace',
|
fontFamily: 'ui-monospace,SFMono-Regular,SF Mono,Consolas,Liberation Mono,Menlo,monospace',
|
||||||
|
...props.style,
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
import { Button, Input, message, Modal, Table } from 'antd';
|
import { Button, Input, message, Modal, Table } from 'antd';
|
||||||
import { useEffect, useState } from 'react';
|
import { Fragment, useEffect, useMemo, useState } from 'react';
|
||||||
import { TextArea } from '../components/TextArea';
|
import { TextArea } from '../components/TextArea';
|
||||||
import { useContainerStore } from '../store';
|
import { useContainerStore } from '../store';
|
||||||
import { useShallow } from 'zustand/react/shallow';
|
import { useShallow } from 'zustand/react/shallow';
|
||||||
import { Form } from 'antd';
|
import { Form } from 'antd';
|
||||||
import copy from 'copy-to-clipboard';
|
import copy from 'copy-to-clipboard';
|
||||||
import { useNavigate } from 'react-router';
|
import { useNavigate } from 'react-router';
|
||||||
|
import { EditOutlined, SettingOutlined, LinkOutlined, SaveOutlined, DeleteOutlined, LeftOutlined } from '@ant-design/icons';
|
||||||
|
import clsx from 'clsx';
|
||||||
const FormModal = () => {
|
const FormModal = () => {
|
||||||
const [form] = Form.useForm();
|
const [form] = Form.useForm();
|
||||||
const containerStore = useContainerStore(
|
const containerStore = useContainerStore(
|
||||||
@ -22,8 +24,6 @@ const FormModal = () => {
|
|||||||
const open = containerStore.showEdit;
|
const open = containerStore.showEdit;
|
||||||
if (open) {
|
if (open) {
|
||||||
form.setFieldsValue(containerStore.formData || {});
|
form.setFieldsValue(containerStore.formData || {});
|
||||||
} else {
|
|
||||||
form.resetFields();
|
|
||||||
}
|
}
|
||||||
}, [containerStore.showEdit]);
|
}, [containerStore.showEdit]);
|
||||||
const onFinish = async (values: any) => {
|
const onFinish = async (values: any) => {
|
||||||
@ -59,7 +59,12 @@ const FormModal = () => {
|
|||||||
<Input />
|
<Input />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item name='code' label='code'>
|
<Form.Item name='code' label='code'>
|
||||||
<TextArea value={containerStore.formData.code} />
|
<TextArea
|
||||||
|
value={containerStore.formData.code}
|
||||||
|
style={{
|
||||||
|
height: '200px',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item label=' ' colon={false}>
|
<Form.Item label=' ' colon={false}>
|
||||||
<Button type='primary' htmlType='submit'>
|
<Button type='primary' htmlType='submit'>
|
||||||
@ -85,111 +90,122 @@ export const ContainerList = () => {
|
|||||||
getList: state.getList,
|
getList: state.getList,
|
||||||
loading: state.loading,
|
loading: state.loading,
|
||||||
publishData: state.publishData,
|
publishData: state.publishData,
|
||||||
|
updateData: state.updateData,
|
||||||
|
formData: state.formData,
|
||||||
};
|
};
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
const [codeEdit, setCodeEdit] = useState(false);
|
||||||
|
const [code, setCode] = useState('');
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
containerStore.getList();
|
containerStore.getList();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const columns = [
|
const onAdd = () => {
|
||||||
{
|
containerStore.setFormData({});
|
||||||
title: 'ID',
|
containerStore.setShowEdit(true);
|
||||||
dataIndex: 'id',
|
};
|
||||||
render: (text: string) => {
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
className='w-40 truncate cursor-pointer'
|
|
||||||
title={text}
|
|
||||||
onClick={() => {
|
|
||||||
copy(text);
|
|
||||||
message.success('copy success');
|
|
||||||
}}>
|
|
||||||
{text}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'Title',
|
|
||||||
dataIndex: 'title',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'Code',
|
|
||||||
dataIndex: 'code',
|
|
||||||
width: '40%',
|
|
||||||
render: (text: string, record: any) => {
|
|
||||||
return <TextArea value={text} readonly />;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'Source',
|
|
||||||
dataIndex: 'source',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'Operation',
|
|
||||||
dataIndex: 'operation',
|
|
||||||
render: (text: string, record: any) => {
|
|
||||||
return (
|
|
||||||
<div className='flex gap-2'>
|
|
||||||
<Button
|
|
||||||
type='primary'
|
|
||||||
onClick={() => {
|
|
||||||
containerStore.setFormData(record);
|
|
||||||
containerStore.setShowEdit(true);
|
|
||||||
}}>
|
|
||||||
Edit
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
onClick={() => {
|
|
||||||
navicate('/container/preview/' + record.id);
|
|
||||||
}}>
|
|
||||||
Preview
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
onClick={() => {
|
|
||||||
containerStore.publishData(record);
|
|
||||||
}}>
|
|
||||||
Publish
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
danger
|
|
||||||
onClick={() => {
|
|
||||||
containerStore.deleteData(record.id);
|
|
||||||
}}>
|
|
||||||
Delete
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
];
|
|
||||||
return (
|
return (
|
||||||
<div className='w-full h-full flex flex-col'>
|
<div className='w-full h-full flex flex-col'>
|
||||||
<div className='mb-2 w-full p-2 bg-white rounded-lg'>
|
<div className='flex flex-grow overflow-hidden h-full'>
|
||||||
<Button
|
<div className='flex-grow overflow-auto scrollbar bg-gray-100'>
|
||||||
className='w-20 '
|
<div className='flex flex-wrap gap-x-10 gap-y-4 rounded pt-10 justify-center'>
|
||||||
type='primary'
|
{containerStore.list.length > 0 &&
|
||||||
onClick={() => {
|
containerStore.list.map((item) => {
|
||||||
containerStore.setFormData({});
|
return (
|
||||||
containerStore.setShowEdit(true);
|
<Fragment key={item.id}>
|
||||||
}}>
|
<div
|
||||||
Add
|
className='flex text-sm gap flex-col w-[400px] max-h-[400px] bg-white p-4 rounded-lg'
|
||||||
</Button>
|
key={item.id}
|
||||||
|
onClick={() => {
|
||||||
|
setCode(item.code);
|
||||||
|
containerStore.setFormData(item);
|
||||||
|
setCodeEdit(true);
|
||||||
|
}}>
|
||||||
|
<div className='px-4 cursor-pointer'>
|
||||||
|
<div
|
||||||
|
className='font-bold'
|
||||||
|
onClick={(e) => {
|
||||||
|
copy(item.code);
|
||||||
|
e.stopPropagation();
|
||||||
|
message.success('copy code success');
|
||||||
|
}}>
|
||||||
|
{item.title || '-'}
|
||||||
|
</div>
|
||||||
|
<div className='font-light'>{item.description ? item.description : '-'}</div>
|
||||||
|
</div>
|
||||||
|
<div className='w-full text-xs'>
|
||||||
|
<TextArea className='max-h-[240px] scrollbar' value={item.code} readonly />
|
||||||
|
</div>
|
||||||
|
<div className='flex mt-2 '>
|
||||||
|
<Button.Group>
|
||||||
|
<Button onClick={() => containerStore.publishData(item)} icon={<SettingOutlined />}></Button>
|
||||||
|
<Button
|
||||||
|
onClick={(e) => {
|
||||||
|
containerStore.setFormData(item);
|
||||||
|
containerStore.setShowEdit(true);
|
||||||
|
setCodeEdit(false);
|
||||||
|
e.stopPropagation();
|
||||||
|
}}
|
||||||
|
icon={<EditOutlined />}></Button>
|
||||||
|
<Button
|
||||||
|
onClick={(e) => {
|
||||||
|
// navicate('/container/preview/' + item.id);
|
||||||
|
window.open('/container/preview/' + item.id);
|
||||||
|
e.stopPropagation();
|
||||||
|
}}
|
||||||
|
icon={<LinkOutlined />}></Button>
|
||||||
|
<Button
|
||||||
|
onClick={(e) => {
|
||||||
|
containerStore.deleteData(item.id);
|
||||||
|
e.stopPropagation();
|
||||||
|
}}
|
||||||
|
icon={<DeleteOutlined />}></Button>
|
||||||
|
</Button.Group>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Fragment>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
{new Array(4).fill(0).map((_, index) => {
|
||||||
|
return <div key={index} className='w-[400px]'></div>;
|
||||||
|
})}
|
||||||
|
{containerStore.list.length == 0 && (
|
||||||
|
<div className='text-center' key={'no-data'}>
|
||||||
|
No Data
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className={clsx('bg-gray-100 border-l border-bg-slate-300 w-[600px] flex-shrink-0', !codeEdit && 'hidden')}>
|
||||||
|
<div className='bg-white p-2'>
|
||||||
|
<div className='mt-2 ml-2 flex gap-2'>
|
||||||
|
<Button
|
||||||
|
onClick={() => {
|
||||||
|
setCodeEdit(false);
|
||||||
|
containerStore.setFormData({});
|
||||||
|
}}
|
||||||
|
icon={<LeftOutlined />}></Button>
|
||||||
|
<Button
|
||||||
|
onClick={() => {
|
||||||
|
console.log('save', containerStore.formData);
|
||||||
|
containerStore.updateData({ ...containerStore.formData, code });
|
||||||
|
}}
|
||||||
|
icon={<SaveOutlined />}></Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className='h-[94%] p-2 rounded-2 shadow-sm'>
|
||||||
|
<TextArea
|
||||||
|
value={code}
|
||||||
|
onChange={(value) => {
|
||||||
|
setCode(value);
|
||||||
|
}}
|
||||||
|
className='h-full max-h-full scrollbar'
|
||||||
|
style={{ overflow: 'auto' }}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className='flex-grow overflow-scroll'>
|
|
||||||
<Table
|
|
||||||
pagination={false}
|
|
||||||
scroll={{
|
|
||||||
y: 600,
|
|
||||||
}}
|
|
||||||
loading={containerStore.loading}
|
|
||||||
dataSource={containerStore.list}
|
|
||||||
rowKey='id'
|
|
||||||
columns={columns}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className='h-2'></div>
|
|
||||||
<FormModal />
|
<FormModal />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -1,17 +1,17 @@
|
|||||||
import { Navigate, Route, Routes } from 'react-router-dom';
|
import { Navigate, Route, Routes } from 'react-router-dom';
|
||||||
import { ContainerList } from './edit/List';
|
import { ContainerList } from './edit/List';
|
||||||
import { Main } from './layouts';
|
import { Main } from './layouts';
|
||||||
import { Preview } from './preview';
|
import { Preview, PreviewWrapper } from './preview';
|
||||||
export const App = () => {
|
export const App = () => {
|
||||||
return (
|
return (
|
||||||
<Routes>
|
<Routes>
|
||||||
<Route element={<Main />}>
|
<Route element={<Main />}>
|
||||||
<Route path='/' element={<Navigate to='/container/edit/list' />}></Route>
|
<Route path='/' element={<Navigate to='/container/edit/list' />}></Route>
|
||||||
<Route path='edit/list' element={<ContainerList />} />
|
<Route path='edit/list' element={<ContainerList />} />
|
||||||
<Route path='preview/:id' element={<Preview />} />
|
<Route path='preview/:id/wrapper' element={<PreviewWrapper />} />
|
||||||
|
|
||||||
<Route path='/' element={<div>Home</div>} />
|
<Route path='/' element={<div>Home</div>} />
|
||||||
</Route>
|
</Route>
|
||||||
|
<Route path='preview/:id' element={<Preview />} />
|
||||||
</Routes>
|
</Routes>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -1,15 +1,41 @@
|
|||||||
import { Outlet } from 'react-router';
|
import { PlusOutlined } from '@ant-design/icons';
|
||||||
|
import { Button } from 'antd';
|
||||||
|
import { Outlet, useLocation } from 'react-router';
|
||||||
|
import { useContainerStore } from '../store';
|
||||||
|
import { useEffect } from 'react';
|
||||||
|
import { useShallow } from 'zustand/react/shallow';
|
||||||
|
|
||||||
export const Main = () => {
|
export const Main = () => {
|
||||||
|
const containerStore = useContainerStore(
|
||||||
|
useShallow((state) => {
|
||||||
|
return {
|
||||||
|
setFormData: state.setFormData,
|
||||||
|
setShowEdit: state.setShowEdit,
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
const location = useLocation();
|
||||||
|
const isEdit = location.pathname.includes('edit/list');
|
||||||
return (
|
return (
|
||||||
<div className='flex w-full h-full flex-col bg-gray-200'>
|
<div className='flex w-full h-full flex-col'>
|
||||||
<div className='h-12 bg-white p-2 mb-2'>Container</div>
|
<div className='layout-menu'>
|
||||||
|
Container
|
||||||
|
<Button
|
||||||
|
className={!isEdit ? 'hidden' : ''}
|
||||||
|
icon={<PlusOutlined />}
|
||||||
|
onClick={() => {
|
||||||
|
console.log('add');
|
||||||
|
containerStore.setFormData({});
|
||||||
|
containerStore.setShowEdit(true);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
<div
|
<div
|
||||||
className='flex'
|
className='flex'
|
||||||
style={{
|
style={{
|
||||||
height: 'calc(100vh - 4rem)',
|
height: 'calc(100vh - 3rem)',
|
||||||
}}>
|
}}>
|
||||||
<div className='flex-grow overflow-hidden mx-2'>
|
<div className='flex-grow overflow-hidden'>
|
||||||
<div className='w-full h-full rounded-lg'>
|
<div className='w-full h-full rounded-lg'>
|
||||||
<Outlet />
|
<Outlet />
|
||||||
</div>
|
</div>
|
||||||
|
@ -57,6 +57,75 @@ export const Preview = () => {
|
|||||||
const containerRef = useRef<Container | null>(null);
|
const containerRef = useRef<Container | null>(null);
|
||||||
const [data, setData] = useState<any>({});
|
const [data, setData] = useState<any>({});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!id) return;
|
||||||
|
fetch();
|
||||||
|
}, []);
|
||||||
|
const fetch = async () => {
|
||||||
|
const res = await query.post({
|
||||||
|
path: 'container',
|
||||||
|
key: 'get',
|
||||||
|
id,
|
||||||
|
});
|
||||||
|
if (res.code === 200) {
|
||||||
|
const data = res.data;
|
||||||
|
// setData([data]);
|
||||||
|
console.log('data', data);
|
||||||
|
const code = {
|
||||||
|
id: data.id,
|
||||||
|
title: data.title,
|
||||||
|
codeId: data.id,
|
||||||
|
code: data.code,
|
||||||
|
data: data.data,
|
||||||
|
};
|
||||||
|
init([code]);
|
||||||
|
} else {
|
||||||
|
message.error(res.msg || 'Failed to fetch data');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const refresh = (data: any) => {
|
||||||
|
if (!data.id) return;
|
||||||
|
const code = {
|
||||||
|
id: data.id,
|
||||||
|
title: data.title,
|
||||||
|
codeId: data.id,
|
||||||
|
code: data.code,
|
||||||
|
data: data.data,
|
||||||
|
hash: '',
|
||||||
|
};
|
||||||
|
init([code], true);
|
||||||
|
};
|
||||||
|
useListener(id, { refresh: refresh });
|
||||||
|
const init = async (data: any[], replace: boolean = false) => {
|
||||||
|
// console.log('data', data, ref.current);
|
||||||
|
if (containerRef.current) {
|
||||||
|
const container = containerRef.current;
|
||||||
|
console.log('data', data, container.data);
|
||||||
|
container.updateData(data);
|
||||||
|
await new Promise((resolve) => {
|
||||||
|
setTimeout(resolve, 2000);
|
||||||
|
});
|
||||||
|
console.log('update---data', data, container.data);
|
||||||
|
container.destroy(id!);
|
||||||
|
container.renderId(id!);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.log('data', containerRef.current);
|
||||||
|
const container = new Container({
|
||||||
|
root: ref.current!,
|
||||||
|
data: data as any,
|
||||||
|
showChild: false,
|
||||||
|
});
|
||||||
|
container.renderId(id!);
|
||||||
|
containerRef.current = container;
|
||||||
|
};
|
||||||
|
return <div className='mx-auto border bg-gray-200 h-full w-full' ref={ref}></div>;
|
||||||
|
};
|
||||||
|
export const PreviewWrapper = () => {
|
||||||
|
const params = useParams<{ id: string }>();
|
||||||
|
const id = params.id;
|
||||||
|
const ref = useRef<HTMLDivElement>(null);
|
||||||
|
const containerRef = useRef<Container | null>(null);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!id) return;
|
if (!id) return;
|
||||||
fetch();
|
fetch();
|
||||||
@ -121,13 +190,13 @@ export const Preview = () => {
|
|||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<div className='w-full h-full bg-gray-200'>
|
<div className='w-full h-full bg-gray-200'>
|
||||||
<div className='text-center mb-10 font-bold text-4xl mt-4 '>Preview</div>
|
<div className='text-center mb-4 pt-2 font-bold text-4xl '>Preview</div>
|
||||||
<div
|
<div
|
||||||
className='flex '
|
className='flex '
|
||||||
style={{
|
style={{
|
||||||
height: 'calc(100% - 32px)',
|
height: 'calc(100% - 32px)',
|
||||||
}}>
|
}}>
|
||||||
<div className='mx-auto border bg-white h-h-full w-[80%] h-[80%]' ref={ref}></div>
|
<div className='mx-auto border bg-white h-h-full w-[80%] h-[80%] overflow-y-auto' ref={ref}></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
16
src/pages/map/index.tsx
Normal file
16
src/pages/map/index.tsx
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
export const App = () => {
|
||||||
|
const serverList = ['container', 'panel', 'publish', 'code-editor', 'map'];
|
||||||
|
return (
|
||||||
|
<div className='p-2 w-full h-full bg-gray-200'>
|
||||||
|
<div className='flex flex-col w-1/2 m-auto bg-white p-4 border rounded-md shadow-md'>
|
||||||
|
{serverList.map((item) => {
|
||||||
|
return (
|
||||||
|
<div key={item} className='flex flex-col'>
|
||||||
|
<div>{item}</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
57
src/pages/prompt/index.tsx
Normal file
57
src/pages/prompt/index.tsx
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
import { Button, Form, Input } from 'antd';
|
||||||
|
import { TextArea } from '../container/components/TextArea';
|
||||||
|
import clsx from 'clsx';
|
||||||
|
|
||||||
|
export const App = () => {
|
||||||
|
const [form] = Form.useForm();
|
||||||
|
const onFinish = (values: any) => {
|
||||||
|
console.log('Success:', values);
|
||||||
|
};
|
||||||
|
const onSave = () => {
|
||||||
|
//
|
||||||
|
};
|
||||||
|
const isEdit = form.getFieldValue('id');
|
||||||
|
return (
|
||||||
|
<div className='w-full h-full felx flex-col bg-gray-200'>
|
||||||
|
<h1 className='text-center py-4'>Prompt JS Code Generate</h1>
|
||||||
|
<div className='py-2 px-4 w-3/4 min-w-[600px] mx-auto border shadow rounded bg-white'>
|
||||||
|
<Form form={form} onFinish={onFinish} className='mt-4' labelCol={{ span: 4 }}>
|
||||||
|
<Form.Item name='id' hidden>
|
||||||
|
<Input />
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item name='title' label='Title'>
|
||||||
|
<Input />
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item name='description' label='Description'>
|
||||||
|
<Input.TextArea rows={4} />
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item name='code' label='Code'>
|
||||||
|
<TextArea className='max-h-full' style={{ minHeight: 300 }} />
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item label=' ' colon={false}>
|
||||||
|
<div className='flex gap-2'>
|
||||||
|
<Button type='primary' htmlType='submit'>
|
||||||
|
Generate
|
||||||
|
</Button>
|
||||||
|
<Button htmlType='reset'>Reset</Button>
|
||||||
|
<Button
|
||||||
|
type='primary'
|
||||||
|
onClick={() => {
|
||||||
|
//
|
||||||
|
}}>
|
||||||
|
Save
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
className={clsx(isEdit ? 'block' : 'hidden')}
|
||||||
|
onClick={() => {
|
||||||
|
//
|
||||||
|
}}>
|
||||||
|
Preview
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</Form.Item>
|
||||||
|
</Form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
Loading…
x
Reference in New Issue
Block a user