3.10 工程代码同步master

This commit is contained in:
jl-zhoujl2
2022-03-10 14:24:13 +08:00
parent 41ab55a4ac
commit 62f6b07ee2
914 changed files with 143121 additions and 29110 deletions

View File

@ -0,0 +1,253 @@
/*
* @Author: liqiang
* @Date: 2021-02-25 10:50:04
* @LastEditTime: 2021-03-18 16:40:27
* @Description: In User Settings Edit
* @FilePath: \ebtp-cloud-frontend\src\pages\Auction\AuctionViewAuctions\components\AuctionImage.tsx
*/
import React, { useEffect } from 'react';
import { Image } from 'antd';
import '../AuctionImage.less';
import defaultImage from '@/assets/defaultImage/defaultImage.jpg';
import { isEmpty, isNotEmpty } from '@/utils/CommonUtils';
interface auctionImageItem {
image: string[]
}
const AuctionImage: React.FC<auctionImageItem> = (props) => {
const { image } = props;
const images = isEmpty(image) || image.length === 0 ? [defaultImage] : image;
const imgArr = {
big: images,
small: images
};
useEffect(() => {
let ele: any,
eleWidth: any,
eleHeight: any,
url: any,
maskLayerWidth: any,
maskLayerHeight: any,
backgroundScaleX: any,
backgroundScaleY: any,
scaleX: any,
scaleY: any;
let maskLayer: any = document.createElement('div'),
asideBox: any = document.createElement('div');
const Magnifier = function (ele1: any, obj: any) {
ele = ele1;//原始图片盒子
eleWidth = ele.offsetWidth;//原始图片盒子宽度
eleHeight = ele.offsetHeight;//原始图片盒子高度
url = '';//放大图片url
maskLayerWidth = obj.maskLayerWidth || obj.maskLayerHeight || 180;//遮罩宽度
maskLayerHeight = obj.maskLayerHeight || obj.maskLayerWidth || 180;//遮罩高度
backgroundScaleX = eleWidth / maskLayerWidth;//放大后图片与原始图片的放大比例(X)
backgroundScaleY = eleHeight / maskLayerHeight;//放大后图片与原始图片的放大比例(Y)
scaleX = obj.scale ? obj.scale[0] || obj.scale[1] : backgroundScaleX;//放大图片盒子与遮罩的放大比例(X)
scaleY = obj.scale ? obj.scale[1] || obj.scale[0] : backgroundScaleY;//放大图片盒子与遮罩的放大比例(Y)
ele.style.backgroundSize = '100% 100%';
return {
ele: ele,//原始图片盒子
eleWidth: eleWidth,//原始图片盒子宽度
eleHeight: eleHeight,//原始图片盒子高度
url: '',//放大图片url
maskLayerWidth: maskLayerWidth,//遮罩宽度
maskLayerHeight: maskLayerHeight,//遮罩高度
backgroundScaleX: backgroundScaleX,//放大后图片与原始图片的放大比例(X)
backgroundScaleY: backgroundScaleY,//放大后图片与原始图片的放大比例(Y)
scaleX: scaleX,//放大图片盒子与遮罩的放大比例(X)
scaleY: scaleY,//放大图片盒子与遮罩的放大比例(Y)
}
};
function calcPosition(e: any) {
var left = e.pageX - ele.offsetLeft - maskLayerWidth / 2,
top = e.pageY - ele.offsetTop - maskLayerHeight / 2;
if (left < 0) {
left = 0;
} else if (left > eleWidth - maskLayerWidth) {
left = eleWidth - maskLayerWidth;
};
if (top < 0) {
top = 0;
} else if (top > eleHeight - maskLayerHeight) {
top = eleHeight - maskLayerHeight;
};
maskLayer.style.left = left + 'px';
maskLayer.style.top = top + 'px';
asideBox.style.backgroundPosition = left * -scaleX + 'px ' + top * -scaleY + 'px';
}
function createRelativeBox() {
maskLayer = document.createElement('div')
//遮罩
maskLayer.style.cssText = 'position: absolute;border: 1px solid #ccc;background: rgba(255, 255, 255, .7);cursor: move;' +
'width:' + maskLayerWidth + 'px;height:' + maskLayerHeight + 'px;'
ele.appendChild(maskLayer);
//放大图片盒子
asideBox = document.createElement('div');
asideBox.style.cssText = 'position:absolute;left:105%;top:50%;border:2px solid #ccc;transform:translateY(-50%);' +
'width:' + maskLayerWidth * scaleX + 'px;height:' + maskLayerHeight * scaleY + 'px;' +
'background-image:url(' + url + ');background-repeat:no-repeat;background-size:' + backgroundScaleX * 100 + '% ' + backgroundScaleY * 100 + '%';
ele.appendChild(asideBox);
}
// window['Magnifier'] = Magnifier;
info()
function info() {
var smallImgUl = document.querySelector('ul.small-img-ul'),
phoneDispaly = document.querySelector('a.phone-display');
var i = 0, flag = true;
//插入小图片
var arr: string[] = [];
imgArr['small'].forEach(function (ele: string) {
arr.push('<li class=\'img\' style=\'background-image:url(' + ele + ')\'></li>')
});
smallImgUl.innerHTML = arr.join('');
var imgList = smallImgUl.children,
smallImgWidth = imgList[0].offsetWidth + 5 + (imgList.length << 1);
smallImgUl.style.width = imgList.length * smallImgWidth + 'px';
//获取索引
function getIndex(item: EventTarget | null) {
return Array.prototype.indexOf.call(imgList, item);
};
//初始化展示的大图和小图以及相关样式
initImg();
function initImg() {
Array.prototype.forEach.call(imgList, function (ele, index) {
ele.className = 'img';
});
if (imgList[i] !== void 0) {
imgList[i].className += ' active';
}
phoneDispaly.style.backgroundImage = 'url(' + imgArr['big'][i] + ')';
};
//鼠标移入事件
smallImgUl.addEventListener('click', function (e) {
i = getIndex(e.target);
if (i === -1) {
return;
}
initImg();
});
var magnifier = Magnifier(phoneDispaly, {
maskLayerWidth: 180,
maskLayerHeight: 240,
scale: [2]
});
function moveEffect(e: any) {
if (flag) {
magnifier.url = imgArr['big'][i];
createRelativeBox();
flag = false;
};
calcPosition(e);
};
// phoneDispaly.addEventListener('mouseenter', function () {
// phoneDispaly.addEventListener('mousemove', moveEffect, false);
// phoneDispaly.addEventListener('mouseleave', function () {
// // phoneDispaly.removeEventListener('mousemove', moveEffect);
// phoneDispaly.innerHTML = '';
// flag = true;
// }, false);
// }, false);
phoneDispaly.addEventListener('click', function () {
if (isEmpty(image) || image.length === 0) {
return;
}
document.getElementById(`image-${i}`)?.click();
});
//左右按钮点击
var btnLeft = document.querySelector('.btn-left'),
btnRight = document.querySelector('.btn-right');
var overNum = (parseFloat(window.getComputedStyle(smallImgUl, null)['width']) - parseFloat(window.getComputedStyle(smallImgUl.parentNode, null)['width'])) / smallImgWidth;
var record = 0;
btnLeft.addEventListener('click', function () {
record--;
if (record < 0) {
record = 0;
return;
};
smallImgUl.style.left = parseFloat(window.getComputedStyle(smallImgUl, null)['left']) + smallImgWidth + 'px';
}, false);
btnRight.addEventListener('click', function () {
record++;
if (record > overNum) {
record = overNum;
return;
};
smallImgUl.style.left = parseFloat(window.getComputedStyle(smallImgUl, null)['left']) - smallImgWidth + 'px';
}, false);
}
}, []);
return (
<>
{/* <!--左侧轮播--> */}
<div className="img-content">
<div className="effectBox">
<a href="javascript:;" className="phone-display"></a>
<div className="bottom-nav">
<div className="tab-btn btn-left">
<i className="shift-icon">
<span></span>
</i>
</div>
<div className="tab-btn btn-right">
<i className="shift-icon">
<span></span>
</i>
</div>
<div className="bottom-center-nav">
<ul className="small-img-ul">
</ul>
</div>
</div>
</div>
</div>
{/* <!--//左侧轮播--> */}
{/* 放大图片 */}
<div style={{ display: 'none' }}>
<Image.PreviewGroup>
{
(isNotEmpty(images) && images.length !== 0) &&
images.map((item: string, index: number) =>
<Image
id={`image-${index}`}
src={item}
/>
)
}
</Image.PreviewGroup>
</div>
</>
)
};
export default AuctionImage;

