ai窗口一键生成

This commit is contained in:
lyp 2025-01-17 16:50:18 +08:00
parent 13d9a760c2
commit 10803f293c
5 changed files with 453 additions and 84 deletions

View File

@ -4,8 +4,14 @@ import { GlobalContext } from "../../context/GlobalContext.ts";
import { del, get, post, put, websocketUrl, Axios } from "../../util/AjaxUtils.ts";
import {
// Col, Divider, Row,
Spin, Image, Pagination
Spin, Image, Pagination,
Button, Dropdown, notification
} from "antd";
const close = () => {
console.log(
'Notification was closed. Either the close button was clicked or duration time elapsed.',
);
};
import { AxiosResponse } from "axios";
import useMessage from "antd/es/message/useMessage";
import AiHelperText from "./text/AiHelperText.tsx";
@ -17,7 +23,7 @@ import {
// useParams
} from "react-router-dom";
import { uuid } from "../../util/CommonUtil.ts";
const key = `open${Date.now()}`;
type PropsType = {
projId: string;
projIntroduction?: string;
@ -33,6 +39,7 @@ type ProjModType = {
}
export default function AiHelper(props: PropsType) {
// 页面样式相关
const [pageImgArray, setpageImgArray] = useState<any[]>([])
const [pageTotal, setPageTotal] = useState(0)
@ -76,6 +83,8 @@ export default function AiHelper(props: PropsType) {
}
const height = window.innerHeight - 265;
// 是否点击了快速生成
const [isFast, setIsFast] = useState(false)
// 提示是否可以生成模块
// const [modal, setModal] = useState(false)
// const pathParams = useParams();
@ -188,6 +197,7 @@ export default function AiHelper(props: PropsType) {
if (data.type == 'REFRESH_PROJ_INTRODUCTION') {
setIsProjIntroductionLoading(false);
setNewProjIntroduction(data.content);
// if (!projIntroduction) {
// setProjIntroduction(data.content)
// updateProjIntroduction(data.content);
@ -203,6 +213,31 @@ export default function AiHelper(props: PropsType) {
// }
} else if (data.type == 'REFRESH_PROJ_MODS') {
setIsProjModArrayLoading(false);
notification.open({
message: '提示',
description:
`功能列表已生成完毕,是否前去查看?`,
btn: (
<div>
<Button size="small" type="primary" onClick={() => {
notification.destroy(key)
setActiveTab('模块')
}}>
</Button>
</div>
),
key,
onClose: close,
duration: null,
placement: 'bottomRight', // 设置通知框显示在右下角
style: {
width: 300, // 设置通知框的宽度
height: 130, // 设置通知框的高度
},
});
const projMods = JSON.parse(data.content) as ProjModType[];
projMods.forEach(projMod => projMod.id = uuid())
setNewProjModArray(projMods);
@ -258,6 +293,17 @@ export default function AiHelper(props: PropsType) {
ping();
setIsProjIntroductionLoading(true);
}
const xixi = () => {
setIsFast(true)
ws.current?.send(JSON.stringify({
type: 'REFRESH_AI_PROJ',
projId: props.projId
}));
ping();
setIsProjIntroductionLoading(true);
setIsProjDescLoading(true);
setIsProjModArrayLoading(true);
}
const generateProjDesc = () => {
@ -277,7 +323,11 @@ export default function AiHelper(props: PropsType) {
ping();
setIsProjModArrayLoading(true);
}
useEffect(() => {
if (isFast && !isProjIntroductionLoading && !isProjDescLoading && !isProjModArrayLoading) {
setIsFast(false)
}
}, [isFast, isProjIntroductionLoading, isProjDescLoading, isProjModArrayLoading])
/**
*
*/
@ -292,7 +342,7 @@ export default function AiHelper(props: PropsType) {
setIsProjIntroductionLoading(true);
},
onSuccess(data) {
messageApi.success('保存成功,点击编辑按钮可继续修改项目简介');
messageApi.success('项目简介保存成功,点击编辑按钮可继续修改项目简介');
setProjIntroduction(content);
setNewProjIntroduction('');
console.log('更新成功', data);
@ -319,7 +369,7 @@ export default function AiHelper(props: PropsType) {
setIsProjDescLoading(true);
},
onSuccess() {
messageApi.success('保存成功,点击编辑按钮可继续修改项目详情').then();
messageApi.success('项目详情保存成功,点击编辑按钮可继续修改项目详情').then();
setProjDesc(content);
setNewProjDesc('');
},
@ -476,72 +526,115 @@ export default function AiHelper(props: PropsType) {
</Col>
</Row> */}
<div className="aiTabBtnBox">
<div className={activeTab == '简介' ? 'tabActive' : "aiTabBtn"}
onClick={() => {
setActiveTab('简介')
}}
>
</div>
<div className={activeTab == '详情' ? 'tabActive' : "aiTabBtn"}
onClick={() => {
setActiveTab('详情')
}}
>
</div>
<div className={activeTab == '模块' ? 'tabActive' : "aiTabBtn"}
onClick={() => {
setActiveTab('模块')
}}
>
</div>
<div className={activeTab == '登录' ? 'tabActive' : "aiTabBtn"}
onClick={() => {
setActiveTab('登录')
getLoginPageInfo()
}}
>
</div>
<div className={activeTab == '页面' ? 'tabActive' : "aiTabBtn"}
onClick={() => {
setActiveTab('页面')
getData()
<div style={{
display: 'flex',
justifyContent: 'space-between',
}}>
<div className="aiTabBtnBox">
<div className={activeTab == '简介' ? 'tabActive' : "aiTabBtn"}
onClick={() => {
setActiveTab('简介')
}}
>
</div>
<div className={activeTab == '详情' ? 'tabActive' : "aiTabBtn"}
onClick={() => {
setActiveTab('详情')
}}
>
</div>
<div className={activeTab == '模块' ? 'tabActive' : "aiTabBtn"}
onClick={() => {
setActiveTab('模块')
}}
>
</div>
<div className={activeTab == '登录' ? 'tabActive' : "aiTabBtn"}
onClick={() => {
setActiveTab('登录')
getLoginPageInfo()
}}
>
</div>
<div className={activeTab == '页面' ? 'tabActive' : "aiTabBtn"}
onClick={() => {
setActiveTab('页面')
getData()
}}
>
</div>
}}
>
</div>
{/*
<Dropdown menu={{
items: [
{
key: '1',
label: (
<div >
<div
onClick={() => {
setIsFast(true)
xixi()
}}>
</div>
</div>
),
},
],
}} placement="bottomLeft" arrow>
<Button className=''
>
</Button>
</Dropdown> */}
</div>
<div className='aiTabContent'>
<div style={{ display: activeTab == '简介' ? 'block' : 'none' }}>
{/* <Spin tip="正在处理,请稍后..." size="small" className='fastmask' spinning={isFast} > */}
<div className='masksmall' style={{ display: activeTab == '简介' ? 'block' : 'none' }}>
<Spin tip="正在处理,请稍后..." size="small" spinning={isProjIntroductionLoading}>
<AiHelperText
isFast={isFast}
title="系统简介"
text={projIntroduction}
projIntroduction={projIntroduction}
newText={newProjIntroduction}
maxLength={1500}
handleGenerate={() => {
generateProjIntroduction();
// setProjIntroduction(newProjIntroduction)
// xixi()
setProjIntroduction(newProjIntroduction)
}}
xixi={() => {
xixi()
}}
handleSave={(text) => {
updateProjIntroduction(text);
}}
setActiveTab={
(data: string) => {
setActiveTab(data)
}
}
></AiHelperText>
</Spin>
</div>
<div style={{ display: activeTab == '详情' ? 'block' : 'none' }}>
<div className='masksmall' style={{ display: activeTab == '详情' ? 'block' : 'none' }}>
<Spin tip="正在处理,请稍后..." size="small" spinning={isProjDescLoading}>
<AiHelperText title="系统详情"
isFast={isFast}
text={projDesc}
projIntroduction={projIntroduction}
newText={newProjDesc}
maxLength={1500}
handleGenerate={() => {
@ -550,13 +643,31 @@ export default function AiHelper(props: PropsType) {
handleSave={(text) => {
updateProjDesc(text);
}}
setActiveTab={
(data: string) => {
setActiveTab(data)
}
}
xixi={() => {
xixi()
}}
/>
</Spin>
</div>
<div style={{ display: activeTab == '模块' ? 'block' : 'none' }}>
<div className='masksmall' style={{ display: activeTab == '模块' ? 'block' : 'none' }}>
<Spin tip="正在处理,请稍后..." size="small" spinning={isProjModArrayLoading}>
<AiHelperMod mods={projModArray}
isFast={isFast}
projIntroduction={projIntroduction}
xixi={() => {
xixi()
}}
setActiveTab={
(data: string) => {
setActiveTab(data)
}
}
newMods={newProjModArray}
handleGenerate={() => {
// getProjDesc()
@ -584,6 +695,31 @@ export default function AiHelper(props: PropsType) {
setNewProjModArray([
...newProjModArray
]);
// notification.open({
// message: '提示',
// description:
// `功能列表已生成完毕,是否前去查看?`,
// btn: (
// <div>
// <Button size="small" type="primary" onClick={() => {
// notification.destroy(key)
// setActiveTab('模块')
// }}>
// 确定
// </Button>
// </div>
// ),
// key,
// onClose: close,
// duration: null,
// placement: 'bottomRight', // 设置通知框显示在右下角
// style: {
// width: 300, // 设置通知框的宽度
// height: 150, // 设置通知框的高度
// },
// });
},
onFinally() {
setIsProjModArrayLoading(false);
@ -640,7 +776,9 @@ export default function AiHelper(props: PropsType) {
/>
</Spin>
</div>
{/* </Spin> */}
</div>
<div style={{ display: activeTab == '登录' ? 'block' : 'none' }}>
<div style={{ height: `${height - 80}px`, overflow: 'auto', display: '', justifyContent: '', flexWrap: 'wrap', marginTop: 10 }}>
{

View File

@ -45,4 +45,18 @@
display: flex;
margin-top: 20px;
box-sizing: border-box;
}
}
/* .aiTabContent .css-dev-only-do-not-override-11lehqq.ant-spin-nested-loading .ant-spin-container::after{
background: rgba(189, 84, 84, 0);
transition: all 0.3s;
}
.masksmall .css-dev-only-do-not-override-11lehqq.ant-spin-nested-loading .ant-spin-container::after{
}
.ant-spin-spinning {
background: rgba(189, 84, 84, 0);
transition: transform 0.3s cubic-bezier(0.78, 0.14, 0.15, 0.86)
} */

View File

@ -2,8 +2,14 @@ import './ai-helper-mod.css'
import {
Button,
// Divider, Dropdown, Space,
Table, TableProps, Modal
Table, TableProps, Modal,
// notification
} from "antd";
// const close = () => {
// console.log(
// 'Notification was closed. Either the close button was clicked or duration time elapsed.',
// );
// };
import {
// CheckOutlined,
LoadingOutlined,
@ -29,6 +35,10 @@ type PropsType = {
handleResaveField: (index: number, projModId: string) => void;
handleRemove: (index: number, projModId: string, item: IProjMod) => void;
handleEdit: (index: number, projModId: string, item: IProjMod) => void;
setActiveTab: (key: string) => void;
xixi: any;
projIntroduction: string;
isFast: boolean;
}
type ProjModType = {
@ -51,12 +61,80 @@ export default function AiHelperMod(props: PropsType) {
// const [items, setItems] = useState<any[]>([])
const pathParams = useParams();
// useEffect(() => {
// // console.log('mods', props.mods);
// if( newModArray.length > 0){
// alert('请先保存')
// }
// }, [modArray, newModArray]);
// const key = `open${Date.now()}`;
useEffect(() => {
// console.log('mods', props.mods);
setModArray(props.mods);
setNewModArray(props.newMods);
// if (props.newMods.length > 0 ) {
// notification.open({
// message: '提示',
// description:
// `功能列表已生成完毕,是否前去查看?`,
// btn: (
// <div>
// <Button size="small" type="primary" onClick={() => {
// notification.destroy(key)
// props.setActiveTab('模块')
// }}>
// 确定
// </Button>
// </div>
// ),
// key,
// onClose: close,
// // duration: null,
// placement: 'bottomRight', // 设置通知框显示在右下角
// style: {
// width: 300, // 设置通知框的宽度
// height: 150, // 设置通知框的高度
// },
// });
// }
}, [props.mods, props.newMods]);
// useEffect(() => {
// // console.log('mods', props.mods);
// if (newModArray.length > 0 && newModArray != props.newMods) {
// notification.open({
// message: '提示',
// description:
// `功能列表已生成完毕,是否前去查看?`,
// btn: (
// <div>
// <Button size="small" type="primary" onClick={() => {
// notification.destroy(key)
// props.setActiveTab('模块')
// }}>
// 确定
// </Button>
// </div>
// ),
// key,
// onClose: close,
// duration: null,
// placement: 'bottomRight', // 设置通知框显示在右下角
// style: {
// width: 300, // 设置通知框的宽度
// height: 150, // 设置通知框的高度
// },
// });
// }
// }, [newModArray]);
useEffect(() => {
if (updata.length != 0) {
// console.log('更新数据', updata);
@ -126,7 +204,7 @@ export default function AiHelperMod(props: PropsType) {
title: '操作',
dataIndex: 'option',
key: 'option',
// width: 120,
width: 100,
align: 'center',
render: (_value, record, index) => {
if (status == 'SUCCESS') {
@ -160,7 +238,7 @@ export default function AiHelperMod(props: PropsType) {
style={{
cursor: 'pointer',
// background: 'pink',
width:40,
width: 40,
}}
onClick={() => {
props.handleResaveField(index, record.projModId);
@ -170,9 +248,9 @@ export default function AiHelperMod(props: PropsType) {
cursor: 'pointer',
marginLeft: 19,
color: '#FF4040',
width:40,
width: 40,
}}
onClick={() => {
props.handleRemove(index, record.projModId, record);
@ -183,17 +261,17 @@ export default function AiHelperMod(props: PropsType) {
}
return (
<div
style={{
whiteSpace: 'nowrap' , display: 'flex',
style={{
whiteSpace: 'nowrap', display: 'flex',
alignItems: 'center',
justifyContent: 'center',
}}
>
<div
style={{
cursor: 'pointer',
width:40,
width: 40,
}}
onClick={() => {
setId(record.projModId)
@ -203,9 +281,9 @@ export default function AiHelperMod(props: PropsType) {
<div
style={{
cursor: 'pointer',
marginLeft: 19,
marginLeft: 5,
color: '#FF4040',
width:40,
width: 40,
}}
onClick={() => {
props.handleRemove(index, record.projModId, record);
@ -437,7 +515,17 @@ export default function AiHelperMod(props: PropsType) {
,
<span style={{ color: '#FF9D00', cursor: 'pointer' }}
onClick={() => {
props.handleGenerate()
if (props.isFast) {
return
} else {
if (props.projIntroduction) {
props.handleGenerate()
} else {
props.xixi()
}
}
}}
></span>
@ -481,12 +569,13 @@ export default function AiHelperMod(props: PropsType) {
marginLeft: 15,
width: 109,
}}
disabled={status == 'SUCCESS' || status == 'GENERATING' ? true : false}
disabled={status == 'SUCCESS' || status == 'GENERATING' || props.isFast ? true : false}
onClick={() => {
props.handleGenerate()
}}
>AI生成</Button>
</div>
</div>
<Modal title="编辑"
destroyOnClose={true}

View File

@ -1,8 +1,15 @@
import {
Button,
// Divider, Empty, Space
Modal
// Modal,
notification
} from "antd";
const close = () => {
console.log(
'Notification was closed. Either the close button was clicked or duration time elapsed.',
);
};
import './ai-helper-text.css'
import TextArea from "antd/es/input/TextArea";
import { useEffect, useState } from "react";
@ -20,7 +27,10 @@ type PropsType = {
newText: string;
handleGenerate: () => void;
handleSave: (newText: string) => void;
xixi?: any;
setActiveTab: (key: string) => void;
projIntroduction: string;
isFast: boolean;
}
export default function AiHelperText(props: PropsType) {
@ -44,9 +54,10 @@ export default function AiHelperText(props: PropsType) {
const [text, setText] = useState('');
const [newText, setNewText] = useState('');
const [isShow, setIsShow] = useState(false) //替换按钮是否显示
const [modal, setModal] = useState(false) //提示替换弹窗
// const [modal, setModal] = useState(false) //提示替换弹窗
const [isTextEdit, setIsTextEdit] = useState(false);
// const [isNewTextEdit, setIsNewTextEdit] = useState(false);
const key = `${props.title}`;
useEffect(() => {
setText(props.text);
@ -55,7 +66,93 @@ export default function AiHelperText(props: PropsType) {
setIsShow(true)
}
if (props.text && props.newText) {
setModal(true)
// console.log(props.text, props.newText);
// notification.open({
// message: '提示',
// description: (
// <div>
// 是否替换当前{props.title}
// <div>
// <Button
// type="link"
// onClick={() => {
// // setModal(false);
// setText(newText)
// props.handleSave(newText);
// setNewText('')
// api.destroy(key)
// }}
// >
// 替换
// </Button>
// <Button
// type="link"
// onClick={() => api.destroy(key)}
// >
// 取消
// </Button>
// </div>
// </div>
// ),
// key,
// onClose: close,
// // onClose: () => {
// // close();
// // },
// });
notification.open({
message: '提示',
description:
`${props.title}已生成完毕,是否替换当前${props.title}`,
btn: (
<div>
<Button size="small" onClick={() => {
if (props.title == key) {
notification.destroy(key)
}
// if (props.title == '系统简介') {
// props.setActiveTab('简介')
// }
// if (props.title == '系统详情') {
// props.setActiveTab('详情')
// }
}}>
</Button>
<Button type="primary" size="small"
style={{ marginLeft: 8 }}
onClick={() => {
setText(props.newText)
props.handleSave(props.newText);
setNewText('')
if (props.title == key) {
notification.destroy(key)
}
if (props.title == '系统简介') {
props.setActiveTab('简介')
}
if (props.title == '系统详情') {
props.setActiveTab('详情')
}
}}>
</Button>
</div>
),
key,
onClose: close,
// duration: null,
placement: 'bottomRight', // 设置通知框显示在右下角
style: {
width: 300, // 设置通知框的宽度
height: 150, // 设置通知框的高度
},
});
}
if (!props.text && props.newText) {
// console.log('aaaaaaaa',props.newText);
@ -134,7 +231,7 @@ export default function AiHelperText(props: PropsType) {
const renderTextDom = () => {
if (!props.text) {
return (
<div className="aiText-top-notext"
<div className="aiText-top-notext"
// style={{position:'relative'}}
>
{/* <Empty description="暂无内容" /> */}
@ -144,16 +241,30 @@ export default function AiHelperText(props: PropsType) {
,
<span style={{ color: '#FF9D00', cursor: 'pointer' }}
onClick={() => {
props.handleGenerate();
if (props.isFast) {
return
} else {
if (props.title == '系统简介') {
props.xixi()
}
if (props.title == '系统详情') {
if (!props.projIntroduction) {
props.xixi()
} else {
props.handleGenerate()
}
}
}
}}
></span>
</div>
<div className="aiNotext-tip"
style={{
display:props.title=='系统详情'? 'block' : 'none'
}}
></div>
<div className="aiNotext-tip"
style={{
display: props.title == '系统详情' ? 'block' : 'none'
}}
></div>
</div>
{/* <div style={{color:'red',position: 'absolute', bottom: 70,textAlign:'center',width:600 , left: -140}}>为了合理生成功能列表,建议在项目简介生成完成后再生成功能列表</div> */}
</div>
@ -209,7 +320,7 @@ export default function AiHelperText(props: PropsType) {
<div className="aiText" style={{ height: `${height}px`,overflow:'auto' }}>
<div className="aiText" style={{ height: `${height}px`, overflow: 'auto' }}>
<div className="aiText-top">
{renderTextDom()}
<div className="aiText-top-btn" style={{ display: props.text ? 'block' : 'none' }}>
@ -284,26 +395,41 @@ export default function AiHelperText(props: PropsType) {
}}
onClick={() => {
setModal(true)
setText(newText)
props.handleSave(newText);
setNewText('')
// setModal(true)
// setNewText('')
notification.destroy(key)
}}
></Button>
<Button
disabled={status == 'SUCCESS' || status == 'GENERATING' ? true : false}
disabled={status == 'SUCCESS' || status == 'GENERATING' || props.isFast ? true : false}
// size="large"
type="primary" style={{
width: 109,
marginLeft: 15,
}}
onClick={() => {
props.handleGenerate()
if (props.title == '系统简介') {
props.xixi()
}
if (props.title == '系统详情') {
if (!props.projIntroduction) {
props.xixi()
} else {
props.handleGenerate()
}
}
}}
>AI生成</Button>
>{props.title == '系统简介' ? '一键生成' : 'AI生成'}</Button>
{/* <Button
onClick={() => {
props.xixi()
}}></Button> */}
</div>
</div>
<Modal
{/* <Modal
title={'提示'}
destroyOnClose={true}
open={modal}
@ -332,7 +458,7 @@ export default function AiHelperText(props: PropsType) {
{props.title}
</div>
</Modal>
</Modal> */}
</div>
</>
)

View File

@ -5,7 +5,8 @@ import { useNavigate, useParams } from "react-router-dom";
import {
Button,
// FloatButton,
message, Modal
message, Modal,
notification
} from "antd";
import StepProjEdit from "../../components/step/StepProjEdit.tsx";
import CardProjEdit from "../../components/card/CardProjEdit.tsx";
@ -701,6 +702,7 @@ export default function ProjEdit() {
maskClosable={false}
destroyOnClose={true}
onCancel={() => {
notification.destroy()
getListMods()
// if (aiHelper.projIntroduction && aiHelper.projDesc && listMods.length > 0) {
// setAiHelperModalOpen(false);