调整AI
This commit is contained in:
parent
5099637414
commit
4058877acd
@ -1,10 +1,12 @@
|
|||||||
import {useContext, useEffect, useRef, useState} from "react";
|
import {useContext, useEffect, useRef, useState} from "react";
|
||||||
import {GlobalContext} from "../../context/GlobalContext.ts";
|
import {GlobalContext} from "../../context/GlobalContext.ts";
|
||||||
import {put, WebSocketBaseUrl} from "../../util/AjaxUtils.ts";
|
import {get, post, put, WebSocketBaseUrl} from "../../util/AjaxUtils.ts";
|
||||||
import {Button, Col, Divider, Empty, Row, Space, Spin, Table, TableProps} from "antd";
|
import {Col, Divider, Row, Spin} from "antd";
|
||||||
import {CheckOutlined, EditOutlined, ReloadOutlined} from "@ant-design/icons";
|
|
||||||
import useMessage from "antd/es/message/useMessage";
|
import useMessage from "antd/es/message/useMessage";
|
||||||
import TextArea from "antd/es/input/TextArea";
|
import AiHelperText from "./text/AiHelperText.tsx";
|
||||||
|
import AiHelperMod from "./mod/AiHelperMod.tsx";
|
||||||
|
import {IProjMod} from "../../interfaces/proj/IProj.ts";
|
||||||
|
import {MAX_MOD_SIZE} from "../../route/proj/edit/ProjConfigModList.tsx";
|
||||||
|
|
||||||
type PropsType = {
|
type PropsType = {
|
||||||
projId: string;
|
projId: string;
|
||||||
@ -14,6 +16,7 @@ type PropsType = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type ProjModType = {
|
type ProjModType = {
|
||||||
|
id: string,
|
||||||
name: string,
|
name: string,
|
||||||
desc: string
|
desc: string
|
||||||
}
|
}
|
||||||
@ -25,20 +28,17 @@ export default function AiHelper(props: PropsType) {
|
|||||||
const [messageApi, messageApiHolder] = useMessage();
|
const [messageApi, messageApiHolder] = useMessage();
|
||||||
const [projIntroduction, setProjIntroduction] = useState<string>(props.projIntroduction ? props.projIntroduction : '');
|
const [projIntroduction, setProjIntroduction] = useState<string>(props.projIntroduction ? props.projIntroduction : '');
|
||||||
const [newProjIntroduction, setNewProjIntroduction] = useState<string>('');
|
const [newProjIntroduction, setNewProjIntroduction] = useState<string>('');
|
||||||
const [isProjIntroductionEdit, setIsProjIntroductionEdit] = useState<boolean>(false);
|
|
||||||
const [isNewProjIntroductionEdit, setIsNewProjIntroductionEdit] = useState<boolean>(false);
|
|
||||||
const [isProjIntroductionLoading, setIsProjIntroductionLoading] = useState(false);
|
const [isProjIntroductionLoading, setIsProjIntroductionLoading] = useState(false);
|
||||||
|
|
||||||
const [projDesc, setProjDesc] = useState<string>(props.projDesc ? props.projDesc : '');
|
const [projDesc, setProjDesc] = useState<string>(props.projDesc ? props.projDesc : '');
|
||||||
const [newProjDesc, setNewProjDesc] = useState<string>('');
|
const [newProjDesc, setNewProjDesc] = useState<string>('');
|
||||||
const [isProjDescEdit, setIsProjDescEdit] = useState<boolean>(false);
|
|
||||||
const [isNewProjDescEdit, setIsNewProjDescEdit] = useState<boolean>(false);
|
|
||||||
const [isProjDescLoading, setIsProjDescLoading] = useState(false);
|
const [isProjDescLoading, setIsProjDescLoading] = useState(false);
|
||||||
|
|
||||||
const [projModArray, setProjModArray] = useState<ProjModType[]>(props.projMods ? props.projMods : []);
|
const [projModArray, setProjModArray] = useState<IProjMod[]>([]);
|
||||||
const [newProjModArray, setNewProjModArray] = useState<ProjModType[]>([]);
|
const [newProjModArray, setNewProjModArray] = useState<ProjModType[]>([]);
|
||||||
const [isProjModArrayLoading, setIsProjModArrayLoading] = useState(false);
|
const [isProjModArrayLoading, setIsProjModArrayLoading] = useState(false);
|
||||||
|
|
||||||
|
|
||||||
const ping = () => {
|
const ping = () => {
|
||||||
clearTimeout(pingTimeout.current);
|
clearTimeout(pingTimeout.current);
|
||||||
pingTimeout.current = setTimeout(() => {
|
pingTimeout.current = setTimeout(() => {
|
||||||
@ -74,6 +74,8 @@ export default function AiHelper(props: PropsType) {
|
|||||||
setIsProjModArrayLoading(false);
|
setIsProjModArrayLoading(false);
|
||||||
const projMods = JSON.parse(data.content) as ProjModType[];
|
const projMods = JSON.parse(data.content) as ProjModType[];
|
||||||
setNewProjModArray(projMods);
|
setNewProjModArray(projMods);
|
||||||
|
} else if (data.type == 'REFRESH_PROJ_MOD_FIELDS') {
|
||||||
|
listMods();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ws.current.onerror = (event) => {
|
ws.current.onerror = (event) => {
|
||||||
@ -85,20 +87,21 @@ export default function AiHelper(props: PropsType) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const projModColumnArray: TableProps<ProjModType>['columns'] = [
|
const listMods = () => {
|
||||||
{
|
get<IProjMod[]>({
|
||||||
title: '序号',
|
messageApi,
|
||||||
dataIndex: 'index',
|
url: `/api/proj-mod/list/proj-id/${props.projId}`,
|
||||||
key: 'index',
|
onBefore() {
|
||||||
width: 60,
|
setIsProjModArrayLoading(true);
|
||||||
align: 'center',
|
},
|
||||||
render: (_value, _record, index) => {
|
onSuccess({data}) {
|
||||||
return index + 1
|
setProjModArray(data);
|
||||||
|
},
|
||||||
|
onFinally() {
|
||||||
|
setIsProjModArrayLoading(false);
|
||||||
}
|
}
|
||||||
},
|
})
|
||||||
{title: '模块名称', dataIndex: 'name', key: 'name', width: 200, align: 'center'},
|
}
|
||||||
{title: '模块描述', dataIndex: 'desc', key: 'desc', align: 'center'},
|
|
||||||
];
|
|
||||||
|
|
||||||
const generateProjIntroduction = () => {
|
const generateProjIntroduction = () => {
|
||||||
ws.current?.send(JSON.stringify({
|
ws.current?.send(JSON.stringify({
|
||||||
@ -174,239 +177,106 @@ export default function AiHelper(props: PropsType) {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* 保存模块
|
|
||||||
*/
|
|
||||||
const updateProjModArray = () => {
|
|
||||||
put<any>({
|
|
||||||
messageApi,
|
|
||||||
url: `/api/proj-mod/update-mods/${props.projId}`,
|
|
||||||
body: {
|
|
||||||
list: newProjModArray
|
|
||||||
},
|
|
||||||
onBefore() {
|
|
||||||
setIsProjModArrayLoading(true);
|
|
||||||
},
|
|
||||||
onSuccess() {
|
|
||||||
messageApi.success('保存成功').then();
|
|
||||||
setProjModArray(newProjModArray);
|
|
||||||
setNewProjModArray([]);
|
|
||||||
},
|
|
||||||
onFinally() {
|
|
||||||
setIsProjModArrayLoading(false)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!props.projId) {
|
if (!props.projId) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
listMods();
|
||||||
websocket();
|
websocket();
|
||||||
}, [globalContext.user.userId, props.projId]);
|
}, [globalContext.user.userId, props.projId]);
|
||||||
|
|
||||||
/**
|
|
||||||
* 项目简介按钮
|
|
||||||
*/
|
|
||||||
const renderNewProjIntroductionBtn = () => {
|
|
||||||
if(!newProjIntroduction) {
|
|
||||||
if(!isProjIntroductionEdit) {
|
|
||||||
return (
|
|
||||||
<Space>
|
|
||||||
<Button type="link" style={{cursor: 'pointer'}} onClick={generateProjIntroduction}>AI生成</Button>
|
|
||||||
{
|
|
||||||
projIntroduction ? (
|
|
||||||
<Button type="link" style={{cursor: 'pointer'}} onClick={() => {
|
|
||||||
setIsProjIntroductionEdit(true);
|
|
||||||
}}><EditOutlined /> 编辑</Button>
|
|
||||||
) : <></>
|
|
||||||
}
|
|
||||||
</Space>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<Space>
|
|
||||||
<Button type="link" style={{cursor: 'pointer'}} onClick={() => {
|
|
||||||
setIsProjIntroductionEdit(false);
|
|
||||||
updateProjIntroduction(projIntroduction);
|
|
||||||
}}><CheckOutlined/> 保存结果</Button>
|
|
||||||
</Space>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
if(!isNewProjIntroductionEdit) {
|
|
||||||
return (
|
|
||||||
<Space>
|
|
||||||
<Button type="link" style={{cursor: 'pointer'}} onClick={() => {
|
|
||||||
updateProjIntroduction(newProjIntroduction);
|
|
||||||
}}><CheckOutlined/> 保存结果</Button>
|
|
||||||
<Button type="link" style={{cursor: 'pointer'}} onClick={generateProjIntroduction}><ReloadOutlined/> 重新生成</Button>
|
|
||||||
<Button type="link" style={{cursor: 'pointer'}} onClick={() => {
|
|
||||||
setIsNewProjIntroductionEdit(true);
|
|
||||||
}}><EditOutlined /> 编辑</Button>
|
|
||||||
</Space>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<Space>
|
|
||||||
<Button type="link" style={{cursor: 'pointer'}} onClick={() => {
|
|
||||||
setIsNewProjIntroductionEdit(false);
|
|
||||||
}}><CheckOutlined/> 确定</Button>
|
|
||||||
</Space>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* 项目简介按钮
|
|
||||||
*/
|
|
||||||
const renderNewProjDescBtn = () => {
|
|
||||||
if(!newProjDesc) {
|
|
||||||
if(!isProjDescEdit) {
|
|
||||||
return (
|
|
||||||
<Space>
|
|
||||||
<Button type="link" style={{cursor: 'pointer'}} onClick={generateProjDesc}>AI生成</Button>
|
|
||||||
{
|
|
||||||
projIntroduction ? (
|
|
||||||
<Button type="link" style={{cursor: 'pointer'}} onClick={() => {
|
|
||||||
setIsProjDescEdit(true);
|
|
||||||
}}><EditOutlined /> 编辑</Button>
|
|
||||||
) : <></>
|
|
||||||
}
|
|
||||||
</Space>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<Space>
|
|
||||||
<Button type="link" style={{cursor: 'pointer'}} onClick={() => {
|
|
||||||
setIsProjDescEdit(false);
|
|
||||||
updateProjDesc(projDesc);
|
|
||||||
}}><CheckOutlined/> 保存结果</Button>
|
|
||||||
</Space>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
if(!isNewProjDescEdit) {
|
|
||||||
return (
|
|
||||||
<Space>
|
|
||||||
<Button type="link" style={{cursor: 'pointer'}} onClick={() => {
|
|
||||||
updateProjDesc(newProjDesc);
|
|
||||||
}}><CheckOutlined/> 保存结果</Button>
|
|
||||||
<Button type="link" style={{cursor: 'pointer'}} onClick={generateProjDesc}><ReloadOutlined/> 重新生成</Button>
|
|
||||||
<Button type="link" style={{cursor: 'pointer'}} onClick={() => {
|
|
||||||
setIsNewProjDescEdit(true);
|
|
||||||
}}><EditOutlined /> 编辑</Button>
|
|
||||||
</Space>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<Space>
|
|
||||||
<Button type="link" style={{cursor: 'pointer'}} onClick={() => {
|
|
||||||
setIsNewProjDescEdit(false);
|
|
||||||
}}><CheckOutlined/> 确定</Button>
|
|
||||||
</Space>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{messageApiHolder}
|
{messageApiHolder}
|
||||||
<Row>
|
<Row>
|
||||||
<Col span={24}>
|
<Col span={24}>
|
||||||
<div style={{padding: '5px 0 0 0', fontWeight: 'bold'}}>项目简介</div>
|
|
||||||
<Spin tip="正在处理,请稍后..." size="small" spinning={isProjIntroductionLoading}>
|
<Spin tip="正在处理,请稍后..." size="small" spinning={isProjIntroductionLoading}>
|
||||||
<div style={{padding: '5px 0 0 0'}}>
|
<AiHelperText title="项目简介"
|
||||||
{newProjIntroduction ? <Divider orientation="right" plain>原简介</Divider> : <></>}
|
text={projIntroduction}
|
||||||
{projIntroduction ? (
|
newText={newProjIntroduction}
|
||||||
isProjIntroductionEdit ? <TextArea rows={10} value={projIntroduction} placeholder="请编辑简介" maxLength={1500} onChange={(e) => {
|
maxLength={1500}
|
||||||
setProjIntroduction(e.currentTarget.value);
|
handleGenerate={() => {
|
||||||
}}/>
|
generateProjIntroduction();
|
||||||
: <div>{projIntroduction}</div>
|
}}
|
||||||
) : <Empty description="暂无内容"/>}
|
handleSave={(text) => {
|
||||||
{
|
updateProjIntroduction(text);
|
||||||
newProjIntroduction ? (
|
}}
|
||||||
<>
|
/>
|
||||||
<Divider orientation="right" plain>新简介</Divider>
|
|
||||||
{
|
|
||||||
isNewProjIntroductionEdit ? (
|
|
||||||
<TextArea rows={10} value={newProjIntroduction} placeholder="请编辑简介" maxLength={1500} onChange={(e) => {
|
|
||||||
setNewProjIntroduction(e.currentTarget.value);
|
|
||||||
}}/>
|
|
||||||
) : <div>{newProjIntroduction}</div>
|
|
||||||
}
|
|
||||||
</>
|
|
||||||
) : <></>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
<div style={{padding: '5px 0 0 0', textAlign: 'center'}}>
|
|
||||||
{renderNewProjIntroductionBtn()}
|
|
||||||
</div>
|
|
||||||
</Spin>
|
</Spin>
|
||||||
</Col>
|
</Col>
|
||||||
<Col span={24}>
|
<Col span={24}>
|
||||||
<Divider dashed/>
|
<Divider dashed/>
|
||||||
<div style={{padding: '5px 0 0 0', fontWeight: 'bold'}}>项目详情</div>
|
|
||||||
<Spin tip="正在处理,请稍后..." size="small" spinning={isProjDescLoading}>
|
<Spin tip="正在处理,请稍后..." size="small" spinning={isProjDescLoading}>
|
||||||
<div style={{padding: '5px 0 0 0'}}>
|
<AiHelperText title="项目详情"
|
||||||
{newProjDesc ? <Divider orientation="right" plain>原详情</Divider> : <></>}
|
text={projDesc}
|
||||||
{projDesc ? (
|
newText={newProjDesc}
|
||||||
isProjDescEdit ?
|
maxLength={1500}
|
||||||
<TextArea rows={10} value={projDesc} placeholder="请编辑详情"
|
handleGenerate={() => {
|
||||||
maxLength={1500} onChange={(e) => {
|
generateProjDesc();
|
||||||
setProjDesc(e.currentTarget.value);
|
}}
|
||||||
}}/>
|
handleSave={(text) => {
|
||||||
: <div>{projDesc}</div>
|
updateProjDesc(text);
|
||||||
) : <Empty description="暂无内容"/>}
|
}}
|
||||||
{
|
/>
|
||||||
newProjDesc ? (
|
|
||||||
<>
|
|
||||||
<Divider orientation="right" plain>新详情</Divider>
|
|
||||||
{
|
|
||||||
isNewProjDescEdit ? (
|
|
||||||
<TextArea rows={10} value={newProjDesc} placeholder="请编辑简介"
|
|
||||||
maxLength={1500} onChange={(e) => {
|
|
||||||
setNewProjDesc(e.currentTarget.value);
|
|
||||||
}}/>
|
|
||||||
) : <div>{newProjDesc}</div>
|
|
||||||
}
|
|
||||||
</>
|
|
||||||
) : <></>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
<div style={{padding: '5px 0 0 0', textAlign: 'center'}}>
|
|
||||||
{renderNewProjDescBtn()}
|
|
||||||
</div>
|
|
||||||
</Spin>
|
</Spin>
|
||||||
</Col>
|
</Col>
|
||||||
<Col span={24}>
|
<Col span={24}>
|
||||||
<Divider dashed/>
|
<Divider dashed/>
|
||||||
<div style={{padding: '5px 0 0 0', fontWeight: 'bold'}}>项目模块</div>
|
|
||||||
<Spin tip="正在处理,请稍后..." size="small" spinning={isProjModArrayLoading}>
|
<Spin tip="正在处理,请稍后..." size="small" spinning={isProjModArrayLoading}>
|
||||||
<div style={{padding: '5px 0 0 0'}}>
|
<AiHelperMod mods={projModArray}
|
||||||
{newProjModArray.length > 0 ? <Divider orientation="right" plain>原模块</Divider> : <></>}
|
newMods={newProjModArray}
|
||||||
<Table columns={projModColumnArray} dataSource={projModArray} size="small" bordered={true}
|
handleGenerate={() => {
|
||||||
scroll={{y: 240}} pagination={{pageSize: 20}}/>
|
generateProjModArray();
|
||||||
{
|
}}
|
||||||
newProjModArray.length > 0 ? (
|
handleSave={(index, mod) => {
|
||||||
<>
|
if(projModArray.length > MAX_MOD_SIZE) {
|
||||||
<Divider orientation="right" plain>新模块</Divider>
|
messageApi.error(`模块最大数量为${MAX_MOD_SIZE}`);
|
||||||
<Table columns={projModColumnArray} dataSource={newProjModArray} size="small"
|
return;
|
||||||
bordered={true} scroll={{y: 240}} pagination={{pageSize: 20}}/>
|
}
|
||||||
</>
|
post<any>({
|
||||||
) : <></>
|
messageApi,
|
||||||
}
|
url: `/api/proj-mod/save-ai/${props.projId}`,
|
||||||
</div>
|
body: {
|
||||||
<div style={{padding: '5px 0 0 0', textAlign: 'center'}}>
|
name: mod.name,
|
||||||
{
|
desc: mod.desc,
|
||||||
newProjModArray.length > 0 ? (
|
},
|
||||||
<Space>
|
onBefore() {
|
||||||
<Button type="link" style={{cursor: 'pointer'}}
|
setIsProjModArrayLoading(true);
|
||||||
onClick={updateProjModArray}><CheckOutlined/> 保存结果</Button>
|
},
|
||||||
<Button type="link" style={{cursor: 'pointer'}}
|
onSuccess() {
|
||||||
onClick={generateProjModArray}><ReloadOutlined/> 重新生成</Button>
|
messageApi.success('提交成功')
|
||||||
</Space>
|
listMods();
|
||||||
) : <Button type="link" style={{cursor: 'pointer'}}
|
newProjModArray.splice(index, 1);
|
||||||
onClick={generateProjModArray}>AI生成</Button>
|
setNewProjModArray([
|
||||||
}
|
...newProjModArray
|
||||||
</div>
|
]);
|
||||||
|
},
|
||||||
|
onFinally() {
|
||||||
|
setIsProjModArrayLoading(false);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}}
|
||||||
|
handleResaveField={(_index, projModId) => {
|
||||||
|
post<any>({
|
||||||
|
messageApi,
|
||||||
|
url: `/api/proj-mod/resave-ai-field/${props.projId}/${projModId}`,
|
||||||
|
onBefore() {
|
||||||
|
setIsProjModArrayLoading(true);
|
||||||
|
},
|
||||||
|
onSuccess() {
|
||||||
|
messageApi.success('提交成功')
|
||||||
|
listMods();
|
||||||
|
},
|
||||||
|
onFinally() {
|
||||||
|
setIsProjModArrayLoading(false);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}}
|
||||||
|
/>
|
||||||
</Spin>
|
</Spin>
|
||||||
</Col>
|
</Col>
|
||||||
|
|
||||||
</Row>
|
</Row>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
|
155
src/components/ai/mod/AiHelperMod.tsx
Normal file
155
src/components/ai/mod/AiHelperMod.tsx
Normal file
@ -0,0 +1,155 @@
|
|||||||
|
import {Button, Divider, Dropdown, Space, Table, TableProps} from "antd";
|
||||||
|
import {CheckOutlined, LoadingOutlined, ReloadOutlined, RedoOutlined} from "@ant-design/icons";
|
||||||
|
import {useEffect, useState} from "react";
|
||||||
|
import {IProjMod} from "../../../interfaces/proj/IProj.ts";
|
||||||
|
|
||||||
|
type PropsType = {
|
||||||
|
mods: IProjMod[];
|
||||||
|
newMods: ProjModType[],
|
||||||
|
handleGenerate: () => void;
|
||||||
|
handleSave: (index: number, mod: ProjModType) => void;
|
||||||
|
handleResaveField: (index: number, projModId: string) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
type ProjModType = {
|
||||||
|
name: string,
|
||||||
|
desc: string,
|
||||||
|
}
|
||||||
|
|
||||||
|
const savedItems = [
|
||||||
|
{
|
||||||
|
key: 'edit',
|
||||||
|
label: '编辑',
|
||||||
|
},{
|
||||||
|
key: 'remove',
|
||||||
|
label: '删除',
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
export default function AiHelperMod(props: PropsType) {
|
||||||
|
const [modArray, setModArray] = useState<IProjMod[]>([]);
|
||||||
|
const [newModArray, setNewModArray] = useState<ProjModType[]>([]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setModArray(props.mods);
|
||||||
|
setNewModArray(props.newMods);
|
||||||
|
}, [props.mods, props.newMods]);
|
||||||
|
|
||||||
|
const modColumnArray: TableProps<IProjMod>['columns'] = [
|
||||||
|
{
|
||||||
|
title: '序号',
|
||||||
|
dataIndex: 'index',
|
||||||
|
key: 'index',
|
||||||
|
width: 60,
|
||||||
|
align: 'center',
|
||||||
|
render: (_value, _record, index) => {
|
||||||
|
return index + 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{title: '模块名称', dataIndex: 'modName', key: 'name', width: 200, align: 'center'},
|
||||||
|
{title: '模块描述', dataIndex: 'modDesc', key: 'desc', align: 'center'},
|
||||||
|
{
|
||||||
|
title: 'AI状态',
|
||||||
|
dataIndex: 'aiFieldStatus',
|
||||||
|
key: 'desc',
|
||||||
|
width: 100,
|
||||||
|
align: 'center',
|
||||||
|
render: (value) => {
|
||||||
|
if(value == 'GENERATING') {
|
||||||
|
return '处理中'
|
||||||
|
}
|
||||||
|
if(value == 'FIELD') {
|
||||||
|
return '失败'
|
||||||
|
}
|
||||||
|
if(value == 'SUCCESS') {
|
||||||
|
return '成功'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '操作',
|
||||||
|
dataIndex: 'option',
|
||||||
|
key: 'option',
|
||||||
|
width: 80,
|
||||||
|
align: 'center',
|
||||||
|
render: (_value, record, index) => {
|
||||||
|
if(record.aiFieldStatus == 'GENERATING') {
|
||||||
|
return <LoadingOutlined />
|
||||||
|
}
|
||||||
|
if(record.aiFieldStatus == 'FAILED') {
|
||||||
|
return <Button onClick={() => {
|
||||||
|
props.handleResaveField(index, record.projModId);
|
||||||
|
}}><RedoOutlined /></Button>
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<Dropdown menu={{ items: savedItems }} placement="bottomCenter" arrow>
|
||||||
|
<Button>…</Button>
|
||||||
|
</Dropdown>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const newModColumnArray: TableProps<ProjModType>['columns'] = [
|
||||||
|
{
|
||||||
|
title: '序号',
|
||||||
|
dataIndex: 'index',
|
||||||
|
key: 'index',
|
||||||
|
width: 60,
|
||||||
|
align: 'center',
|
||||||
|
render: (_value, _record, index) => {
|
||||||
|
return index + 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{title: '模块名称', dataIndex: 'name', key: 'name', width: 200, align: 'center'},
|
||||||
|
{title: '模块描述', dataIndex: 'desc', key: 'desc', align: 'center'},
|
||||||
|
{
|
||||||
|
title: '确认',
|
||||||
|
dataIndex: 'option',
|
||||||
|
key: 'option',
|
||||||
|
width: 80,
|
||||||
|
align: 'center',
|
||||||
|
render: (_value, record, index) => {
|
||||||
|
return (
|
||||||
|
<Button onClick={() => {
|
||||||
|
props.handleSave(index, record);
|
||||||
|
}}>
|
||||||
|
<CheckOutlined />
|
||||||
|
</Button>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div style={{padding: '5px 0 0 0'}}>
|
||||||
|
{newModArray.length > 0 ? <Divider orientation="right" plain>原模块</Divider> : <></>}
|
||||||
|
<Table columns={modColumnArray} dataSource={modArray} size="small" bordered={true} scroll={{y: 240}} pagination={false}/>
|
||||||
|
{
|
||||||
|
newModArray.length > 0 ? (
|
||||||
|
<>
|
||||||
|
<Divider orientation="right" plain>新模块</Divider>
|
||||||
|
<Table columns={newModColumnArray} dataSource={newModArray} size="small" bordered={true} scroll={{y: 240}} pagination={false}/>
|
||||||
|
</>
|
||||||
|
) : <></>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
<div style={{padding: '5px 0 0 0', textAlign: 'center'}}>
|
||||||
|
{
|
||||||
|
newModArray.length > 0 ? (
|
||||||
|
<Space>
|
||||||
|
<Button type="link" style={{cursor: 'pointer'}}
|
||||||
|
onClick={() => {
|
||||||
|
props.handleGenerate();
|
||||||
|
}}><ReloadOutlined/> 重新生成</Button>
|
||||||
|
</Space>
|
||||||
|
) : <Button type="link" style={{cursor: 'pointer'}}
|
||||||
|
onClick={() => {
|
||||||
|
props.handleGenerate();
|
||||||
|
}}>AI生成</Button>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
129
src/components/ai/text/AiHelperText.tsx
Normal file
129
src/components/ai/text/AiHelperText.tsx
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
import {Button, Divider, Empty, Space} from "antd";
|
||||||
|
import TextArea from "antd/es/input/TextArea";
|
||||||
|
import {useEffect, useState} from "react";
|
||||||
|
import {CheckOutlined, EditOutlined, ReloadOutlined} from "@ant-design/icons";
|
||||||
|
|
||||||
|
type PropsType = {
|
||||||
|
title: string;
|
||||||
|
maxLength: number;
|
||||||
|
text: string;
|
||||||
|
newText: string;
|
||||||
|
handleGenerate: () => void;
|
||||||
|
handleSave: (newText: string) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function AiHelperText(props: PropsType) {
|
||||||
|
|
||||||
|
const [text, setText] = useState('');
|
||||||
|
const [newText, setNewText] = useState('');
|
||||||
|
const [isTextEdit, setIsTextEdit] = useState(false);
|
||||||
|
const [isNewTextEdit, setIsNewTextEdit] = useState(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setText(props.text);
|
||||||
|
setNewText(props.newText);
|
||||||
|
}, [props.text, props.newText])
|
||||||
|
|
||||||
|
const renderTextBtn = () => {
|
||||||
|
if (!newText) {
|
||||||
|
if (!isTextEdit) {
|
||||||
|
return (
|
||||||
|
<Space>
|
||||||
|
<Button type="link" style={{cursor: 'pointer'}} onClick={() => {
|
||||||
|
props.handleGenerate();
|
||||||
|
}}>AI生成</Button>
|
||||||
|
{
|
||||||
|
text ? (
|
||||||
|
<Button type="link" style={{cursor: 'pointer'}} onClick={() => {
|
||||||
|
setIsTextEdit(true);
|
||||||
|
}}><EditOutlined/> 编辑</Button>
|
||||||
|
) : <></>
|
||||||
|
}
|
||||||
|
</Space>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<Space>
|
||||||
|
<Button type="link" style={{cursor: 'pointer'}} onClick={() => {
|
||||||
|
props.handleSave(text);
|
||||||
|
setIsTextEdit(false);
|
||||||
|
}}><CheckOutlined/> 保存结果</Button>
|
||||||
|
</Space>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if (!isNewTextEdit) {
|
||||||
|
return (
|
||||||
|
<Space>
|
||||||
|
<Button type="link" style={{cursor: 'pointer'}} onClick={() => {
|
||||||
|
props.handleSave(newText);
|
||||||
|
setIsNewTextEdit(false);
|
||||||
|
}}><CheckOutlined/> 保存结果</Button>
|
||||||
|
<Button type="link" style={{cursor: 'pointer'}} onClick={() => {
|
||||||
|
props.handleGenerate();
|
||||||
|
}}><ReloadOutlined/> 重新生成</Button>
|
||||||
|
<Button type="link" style={{cursor: 'pointer'}} onClick={() => {
|
||||||
|
setIsNewTextEdit(true);
|
||||||
|
}}><EditOutlined/> 编辑</Button>
|
||||||
|
</Space>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<Space>
|
||||||
|
<Button type="link" style={{cursor: 'pointer'}} onClick={() => {
|
||||||
|
setIsNewTextEdit(false);
|
||||||
|
}}><CheckOutlined/> 确定</Button>
|
||||||
|
</Space>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const renderTextDom = () => {
|
||||||
|
if(!text) {
|
||||||
|
return <Empty description="暂无内容"/>
|
||||||
|
}
|
||||||
|
if(!isTextEdit) {
|
||||||
|
return <div>{text}</div>
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<TextArea autoSize={true} value={text} placeholder={`请编辑${props.title}`} maxLength={props.maxLength} onChange={(e) => {
|
||||||
|
setText(e.currentTarget.value);
|
||||||
|
}}/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const renderNewTextDom = () => {
|
||||||
|
if(!newText) {
|
||||||
|
return <></>
|
||||||
|
}
|
||||||
|
if(!isNewTextEdit) {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Divider orientation="right" plain>新{props.title}</Divider>
|
||||||
|
<div>{newText}</div>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Divider orientation="right" plain>新{props.title}</Divider>
|
||||||
|
<TextArea autoSize={true} value={newText} placeholder={`请编辑${props.title}`} maxLength={props.maxLength} onChange={(e) => {
|
||||||
|
setNewText(e.currentTarget.value);
|
||||||
|
}}/>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div style={{padding: '5px 0 0 0', fontWeight: 'bold'}}>{props.title}</div>
|
||||||
|
<div style={{padding: '5px 0 0 0'}}>
|
||||||
|
{newText ? <Divider orientation="right" plain>原{props.title}</Divider> : <></>}
|
||||||
|
{renderTextDom()}
|
||||||
|
{renderNewTextDom()}
|
||||||
|
</div>
|
||||||
|
<div style={{padding: '5px 0 0 0', textAlign: 'center'}}>
|
||||||
|
{renderTextBtn()}
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
|
||||||
|
}
|
@ -59,6 +59,19 @@ export interface IProjPay {
|
|||||||
chargeAdditionals: string;
|
chargeAdditionals: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 项目模块
|
||||||
|
*/
|
||||||
|
export interface IProjMod {
|
||||||
|
projModId: string;
|
||||||
|
projId: string;
|
||||||
|
projContext: string;
|
||||||
|
modName: string;
|
||||||
|
modDesc: string;
|
||||||
|
modIcon: string;
|
||||||
|
modContext: string;
|
||||||
|
aiFieldStatus: string;
|
||||||
|
}
|
||||||
|
|
||||||
export interface IProj {
|
export interface IProj {
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user