Commit 9960fab3 authored by 卢均锐's avatar 卢均锐

feat: 采购竞价&在线竞价 接入websocket消息 修改字段

parent 946962b6
......@@ -26,12 +26,10 @@ const BidDetailLayout: React.FC<BidDetailLayoutProps> = (props: any) => {
const { awardProcess = [], isOpenPurchase, isOpenRanking } = detail;
const [showMore, setShowMore] = useState<boolean>(false);
const [activeItem, setActiveItem] = useState<any>(awardProcess?.[0] || { detailss: [] });
const [activeIndex, setActiveIndex] = useState<any>(awardProcess?.[0] || { detailss: [] });
const dataSource = showMore ? [...activeItem.detailss].splice(0, 4) : activeItem.detailss;
useEffect(() => {
awardProcess && setActiveItem(awardProcess?.[0] || { detailss: [] })
awardProcess && setActiveIndex(awardProcess?.[0] ? 0 : '')
awardProcess && setActiveItem(awardProcess?.[0] || { detailss: [] });
}, [detail])
const columns: ColumnType<any>[] = [
......@@ -46,9 +44,9 @@ const BidDetailLayout: React.FC<BidDetailLayoutProps> = (props: any) => {
</Space>
)
},
{ title: '规格型号',key: 'model', dataIndex: 'model', },
{ title: '品类',key: 'category', dataIndex: 'category', },
{ title: '品牌',key: 'brand', dataIndex: 'brand', },
{ title: '规格型号', key: 'model', dataIndex: 'model', },
{ title: '品类', key: 'category', dataIndex: 'category', },
{ title: '品牌', key: 'brand', dataIndex: 'brand', },
{
title: '采购数量/单位',
dataIndex: 'unit',
......@@ -85,11 +83,10 @@ const BidDetailLayout: React.FC<BidDetailLayoutProps> = (props: any) => {
},
]
const chooseItem = (item: any, index: number) => {
if (index !== activeIndex) {
const chooseItem = (item: any) => {
if (item.peportTime !== activeItem?.peportTime) {
setShowMore(false);
setActiveItem(item);
setActiveIndex(index)
}
}
......@@ -103,13 +100,15 @@ const BidDetailLayout: React.FC<BidDetailLayoutProps> = (props: any) => {
<Row gutter={[8, 8]} style={{ marginBottom: '10px' }}>
{awardProcess?.map((item, index, arr) => {
let _ratio = 0;
let _arrLength = arr.length;
if (index != _arrLength - 1 && _arrLength > 2) {
_ratio = Number(((item.sumPice - arr[index + 1].sumPice) / arr[index + 1].sumPice * 100).toFixed(2))
const _arrLength = arr.length;
if (btnType === 2) {
if (index != _arrLength - 1 && _arrLength > 2) {
_ratio = Number(((item.sumPice - arr[index + 1].sumPice) / arr[index + 1].sumPice * 100).toFixed(2))
}
}
return (
<Col span={7} key={`${item.id}_${item.peportTime}`} onClick={() => { chooseItem(item, index) }}>
<BtnItem btnType={btnType} detail={{ ...item, isOpenPurchase, isOpenRanking, ratio: _ratio }} active={index === activeIndex} />
<Col span={7} key={`${item.id}_${item.peportTime}`} onClick={() => { chooseItem(item) }}>
<BtnItem btnType={btnType} detail={{ ...item, isOpenPurchase, isOpenRanking, ratio: _ratio, selfRanking: index+1 }} active={item.peportTime === activeItem?.peportTime} />
</Col>
)
})}
......
import React, { useEffect, useState } from 'react';
import React, { useEffect, useState, useRef, useCallback } from 'react';
import { history } from 'umi';
import { Row, Col } from 'antd';
import { ArrowLeftOutlined } from '@ant-design/icons';
......@@ -6,6 +6,8 @@ import { ArrowLeftOutlined } from '@ant-design/icons';
import { PublicApi } from '@/services/api';
import { priceFormat } from '@/utils/numberFomat';
import { formatTimeString } from '@/utils'
import { getAuth } from '@/utils/auth';
import { SOCKET_URL } from '@/constants';
import StatusBox from '../../../purchaseBid/readyBid/management/components/statusBox';
import QuotationDeskLayout from '../../../components/detail/components/quotationDeskLayout';
......@@ -30,7 +32,45 @@ const Detail = () => {
const [dataSource, setDataSource] = useState<any>({});
const [chartsList, setChartsList] = useState<any>([]);
const fetchDataSource = async () => {
const userInfo = getAuth();
const ws = useRef<WebSocket | null>(null);
const webSocketInit = useCallback(() => {
if (SOCKET_URL && (!ws.current || ws.current.readyState === 3) && userInfo) {
const url = `${SOCKET_URL}/message/websocket?memberId=${userInfo.memberId}&roleId=${userInfo.memberRoleId}&token=${userInfo.token}&source=${1}`;
console.log(url)
ws.current = new WebSocket(url);
// ws.current.onopen = (e) => {}
ws.current.onmessage = (e) => {
const data = JSON.parse(e.data);
console.log(data)
const _data = data.data;
if(data.action === 'purchase_bidding_message_supplier' && _data.id == onlineId){
const _obj = {
ranking: _data.ranking,
minLowPrice : _data.minPrice,
quotationDesks : _data.awardProcesss
}
fetchDataSource(_obj);
}
};
ws.current.onclose = (e) => {
console.log("关闭连接")
}
ws.current.onerror = (e) => {
console.log("socket 出错")
}
}
}, [ws]);
useEffect(() => {
webSocketInit();
return () => {
ws.current?.close();
};
}, [ws, webSocketInit]);
const fetchDataSource = async (socketObj?: any) => {
const params = {
id,
number,
......@@ -43,19 +83,28 @@ const Detail = () => {
return;
}
const { data } = res;
let _flag = false;
if(socketObj){
_flag = true;
data.ranking = socketObj.ranking;
data.minLowPrice = socketObj.minLowPrice;
}
data.onlineId = Number(onlineId);
setDataSource(data);
let _list = [];
let _offerList = [];
let _minList = [];
let _quotationDesks = data?.quotationDesks ? [...data.quotationDesks].reverse() : [];
if(_flag){
_quotationDesks = socketObj.quotationDesks.filter((item) => item.id == onlineId)
}
_quotationDesks.forEach((item) => {
_offerList.push({ type: 'offer', time: formatTimeString(item.offerTime, 'HH:mm:ss'), value: priceFormat(item.price,0) });
_offerList.push({ type: 'offer', time: formatTimeString(item.offerTime || item.peportTime, 'HH:mm:ss'), value: priceFormat(item.price || item.sumPice,0) });
})
_list.push({ title: '报价金额', type: 'offer', list: _offerList });
if (data.isOpenPurchase) {
_quotationDesks.forEach((item) => {
_minList.push({ type: 'min', time: formatTimeString(item.offerTime, 'HH:mm:ss'), value: priceFormat(item.minPrice,0) });
_minList.push({ type: 'min', time: formatTimeString(item.offerTime || item.peportTime, 'HH:mm:ss'), value: priceFormat(item.minPrice,0) });
})
_list.push({ title: '最低价', type: 'min', list: _minList });
}
......
......@@ -43,7 +43,7 @@ const RankRow: React.FC<RankRowProps> = (props: any) => {
<div className={styles.rankRowLeftTop}>
{_returnBadge(detail.ranking)}
{detail.memberName}
{detail.ranking === 1 && <TriangleTag text='最低价' wrapStyle={{ backgroundColor: '#EA8000', position: 'absolute', right: '0' }} bgcolor='#EA8000' direction='left' />}
{detail.ranking === 1 && <TriangleTag text='最低价' wrapStyle={{ backgroundColor: '#EA8000', marginLeft: '8px' }} bgcolor='#EA8000' direction='left' />}
</div>
<div className={styles.rankRowLeftBottom}>
¥{priceFormat(detail.sumPrice)}
......
import React, { useState, useEffect, useMemo } from 'react';
import { history } from 'umi';
import { Row, Col, Input, Drawer, Table, Space, Typography, message } from 'antd';
import { ColumnType } from 'antd/lib/table/interface';
......@@ -35,6 +34,7 @@ const DetailBottomDrawer: React.FC<DetailBottomDrawerProps> = (props: any) => {
{
title: '物料编号/名称',
dataIndex: 'number',
key: 'number',
render: (text: any, record: any) => (
<Space direction='vertical'>
<Text type='secondary' key={'number_1'} >{text}</Text>
......@@ -42,12 +42,13 @@ const DetailBottomDrawer: React.FC<DetailBottomDrawerProps> = (props: any) => {
</Space>
)
},
{ title: '规格型号', dataIndex: 'model', },
{ title: '品类', dataIndex: 'category', },
{ title: '品牌', dataIndex: 'brand', },
{ title: '规格型号', key: 'model', dataIndex: 'model', },
{ title: '品类', key: 'category', dataIndex: 'category', },
{ title: '品牌', key: 'brand', dataIndex: 'brand', },
{
title: '采购数量/单位',
dataIndex: 'unit',
key: 'unit',
render: (text: any, record: any) => (
<Space direction='vertical'>
<Text type='secondary' key={'unit_1'} >{record.purchaseCount}</Text>
......@@ -58,16 +59,19 @@ const DetailBottomDrawer: React.FC<DetailBottomDrawerProps> = (props: any) => {
{
title: '含税/税率',
dataIndex: 'isTax',
key: 'isTax',
render: (text: any, record: any) => <Input value={record.taxRate} onChange={(e) => { _changeTax(record, e.target.value) }} addonAfter="%" />
},
{
title: '单价(含税)',
dataIndex: 'unitPrice',
key: 'unitPrice',
render: (text: any, record: any) => <Input value={record.unitPrice} onChange={(e) => { _changeUnitPrice(record, e.target.value) }} addonBefore="¥" />
},
{
title: '金额(含税)',
dataIndex: 'price',
key: 'price',
render: (text: any, record: any) => <Text type='secondary'>{text && `¥${priceFormat(text)}`}</Text>
},
]
......@@ -135,7 +139,7 @@ const DetailBottomDrawer: React.FC<DetailBottomDrawerProps> = (props: any) => {
}
PublicApi.postPurchaseOnlineBiddingSubmitReportPrice(_params).then(res => {
if (res.code === 1000) {
history.goBack();
onClose && onClose();
}
})
}
......@@ -158,13 +162,13 @@ const DetailBottomDrawer: React.FC<DetailBottomDrawerProps> = (props: any) => {
</Col>
{awardProcess?.map((item, index, arr) => {
let _ratio = 0;
let _arrLength = arr.length;
const _arrLength = arr.length;
if (index != _arrLength - 1 && _arrLength > 2) {
_ratio = Number(((item.sumPice - arr[index + 1].sumPice) / arr[index + 1].sumPice * 100).toFixed(2))
}
return (
<Col span={7} key={`${item.id}_${item.peportTime}`} onClick={() => { chooseItem(item, index) }}>
<BtnItem btnType={2} detail={{ ...item, isOpenPurchase, isOpenRanking, ratio: _ratio }} active={index === activeIndex} />
<BtnItem btnType={2} detail={{ ...item, isOpenPurchase, isOpenRanking, ratio: _ratio, selfRanking: index + 1 }} active={index === activeIndex} />
</Col>
)
})}
......
import React, { useEffect, useState } from 'react';
import React, { useEffect, useState, useRef, useCallback } from 'react';
import { history } from 'umi';
import { Row, Col } from 'antd';
import { ArrowLeftOutlined } from '@ant-design/icons';
......@@ -6,6 +6,8 @@ import { ArrowLeftOutlined } from '@ant-design/icons';
import { PublicApi } from '@/services/api';
import { formatTimeString } from '@/utils'
import { priceFormat } from '@/utils/numberFomat';
import { getAuth } from '@/utils/auth';
import { SOCKET_URL } from '@/constants';
import QuotationDeskLayout from '../../../components/detail/components/quotationDeskLayout';
import BidDetailLayout from '../../../components/detail/components/bidDetailLayout';
......@@ -32,6 +34,53 @@ const Management = () => {
const [awardProcess, setAwardProcess] = useState<any>([]);
const [lowestList, setLowestList] = useState<any>({});
const userInfo = getAuth();
const ws = useRef<WebSocket | null>(null);
const webSocketInit = useCallback(() => {
if (SOCKET_URL && (!ws.current || ws.current.readyState === 3) && userInfo) {
const url = `${SOCKET_URL}/message/websocket?memberId=${userInfo.memberId}&roleId=${userInfo.memberRoleId}&token=${userInfo.token}&source=${1}`;
console.log(url)
ws.current = new WebSocket(url);
// ws.current.onopen = (e) => {}
ws.current.onmessage = (e) => {
const data = JSON.parse(e.data);
console.log(data)
const _data = data.data;
if (data.action === 'purchase_bidding_message' && _data.id == id) {
let _dynamic = { ...dynamic };
_dynamic.count = _data.count;
_dynamic.id = _data.id;
_dynamic.memberName = _data.memberName;
_dynamic.minPrice = _data.minPrice;
setDynamic(_dynamic);
setQueryPriceDynamics(_data.queryPriceDynamics);
setSignupMembers(_data.sginUpInfos);
setAwardProcess(_data.awardProcesss);
setLowestList({
type: 'min',
title: '最低价',
list: _data.awardProcesss ? _data.awardProcesss.map((item) => { return { type: 'min', time: formatTimeString(item.peportTime, 'HH:mm:ss'), value: priceFormat(item.sumPice, 0) } }) : []
})
}
};
ws.current.onclose = (e) => {
console.log(e)
console.log("关闭连接")
}
ws.current.onerror = (e) => {
console.log("socket 出错")
}
}
}, [ws]);
useEffect(() => {
webSocketInit();
return () => {
ws.current?.close();
};
}, [ws, webSocketInit]);
const fetchDataSource = async () => {
const params = {
id,
......@@ -89,7 +138,7 @@ const Management = () => {
setLowestList({
type: 'min',
title: '最低价',
list: data ? data.map((item) => { return { type: 'min', time: formatTimeString(item.peportTime, 'HH:mm:ss'), value: priceFormat(item.sumPice,0) } }) : []
list: data ? data.map((item) => { return { type: 'min', time: formatTimeString(item.peportTime, 'HH:mm:ss'), value: priceFormat(item.sumPice, 0) } }) : []
})
})
}
......
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