Commit 578defc9 authored by 卢均锐's avatar 卢均锐

feat: 采购竞价&在线竞价部分接入

parent c585b300
import React from 'react';
import { Tabs, Table, Row, Col, Space, Typography, Button, Tooltip } from 'antd';
import { LinkOutlined } from '@ant-design/icons';
import styles from './index.less';
......@@ -20,9 +21,25 @@ const MsgItem: React.FC<MsgItemPrpos> = (props: any) => {
<div className={styles.msgItemRow}><div className={styles.label}>联系人手机:</div><div className={styles.title}>185 2929 6758</div></div>
<div className={styles.msgItemRow}><div className={styles.label}>电子邮箱:</div><div className={styles.title}>kuaimeizheng@qq.com</div></div>
<div className={styles.msgItemRow}><div className={styles.label}>联系地址:</div>{<Tooltip placement="top" title={'广东省广州市海珠区新港东路168…'}>
<div className={styles.title}>广东省广州市海珠区新港东路168…</div>
</Tooltip>}</div>
<div className={styles.msgItemRow}><div className={styles.label}>报名文件:</div></div>
<div className={styles.title}>广东省广州市海珠区新港东路168…</div>
</Tooltip>}</div>
<div className={styles.msgItemRow}>
<div className={styles.label}>报名文件:</div>
<div className={styles.files}>
<Typography.Link
style={{ display: 'block', paddingBottom: '8px' }}
target="_blank"
>
<LinkOutlined />营业执照.pdf
</Typography.Link>
<Typography.Link
style={{ display: 'block', paddingBottom: '8px' }}
target="_blank"
>
<LinkOutlined />报名信息.doc
</Typography.Link>
</div>
</div>
</div>
)
}
......
......@@ -2,64 +2,67 @@ import React, { useContext, useEffect, useState } from 'react';
import { Row, Col, Table, Button } from 'antd';
import { CaretDownOutlined } from '@ant-design/icons'
import { formatTimeString } from '@/utils'
import TrendTag from '../../trendTag';
import styles from './index.less';
interface BtnItemProps {
btnType?: number,
active?: boolean
active?: boolean,
detail?: any
}
const BtnItem: React.FC<BtnItemProps> = (props: any) => {
const { btnType, active } = props;
const { btnType, active, detail } = props;
const _returnBtn = () => {
if (btnType === 1) {
return (
<div className={styles.btnItem} style={{borderColor: active ? '#00B37A' : '#F4F5F7'}}>
<div className={styles.btnItem} style={{ borderColor: active ? '#00B37A' : '#F4F5F7' }}>
<div className={styles.btnItemTitle}>
<div>广州白马皮具交易中心</div>
2</div>
<div>{detail?.memberName}</div>
{detail?.peportPriceSum}</div>
<div className={styles.btnItemPrice}>
<div>
¥900.00
¥{detail?.sumPice}
<span>(含税)</span>
</div>
10:43:56
{formatTimeString(detail?.peportTime)}
</div>
</div>
)
}else if(btnType === 2){
} else if (btnType === 2) {
return (
<div className={styles.btnItem2} style={{borderColor: active ? '#00B37A' : '#F4F5F7'}}>
<div className={styles.btnItem2} style={{ borderColor: active ? '#00B37A' : '#F4F5F7' }}>
<div className={styles.info}>
第 2 名
<span>当前最低价:¥1,000.00</span>
</div>
<div className={styles.box}>
<div className={styles.price}>
<div>¥900.00<span>(含税)</span></div>
2
<div>¥{detail?.sumPice}<span>(含税)</span></div>
{detail?.peportPriceSum}
</div>
<div className={styles.time}>
<span>10:43:56</span>
<span>{formatTimeString(detail?.peportTime)}</span>
<TrendTag />
</div>
</div>
</div>
)
}else if(btnType === 3){
} else if (btnType === 3) {
return (
<div className={styles.btnItem3} style={{borderColor: active ? '#00B37A' : '#F4F5F7'}}>
<div className={styles.btnItem3} style={{ borderColor: active ? '#00B37A' : '#F4F5F7' }}>
<div className={styles.title}>
<div>
¥900.00
¥{detail?.sumPice}
<span>(含税)</span>
</div>
2
{detail?.peportPriceSum}
</div>
<Row>
<Col span={12}>
<Button block style={{backgroundColor: '#F4F5F7',border: 0}}>取消</Button>
<Button block style={{ backgroundColor: '#F4F5F7', border: 0 }}>取消</Button>
</Col>
<Col span={12}>
<Button type="primary" block>提交报价</Button>
......
import React, { useContext, useEffect, useState } from 'react';
import { Row, Col, Table, Button } from 'antd';
import { Row, Col, Table, Button, Typography, Space } from 'antd';
import { ColumnType } from 'antd/lib/table/interface';
import Card from '../../../card';
import BtnItem from './btnItem';
const { Text } = Typography;
const transforType = {
1: '是',
0: '否'
}
interface BidDetailLayoutProps {
detail?: any
}
const BidDetailLayout: React.FC<BidDetailLayoutProps> = (props: any) => {
const { detail } = props;
const { awardProcess = [] } = detail;
const [showMore, setShowMore] = useState<boolean>(false);
const [activeItem, setActiveItem] = useState<any>({});
const dataSource = showMore ? [...activeItem.detailss].splice(0, 4) : activeItem.detailss;
const BidDetailLayout = () => {
const columns: ColumnType<any>[] = [
{ title: '物料编号/名称', dataIndex: 'materielNo', align: 'center', },
{ title: '规格型号', dataIndex: 'type', align: 'center', },
{ title: '品类', dataIndex: 'category', align: 'center', },
{ title: '品牌', dataIndex: 'brand', align: 'center', },
{ title: '采购数量/单位', dataIndex: 'unit', align: 'center', },
{ title: '含税/税率', dataIndex: 'isHasTaxName', align: 'center', },
{ title: '单价(含税)', dataIndex: 'price', align: 'center', },
{ title: '金额(含税)', dataIndex: 'price', align: 'center', },
{
title: '物料编号/名称',
dataIndex: 'number',
render: (text: any, record: any) => (
<Space direction='vertical'>
<Text type='secondary'>{text}</Text>
<Text type='secondary'>{record.name}</Text>
</Space>
)
},
{ title: '规格型号', dataIndex: 'model', },
{ title: '品类', dataIndex: 'category', },
{ title: '品牌', dataIndex: 'brand', },
{
title: '采购数量/单位',
dataIndex: 'unit',
render: (text: any, record: any) => (
<Space direction='vertical'>
<Text type='secondary'>{record.unit}</Text>
<Text type='secondary'>{text}</Text>
</Space>
)
},
{
title: '含税/税率',
dataIndex: 'isHasTaxName',
render: (text: any, record: any) => (
<Space direction='vertical'>
<Text type='secondary'>{transforType[text]}</Text>
<Text type='secondary'>{record.taxRate}</Text>
</Space>
)
},
{
title: '单价(含税)',
dataIndex: 'price',
render: (text: any, record: any) => <Text type='secondary'>¥{text}</Text>
},
{
title: '金额(含税)',
dataIndex: 'price',
render: (text: any, record: any) => <Text type='secondary'>¥{text}</Text>
},
]
const dataSource = []
const chooseItem = (item: any) => {
if (item.id !== activeItem.id) {
setShowMore(false);
setActiveItem(item);
}
}
return (
<div style={{ width: '100%' }}>
<Card
id={'BidDetailLayout'}
title={'竞价详情'}
>
<Row gutter={[8, 8]} style={{marginBottom: '10px'}}>
<Col span={7}>
<BtnItem />
</Col>
<Row gutter={[8, 8]} style={{ marginBottom: '10px' }}>
{awardProcess.map((item, index) => {
return (
<Col span={7} key={item.id} onClick={() => { chooseItem(item) }}>
<BtnItem detail={item} active={item.id === activeItem.id} />
</Col>
)
})}
</Row>
<Table dataSource={dataSource} columns={columns} />;
<Button type="link" block>显示更多</Button>
<Button type="link" block onClick={() => { setShowMore(true) }}>显示更多</Button>
</Card>
</div>
)
......
import React, { useEffect, useState } from 'react';
import Icon from '@ant-design/icons';
import { Typography } from 'antd';
const { Link } = Typography;
import ImIcon from '@/assets/icons/message_square.svg';
import styles from './index.less';
......@@ -13,9 +15,11 @@ interface IMBtnProps {
const IMBtn: React.FC<IMBtnProps> = (props: any) => {
const { func, btnStyle } = props;
return (
<div className={styles.iMBtn} style={btnStyle} onClick={func}>
<img src={ImIcon} alt="" />
</div>
<Link target='_blank' style={btnStyle}>
<div className={styles.iMBtn} onClick={func}>
<img src={ImIcon} alt="" />
</div>
</Link>
)
}
......
......@@ -34,7 +34,7 @@ const Detail = () => {
</Col>
</Row>
<Row>
<BidDetailLayout />
<BidDetailLayout detail={{}} />
</Row>
</div>
</div>
......
import React, { useEffect, useState } from 'react';
import React, { useEffect, useState, useMemo } from 'react';
import { Row, Col, Tabs, Button } from 'antd';
import level1 from '@/assets/icons/the_first.png';
......@@ -12,28 +12,45 @@ import styles from './index.less';
const { TabPane } = Tabs;
const RankItem = () => {
interface RankItemProps {
detail?: any
}
const RankItem: React.FC<RankItemProps> = (props: any) => {
const { detail } = props;
const { queryPriceDynamics = [], signupMembers = [] } = detail;
const [showMoreQuery, setShowMoreQuery] = useState<boolean>(false);
const [showMoreSign, setShowMoreSign] = useState<boolean>(false);
const queryPriceDynamicsData = showMoreQuery ? [...queryPriceDynamics].splice(0, 10) : queryPriceDynamics;
const signupMembersData = showMoreSign ? [...signupMembers].splice(0, 10) : signupMembers;
return (
<div className={styles.rank}>
<div className={styles.rankHeader}>
<h5>竞价排名</h5>
<div className={styles.rankHeaderBox}>
<img src={level1} alt={`排名1`} />
<h4><div style={{display: 'inline-block',position: 'relative',left: '-3%',top: '-5%'}}><TriangleTag text='最低价' wrapStyle={{backgroundColor : '#EA8000'}} bgcolor='#EA8000' direction='right' /></div>广州白马皮具交易中心</h4>
<h4>
<div style={{ display: 'inline-block', position: 'relative', left: '-3%', top: '-5%' }}>
{queryPriceDynamics.length > 0 && <TriangleTag text='最低价' wrapStyle={{ backgroundColor: '#EA8000' }} bgcolor='#EA8000' direction='right' />}
</div>
{queryPriceDynamics[0]?.memberName}
</h4>
<div className={styles.rankHeaderBoxInfo}>
<div className={styles.rankHeaderBoxInfoChild}>当前最低价:<span>¥ 900.00</span></div>
<div className={styles.rankHeaderBoxInfoChild}>当前最低价:<span>¥ {queryPriceDynamics[0]?.sumPrice}</span></div>
<div className={styles.rankHeaderBoxInfoChild}>报价次数:<span>5</span></div>
</div>
</div>
</div>
<Tabs defaultActiveKey="1">
<TabPane tab="报价排名" key="1">
<RankRow />
<Button type="link" block>显示更多</Button>
{queryPriceDynamicsData.map((item, index) => <RankRow detail={item} key={item.id} />)}
<Button type="link" block onClick={() => {setShowMoreQuery(true)}}>显示更多</Button>
</TabPane>
<TabPane tab="报名会员" key="2">
<RankRow rowType={2} />
<Button type="link" block>显示更多</Button>
{signupMembersData.map((item, index) => <RankRow detail={item} key={item.id} rowType={2} />)}
<Button type="link" block onClick={() => {setShowMoreSign(true)}}>显示更多</Button>
</TabPane>
</Tabs>
</div>
......
......@@ -14,8 +14,14 @@ interface RankRowProps {
rowType?: number
}
const RankForLeve = {
1: level1,
2: level2,
3: level3,
}
const RankRow: React.FC<RankRowProps> = (props: any) => {
const { detail, rowType } = props;
const { detail = {}, rowType } = props;
const _returnRow = () => {
if (rowType === 1) {
......@@ -23,17 +29,17 @@ const RankRow: React.FC<RankRowProps> = (props: any) => {
<div className={`${styles.rankRow} ${styles.rankRow_level_1}`}>
<div className={styles.rankRowLeft}>
<div className={styles.rankRowLeftTop}>
<img src={level1} alt="" />
广州白马皮具交易中心
<img src={RankForLeve[detail.ranking]} alt={`第${detail.ranking}名`} />
{detail.memberName}
<TriangleTag text='最低价' wrapStyle={{ backgroundColor: '#EA8000', marginLeft: '8px' }} bgcolor='#EA8000' direction='left' />
</div>
<div className={styles.rankRowLeftBottom}>
¥900.00
<div className={styles.rankRowLeftBottomTag}>2</div>
¥{detail.sumPrice}
<div className={styles.rankRowLeftBottomTag}>{detail.sumNumber}</div>
</div>
</div>
<div className={styles.rankRowRight}>
蒯美政
{detail.memberName}
<IMBtn func={() => console.log(1)} />
</div>
</div>
......@@ -42,12 +48,12 @@ const RankRow: React.FC<RankRowProps> = (props: any) => {
return (
<div className={`${styles.rankRow}`}>
<div className={styles.rankRowLeft}>
<div className={styles.rankRowLeftTop}>广州白马皮具交易中心</div>
<div className={styles.rankRowLeftTop}>{detail.memberName}</div>
<div className={styles.rankRowLeftBottomPhone}>185 2929 6758</div>
</div>
<div className={styles.rankRowRight}>
蒯美政
<IMBtn func={() => console.log(1)} />
{detail.memberName}
<IMBtn func={() => console.log(1)} />
</div>
</div>
)
......
import React from 'react';
import { Row, Col, Button, Drawer, Table } from 'antd';
import React, { useState } from 'react';
import { Row, Col, Input, Drawer, Table, Space, Typography } from 'antd';
import { ColumnType } from 'antd/lib/table/interface';
import BtnItem from '../../../../../../components/detail/components/bidDetailLayout/btnItem';
import styles from './index.less';
import { div } from '@/pages/editor/configs/componentConfigs/HTML';
const { Text } = Typography;
interface DetailBottomDrawerProps {
visible: boolean,
onClose?: Function
onClose?: Function,
detail?: any
}
const DetailBottomDrawer: React.FC<DetailBottomDrawerProps> = (props: any) => {
const { visible, onClose } = props;
const { visible, onClose, detail } = props;
const { awardProcess = [] } = detail;
const [activeItem, setActiveItem] = useState<any>({});
const columns: ColumnType<any>[] = [
{ title: '物料编号/名称', dataIndex: 'materielNo', align: 'center', },
{ title: '规格型号', dataIndex: 'type', align: 'center', },
{ title: '品类', dataIndex: 'category', align: 'center', },
{ title: '品牌', dataIndex: 'brand', align: 'center', },
{ title: '采购数量/单位', dataIndex: 'unit', align: 'center', },
{ title: '含税/税率', dataIndex: 'isHasTaxName', align: 'center', },
{ title: '单价(含税)', dataIndex: 'price', align: 'center', },
{ title: '金额(含税)', dataIndex: 'price', align: 'center', },
{
title: '物料编号/名称',
dataIndex: 'number',
render: (text: any, record: any) => (
<Space direction='vertical'>
<Text type='secondary'>{text}</Text>
<Text type='secondary'>{record.name}</Text>
</Space>
)
},
{ title: '规格型号', dataIndex: 'model', },
{ title: '品类', dataIndex: 'category', },
{ title: '品牌', dataIndex: 'brand', },
{
title: '采购数量/单位',
dataIndex: 'unit',
render: (text: any, record: any) => (
<Space direction='vertical'>
<Text type='secondary'>{record.unit}</Text>
<Text type='secondary'>{text}</Text>
</Space>
)
},
{
title: '含税/税率',
dataIndex: 'isHasTaxName',
render: (text: any, record: any) => <Input value={record.taxRate} addonAfter="%" />
},
{
title: '单价(含税)',
dataIndex: 'price',
render: (text: any, record: any) => <Input value={record.price} addonBefore="¥" />
},
{
title: '金额(含税)',
dataIndex: 'price',
render: (text: any, record: any) => <Text type='secondary'>¥{text}</Text>
},
]
const dataSource = []
const chooseItem = (item: any) => {
setActiveItem(item);
}
return (
<Drawer
title="竞价详情"
......@@ -38,11 +76,15 @@ const DetailBottomDrawer: React.FC<DetailBottomDrawerProps> = (props: any) => {
closeIcon={<div>取消报价</div>}
>
<Row gutter={[8, 8]} style={{ marginBottom: '10px' }}>
<Col span={7}>
<BtnItem />
</Col>
{awardProcess.map((item, index) => {
return (
<Col span={7} key={item.id} onClick={() => { chooseItem(item) }}>
<BtnItem btnType={item.id === activeItem.id ? 3 : 2} detail={item} active={item.id === activeItem.id} />
</Col>
)
})}
</Row>
<Table dataSource={dataSource} columns={columns} />;
<Table dataSource={activeItem?.detailss} columns={columns} />;
</Drawer>
)
}
......
......@@ -9,12 +9,18 @@ import DetailBottomDrawer from './detailBottomDrawer'
import styles from './index.less'
interface StatuBoxProps {
hasBidBtn?: boolean
hasBidBtn?: boolean,
detail?: any
}
const transforType = {
1: '是',
0: '否'
}
const StatuBox: React.FC<StatuBoxProps> = (props: any) => {
const { hasBidBtn } = props;
const [hour, minute, second, stillRun] = useCountDown(1619514793947 / 1000);
const { hasBidBtn, detail = {} } = props;
const [hour, minute, second, stillRun] = useCountDown(detail?.biddingEndTime / 1000);
const [visible, setVisible] = useState<boolean>(false);
return (
<>
......@@ -42,17 +48,17 @@ const StatuBox: React.FC<StatuBoxProps> = (props: any) => {
<Divider dashed style={{ color: '#EBECF0', margin: '6px 0' }} />
<h4>竞价规则</h4>
<div className={styles.statusBoxText}><div>报价规则:</div>项目总价(含税)</div>
<div className={styles.statusBoxText}><div>起拍价:</div>¥ 1,500.00</div>
{!hasBidBtn && <div className={styles.statusBoxText}><div>目标价:</div>¥ 900.00</div>}
<div className={styles.statusBoxText}><div>最小价差:</div>¥ 100.00</div>
<div className={styles.statusBoxText}><div>允许报价次数:</div>3</div>
<div className={styles.statusBoxText}><div>起拍价:</div>¥ {detail?.startingPrice}</div>
{!hasBidBtn && <div className={styles.statusBoxText}><div>目标价:</div>¥ {detail?.targetPrice}</div>}
<div className={styles.statusBoxText}><div>最小价差:</div>¥ {detail?.minPrice}</div>
<div className={styles.statusBoxText}><div>允许报价次数:</div>{detail?.allowPurchaseCount}</div>
<div className={styles.statusBoxText}><div>报价排名:</div>按项目总价排名</div>
{hasBidBtn ? (
<Button type="primary" icon={<PlusOutlined />} block onClick={() => {setVisible(true)}} size={'large'} style={{ margin: '15px 0' }}>我要报价</Button>
<Button type="primary" icon={<PlusOutlined />} block onClick={() => { setVisible(true) }} size={'large'} style={{ margin: '15px 0' }}>我要报价</Button>
) : (
<>
<div className={styles.statusBoxText}><div>公开最低报价:</div></div>
<div className={styles.statusBoxText}><div>公开报价排名:</div></div>
<div className={styles.statusBoxText}><div>公开最低报价:</div>{transforType[detail?.isOpenPurchase]}</div>
<div className={styles.statusBoxText}><div>公开报价排名:</div>{transforType[detail?.isOpenRanking]}</div>
</>
)}
</div>
......@@ -61,6 +67,7 @@ const StatuBox: React.FC<StatuBoxProps> = (props: any) => {
<DetailBottomDrawer
visible={visible}
onClose={() => { setVisible(false) }}
detail={detail}
/>
</>
)
......
......@@ -3,6 +3,8 @@ import { history } from 'umi';
import { Row, Col, Tooltip, Button } from 'antd';
import { ArrowLeftOutlined } from '@ant-design/icons';
import { PublicApi } from '@/services/api';
import QuotationDeskLayout from '../../../components/detail/components/quotationDeskLayout';
import BidDetailLayout from '../../../components/detail/components/bidDetailLayout';
......@@ -13,6 +15,16 @@ import StatusBox from './components/statusBox';
import styles from './index.less';
const Management = () => {
const [detailData, setDetailData] = useState<any>({});
const getData = () => {
PublicApi.postPurchaseBiddingManageBidding().then(res => {
if(res.code === 1000){
setDetailData(res.data);
}
})
}
return (
<div className={styles.warp}>
<div className={styles.header}>
......@@ -22,7 +34,7 @@ const Management = () => {
<div className={styles.layout}>
<Row gutter={[8, 8]}>
<Col span={6}>
<RankItem />
<RankItem detail={detailData} />
</Col>
<Col span={18}>
<Row gutter={[8, 8]} style={{ marginBottom: '8px' }}>
......@@ -30,11 +42,11 @@ const Management = () => {
<QuotationDeskLayout />
</Col>
<Col span={8}>
<StatusBox />
<StatusBox detail={detailData} />
</Col>
</Row>
<Row>
<BidDetailLayout />
<BidDetailLayout detail={detailData} />
</Row>
</Col>
</Row>
......
......@@ -57,6 +57,7 @@ const SearchDetail = () => {
} = history.location;
const [path] = useState(pathname.split('/')[pathname.split('/').length - 1]);
const [pathPci] = useState(pathname.split('/')[pathname.split('/').length - 2]);
console.log(pathPci)
const [visible, setVisible] = useState<boolean>(false);
// 确认竞价结果
const [confirmBidResultVisible, setConfirmBidResultVisible] = useState<boolean>(false);
......
......@@ -96,7 +96,7 @@ export const PURCHASEBIDORDER_SCHEMA: ISchema = {
}
}
/** 采购竞价 - 待新增采购竞价单 */
/** 采购竞价 - 待新增采购竞价单&待审核(一级)&待审核(二级)&待审核结果(一级)&待审核结果(二级)&待提交&待提交审核结果 */
export const PURCHASEBIDREADYADD_SCHEMA: ISchema = {
type: 'object',
properties: {
......@@ -177,7 +177,7 @@ export const PURCHASEBIDREADYADD_SCHEMA: ISchema = {
}
}
/** 采购竞价 - 待审核竞价报名 */
/** 采购竞价 - 待审核竞价报名&待确认&待审核报名 */
export const PURCHASEBIDOSIGNUP_SCHEMA: ISchema = {
type: 'object',
properties: {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment