Commit 15f586ce authored by 卢均锐's avatar 卢均锐

feat: 在线竞价&采购竞价 修改字段 业务逻辑实现 增加流转记录公用组件

parent e45be8ef
......@@ -18,7 +18,7 @@ const FilesItem = (props: any) => {
})
)
}else{
return ''
return '-'
}
}
......
......@@ -20,7 +20,7 @@
color: #303133;
display: flex;
flex-direction: row;
align-items: center;
div {
flex: 1;
font-size: 16px;
......
......@@ -29,7 +29,7 @@ const BtnItem: React.FC<BtnItemProps> = (props: any) => {
¥{detail?.sumPice}
<span>(含税)</span>
</div>
{formatTimeString(detail?.peportTime)}
{formatTimeString(detail?.peportTime, 'HH:mm:ss')}
</div>
</div>
)
......@@ -37,8 +37,8 @@ const BtnItem: React.FC<BtnItemProps> = (props: any) => {
return (
<div className={styles.btnItem2} style={{ borderColor: active ? '#00B37A' : '#F4F5F7' }}>
<div className={styles.info}>
{detail?.ranking}
<span>当前最低价:¥{detail?.minPrice}</span>
{detail?.isOpenRanking ? `第 ${detail?.ranking} 名` : '不公开'}
<span>当前最低价:{detail?.isOpenPurchase ? `¥${detail?.minPrice}` : '不公开'}</span>
</div>
<div className={styles.box}>
<div className={styles.price}>
......@@ -46,7 +46,7 @@ const BtnItem: React.FC<BtnItemProps> = (props: any) => {
{detail?.peportPriceSum}
</div>
<div className={styles.time}>
<span>{formatTimeString(detail?.peportTime)}</span>
<span>{formatTimeString(detail?.peportTime, 'HH:mm:ss')}</span>
<TrendTag />
</div>
</div>
......
......@@ -21,7 +21,7 @@ interface BidDetailLayoutProps {
const BidDetailLayout: React.FC<BidDetailLayoutProps> = (props: any) => {
const { detail, btnType } = props;
const { awardProcess = [], materiels = [] } = detail;
const { awardProcess = [], materiels = [], isOpenPurchase, isOpenRanking } = detail;
const [showMore, setShowMore] = useState<boolean>(false);
const [activeItem, setActiveItem] = useState<any>(awardProcess?.[0] || { detailss: [] });
const dataSource = showMore ? [...activeItem.detailss].splice(0, 4) : activeItem.detailss;
......@@ -56,7 +56,7 @@ const BidDetailLayout: React.FC<BidDetailLayoutProps> = (props: any) => {
},
{
title: '含税/税率',
dataIndex: 'isHasTaxName',
dataIndex: 'isTax',
render: (text: any, record: any) => (
<Space direction='vertical'>
<Text type='secondary'>{transforType[text]}</Text>
......@@ -94,7 +94,7 @@ const BidDetailLayout: React.FC<BidDetailLayoutProps> = (props: any) => {
{awardProcess?.map((item, index) => {
return (
<Col span={7} key={item.id} onClick={() => { chooseItem(item) }}>
<BtnItem btnType={btnType} detail={item} active={item.id === activeItem.id} />
<BtnItem btnType={btnType} detail={{ ...item, isOpenPurchase, isOpenRanking }} active={item.id === activeItem.id} />
</Col>
)
})}
......
import React, { useMemo, useEffect } from 'react';
import React, { useMemo, useState } from 'react';
import { Chart, Tooltip, Axis } from 'bizcharts';
import { Radio, Row } from 'antd';
import Point from 'bizcharts/lib/geometry/Point';
......@@ -17,7 +17,10 @@ interface QuotationDeskProps {
const QuotationDesk: React.FC<QuotationDeskProps> = (props: any) => {
const { title, chartsList } = props;
const data = chartsList.reduce((total, cur) => total.concat(cur.list), []);
const [listLen, setListLen] = useState(7);
const data = useMemo(() => {
return chartsList ? chartsList.reduce((total, cur) => total.concat(cur?.list ? (listLen ? [...cur.list].splice(0, listLen) : [...cur.list]) : []), []) : []
}, [chartsList, listLen]);
const scaleObj = useMemo(() => {
let _obj = {};
chartsList.forEach(item => {
......@@ -34,6 +37,7 @@ const QuotationDesk: React.FC<QuotationDeskProps> = (props: any) => {
}
}
}
console.log(data)
return (
<div className={styles.wrap}>
<div className={styles.layout} style={{ margin: 0 }}>
......@@ -51,11 +55,12 @@ const QuotationDesk: React.FC<QuotationDeskProps> = (props: any) => {
{chartsList[0]?.title}
</div>
<Radio.Group
defaultValue={1}
defaultValue={listLen}
onChange={(e) => { setListLen(e.target.value) }}
>
<Radio.Button value={1}>最近7次</Radio.Button>
<Radio.Button value={2}>最近15次</Radio.Button>
<Radio.Button value={3}>全部</Radio.Button>
<Radio.Button value={7}>最近7次</Radio.Button>
<Radio.Button value={15}>最近15次</Radio.Button>
<Radio.Button value={0}>全部</Radio.Button>
</Radio.Group>
</Row>
}
......
/** 详情通用 - 流转进度 */
import React, { useContext, useState, useMemo } from 'react';
import { Radio, Table, Typography, Tag } from 'antd';
const { Text } = Typography;
import { formatTimeString } from '@/utils'
import { Context } from '../context';
import Card from '../../../card';
const LOGSTATESTYPE = {
/** 外部流转 */
EXTERNALSTATES: 1,
/** 内部流转 */
INTERIORSTATES: 2
}
// recordType做加法
export interface ProgressProps {
externalColors: any,
internalColors: any,
layoutId?: string,
layoutTitle?: string
}
const RecordLayout: React.FC<ProgressProps> = (props: any) => {
const { externalColors, internalColors, layoutId, layoutTitle } = props;
const context = useContext(Context);
const [logStatus, setLogStatus] = useState<number>(LOGSTATESTYPE.EXTERNALSTATES);
const EXTERNALLOGS = useMemo(() => {
return (
[
{
title: '流转顺序号',
key: 'index',
dataIndex: 'index',
render: (_text: any, _record: any, index: number) => <Text>{index + 1}</Text>
},
{
title: '操作角色',
key: 'roleName',
dataIndex: 'roleName',
},
{
title: '状态',
key: 'state',
dataIndex: 'state',
render: (_text: any, _record: any) => <Tag color={externalColors[_text]}>{_record.stateName}</Tag>
},
{
title: '操作',
key: 'operation',
dataIndex: 'operation',
},
{
title: '操作时间',
key: 'createTime',
dataIndex: 'createTime',
render: (_text: any, _record: any) => <Text>{formatTimeString(_text)}</Text>
},
{
title: '审核意见',
key: 'auditOpinion',
dataIndex: 'auditOpinion',
},
]
)
}, [externalColors])
const INTERNALLOGS = useMemo(() => {
return [
{
title: '流转顺序号',
key: 'index',
dataIndex: 'index',
render: (_text: any, _record: any, index: number) => <Text>{index + 1}</Text>
},
{
title: '操作人',
key: 'roleName',
dataIndex: 'roleName',
},
{
title: '部门',
key: 'department',
dataIndex: 'department',
},
{
title: '职位',
key: 'position',
dataIndex: 'position',
},
{
title: '状态',
key: 'state',
dataIndex: 'state',
render: (_text: any, _record: any) => <Tag color={internalColors[_text]}>{_record.stateName}</Tag>
},
{
title: '操作',
key: 'operation',
dataIndex: 'operation',
},
{
title: '操作时间',
key: 'createTime',
dataIndex: 'createTime',
render: (_text: any, _record: any) => <Text>{formatTimeString(_text)}</Text>
},
{
title: '审核意见',
key: 'auditOpinion',
dataIndex: 'auditOpinion',
},
]
}, [internalColors])
return (
<Card
id={layoutId}
title={layoutTitle}
extra={
<Radio.Group
onChange={(e) => setLogStatus(e.target.value)}
defaultValue={LOGSTATESTYPE.EXTERNALSTATES}
>
{context.externalLogs && <Radio.Button value={LOGSTATESTYPE.EXTERNALSTATES}>外部流转</Radio.Button>}
{context.interiorLogs && <Radio.Button value={LOGSTATESTYPE.INTERIORSTATES}>内部流转</Radio.Button>}
</Radio.Group>
}
>
<Table
columns={logStatus === LOGSTATESTYPE.EXTERNALSTATES ? EXTERNALLOGS : INTERNALLOGS}
dataSource={
logStatus === LOGSTATESTYPE.EXTERNALSTATES ?
context.externalLogs :
context.interiorLogs
}
rowKey={(record) => record.id}
pagination={{
hideOnSinglePage: true
}}
/>
</Card>
)
}
RecordLayout.defaultProps = {
layoutId : 'recordLayout',
layoutTitle : '流转进度'
}
export default RecordLayout
......@@ -23,4 +23,8 @@ export const BID_INTERNALSTATE_COLOR = {
9: 'error',
10: 'default',
11: 'error',
12: 'processing',
13: 'warning',
14: 'warning',
15: 'warning',
}
\ No newline at end of file
......@@ -10,7 +10,7 @@ import { formatTimeString } from '@/utils'
import { Context } from '../../components/detail/components/context';
import PeripheralLayout from '../../components/detail';
import ProgressLayout from '../../components/detail/components/progressCommonLayout';
import RecordLyout from '../../components/detail/components/recordLyout';
import RecordComontLayout from '../../components/detail/components/recordComontLayout';
import MaterialLayout from '../../components/detail/components/materialLayout';
import BidCommonLayout from '../../components/detail/components/bidCommonLayout';
import TableCommonLayout from '../../components/detail/components/tableCommonLayout';
......@@ -41,7 +41,7 @@ const TABLINK = [
{ id: 'fileLayout', title: '附件' },
{ id: 'quotationRecordLayout', title: '最低报价记录' },
{ id: 'resultLayout', title: '授标结果' },
{ id: 'recordLyout', title: '流转记录' },
{ id: 'recordLayout', title: '流转记录' },
]
const SearchDetail = () => {
......@@ -347,7 +347,7 @@ const SearchDetail = () => {
{_returnFileLayout()}
{_returnLowestQuotationRecordLayout()}
{_returnResultLayout()}
<RecordLyout />
<RecordComontLayout externalColors={BID_EXTERNALSTATE_COLOR} internalColors={BID_INTERNALSTATE_COLOR} />
</Fragment>
}
/>
......
import React, { useEffect, useState } from 'react';
import React, { useMemo, useState } from 'react';
import { Row, Col, Tabs, Button } from 'antd';
import level1 from '@/assets/icons/the_first.png';
......@@ -14,7 +14,15 @@ interface HistoryItemProps {
const HistoryItem: React.FC<HistoryItemProps> = (props: any) => {
const { detail } = props;
const mapData = detail.offerLogs ? [...detail.offerLogs].splice(0, 3): [];
const mapData = detail.offerLogs ? [...detail.offerLogs].splice(0, 3) : [];
const currentMinPrice = useMemo(() => {
if (!detail.isOpenPurchase) {
return '不公开'
} else {
return detail?.offerLogs != null ? (detail?.offerLogs[0]?.minPrice ? `${detail?.offerLogs[0]?.minPrice}` : '-') : '-'
}
}, [detail])
return (
<div className={styles.history}>
<div className={styles.historyHeader}>
......@@ -25,9 +33,9 @@ const HistoryItem: React.FC<HistoryItemProps> = (props: any) => {
{detail?.offerRatio ? <TrendTag ratio={detail?.offerRatio} /> : ''}
</div>
<p>本次报价金额</p>
<p className={styles.currentPrice}><span>¥</span>{detail?.offerPrice}</p>
<p className={styles.currentPrice}><span>¥</span>{detail?.offerPrice || '-'}</p>
<div className={styles.row}>
<div className={styles.col} style={{ borderRight: '1px solid #EBECF0' }}>当前最低价:<span>{detail?.minPrice && detail.isOpenPurchase ? `¥ ${detail?.minPrice}` : '-'}</span></div>
<div className={styles.col} style={{ borderRight: '1px solid #EBECF0' }}>当前最低价:<span>{currentMinPrice}</span></div>
<div className={styles.col}>报价次数:<span>{detail?.offerCount ? detail?.offerCount : '-'}</span></div>
</div>
</div>
......@@ -35,7 +43,7 @@ const HistoryItem: React.FC<HistoryItemProps> = (props: any) => {
<div className={styles.historyFootter}>
<h5>最近报价</h5>
{mapData && mapData.map((item) => {
return (<OfferItem key={item.offerTime} detail={item} />)
return (<OfferItem key={item.offerTime} detail={{ ...item, isOpenRanking: detail.isOpenRanking, isOpenPurchase: detail.isOpenPurchase }} />)
})}
</div>
</div>
......
......@@ -45,10 +45,18 @@ const Detail = () => {
data.onlineId = Number(onlineId);
setDataSource(data);
let _list = [];
let _offerList = [];
let _minList = [];
data?.offerLogs.forEach((item) => {
_offerList.push({type: 'offer',time: formatTimeString(item.offerTime, 'HH:mm:ss'),value: item.offerPrice});
})
_list.push({title: '报价金额',type: 'offer',list: _offerList});
if(data.isOpenPurchase){
_list.push({title: '最低价',type: 'min',list: data.quotationDesks.map((item) => {return {type: 'min',time: formatTimeString(item.offerTime, 'HH:mm:ss'),value: item.price}})})
data?.offerLogs.forEach((item) => {
_minList.push({type: 'min',time: formatTimeString(item.offerTime, 'HH:mm:ss'),value: item.minPrice});
})
_list.push({title: '最低价',type: 'min',list: _minList});
}
_list.push({title: '报价金额',type: 'offer',list: data.quotationDesks.map((item) => {return {type: 'offer',time: formatTimeString(item.offerTime, 'HH:mm:ss'),value: item.price}})})
setChartsList(_list)
})
}
......
......@@ -15,12 +15,12 @@ const OfferItem: React.FC<OfferItemProps> = (props: any) => {
const { detail } = props;
return (
<div className={styles.offerItem}>
<div className={styles.left}>{detail.ranking}</div>
<div className={styles.left}>{detail.isOpenRanking ? `第${detail.ranking}名` : '不公开'}</div>
<div className={styles.right}>
<div className={styles.row}>
<div className={styles.rowPrice}>
<span>¥ {detail.offerPrice}</span>
当前最低价:¥{detail.minPrice}
当前最低价:{detail.isOpenPurchase ? `¥${detail.minPrice}` : '不公开'}
</div>
{detail.offerCount}
</div>
......
......@@ -18,7 +18,7 @@ interface DetailBottomDrawerProps {
const DetailBottomDrawer: React.FC<DetailBottomDrawerProps> = (props: any) => {
const { visible, onClose, detail } = props;
const { awardProcess = [], materiels = [] } = detail;
const { awardProcess = [], materiels = [], offerCount, isOpenPurchase, isOpenRanking } = detail;
const [activeItem, setActiveItem] = useState<any>('');
const [dataSource, setDataSource] = useState<any>(materiels);
const [dataSource2, setDataSource2] = useState<any>(materiels);
......@@ -137,12 +137,12 @@ const DetailBottomDrawer: React.FC<DetailBottomDrawerProps> = (props: any) => {
>
<Row gutter={[8, 8]} style={{ marginBottom: '10px' }}>
<Col span={7} key={'BtnItem_0'} onClick={() => { chooseItem() }}>
<BtnItem btnType={3} detail={{ sumPice: _calcCurrentTotal, peportPriceSum: dataSource.length + 1 }} active={!activeItem} onOk={bidOk} onCancle={onClose} />
<BtnItem btnType={3} detail={{ sumPice: _calcCurrentTotal, peportPriceSum: offerCount + 1 }} active={!activeItem} onOk={bidOk} onCancle={onClose} />
</Col>
{awardProcess?.map((item, index) => {
return (
<Col span={7} key={`BtnItem_${item.id}`} onClick={() => { chooseItem(item) }}>
<BtnItem btnType={2} detail={item} active={item.id === activeItem.id} />
<BtnItem btnType={2} detail={{ ...item, isOpenPurchase, isOpenRanking }} active={item.id === activeItem.id} />
</Col>
)
})}
......
......@@ -63,7 +63,7 @@ const StatuBox: React.FC<StatuBoxProps> = (props: any) => {
<div className={styles.statusBoxText}><div>允许报价次数:</div>{detail?.allowPurchaseCount}</div>
<div className={styles.statusBoxText}><div>报价排名:</div>{detail.isOpenPurchase ? '按项目总价排名' : '无'}</div>
{hasBidBtn ? (
<Button type="primary" icon={<PlusOutlined />} block onClick={_handleBid} size={'large'} style={{ margin: '15px 0' }}>我要报价</Button>
<Button disabled={!stillRun} type="primary" icon={<PlusOutlined />} block onClick={_handleBid} size={'large'} style={{ margin: '15px 0' }}>我要报价</Button>
) : (
<>
<div className={styles.statusBoxText}><div>公开最低报价:</div>{transforType[detail?.isOpenPurchase]}</div>
......
......@@ -89,7 +89,7 @@ const Management = () => {
setLowestList({
type: 'min',
title: '最低价',
list: data.map((item) => { return { type: 'min', time: formatTimeString(item.peportTime, 'HH:mm:ss'), value: item.sumPice } })
list: data ? data.map((item) => { return { type: 'min', time: formatTimeString(item.peportTime, 'HH:mm:ss'), value: item.sumPice } }) : []
})
})
}
......
......@@ -42,8 +42,8 @@ const ReadyConfirm = () => {
)
}, {
title: '授标会员',
key: 'createMemberName',
dataIndex: 'createMemberName',
key: 'memberName',
dataIndex: 'memberName',
render: (text: any, record: any) => (
<EyePreview url={`/shop?shopId=${btoa(JSON.stringify({ shopId: record.memberShopId, memberId: record.memberId }))}`}>{text}</EyePreview>
)
......
......@@ -36,10 +36,10 @@ const ReadyExamineResultOne = () => {
)
}, {
title: '授标会员',
key: 'createMemberId',
dataIndex: 'createMemberId',
key: 'memberName',
dataIndex: 'memberName',
render: (text: any, record: any) => (
<EyePreview url={`/shop?shopId=${btoa(JSON.stringify({ shopId: record.memberShopId, memberId: record.memberId }))}`}>{record.createMemberName}</EyePreview>
<EyePreview url={`/shop?shopId=${btoa(JSON.stringify({ shopId: record.memberShopId, memberId: record.memberId }))}`}>{text}</EyePreview>
)
}, {
title: '竞价开始/结束时间',
......
......@@ -37,10 +37,10 @@ const ReadyExamineResultTwo = () => {
)
}, {
title: '授标会员',
key: 'createMemberId',
dataIndex: 'createMemberId',
key: 'memberName',
dataIndex: 'memberName',
render: (text: any, record: any) => (
<EyePreview url={`/shop?shopId=${btoa(JSON.stringify({ shopId: record.memberShopId, memberId: record.memberId }))}`}>{record.createMemberName}</EyePreview>
<EyePreview url={`/shop?shopId=${btoa(JSON.stringify({ shopId: record.memberShopId, memberId: record.memberId }))}`}>{text}</EyePreview>
)
}, {
title: '竞价开始/结束时间',
......
......@@ -37,8 +37,8 @@ const ReadySubmitExamineResult = () => {
)
}, {
title: '授标会员',
key: 'createMemberName',
dataIndex: 'createMemberName',
key: 'memberName',
dataIndex: 'memberName',
render: (text: any, record: any) => (
<EyePreview url={`/shop?shopId=${btoa(JSON.stringify({ shopId: record.memberShopId, memberId: record.memberId }))}`}>{text}</EyePreview>
)
......@@ -72,9 +72,7 @@ const ReadySubmitExamineResult = () => {
key: 'operate',
dataIndex: 'operate',
align: 'center',
render: (text: any, record: any) => <>
<Button onClick={() => handleSubmit(record.id)} type='link'>提交审核</Button>
</>
render: (text: any, record: any) => <Button onClick={() => handleSubmit(record.id)} type='link'>提交审核</Button>
}];
const handleSubmit = (id: number) => {
......@@ -88,7 +86,6 @@ const ReadySubmitExamineResult = () => {
signUpIdea,
urls
}
console.log(_params)
PublicApi.postPurchaseBiddingSubmitExamineBiddingReturn(_params).then(res => {
if (res.code === 1000) {
setVisible(false);
......
......@@ -10,7 +10,7 @@ import { formatTimeString } from '@/utils'
import { Context } from '../../components/detail/components/context';
import PeripheralLayout from '../../components/detail';
import ProgressLayout from '../../components/detail/components/progressCommonLayout';
import RecordLyout from '../../components/detail/components/recordLyout';
import RecordComontLayout from '../../components/detail/components/recordComontLayout';
import MaterialLayout from '../../components/detail/components/materialLayout';
import DemandLayout from '../../components/detail/components/purchaseBidDemandLayout';
import BidCommonLayout from '../../components/detail/components/bidCommonLayout';
......@@ -45,7 +45,7 @@ const TABLINK = [
{ id: 'fileLayout', title: '附件', include: ['search', 'readyAdd', 'readySubmitExamineResult', 'readyBid', 'readyExamineResultOne', 'readyExamineResultTwo', 'readyConfirm'] },
{ id: 'demandLayout', title: '需求对接', include: ['search', 'readyAdd', 'readyBid'] },
{ id: 'resultLayout', title: '授标结果', include: ['search', 'readyAdd', 'readyExamineOne', 'readyExamineTwo', 'readySubmit', 'readySubmitExamineResult', 'readyBid', 'readyExamineResultOne', 'readyExamineResultTwo', 'readyConfirm'] },
{ id: 'recordLyout', title: '流转记录' },
{ id: 'recordLayout', title: '流转记录' },
]
const SearchDetail = () => {
......@@ -588,7 +588,7 @@ const SearchDetail = () => {
{_returnFileLayout()}
{_returnDemandLayout()}
{_returnResultLayout()}
<RecordLyout />
<RecordComontLayout externalColors={BID_EXTERNALSTATE_COLOR} internalColors={BID_INTERNALSTATE_COLOR} />
</Fragment>
}
/>
......
......@@ -28,7 +28,7 @@ const Search = () => {
dataIndex: 'id',
key: 'id',
render: (t, r, i) => ++i
}, {
}, {
title: '竞价单号/摘要',
key: 'biddingNo',
dataIndex: 'biddingNo',
......@@ -68,19 +68,17 @@ const Search = () => {
title: '操作',
key: 'operate',
dataIndex: 'operate',
align: 'center',
render: (text: any, record: any) => (
<>
<Button
type='link'
disabled={record.externalState === -1}
onClick={() => {
setId(record.id);
setVisible(true);
}}
>
作废
</Button>
</>
<Button
type='link'
onClick={() => {
setId(record.id);
setVisible(true);
}}
>
作废
</Button>
)
}];
......
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