View File

@ -0,0 +1,517 @@
/*
* @Author: liqiang
* @Date: 2021-02-23 13:49:53
* @LastEditTime: 2021-03-25 16:46:14
* @LastEditors: Please set LastEditors
* @Description: In User Settings Edit
* @FilePath: \ebtp-cloud-frontend\src\pages\Auction\AuctionViewAuctions\components\A.tsx
*/
import { isEmpty } from '@/utils/CommonUtils';
import { Col, Divider, Form, Input, message, Modal, Row, Tabs } from 'antd';
import React, { useEffect, useRef, useState } from 'react';
import { getAuctionViewAuctions, getRedisBidData, putOrderBidPrice, updatetOnlookers } from '../service';
import ProTable from '@ant-design/pro-table';
import ExtendUpload from '@/utils/ExtendUpload';
import AuctionImage from './AuctionImage';
import CountDownUtils from './CountDownUtils';
import '../auctionParts.less';
import { getProId, getSessionRoleData } from '@/utils/session';
import { getBidFile } from '@/pages/Tender/supplier/LookingForBusinessOpportunities/service';
import { downloadAttachmentPathOId, getDownloadToken } from '@/utils/DownloadUtils';
import { algebraicAddition, digitalConversionAmount } from '@/utils/NumberUtils';
const { TabPane } = Tabs;
//定时器间隔时间
const timingInterval = 5000;
//金额校验正则 保留两位小数
const amountMoney = /^\d{1,15}([.]\d{1,2})?$/;
const AuctionViewAuctions: React.FC = () => {
//项目id
const tpId = getProId();
//状态 0围观 1 参拍
const [viewStatus, setViewStatus] = useState<string>('');
//出价数据
const [cjDataSource, setCjDataSource] = useState<any[]>([]);
//起拍价
const [startingPrice, setStartingPrice] = useState<any>();
//公告数据
const [noticeData, setNoticeData] = useState<any>();
//物资数据
const [auctionMaterialsList, setAuctionMaterialsList] = useState<any[]>([]);
//标的物所在地:右侧信息
const [locationOfTheSubjectMatter, setLocationOfTheSubjectMatter] = useState<any>();
const [subjectMatterIntroductionForm] = Form.useForm();
//标的物清单附件bid
const [subjectMatterIntroductionBid, setSubjectMatterIntroductionBid] = useState<string>('');
//项目名称
const [projectName, setProjectName] = useState<string>('');
//参拍信息
const [participateData, setParticipateData] = useState<any>();
//当前价
const [currentPrice, setCurrentPrice] = useState<number>(0);
//延时次数
const [delay, setDelay] = useState<any>();
//是否结束
const [overFlag, setOverFlag] = useState<boolean>(false);
//倒计时剩余时间
const [countDownTime, setCountDownTime] = useState<any>(null);
//结束时间
const [endTime, setEndTime] = useState<string>('');
const ref = useRef<any>();
const overFlagRef = useRef<any>();
//图片
const [auctionImage, setAuctionImage] = useState<string[]>([]);
//显示图片
const [auctionImageFlag, setAuctionImageFlag] = useState<boolean>(false);
let downloadToken = getDownloadToken();
const cjColumns = [
{
title: '序号',
valueType: 'index'
},
{
title: '参拍人',
dataIndex: 'supplierId',
},
{
title: '出价(元)',
dataIndex: 'price',
},
{
title: '出价时间',
dataIndex: 'bidTime',
},
];
const wzColumns = [
{
title: '所属OU组织',
dataIndex: 'organization',
},
{
title: '物资名称',
dataIndex: 'materialName',
},
{
title: '物料编码',
dataIndex: 'materialCode',
},
{
title: '物资厂家',
dataIndex: 'manufacturer',
},
{
title: '规格型号',
dataIndex: 'specification',
key: 'specification',
},
{
title: '库龄',
dataIndex: 'reservoirAge',
},
{
title: '数量',
dataIndex: 'amount',
},
{
title: '计量单位',
dataIndex: 'materialUnit',
},
{
title: '单价',
dataIndex: 'unitPrice',
},
{
title: '统一目录名称',
dataIndex: 'directoryName',
},
{
title: '统一目录编码',
dataIndex: 'directoryCode',
},
];
useEffect(() => {
init();
setTimeout(() => {
//项目已结束
if (overFlagRef.current) {
return;
}
ref.current = setInterval(() => {
getRedisBidData(tpId).then(res => {
res = res !== null ? res : {};
if (res.code === 200) {
let data = res.data;
timedRefreshData(data);
if (Number(data.jssj) <= 0) {
setOverFlag(true);
clearInterval(ref.current);
}
} else {
// clearInterval(ref.current);
}
})
}, timingInterval);
}, timingInterval);
}, []);
const reloadData = () => {
getRedisBidData(tpId).then(res => {
if (res.code === 200) {
let data = res.data;
timedRefreshData(data);
if (Number(data.jssj) <= 0) {
setOverFlag(true);
}
}
})
}
const timedRefreshData = (data: any) => {
let participateData = [data.cpr, data.cjcs, data.wgr];
getParticipateData(participateData);
setCjDataSource(data.cjjl);
setCurrentPrice(data.zgjg);
setDelay(data.yscs);
setCountDownTime(data.jssj);
}
/**
* 倒计时结束
*/
const countDownOver = () => {
setOverFlag(true);
}
const getParticipateData = (arr: any[]) => {
setParticipateData(
<>
<span>{arr[0]}</span>
<span>{arr[1]}</span>
<span>{arr[2]}</span>
</>
)
}
/**
* 初始化
*/
const [range, rangeSet] = useState<any>(0)//加价幅度
const init = () => {
const roleID = getSessionRoleData().roleId;
getAuctionViewAuctions(tpId).then(res => {
if (res.code === 200) {
let data = res.data;
//判断项目是否结束
if (data.yczt) {
setOverFlag(data.yczt);
overFlagRef.current = data.yczt;
}
findFile(data.gg.auctionBdwxcdfzp)
setProjectName(data.xm.auction.projectName);
setCurrentPrice(data.inner02_04);
let participateData = [data.inner02_03.cprsl, data.inner02_03.xmcjcs, data.inner02_03.wgrsl];
getParticipateData(participateData);
setDelay(data.inner02_02.yscs);
setCjDataSource(data.tab03_01);
//状态 0围观 1 参拍
setViewStatus(data.cprdm !== null ? '1' : '0');
setStartingPrice(
<>
<span>{digitalConversionAmount(String(data.gg.auctionJpjg), 2)}</span>
<span>{digitalConversionAmount(String(data.gg.auctionJjfd), 2)}</span>
<span>{data.gg.auctionYszq}/</span>
{
data.cprdm !== null && roleID === '20003' && <span>{data.cprdm}</span>
}
</>
);
rangeSet(Number(data.gg.auctionJjfd));//幅度
// offerAPriceSet(Number(data.inner02_04));//出价
//公告数据
setNoticeData(
<div style={{paddingLeft: '25px'}}>
<span dangerouslySetInnerHTML={{ __html: data.gg.htmlContent }}></span>
<br />
<br />
<br />
<span>
<ExtendUpload bid={data.gg.auctionGgfj} btnName="附件" uploadProps={{ disabled: true }} />
</span>
</div>
)
setAuctionMaterialsList(data.xm.auctionMaterialsList);
subjectMatterIntroductionForm.setFieldsValue(data.gg);
setSubjectMatterIntroductionBid(data.gg.auctionBdwqdfj);
setLocationOfTheSubjectMatter(
<>
<li><span className="col333">{data.gg.auctionBdwwz}</span></li>
<li><span className="col333">{data.gg.auctionGpf}</span></li>
<li><span className="col333">{data.gg.auctionLxr}</span></li>
<li><span className="col333">{data.gg.auctionLxdh}</span></li>
</>
)
setEndTime(data.gg.auctionJpjssj);
setCountDownTime(data.jpjssjTime);
//围观+1
if (data.cprdm == null) {
updatetOnlookers(tpId).then(res => {
});
}
}
})
}
const findFile = (id: string) => {
getBidFile(id).then(res => {
let data = isEmpty(res) ? [] : res;
let arr = []
for (const item of data) {
arr.push(downloadAttachmentPathOId + item.id);
}
setAuctionImage(arr);
setAuctionImageFlag(true);
})
}
/**
* 出价
*/
const [offerAPrice, offerAPriceSet] = useState<any>('');
const onSearch = () => {
let value: any = Number(offerAPrice);
if (isEmpty(value)) {
message.info('请出价!');
return;
}
if (!amountMoney.test(value)) {
message.info('请输入正确的格式(小数点前15位,小数点后2位)');
return;
}
if (Number(value) <= Number(currentPrice)) {
message.info('请输入高于当前价的金额!');
return;
}
// let differ = (Number(value) - Number(currentPrice)) % range
let differ = (value*1000- currentPrice*1000) % (range*1000)
if (differ !== 0) {
message.info('请增加加价幅度整数倍的金额!');
return;
}
//出价
confirmBidOrNot(tpId, value);
}
/**
* 确认出价
* @param tpId
* @param value
*/
const confirmBidOrNot = (tpId: any, value: any) => {
const orderBidPrice = (tpId: any, value: any) => {
//出价
putOrderBidPrice(tpId, value).then(res => {
if (res.code === 200) {
let data = res.data;
if (data) {
message.success('出价成功!');
}
reloadData();
}
})
}
Modal.confirm({
content: "请确认出价",
okText: '确认',
cancelText: '取消',
keyboard: false,
centered: true,
onCancel: () => { },
onOk: () => orderBidPrice(tpId, value)
});
}
return (
<>
<div className="htmlWrap">
{
auctionImageFlag && <AuctionImage image={auctionImage} />
}
<div className="contentParts">
{/* <!--核心区域--> */}
<div className="mainText">
<h4>{projectName}</h4>
{/* <!--stateRed是正在进行的状态样式去掉stateRed是竞拍结束状态样式--> */}
<div className={overFlag ? 'stateBlock' : 'stateBlock stateRed'}>
{
overFlag ? (
<>
<span className="stateIco"></span>
<span className="staeTime">
&nbsp;{endTime}{delay}
</span>
</>
) : (
<>
<span className="stateIco"></span>
<span className="staeTime">
&nbsp;
<CountDownUtils countDown={countDownTime} countDownOver={() => countDownOver()} />{delay}
</span>
</>
)
}
<p>
{participateData}
</p>
</div>
<div className="priceBlock">
{overFlag ? '最终价:' : '当前价:'}<span>{digitalConversionAmount(String(currentPrice), 2)}</span>
</div>
<div className="saleBlock">
{
(viewStatus === '1' && !overFlag) && (
<>
<span></span>
<Input type="text" maxLength={15} value={offerAPrice} autoComplete='off'
onChange={(e) => offerAPriceSet(e.target.value)}
/>
<button type="button" onClick={onSearch} style={{ marginLeft: 8 }}></button>
<button type="button" style={{ marginLeft: 8 }} onClick={() => {
let count: number = 0;
if (!Number(offerAPrice)) {
count = algebraicAddition(currentPrice, range);
offerAPriceSet(count);
} else {
count = algebraicAddition(offerAPrice, range);
offerAPriceSet(count);
}
message.success(`加价${range},当前价格为${count}`);
}}>+{range}</button>
</>
)
}
</div>
<div className="otherInform">
{startingPrice}
</div>
</div>
<div className="rightInform">
<ul>
{locationOfTheSubjectMatter}
</ul>
</div>
</div>
<Divider />
<Row>
<Col span={24}>
<Tabs defaultActiveKey="1" size={'large'} centered>
<TabPane tab="竞拍公告" key="1">
<Divider></Divider>
{noticeData}
</TabPane>
<TabPane tab="标的物介绍" key="2">
<Divider></Divider>
<Form form={subjectMatterIntroductionForm} labelCol={{ span: 3 }}>
<Form.Item
label="标的物介绍"
name="auctionBdwjs">
<Input bordered={false} readOnly />
</Form.Item>
<Form.Item
label="标的物预估重量(kg)"
name="auctionBdwygzl">
<Input bordered={false} readOnly />
</Form.Item>
<Form.Item
label="标的物预估体积(m³)"
name="auctionBdwygtj">
<Input bordered={false} readOnly />
</Form.Item>
<Form.Item
label="标的物账面价值(元)"
name="auctionBdwzmjz">
<Input bordered={false} readOnly />
</Form.Item>
<Form.Item
label="标的物在库时间(天)"
name="auctionBdwzksj">
<Input bordered={false} readOnly />
</Form.Item>
<Form.Item
label="标的物位置"
name="auctionBdwwz">
<Input bordered={false} readOnly />
</Form.Item>
<Form.Item
label="标的物清单附件"
name="auctionBdwqdfj">
<ExtendUpload bid={subjectMatterIntroductionBid} btnName="附件" uploadProps={{ disabled: true }} />
</Form.Item>
{/* <Form.Item
label="物资清单"
>
<ProTable
dataSource={auctionMaterialsList}
columns={wzColumns}
pagination={false}
search={false}
options={false}
rowKey="id"
/>
</Form.Item> */}
<ProTable
headerTitle="物资清单"
dataSource={auctionMaterialsList}
columns={wzColumns}
pagination={false}
search={false}
options={false}
rowKey="id"
/>
</Form>
</TabPane>
<TabPane tab="出价记录" key="3">
<Divider></Divider>
<ProTable
dataSource={cjDataSource}
columns={cjColumns}
search={false}
options={false}
pagination={{ defaultPageSize: 10 }}
rowKey="id"
/>
</TabPane>
</Tabs>
</Col>
</Row>
</div>
</>
)
}
export default AuctionViewAuctions;

