This commit is contained in:
WenC 2024-04-25 15:37:50 +08:00
parent 4058877acd
commit 8e8007f570
10 changed files with 226 additions and 148 deletions

View File

@ -1,18 +1,20 @@
import {useContext, useEffect, useRef, useState} from "react";
import {GlobalContext} from "../../context/GlobalContext.ts";
import {get, post, put, WebSocketBaseUrl} from "../../util/AjaxUtils.ts";
import {del, get, post, put, websocketUrl} from "../../util/AjaxUtils.ts";
import {Col, Divider, Row, Spin} from "antd";
import useMessage from "antd/es/message/useMessage";
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";
import {useNavigate} from "react-router-dom";
import {uuid} from "../../util/CommonUtil.ts";
type PropsType = {
projId: string;
projIntroduction?: string;
projDesc?: string;
projMods?: ProjModType[];
isFree: boolean;
}
type ProjModType = {
@ -37,6 +39,7 @@ export default function AiHelper(props: PropsType) {
const [projModArray, setProjModArray] = useState<IProjMod[]>([]);
const [newProjModArray, setNewProjModArray] = useState<ProjModType[]>([]);
const [isProjModArrayLoading, setIsProjModArrayLoading] = useState(false);
const nav = useNavigate();
const ping = () => {
@ -51,7 +54,7 @@ export default function AiHelper(props: PropsType) {
}
const websocket = () => {
ws.current = new WebSocket(`${WebSocketBaseUrl}/ws/ai/${globalContext.user.userId}`);
ws.current = new WebSocket(`${websocketUrl()}/ws/ai/${globalContext.user.userId}`);
ws.current.onopen = (event) => {
console.log('打开', event);
ping();
@ -73,6 +76,7 @@ export default function AiHelper(props: PropsType) {
} else if (data.type == 'REFRESH_PROJ_MODS') {
setIsProjModArrayLoading(false);
const projMods = JSON.parse(data.content) as ProjModType[];
projMods.forEach(projMod => projMod.id = uuid())
setNewProjModArray(projMods);
} else if (data.type == 'REFRESH_PROJ_MOD_FIELDS') {
listMods();
@ -273,6 +277,37 @@ export default function AiHelper(props: PropsType) {
}
})
}}
handleEdit={(_index, projModId, item) => {
if(item.aiFieldStatus != 'SUCCESS') {
messageApi.error('模块未处理完毕不能编辑');
return;
}
if(props.isFree) {
nav(`/proj-edit/config-mod-fedit/${props.projId}/${projModId}`)
} else {
nav(`/proj-edit/config-mod-edit/${props.projId}/${projModId}`)
}
}}
handleRemove={(_index, projModId, item) => {
if(item.aiFieldStatus != 'SUCCESS') {
messageApi.error('模块未处理完毕不能删除');
return;
}
del<any>({
messageApi,
url: `/api/proj-mod/remove/proj-id/${props.projId}/${projModId}`,
onBefore() {
setIsProjModArrayLoading(true);
},
onSuccess() {
messageApi.success('删除成功');
listMods();
},
onFinally() {
setIsProjModArrayLoading(false);
}
})
}}
/>
</Spin>
</Col>

View File

@ -9,6 +9,8 @@ type PropsType = {
handleGenerate: () => void;
handleSave: (index: number, mod: ProjModType) => void;
handleResaveField: (index: number, projModId: string) => void;
handleRemove: (index: number, projModId: string, item: IProjMod) => void;
handleEdit: (index: number, projModId: string, item: IProjMod) => void;
}
type ProjModType = {
@ -16,16 +18,6 @@ type ProjModType = {
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[]>([]);
@ -58,7 +50,7 @@ export default function AiHelperMod(props: PropsType) {
if(value == 'GENERATING') {
return '处理中'
}
if(value == 'FIELD') {
if(value == 'FAILED') {
return '失败'
}
if(value == 'SUCCESS') {
@ -82,7 +74,21 @@ export default function AiHelperMod(props: PropsType) {
}}><RedoOutlined /></Button>
}
return (
<Dropdown menu={{ items: savedItems }} placement="bottomCenter" arrow>
<Dropdown menu={{ items: [
{
key: 'edit',
label: '编辑',
onClick: () => {
props.handleEdit(index, record.projModId, record);
}
},{
key: 'remove',
label: '删除',
onClick: () => {
props.handleRemove(index, record.projModId, record);
}
},
] }} placement="bottom" arrow>
<Button></Button>
</Dropdown>
)
@ -123,14 +129,17 @@ export default function AiHelperMod(props: PropsType) {
return (
<>
<div style={{padding: '5px 0 0 0', fontWeight: 'bold'}}></div>
<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}/>
<Table columns={modColumnArray} dataSource={modArray} size="small" bordered={true} scroll={{y: 240}}
pagination={false} rowKey="projModId"/>
{
newModArray.length > 0 ? (
<>
<Divider orientation="right" plain></Divider>
<Table columns={newModColumnArray} dataSource={newModArray} size="small" bordered={true} scroll={{y: 240}} pagination={false}/>
<Table columns={newModColumnArray} dataSource={newModArray} size="small" bordered={true}
scroll={{y: 240}} pagination={false} rowKey="id"/>
</>
) : <></>
}

View File

@ -19,7 +19,12 @@ export default function CardProjLoading(props: IProjLoading) {
}, [duration])
return (
<div className="card-proj-loading">
<div className="card-proj-loading" onClick={() => {
if (!props.handleClick) {
return;
}
props.handleClick();
}}>
<div className="title">
<Loading3QuartersOutlined spin={true} style={{color: '#0052d9'}}/>
<span className="label">{props.title}</span>

View File

@ -1,6 +1,7 @@
.card-proj-loading {
width: 224px;
padding: 10px 15px;
cursor: pointer;
}
.card-proj-loading .title {

View File

@ -19,6 +19,8 @@ export interface IProjLoading {
desc?: string;
duration: number;
handleClick?(): void;
handleCountDownOver(): void;
}

View File

@ -45,92 +45,92 @@ export default function ProjCreate() {
/>
<div style={{height: `${height}px`, overflow: 'auto'}}>
<div className="proj-create">
<CardProjType
head={'全托管'}
bodyLineArray={[
{
title: '提供的服务:',
contents: [
'提供系统搭建',
'系统可在线运行三年',
'软著材料编写',
'软著申报',
'包下证',
'提供系统演示视频文件',
'提供系统安装包',
]
},
{
title: '使用流程:',
contents: [
'编写软著名称',
'对搭建系统进行核验',
'接受证书',
]
}
]}
buyArray={[
{
id: ProjChargeType.ALL,
price: charge.proj.all,
handleClick: () => {
nav(`/proj-new/${ProjChargeType.ALL}`)
}
}
]}
/>
<CardProjType
head={'写材料+代理'}
bodyLineArray={[
{
title: '提供的服务:',
contents: [
'提供系统搭建平台与客服指导',
'系统可在线运行一年',
'软著材料编写',
'资料补正不限',
'软著申报',
'包下证',
]
},
{
title: '使用流程:',
contents: [
'1、按系统操作手册执行',
]
}
]}
chargeLineArray={[
{
id: ProjAdditionalType.PKG,
price: charge.additional.pkg,
title: `安装包 ${charge.additional.pkg / 100}`
},
{
id: ProjAdditionalType.VIDEO_DEMO,
price: charge.additional.videoDemo,
title: `系统演示视频文件 ${charge.additional.videoDemo / 100}`
}
]}
buyArray={[
{
id: ProjChargeType.MATERIAL_AGENT,
label: '普件:',
price: charge.proj.materialAgent,
handleClick: (_title, additional) => {
nav(`/proj-new/${ProjChargeType.MATERIAL_AGENT}?pkg=${additional.pkg}&videoDemo=${additional.videoDemo}`)
}
},
{
id: ProjChargeType.MATERIAL_AGENT_URGENT,
label: '加急:',
price: charge.proj.materialAgentUrgent,
handleClick: (_title, additional) => {
nav(`/proj-new/${ProjChargeType.MATERIAL_AGENT_URGENT}?pkg=${additional.pkg}&videoDemo=${additional.videoDemo}`)
}
}
]}
/>
{/*<CardProjType*/}
{/* head={'全托管'}*/}
{/* bodyLineArray={[*/}
{/* {*/}
{/* title: '提供的服务:',*/}
{/* contents: [*/}
{/* '提供系统搭建',*/}
{/* '系统可在线运行三年',*/}
{/* '软著材料编写',*/}
{/* '软著申报',*/}
{/* '包下证',*/}
{/* '提供系统演示视频文件',*/}
{/* '提供系统安装包',*/}
{/* ]*/}
{/* },*/}
{/* {*/}
{/* title: '使用流程:',*/}
{/* contents: [*/}
{/* '编写软著名称',*/}
{/* '对搭建系统进行核验',*/}
{/* '接受证书',*/}
{/* ]*/}
{/* }*/}
{/* ]}*/}
{/* buyArray={[*/}
{/* {*/}
{/* id: ProjChargeType.ALL,*/}
{/* price: charge.proj.all,*/}
{/* handleClick: () => {*/}
{/* nav(`/proj-new/${ProjChargeType.ALL}`)*/}
{/* }*/}
{/* }*/}
{/* ]}*/}
{/*/>*/}
{/*<CardProjType*/}
{/* head={'写材料+代理'}*/}
{/* bodyLineArray={[*/}
{/* {*/}
{/* title: '提供的服务:',*/}
{/* contents: [*/}
{/* '提供系统搭建平台与客服指导',*/}
{/* '系统可在线运行一年',*/}
{/* '软著材料编写',*/}
{/* '资料补正不限',*/}
{/* '软著申报',*/}
{/* '包下证',*/}
{/* ]*/}
{/* },*/}
{/* {*/}
{/* title: '使用流程:',*/}
{/* contents: [*/}
{/* '1、按系统操作手册执行',*/}
{/* ]*/}
{/* }*/}
{/* ]}*/}
{/* chargeLineArray={[*/}
{/* {*/}
{/* id: ProjAdditionalType.PKG,*/}
{/* price: charge.additional.pkg,*/}
{/* title: `安装包 ${charge.additional.pkg / 100} 元`*/}
{/* },*/}
{/* {*/}
{/* id: ProjAdditionalType.VIDEO_DEMO,*/}
{/* price: charge.additional.videoDemo,*/}
{/* title: `系统演示视频文件 ${charge.additional.videoDemo / 100} 元`*/}
{/* }*/}
{/* ]}*/}
{/* buyArray={[*/}
{/* {*/}
{/* id: ProjChargeType.MATERIAL_AGENT,*/}
{/* label: '普件:',*/}
{/* price: charge.proj.materialAgent,*/}
{/* handleClick: (_title, additional) => {*/}
{/* nav(`/proj-new/${ProjChargeType.MATERIAL_AGENT}?pkg=${additional.pkg}&videoDemo=${additional.videoDemo}`)*/}
{/* }*/}
{/* },*/}
{/* {*/}
{/* id: ProjChargeType.MATERIAL_AGENT_URGENT,*/}
{/* label: '加急:',*/}
{/* price: charge.proj.materialAgentUrgent,*/}
{/* handleClick: (_title, additional) => {*/}
{/* nav(`/proj-new/${ProjChargeType.MATERIAL_AGENT_URGENT}?pkg=${additional.pkg}&videoDemo=${additional.videoDemo}`)*/}
{/* }*/}
{/* }*/}
{/* ]}*/}
{/*/>*/}
<CardProjType
head={'写材料'}
bodyLineArray={[
@ -171,39 +171,39 @@ export default function ProjCreate() {
{
id: ProjChargeType.MATERIAL,
price: charge.proj.material,
handleClick: () => {
nav(`/proj-new/${ProjChargeType.MATERIAL}`)
}
}
]}
/>
<CardProjType
head={'免费试用'}
bodyLineArray={[
{
title: '提供的服务:',
contents: [
'提供系统搭建平台与客服指导',
'系统可在线存储三天',
]
},
{
title: '使用流程:',
contents: [
'按系统操作手册执行',
]
}
]}
buyArray={[
{
id: ProjChargeType.FREE,
price: charge.proj.free,
handleClick: () => {
nav(`/proj-new/${ProjChargeType.FREE}`)
handleClick: (_title, additional) => {
nav(`/proj-new/${ProjChargeType.MATERIAL}?${additional.pkg ? 'pkg=true' : 'pkg='}&${additional.videoDemo ? 'videoDemo=true' : 'videoDemo='}`);
}
}
]}
/>
{/*<CardProjType*/}
{/* head={'免费试用'}*/}
{/* bodyLineArray={[*/}
{/* {*/}
{/* title: '提供的服务:',*/}
{/* contents: [*/}
{/* '提供系统搭建平台与客服指导',*/}
{/* '系统可在线存储三天',*/}
{/* ]*/}
{/* },*/}
{/* {*/}
{/* title: '使用流程:',*/}
{/* contents: [*/}
{/* '按系统操作手册执行',*/}
{/* ]*/}
{/* }*/}
{/* ]}*/}
{/* buyArray={[*/}
{/* {*/}
{/* id: ProjChargeType.FREE,*/}
{/* price: charge.proj.free,*/}
{/* handleClick: (_title, additional) => {*/}
{/* nav(`/proj-new/${ProjChargeType.FREE}?${additional.pkg ? 'pkg=true' : 'pkg='}&${additional.videoDemo ? 'videoDemo=true' : 'videoDemo='}`)*/}
{/* }*/}
{/* }*/}
{/* ]}*/}
{/*/>*/}
</div>
</div>
</>

View File

@ -11,7 +11,7 @@ import CardProjJump from "../../components/card/CardProjJump.tsx";
import {useEffect, useState} from "react";
import {Axios, get, post} from "../../util/AjaxUtils.ts";
import {EditStepEnum, IProjEdit} from "../../interfaces/card/ICardProj.ts";
import {MAX_MOD_SIZE} from "./edit/ProjConfigModList.tsx";
import {MIN_MOD_SIZE} from "./edit/ProjConfigModList.tsx";
import {GenerateStatus} from "../../interfaces/proj/IProj.ts";
import AiHelper from "../../components/ai/AiHelper.tsx";
@ -168,7 +168,7 @@ export default function ProjEdit() {
desc: '请对系统菜单进行设置',
step: 2,
btnName: !isGenerateSuccess ? '设置' : '查看',
status: data.projModCount > MAX_MOD_SIZE ? EditStepEnum.EDITED : EditStepEnum.UN_EDIT,
status: data.projModCount >= MIN_MOD_SIZE ? EditStepEnum.EDITED : EditStepEnum.UN_EDIT,
handleEdit() {
if (!isGenerateSuccess) {
nav(`/proj-edit/config-mod-list/${pathParams.projId}`)
@ -182,7 +182,7 @@ export default function ProjEdit() {
desc: '调整菜单顺序',
step: 3,
btnName: !isGenerateSuccess ? '设置' : '查看',
status: data.projModCount > MAX_MOD_SIZE ? EditStepEnum.EDITED : EditStepEnum.UN_EDIT,
status: data.projModCount >= MIN_MOD_SIZE ? EditStepEnum.EDITED : EditStepEnum.UN_EDIT,
handleEdit() {
if (!isGenerateSuccess) {
nav(`/proj-edit/config-menu-list/${pathParams.projId}`)
@ -207,7 +207,7 @@ export default function ProjEdit() {
&& data.editSteps[3].editStatus == EditStepEnum.EDITED
&& data.editSteps[4].editStatus == EditStepEnum.EDITED
&& data.editSteps[5].editStatus == EditStepEnum.EDITED;
const isConfig = data.loginpage.loginpageId && data.projModCount > MAX_MOD_SIZE;
const isConfig = data.loginpage.loginpageId && data.projModCount > MIN_MOD_SIZE;
const isGenerate = isEdited && isConfig;
const isGenerateSuccess: boolean = data.generate.generateStatus == GenerateStatus.SUCCESS;
renderEditStep(data.editSteps, isEdited, isGenerateSuccess);
@ -272,7 +272,7 @@ export default function ProjEdit() {
title={item.title}
desc={item.desc}
btnName={item.btnName}
canBtnClick={true}
canBtnClick={item.status == EditStepEnum.EDITED}
status={item.status}
handleEdit={item.handleEdit}
/>
@ -282,6 +282,7 @@ export default function ProjEdit() {
isEditStepEdited && isConfigEdited ? (
<CardProjJump title="预览系统"
desc="点击查看预览系统"
canBtnClick={true}
handleJump={() => {
window.open(`${Axios.defaults?.baseURL}/${previewUrl}`, '_blank')
}}
@ -302,6 +303,9 @@ export default function ProjEdit() {
canBtnClick={canGenerate}
handleEdit={() => {
setIsGenerateModalOpen(true);
setTimeout(() => {
window.location.reload();
}, 1000)
}}
/>
) : <></>
@ -312,7 +316,9 @@ export default function ProjEdit() {
desc="资料正在排队"
duration={generateEmainingTime}
handleCountDownOver={() => {
renderData();
setTimeout(() => {
window.location.reload();
}, 1000)
}}
/>
) : <></>
@ -320,8 +326,11 @@ export default function ProjEdit() {
{
generateStatus == GenerateStatus.GENERATING ? (
<CardProjLoading title="正在生成"
desc="资料正在生成"
desc="资料正在生成,点击刷新"
duration={generateEmainingTime}
handleClick={() => {
renderData();
}}
handleCountDownOver={() => {
renderData();
}}
@ -445,15 +454,18 @@ export default function ProjEdit() {
title="AI助手"
width={1200}
footer={false}
maskClosable={false}
destroyOnClose
onCancel={() => {
setAiHelperModalOpen(false);
renderData()
}}
>
<AiHelper
projId={aiHelper.projId}
projIntroduction={aiHelper.projIntroduction}
projDesc={aiHelper.projDesc}
projMods={aiHelper.projMods}
isFree={false}
/>
</Modal>
</>

View File

@ -10,7 +10,7 @@ import {useEffect, useState} from "react";
import {EditOutlined, PlusOutlined, DeleteOutlined, SearchOutlined} from "@ant-design/icons";
import {del, get} from "../../../util/AjaxUtils.ts";
export const MAX_MOD_SIZE = 18;
export const MAX_MOD_SIZE = 15;
export const MIN_MOD_SIZE = 10
export const MAX_MOD_SIZE_FREE = 3
export const MIN_MOD_SIZE_FREE = 1

View File

@ -66,7 +66,7 @@ export default function ProjEditStep4() {
authorIdCard: data.authorIdCard,
authorNation: data.authorNation ? data.authorNation : '中国',
authorProvince: data.authorProvince ? data.authorProvince.split(',') : '',
authorEstablishDate: dayjs(data.authorEstablishDate, 'YYYY-MM-DD'),
authorEstablishDate: data.authorEstablishDate ? dayjs(data.authorEstablishDate, 'YYYY-MM-DD') : '',
})
}
})

View File

@ -3,12 +3,13 @@ import type {MessageInstance} from "antd/es/message/interface";
export const Axios = axios;
axios.defaults.baseURL = 'http://127.0.0.1:7025/copyright';
// axios.defaults.baseURL = '/copyright';
export const WebSocketBaseUrl: string = "ws://127.0.0.1:7025/copyright"
export const DevUserId: string = '80d3365e-0597-4988-979e-18ef1c3ec671'; // 18634604067
// axios.defaults.baseURL = 'http://127.0.0.1:7025/copyright';
axios.defaults.baseURL = '/copyright';
// export const WebSocketBaseUrl: string = 'ws://127.0.0.1:7025/copyright';
export const WebSocketBaseUrl: string = '/copyright';
// export const DevUserId: string = '80d3365e-0597-4988-979e-18ef1c3ec671'; // 18634604067
// export const DevUserId: string = 'c2438eb8-2685-49a9-bf02-5111a5192d96'; // 18647109157
// export const DevUserId: string = '';
export const DevUserId: string = '';
type Req<T> = {
messageApi: MessageInstance;
@ -36,6 +37,19 @@ axios.interceptors.request.use(config => {
}
);
export function websocketUrl() {
if (WebSocketBaseUrl.startsWith('ws')) {
return WebSocketBaseUrl;
}
const location = window.location;
const protocol = location.protocol;
let wsProtocol = 'ws';
if (protocol == 'https') {
wsProtocol = 'wss';
}
return `${wsProtocol}://${location.host}${WebSocketBaseUrl}`;
}
export function downloadUrl(fileId: string, isDownload?: boolean) {
return `${Axios.defaults?.baseURL}/route/file/v2/download/${isDownload == false}/${fileId}`
}