完善功能
This commit is contained in:
parent
9160a37bbe
commit
c83637d1bc
@ -1,18 +1,20 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
root: true,
|
root: true,
|
||||||
env: { browser: true, es2020: true },
|
env: {browser: true, es2020: true},
|
||||||
extends: [
|
extends: [
|
||||||
'eslint:recommended',
|
'eslint:recommended',
|
||||||
'plugin:@typescript-eslint/recommended',
|
'plugin:@typescript-eslint/recommended',
|
||||||
'plugin:react-hooks/recommended',
|
'plugin:react-hooks/recommended',
|
||||||
],
|
|
||||||
ignorePatterns: ['dist', '.eslintrc.cjs'],
|
|
||||||
parser: '@typescript-eslint/parser',
|
|
||||||
plugins: ['react-refresh'],
|
|
||||||
rules: {
|
|
||||||
'react-refresh/only-export-components': [
|
|
||||||
'warn',
|
|
||||||
{ allowConstantExport: true },
|
|
||||||
],
|
],
|
||||||
},
|
ignorePatterns: ['dist', '.eslintrc.cjs'],
|
||||||
|
parser: '@typescript-eslint/parser',
|
||||||
|
plugins: ['react-refresh'],
|
||||||
|
rules: {
|
||||||
|
'react-refresh/only-export-components': [
|
||||||
|
'warn',
|
||||||
|
{allowConstantExport: true},
|
||||||
|
],
|
||||||
|
// 去除any报错
|
||||||
|
'@typescript-eslint/no-explicit-any': ['off']
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
@ -2,10 +2,13 @@ import './card-proj-type.css';
|
|||||||
import {ICardProj, ICardProjChargeLine} from "../../interfaces/proj/ICardProj.ts";
|
import {ICardProj, ICardProjChargeLine} from "../../interfaces/proj/ICardProj.ts";
|
||||||
import {Checkbox} from 'antd';
|
import {Checkbox} from 'antd';
|
||||||
import {useState} from "react";
|
import {useState} from "react";
|
||||||
|
import {ProjAdditionalType} from "../../interfaces/proj/IProj.ts";
|
||||||
|
|
||||||
export default function CardProjType(props: ICardProj) {
|
export default function CardProjType(props: ICardProj) {
|
||||||
|
|
||||||
const [chargeAmount, setChargeAmount] = useState(0);
|
const [chargeAmount, setChargeAmount] = useState(0);
|
||||||
|
const [pkg, setPkg] = useState(false);
|
||||||
|
const [videoDemo, setVideoDemo] = useState(false);
|
||||||
|
|
||||||
const renderContents = (lineIndex: number, contents: string[]) => {
|
const renderContents = (lineIndex: number, contents: string[]) => {
|
||||||
return contents.map((item, index) => <li key={`content_${lineIndex}_${index}`}>
|
return contents.map((item, index) => <li key={`content_${lineIndex}_${index}`}>
|
||||||
@ -29,8 +32,18 @@ export default function CardProjType(props: ICardProj) {
|
|||||||
|
|
||||||
const onChargeChange = (checked: boolean, line: ICardProjChargeLine) => {
|
const onChargeChange = (checked: boolean, line: ICardProjChargeLine) => {
|
||||||
if (checked) {
|
if (checked) {
|
||||||
|
if (line.id == ProjAdditionalType.PKG) {
|
||||||
|
setPkg(true);
|
||||||
|
} else if (line.id == ProjAdditionalType.VIDEO_DEMO) {
|
||||||
|
setVideoDemo(true);
|
||||||
|
}
|
||||||
setChargeAmount(chargeAmount + line.price);
|
setChargeAmount(chargeAmount + line.price);
|
||||||
} else {
|
} else {
|
||||||
|
if (line.id == ProjAdditionalType.PKG) {
|
||||||
|
setPkg(false);
|
||||||
|
} else if (line.id == ProjAdditionalType.VIDEO_DEMO) {
|
||||||
|
setVideoDemo(false);
|
||||||
|
}
|
||||||
setChargeAmount(chargeAmount - line.price);
|
setChargeAmount(chargeAmount - line.price);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -60,13 +73,15 @@ export default function CardProjType(props: ICardProj) {
|
|||||||
return props.buyArray.map((buy, index) => {
|
return props.buyArray.map((buy, index) => {
|
||||||
return (
|
return (
|
||||||
<div className="buy-btn" key={`buy_${index}`}>
|
<div className="buy-btn" key={`buy_${index}`}>
|
||||||
<div className="price">{buy.label}{buy.price + chargeAmount} 元</div>
|
<div className="price">{buy.label}{(buy.price + chargeAmount) / 100} 元</div>
|
||||||
<hr/>
|
<hr/>
|
||||||
<div className="buy">
|
<div className="buy">
|
||||||
<button onClick={() => {
|
<button onClick={() => {
|
||||||
buy.handleClick(props.head, buy.price + chargeAmount);
|
buy.handleClick(props.head, {
|
||||||
}}>购买
|
pkg: pkg,
|
||||||
</button>
|
videoDemo: videoDemo
|
||||||
|
});
|
||||||
|
}}>购买</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
import './list-proj.css'
|
import './list-proj.css'
|
||||||
import CardProj from "../card/CardProj.tsx";
|
import CardProj from "../card/CardProj.tsx";
|
||||||
import {useRef, MutableRefObject, useState, useEffect} from "react";
|
import {useRef, MutableRefObject, useState, useEffect} from "react";
|
||||||
import {Input, Pagination} from 'antd';
|
import {Input, Pagination, message} from 'antd';
|
||||||
import type {SearchProps} from 'antd/es/input/Search';
|
import type {SearchProps} from 'antd/es/input/Search';
|
||||||
import {Axios} from "../../util/AjaxUtils.ts";
|
import {get} from "../../util/AjaxUtils.ts";
|
||||||
|
|
||||||
|
|
||||||
const {Search} = Input;
|
const {Search} = Input;
|
||||||
@ -17,25 +17,28 @@ export default function ListProj() {
|
|||||||
const listProjRef: MutableRefObject<HTMLDivElement | null> = useRef(null);
|
const listProjRef: MutableRefObject<HTMLDivElement | null> = useRef(null);
|
||||||
const listRef: MutableRefObject<HTMLDivElement | null> = useRef(null);
|
const listRef: MutableRefObject<HTMLDivElement | null> = useRef(null);
|
||||||
|
|
||||||
const [page, _setPage] = useState(1);
|
const [messageApi, contextHolder] = message.useMessage();
|
||||||
const [total, _setTotal] = useState(0);
|
const [page, setPage] = useState(1);
|
||||||
const [projs, _setProjs] = useState([]);
|
const [total, setTotal] = useState(0);
|
||||||
|
const [projs, setProjs] = useState([]);
|
||||||
|
|
||||||
const domHeight = window.innerHeight - 280;
|
const domHeight = window.innerHeight - 280;
|
||||||
|
|
||||||
const renderData = () => {
|
const reqData = (currentPage: number) => {
|
||||||
Axios.get('/api/proj/listpage/self', {
|
get({
|
||||||
params: {
|
messageApi: messageApi,
|
||||||
page: page,
|
url: '/api/proj/listpage/self',
|
||||||
rows: 20
|
config: {
|
||||||
|
params: {
|
||||||
|
page: currentPage,
|
||||||
|
rows: 20
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onSuccess({data}) {
|
||||||
|
setProjs(data.page);
|
||||||
|
setTotal(data.total);
|
||||||
|
setProjs(data.rows);
|
||||||
}
|
}
|
||||||
}).then(res => {
|
|
||||||
const data = res.data;
|
|
||||||
_setProjs(data.page);
|
|
||||||
_setTotal(data.total);
|
|
||||||
_setProjs(data.rows);
|
|
||||||
}).catch(res => {
|
|
||||||
console.log(res);
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -44,22 +47,28 @@ export default function ListProj() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
renderData();
|
reqData(page);
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="list-proj" ref={listProjRef}>
|
<>
|
||||||
<div className="top">
|
{contextHolder}
|
||||||
<Search placeholder="按项目名搜索" onSearch={onSearch} style={{width: 200}}/>
|
<div className="list-proj" ref={listProjRef}>
|
||||||
</div>
|
<div className="top">
|
||||||
<div className="body">
|
<Search placeholder="按项目名搜索" onSearch={onSearch} style={{width: 200}}/>
|
||||||
<div className="list" ref={listRef} style={{height: `${domHeight}px`}}>
|
|
||||||
{renderList()}
|
|
||||||
</div>
|
</div>
|
||||||
<div className="page">
|
<div className="body">
|
||||||
<Pagination defaultCurrent={page} total={total}/>
|
<div className="list" ref={listRef} style={{height: `${domHeight}px`}}>
|
||||||
|
{renderList()}
|
||||||
|
</div>
|
||||||
|
<div className="page">
|
||||||
|
<Pagination defaultCurrent={page} total={total} onChange={(page) => {
|
||||||
|
setPage(page);
|
||||||
|
reqData(page);
|
||||||
|
}}/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
@ -1,18 +1,24 @@
|
|||||||
|
|
||||||
export interface ICardProjBodyLine {
|
export interface ICardProjBodyLine {
|
||||||
title: string;
|
title: string;
|
||||||
contents: string[];
|
contents: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ICardProjChargeLine {
|
export interface ICardProjChargeLine {
|
||||||
|
id: string;
|
||||||
title: string;
|
title: string;
|
||||||
price: number;
|
price: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ICardProjBuy {
|
export interface ICardProjBuy {
|
||||||
|
id: string;
|
||||||
label?: string,
|
label?: string,
|
||||||
price: number;
|
price: number;
|
||||||
|
|
||||||
handleClick(title: string, price: number): void;
|
handleClick(title: string, additional: {
|
||||||
|
pkg: boolean,
|
||||||
|
videoDemo: boolean
|
||||||
|
}): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ICardProj {
|
export interface ICardProj {
|
||||||
|
@ -20,6 +20,34 @@ export enum GenerateStatus {
|
|||||||
ERROR = 'ERROR'
|
ERROR = 'ERROR'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum ProjChargeType {
|
||||||
|
ALL = 'ALL',
|
||||||
|
MATERIAL_AGENT = 'MATERIAL_AGENT',
|
||||||
|
MATERIAL_AGENT_URGENT = 'MATERIAL_AGENT_URGENT',
|
||||||
|
MATERIAL = 'MATERIAL',
|
||||||
|
FREE = 'FREE',
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum ProjAdditionalType {
|
||||||
|
PKG = 'PKG',
|
||||||
|
VIDEO_DEMO = 'VIDEO_DEMO'
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IProjCharge {
|
||||||
|
proj: {
|
||||||
|
all: number;
|
||||||
|
materialAgent: number;
|
||||||
|
materialAgentUrgent: number;
|
||||||
|
material: number;
|
||||||
|
free: number;
|
||||||
|
},
|
||||||
|
additional: {
|
||||||
|
pkg: number;
|
||||||
|
videoDemo: number;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
export interface IProj {
|
export interface IProj {
|
||||||
|
|
||||||
projId: string,
|
projId: string,
|
||||||
@ -33,5 +61,4 @@ export interface IProj {
|
|||||||
gmtCreate: string,
|
gmtCreate: string,
|
||||||
generateStatus: GenerateStatus
|
generateStatus: GenerateStatus
|
||||||
|
|
||||||
|
}
|
||||||
}
|
|
||||||
|
@ -16,11 +16,11 @@ const router = createBrowserRouter([
|
|||||||
element: <ProjCreate />
|
element: <ProjCreate />
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/proj-new/:type/:price',
|
path: '/proj-new/:projChargeType',
|
||||||
element: <ProjNew />
|
element: <ProjNew />
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/proj-edit',
|
path: '/proj-edit/:projId',
|
||||||
element: <ProjEdit />
|
element: <ProjEdit />
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
import React from 'react'
|
|
||||||
import ReactDOM from 'react-dom/client'
|
import ReactDOM from 'react-dom/client'
|
||||||
import App from './App.tsx'
|
import App from './App.tsx'
|
||||||
import './index.css'
|
import './index.css'
|
||||||
|
@ -1,13 +1,42 @@
|
|||||||
import './proj-create.css'
|
import './proj-create.css'
|
||||||
import {Link, useNavigate} from "react-router-dom";
|
import {Link, useNavigate} from "react-router-dom";
|
||||||
import {Breadcrumb} from "antd";
|
import {Breadcrumb, message} from "antd";
|
||||||
import CardProjType from "../../components/card/CardProjType.tsx";
|
import CardProjType from "../../components/card/CardProjType.tsx";
|
||||||
|
import {IProjCharge, ProjAdditionalType, ProjChargeType} from "../../interfaces/proj/IProj.ts";
|
||||||
|
import {useEffect, useState} from "react";
|
||||||
|
import {get} from "../../util/AjaxUtils.ts";
|
||||||
|
|
||||||
export default function ProjCreate() {
|
export default function ProjCreate() {
|
||||||
|
const [messageApi, contextHolder] = message.useMessage();
|
||||||
|
const [charge, setCharge] = useState<IProjCharge>({
|
||||||
|
proj: {
|
||||||
|
all: 0,
|
||||||
|
materialAgent: 0,
|
||||||
|
materialAgentUrgent: 0,
|
||||||
|
material: 0,
|
||||||
|
free: 0,
|
||||||
|
},
|
||||||
|
additional: {
|
||||||
|
pkg: 0,
|
||||||
|
videoDemo: 0
|
||||||
|
}
|
||||||
|
});
|
||||||
const nav = useNavigate();
|
const nav = useNavigate();
|
||||||
const height = window.innerHeight - 150;
|
const height = window.innerHeight - 150;
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
get({
|
||||||
|
messageApi: messageApi,
|
||||||
|
url: '/api/proj/charge/get',
|
||||||
|
onSuccess({data}) {
|
||||||
|
setCharge(data);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}, [])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
{contextHolder}
|
||||||
<Breadcrumb
|
<Breadcrumb
|
||||||
items={[
|
items={[
|
||||||
{title: <Link to={'/'}>首页</Link>},
|
{title: <Link to={'/'}>首页</Link>},
|
||||||
@ -15,7 +44,7 @@ export default function ProjCreate() {
|
|||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
<div style={{height: `${height}px`, overflow: 'auto'}}>
|
<div style={{height: `${height}px`, overflow: 'auto'}}>
|
||||||
<div className="proj-create" >
|
<div className="proj-create">
|
||||||
<CardProjType
|
<CardProjType
|
||||||
head={'全托管'}
|
head={'全托管'}
|
||||||
bodyLineArray={[
|
bodyLineArray={[
|
||||||
@ -42,9 +71,10 @@ export default function ProjCreate() {
|
|||||||
]}
|
]}
|
||||||
buyArray={[
|
buyArray={[
|
||||||
{
|
{
|
||||||
price: 500,
|
id: ProjChargeType.ALL,
|
||||||
handleClick: (_title, price) => {
|
price: charge.proj.all,
|
||||||
nav(`/proj-new/q/${price}`)
|
handleClick: () => {
|
||||||
|
nav(`/proj-new/${ProjChargeType.ALL}`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]}
|
]}
|
||||||
@ -72,27 +102,31 @@ export default function ProjCreate() {
|
|||||||
]}
|
]}
|
||||||
chargeLineArray={[
|
chargeLineArray={[
|
||||||
{
|
{
|
||||||
price: 100,
|
id: ProjAdditionalType.PKG,
|
||||||
title: '安装包100元'
|
price: charge.additional.pkg,
|
||||||
|
title: `安装包 ${charge.additional.pkg / 100} 元`
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
price: 50,
|
id: ProjAdditionalType.VIDEO_DEMO,
|
||||||
title: '系统演示视频文件50元'
|
price: charge.additional.videoDemo,
|
||||||
|
title: `系统演示视频文件 ${charge.additional.videoDemo / 100} 元`
|
||||||
}
|
}
|
||||||
]}
|
]}
|
||||||
buyArray={[
|
buyArray={[
|
||||||
{
|
{
|
||||||
|
id: ProjChargeType.MATERIAL_AGENT,
|
||||||
label: '普件:',
|
label: '普件:',
|
||||||
price: 200,
|
price: charge.proj.materialAgent,
|
||||||
handleClick: (_title, price) => {
|
handleClick: (_title, additional) => {
|
||||||
nav(`/proj-new/xdp/${price}`)
|
nav(`/proj-new/${ProjChargeType.MATERIAL_AGENT}?pkg=${additional.pkg}&videoDemo=${additional.videoDemo}`)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
id: ProjChargeType.MATERIAL_AGENT_URGENT,
|
||||||
label: '加急:',
|
label: '加急:',
|
||||||
price: 300,
|
price: charge.proj.materialAgentUrgent,
|
||||||
handleClick: (_title, price) => {
|
handleClick: (_title, additional) => {
|
||||||
nav(`/proj-new/xdj/${price}`)
|
nav(`/proj-new/${ProjChargeType.MATERIAL_AGENT_URGENT}?pkg=${additional.pkg}&videoDemo=${additional.videoDemo}`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]}
|
]}
|
||||||
@ -123,19 +157,22 @@ export default function ProjCreate() {
|
|||||||
]}
|
]}
|
||||||
chargeLineArray={[
|
chargeLineArray={[
|
||||||
{
|
{
|
||||||
price: 100,
|
id: ProjAdditionalType.PKG,
|
||||||
title: '安装包100元'
|
price: charge.additional.pkg,
|
||||||
|
title: `安装包 ${charge.additional.pkg / 100} 元`
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
price: 50,
|
id: ProjAdditionalType.VIDEO_DEMO,
|
||||||
title: '系统演示视频文件50元'
|
price: charge.additional.videoDemo,
|
||||||
|
title: `系统演示视频文件 ${charge.additional.videoDemo / 100} 元`
|
||||||
}
|
}
|
||||||
]}
|
]}
|
||||||
buyArray={[
|
buyArray={[
|
||||||
{
|
{
|
||||||
price: 200,
|
id: ProjChargeType.MATERIAL,
|
||||||
handleClick: (_title, price) => {
|
price: charge.proj.material,
|
||||||
nav(`/proj-new/x/${price}`)
|
handleClick: () => {
|
||||||
|
nav(`/proj-new/${ProjChargeType.MATERIAL}`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]}
|
]}
|
||||||
@ -159,9 +196,10 @@ export default function ProjCreate() {
|
|||||||
]}
|
]}
|
||||||
buyArray={[
|
buyArray={[
|
||||||
{
|
{
|
||||||
price: 0,
|
id: ProjChargeType.FREE,
|
||||||
handleClick: (_title, price) => {
|
price: charge.proj.free,
|
||||||
nav(`/proj-new/m/${price}`)
|
handleClick: () => {
|
||||||
|
nav(`/proj-new/${ProjChargeType.FREE}`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]}
|
]}
|
||||||
|
@ -1,38 +1,76 @@
|
|||||||
import './proj-new.css';
|
import './proj-new.css';
|
||||||
import {Link, useNavigate, useParams} from "react-router-dom";
|
import {Link, useNavigate, useParams, useSearchParams} from "react-router-dom";
|
||||||
import {Breadcrumb, Button, Flex, Form, type FormProps, Input, Modal} from "antd";
|
import {Breadcrumb, Button, Flex, Form, Input, message, Modal, Spin} from "antd";
|
||||||
import {useState} from "react";
|
import {useEffect, useState} from "react";
|
||||||
|
import {get, post} from "../../util/AjaxUtils.ts";
|
||||||
|
import {IProjCharge, ProjAdditionalType, ProjChargeType} from "../../interfaces/proj/IProj.ts";
|
||||||
|
|
||||||
const {TextArea} = Input;
|
const {TextArea} = Input;
|
||||||
|
|
||||||
type FieldType = {
|
type ProjInfo = {
|
||||||
projTitle: string;
|
projName: string;
|
||||||
projDesc: string;
|
projIntroduction: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function ProjNew() {
|
export default function ProjNew() {
|
||||||
const height = window.innerHeight - 150;
|
|
||||||
const [isModalOpen, setIsModalOpen] = useState(false);
|
|
||||||
const nav = useNavigate();
|
const nav = useNavigate();
|
||||||
const params = useParams();
|
const pathParams = useParams();
|
||||||
|
const [queryParams] = useSearchParams();
|
||||||
|
|
||||||
const onFinish: FormProps<FieldType>["onFinish"] = (values) => {
|
const [messageApi, contextHolder] = message.useMessage();
|
||||||
console.log('Success:', values);
|
const [loading, setLoading] = useState<boolean>(false);
|
||||||
setIsModalOpen(true);
|
const height = window.innerHeight - 150;
|
||||||
};
|
const [isCreateModalOpen, setIsCreateModalOpen] = useState(false);
|
||||||
|
const [isEditModalOpen, setIsEditModalOpen] = useState(false);
|
||||||
|
const [chargePrice, setChargePrice] = useState(0);
|
||||||
|
const [projInfo, setProjInfo] = useState<ProjInfo>({
|
||||||
|
projName: '',
|
||||||
|
projIntroduction: '',
|
||||||
|
});
|
||||||
|
const listProjChargeAdditional: string[] = [];
|
||||||
|
let createProjId = '';
|
||||||
|
|
||||||
const onFinishFailed: FormProps<FieldType>["onFinishFailed"] = (errorInfo) => {
|
useEffect(() => {
|
||||||
console.log('Failed:', errorInfo);
|
get({
|
||||||
};
|
messageApi: messageApi,
|
||||||
|
url: '/api/proj/charge/get',
|
||||||
const handleConfirmOk = () => {
|
onSuccess({data}) {
|
||||||
// 扣款
|
const charge = data as IProjCharge;
|
||||||
nav('/proj-edit');
|
let price = 0;
|
||||||
}
|
switch (pathParams.projChargeType) {
|
||||||
|
case ProjChargeType.ALL:
|
||||||
const handleConfirmCancel = () => {
|
price = charge.proj.all;
|
||||||
setIsModalOpen(false);
|
break;
|
||||||
}
|
case ProjChargeType.MATERIAL_AGENT:
|
||||||
|
price = charge.proj.materialAgent;
|
||||||
|
break;
|
||||||
|
case ProjChargeType.MATERIAL_AGENT_URGENT:
|
||||||
|
price = charge.proj.materialAgentUrgent;
|
||||||
|
break;
|
||||||
|
case ProjChargeType.MATERIAL:
|
||||||
|
price = charge.proj.material;
|
||||||
|
break;
|
||||||
|
case ProjChargeType.FREE:
|
||||||
|
price = charge.proj.free;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
messageApi.error({
|
||||||
|
type: 'error',
|
||||||
|
content: '价格类型错误',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if (queryParams.get('pkg')) {
|
||||||
|
price += charge.additional.pkg;
|
||||||
|
listProjChargeAdditional.push(ProjAdditionalType.PKG);
|
||||||
|
}
|
||||||
|
if (queryParams.get('videoDemo')) {
|
||||||
|
price += charge.additional.videoDemo;
|
||||||
|
listProjChargeAdditional.push(ProjAdditionalType.VIDEO_DEMO);
|
||||||
|
}
|
||||||
|
setChargePrice(price);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}, []);
|
||||||
|
|
||||||
const onBack = () => {
|
const onBack = () => {
|
||||||
nav(-1);
|
nav(-1);
|
||||||
@ -40,6 +78,7 @@ export default function ProjNew() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
{contextHolder}
|
||||||
<Breadcrumb
|
<Breadcrumb
|
||||||
items={[
|
items={[
|
||||||
{title: <Link to={'/'}>首页</Link>},
|
{title: <Link to={'/'}>首页</Link>},
|
||||||
@ -58,21 +97,26 @@ export default function ProjNew() {
|
|||||||
wrapperCol={{span: 24}}
|
wrapperCol={{span: 24}}
|
||||||
style={{width: 500}}
|
style={{width: 500}}
|
||||||
initialValues={{remember: true}}
|
initialValues={{remember: true}}
|
||||||
onFinish={onFinish}
|
onFinish={(formData) => {
|
||||||
onFinishFailed={onFinishFailed}
|
setIsCreateModalOpen(true);
|
||||||
|
setProjInfo({
|
||||||
|
projName: formData.projName,
|
||||||
|
projIntroduction: formData.projIntroduction
|
||||||
|
})
|
||||||
|
}}
|
||||||
autoComplete="off"
|
autoComplete="off"
|
||||||
>
|
>
|
||||||
<Form.Item<FieldType>
|
<Form.Item<ProjInfo>
|
||||||
label="系统标题"
|
label="系统标题"
|
||||||
name="projTitle"
|
name="projName"
|
||||||
rules={[{required: true, message: '请输入系统标题'}]}
|
rules={[{required: true, message: '请输入系统标题'}]}
|
||||||
>
|
>
|
||||||
<Input placeholder="请输入系统标题"/>
|
<Input placeholder="请输入系统标题"/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
|
||||||
<Form.Item<FieldType>
|
<Form.Item<ProjInfo>
|
||||||
label="简单描述"
|
label="简单描述"
|
||||||
name="projDesc"
|
name="projIntroduction"
|
||||||
rules={[{required: true, message: '请输入简单描述'}]}
|
rules={[{required: true, message: '请输入简单描述'}]}
|
||||||
>
|
>
|
||||||
<TextArea rows={6} placeholder="请用一段话简单描述系统"/>
|
<TextArea rows={6} placeholder="请用一段话简单描述系统"/>
|
||||||
@ -80,7 +124,8 @@ export default function ProjNew() {
|
|||||||
|
|
||||||
<Form.Item>
|
<Form.Item>
|
||||||
<Flex align="center" justify="center" gap="large">
|
<Flex align="center" justify="center" gap="large">
|
||||||
<Button type="primary" htmlType="submit" style={{backgroundColor: 'var(--color-primary)'}}>
|
<Button type="primary" htmlType="submit"
|
||||||
|
style={{backgroundColor: 'var(--color-primary)'}}>
|
||||||
提交并付款
|
提交并付款
|
||||||
</Button>
|
</Button>
|
||||||
<Button type="default" htmlType="button" onClick={onBack}>
|
<Button type="default" htmlType="button" onClick={onBack}>
|
||||||
@ -92,10 +137,51 @@ export default function ProjNew() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Modal title="提示" okText="确定" cancelText="取消" open={isModalOpen} onOk={handleConfirmOk}
|
<Modal title="提示"
|
||||||
onCancel={handleConfirmCancel}>
|
okText="确定"
|
||||||
<div>该操作会扣除{params.price}元,确定操作码?</div>
|
cancelText="取消"
|
||||||
|
open={isCreateModalOpen}
|
||||||
|
onOk={() => {
|
||||||
|
setIsCreateModalOpen(false);
|
||||||
|
post({
|
||||||
|
messageApi,
|
||||||
|
url: '/api/proj/create',
|
||||||
|
body: {
|
||||||
|
projName: projInfo.projName,
|
||||||
|
projIntroduction: projInfo.projIntroduction,
|
||||||
|
projChargeType: pathParams.projChargeType,
|
||||||
|
listProjChargeAdditional: listProjChargeAdditional
|
||||||
|
},
|
||||||
|
onBefore() {
|
||||||
|
setLoading(true);
|
||||||
|
},
|
||||||
|
onSuccess({data}) {
|
||||||
|
setIsEditModalOpen(true);
|
||||||
|
createProjId = data.data;
|
||||||
|
},
|
||||||
|
onFinally() {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}}
|
||||||
|
onCancel={() => {
|
||||||
|
setIsCreateModalOpen(false);
|
||||||
|
}}>
|
||||||
|
<div>该操作会扣除 {chargePrice / 100} 元,确定操作码?</div>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
<Modal title="提示"
|
||||||
|
okText="确定"
|
||||||
|
cancelText="取消"
|
||||||
|
open={isEditModalOpen}
|
||||||
|
onOk={() => {
|
||||||
|
nav(`/proj-edit/${createProjId}`);
|
||||||
|
}}
|
||||||
|
onCancel={() => {
|
||||||
|
setIsEditModalOpen(false);
|
||||||
|
}}>
|
||||||
|
<div>项目创建成功,开始编辑项目?</div>
|
||||||
|
</Modal>
|
||||||
|
<Spin tip="正在提交..." spinning={loading} fullscreen/>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
@ -1,6 +1,100 @@
|
|||||||
import axios from "axios";
|
import axios, {AxiosRequestConfig, AxiosResponse} from "axios";
|
||||||
|
import type {MessageInstance} from "antd/es/message/interface";
|
||||||
|
|
||||||
|
type Req = {
|
||||||
|
messageApi: MessageInstance;
|
||||||
|
url: string;
|
||||||
|
body?: any;
|
||||||
|
config?: AxiosRequestConfig;
|
||||||
|
onBefore?(): void;
|
||||||
|
onSuccess(data: AxiosResponse): void;
|
||||||
|
onFinally?(): void;
|
||||||
|
}
|
||||||
|
|
||||||
axios.defaults.baseURL = 'http://127.0.0.1:7025/copyright';
|
axios.defaults.baseURL = 'http://127.0.0.1:7025/copyright';
|
||||||
axios.defaults.headers['X-USER-ID'] = '80d3365e-0597-4988-979e-18ef1c3ec671';
|
axios.interceptors.request.use(config => {
|
||||||
|
if (config.method === 'get') {
|
||||||
|
config.data = {unused: 0} // 这个是关键点,解决get 请求添加不上content_type
|
||||||
|
}
|
||||||
|
config.headers['X-USER-ID'] = '80d3365e-0597-4988-979e-18ef1c3ec671';
|
||||||
|
return config
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
export const Axios = axios;
|
export const Axios = axios;
|
||||||
|
|
||||||
|
export function get(req: Req) {
|
||||||
|
req.onBefore?.();
|
||||||
|
Axios.get(req.url, req.config).then(res => {
|
||||||
|
req.onSuccess(res);
|
||||||
|
}).catch(error => {
|
||||||
|
if (error.response) {
|
||||||
|
const data = error.response.data;
|
||||||
|
req.messageApi.open({
|
||||||
|
type: 'error',
|
||||||
|
content: data.msg ? data.msg : `${data.path}(${data.status})`,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
console.error(error)
|
||||||
|
}
|
||||||
|
}).finally(() => {
|
||||||
|
req.onFinally?.();
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function post(req: Req) {
|
||||||
|
req.onBefore?.();
|
||||||
|
Axios.post(req.url, req.body, req.config).then(res => {
|
||||||
|
req.onSuccess(res);
|
||||||
|
}).catch(error => {
|
||||||
|
if (error.response) {
|
||||||
|
const data = error.response.data;
|
||||||
|
req.messageApi.open({
|
||||||
|
type: 'error',
|
||||||
|
content: data.msg ? data.msg : `${data.path}(${data.status})`,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
console.error(error)
|
||||||
|
}
|
||||||
|
}).finally(() => {
|
||||||
|
req.onFinally?.();
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function put(req: Req) {
|
||||||
|
req.onBefore?.();
|
||||||
|
Axios.put(req.url, req.config).then(res => {
|
||||||
|
req.onSuccess(res);
|
||||||
|
}).catch(error => {
|
||||||
|
if (error.response) {
|
||||||
|
const data = error.response.data;
|
||||||
|
req.messageApi.open({
|
||||||
|
type: 'error',
|
||||||
|
content: data.msg ? data.msg : `${data.path}(${data.status})`,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
console.error(error)
|
||||||
|
}
|
||||||
|
}).finally(() => {
|
||||||
|
req.onFinally?.();
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function del(req: Req) {
|
||||||
|
req.onBefore?.();
|
||||||
|
Axios.delete(req.url, req.config).then(res => {
|
||||||
|
req.onSuccess(res);
|
||||||
|
}).catch(error => {
|
||||||
|
if (error.response) {
|
||||||
|
const data = error.response.data;
|
||||||
|
req.messageApi.open({
|
||||||
|
type: 'error',
|
||||||
|
content: data.msg ? data.msg : `${data.path}(${data.status})`,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
console.error(error)
|
||||||
|
}
|
||||||
|
}).finally(() => {
|
||||||
|
req.onFinally?.();
|
||||||
|
})
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user