View File

@ -0,0 +1,75 @@
/*
* @Author: liqiang
* @Date: 2021-02-26 09:38:47
* @LastEditTime: 2021-03-17 16:45:47
* @LastEditors: Please set LastEditors
* @Description: 根据传入的毫秒值倒计时
* @FilePath: \ebtp-cloud-frontend\src\pages\Auction\AuctionViewAuctions\components\CountDownUtils.tsx
*/
import React, { useEffect, useRef, useState } from 'react';
interface CountDownUtilsItem {
countDown: number | null,
countDownOver: () => void
}
const sixty = 60;
const threeThousandAndSixHundred = 3600;
const twentyFour = 24;
const hourSeconds = twentyFour * threeThousandAndSixHundred;
const ten = 10;
const CountDownUtils: React.FC<CountDownUtilsItem> = (props) => {
const { countDown, countDownOver } = props;
const [time, setTime] = useState<string>();
const ref = useRef<any>();
useEffect(() => {
if (countDown === null) {
return;
}
let maxtime = countDown / 1000; //按秒计算
clearInterval(ref.current);
const interval = setInterval(() => {
// if (maxtime >= 0) {
// //计算出相差天数
// let days = Math.floor(maxtime / hourSeconds);
// //计算出小时数
// let leave1 = maxtime % hourSeconds; //计算天数后剩余的秒数
// let hours = Math.floor(leave1 / threeThousandAndSixHundred);
// //计算相差分钟数
// let leave2 = leave1 % threeThousandAndSixHundred; //计算小时数后剩余的秒数
// let minutes = Math.floor(leave2 / sixty);
// //计算相差秒数
// let leave3 = leave2 % sixty; //计算分钟数后剩余的秒数
// let seconds = Math.round(leave3);
// setTime(days + '天 ' + hours + '小时 ' + minutes + '分钟 ' + seconds + ' 秒');
// --maxtime;
// } else {
// clearInterval(interval);
// //倒计时结束时,触发父组件的方法
// countDownOver();
// }
if (maxtime >= 0) {
let ts = maxtime;//计算剩余的毫秒数
let dd = parseInt(String(ts / sixty / sixty / twentyFour), ten);//计算剩余的天数
let hh = parseInt(String(ts / sixty / sixty % twentyFour), ten);//计算剩余的小时数
let mm = parseInt(String(ts / sixty % sixty), ten);//计算剩余的分钟数
let ss = parseInt(String(ts % sixty), ten);//计算剩余的秒数
setTime(dd + '天 ' + hh + '小时 ' + mm + '分钟 ' + ss + ' 秒');
--maxtime;
} else {
clearInterval(ref.current);
//倒计时结束时,触发父组件的方法
countDownOver();
}
}, 1000);
ref.current = interval;
}, [countDown]);
return (
<>
{time}
</>
)
}
export default CountDownUtils;