import React, { useState, useEffect, useRef } from 'react'; import { Button, Table, Modal, Collapse, message, Row, Col, Tag } from 'antd'; import ReactResumableJs from '@/components/Upload/react-resumable' import { getUpload, withdrawTfile, getReceiptList, getDecrypt, getCodeInfo, saveUploadLog, getSupplierBlack, getCurrentTime, getTendererFileStatus } from './service'; import '@/assets/ld_style.less'; import { getProId, getProMethod, getSessionProjectData, getSessionUserData } from '@/utils/session'; import FileDown from '@/utils/Download'; import { getURLInformation } from '@/utils/CommonUtils'; const { Panel } = Collapse; import { btnAuthority } from '@/utils/authority'; import { verificationSupplier } from '@/utils/IpassVerification' import { ExclamationCircleOutlined } from '@ant-design/icons'; import { getStatusByProId } from '@/services/downLoad'; import SupplierCommitment from './components/SupplierCommitment'; const { confirm } = Modal; function guid() { return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8); return v.toString(16); }); } let switchBtn: boolean = false; // 控制调取刘昊接口状态 let currentDate: any = {}; const Index: React.FC<{}> = () => { let timeInteval: any; let task: any; const projectId = getProId() const savedCallback = useRef(); const [dateList, setDateList] = useState([]); const [receiptList, setReceiptList] = useState([]); const [uploadVisible, setUploadVisible] = useState(false); const [withdrawVisible, setWithdrawVisible] = useState(false); const [receiptVisible, setReceiptVisible] = useState(false); const [timestamp, setTimestamp] = useState(0); // 时间戳 const [subsectionId, setSubsectionId] = useState(); // 分段id const [Tfile, setTfile] = useState({ id: '1' }); // 上传文件参数 const [filePath, setFilePath] = useState(); // 上传文件路径 const [fileT, setFileT] = useState(); const [useIpass, setUseIpass] = useState(); const [iPASSCode, setIpassCode] = useState(); const bidMethodDict = getProMethod(); // 取采购方式 const projectType = getURLInformation('roomType'); const modalHeight = (innerHeight * 96) / 100; const [endTime, setEndTime] = useState(0); // 应答截止时间 const [uuid, setUuid] = useState(); // 生成uuid给上传组件和验证接口 const [supplierStatus, setSupplierStatus] = useState(false); // 供应商资质库显示状态 const [isModalVisible, setIsModalVisible] = useState(false); const [timeDateList, setTimeDateList] = useState([]); const [currentDateList, setCurrentDateList] = useState(); const [isInit, setIsInit] = useState(false);//是否初始化列表-供应商承诺书用 const columns: any[] = [ // 列表数据 { title: '序号', width: '10%', render: (text: any, record: any, index: any) => `${index + 1}` }, { title: '分段名称', width: '25%', dataIndex: 'fileCategory', render: (_: any, record: any) => { if (record.fileCategory === 0) { return (<>商务) } else if (record.fileCategory === 1) { return (<>技术) } else if (record.fileCategory === 2) { return (<>服务) } else if (record.fileCategory === 3) { return (<>报价) } else if (record.fileCategory === 5) { return (<>引用供应商信息库) } else { return (<>其他) } } }, { title: '应答状态', width: '15%', dataIndex: 'status', render: (_: any, record: any) => { if (record.status === 1) { return (<>已应答) } else { return (<>未应答) } } }, { title: '应答时间', width: '20%', render: (text: any, record: any) => { if (record.status == 1) { return ( <>{record.operateTime} ) } else { return ( <> ) } } }, { title: '操作', width: '30%', render: (text: any, record: any) => { let end: any = new Date(record.endDate.replaceAll("-", "/")).getTime() let start: any = new Date(record.startDate.replaceAll("-", "/")).getTime() if (end > timestamp && record.status != 1 && timestamp > start && record.openState == '1') { return ( <> ) } else if (end > timestamp && record.status == null && timestamp > start && record.openState == '1') { return ( <> ) } else if (end > timestamp && record.status == 1 && record.openState == '1') { return ( <> ) } else if (end < timestamp && record.status == 1) { return ( <> ) } else if (end > timestamp && record.status == 1 && record.openState == '0') { return ( <> ) } }, }, ]; const receiptColumns: any[] = [ // 回执列表数据 { title: '序号', render: (text: any, record: any, index: any) => `${index + 1}` }, { title: '回执类别', dataIndex: 'status', render: (_: any, record: any) => { if (record.status === 0) { return (<>撤回) } else if (record.status === 1) { return (<>投标) } } }, { title: '回执时间', dataIndex: 'createDate', }, { title: '操作', render: (text: any, record: any, index: any) => ( ), }, ]; const submitWithdraw = (id: any) => { // 撤回 setWithdrawVisible(true) setSubsectionId(id) } const getWithdraw = () => { // 确定撤回 withdrawTfile(subsectionId).then((res) => { if (res.code == 200) { setWithdrawVisible(false) getList() } }) } const lookReceipt = (id: any) => { // 查看回执 setReceiptVisible(true) const data = { relId: id } getReceiptList(data).then((res) => { if (res.code == 200) { setReceiptList(res.data) } }) } /** * 根据项目id获取供应商资质库信息引用状态 * @param id 项目id * @returns true-有供应商资质库信息 false-无供应商资质库信息 */ const getSupplierStatus = async (id: string) => { await getStatusByProId({ id: id }).then(res => { if (res?.code == 200) { setSupplierStatus(res?.data) } }) } const showConfirm = () => { confirm({ title: <>

请使用客户端工具打开并编辑您所下载的megp文件,若您未安装客户端工具,可至系统菜单-【我的工作台】-【共享文档下载】进行下载和安装。

温馨提示:请您合理控制投标文件大小并留出充足时间提前试上传,以便提前发现问题予以解决。

, icon: , width: supplierStatus || (getSessionProjectData().isIPassFile != '1') ? 600 : 416, okText: '知道了', centered: true, cancelButtonProps: { className: 'display-cancel', }, onOk() { if (START_ENV == 'UAT' || START_ENV == 'DEV' || START_ENV == 'sim') { setUploadVisible(true) } else { if (useIpass == '0') { if (verificationSupplier(iPASSCode)) { setUploadVisible(true) } } else { setUploadVisible(true) } } }, }); } const setOk = () => { setIsModalVisible(false) showConfirm() } const batchUpload = (val: any, index: any) => { // 上传 let deptIdList: any = [] deptIdList.push(getSessionUserData().deptId) let date = { "tpId": getProId(), "ids": deptIdList } getSupplierBlack(date).then((res) => { if (res.code == 200) { if (res?.data[getSessionUserData().deptId] == true) { setIsModalVisible(true) } else { showConfirm() } } }) setUuid(guid()) let path, object, filetype if (index == 'single') { currentDate = val setEndTime(new Date(val.endDate).getTime()) filetype = '.file' // filetype = '.rar,.zip,.doc,.docx,.xls,.xlsx,.pdf' object = JSON.stringify(val) path = '/' + val.createYear + '/' + val.tpId + '/' + val.sectionId + '/' + val.tdocId + '/uploadFile/' + val.tendererId } else { currentDate = dateList[index].tfileList[0] currentDate.tdocCatalogId = "" setEndTime(new Date(dateList[index].endDate).getTime()) filetype = '.zip' // filetype = '.rar,.zip' object = JSON.stringify(dateList[index].tfileList[0]) path = '/' + dateList[index].createYear + '/' + dateList[index].tpId + '/' + dateList[index].sectionId + '/' + dateList[index].id + '/uploadFile/' + dateList[index].tfileList[0].tendererId } setTfile(object) setFilePath(path) setFileT(filetype) } const getCode = (id: any) => { // 获取iPASS码 let idArr = [] idArr.push(id) getCodeInfo(idArr).then((res) => { if (res.code == 200) { if (res?.data[0]) { setIpassCode(res.data[0].organizationCode) } } }) } const closeModal = () => { // 关闭上传 if (!switchBtn) { setUploadVisible(false) getList() } else { message.warn('请上传完附件再关闭弹窗!') } } /** * 大文件上传完成后的组件返回 * * @param file * @param resumable * @param callback */ const onUploadSuccess = (file: any, cache: any, callback: any) => { cache.push({ key: cache.length + 1, filename: "文件验证中", uploading: false,// 这不是文件上传作业 prograss: 0, }); // TODO 下面演示一下接口如何调用 let test = 0; switchBtn = true; let num = 0; task = setInterval(() => { num += 1; if (test < 80) { test += 20; } else if (test == 80) { test = 80 } else if (test == 100) { clearInterval(task); } if (num > 30) { callback(cache.length - 1, "文件验证失败", 2); message.error('缺少文件验证信息,请刷新页面后重新上传!') switchBtn = false clearInterval(task); } else { if (switchBtn) { setTimeout(() => { message.destroy() }, 3000) test = 100; callback(cache.length - 1, "文件验证成功", test); switchBtn = false; clearInterval(task); return; // getDecrypt(uuid).then((res) => { // if (res.code == 200) { // if (res.data.consumptionState == '2' || res.data.consumptionState == '4') { // if (res.data.stateMessage) { // message.error(res.data.stateMessage) // callback(cache.length - 1, res.data.stateMessage, 2); // } else { // message.error('验证错误,请刷新页面后重新上传!') // callback(cache.length - 1, "文件验证失败", 2); // } // switchBtn = false; // clearInterval(task); // return; // } else if (res.data.consumptionState == '3') { // message.success(res.data.stateMessage) // setTimeout(() => { // message.destroy() // }, 3000) // test = 100; // callback(cache.length - 1, "文件验证成功", test); // switchBtn = false; // clearInterval(task); // return; // } else { // callback(cache.length - 1, "文件验证中", test); // } // } // }) } } }, 3000); } const onFileAdded = (file: any, resumable: any) => { // 上传附件 switchBtn = true let date = { "message": Tfile + file.name } saveUploadLog(date).then((res) => { if (res.code == 200) { } }) } const onPauseUpload = (file: any, resumable: any) => { // 上传附件暂停 switchBtn = false } const onResumeUpload = (file: any, resumable: any) => { // 上传附件恢复 switchBtn = true } const onCancelUpload = (file: any, resumable: any) => { // 上传附件 // switchBtn = true } /** * 大文件上传失败后的组件返回 */ const onUploadError = (resumable: any) => { if (resumable == '超过截止时间') { message.error('已超过截止时间') } else if (resumable == '撤销后再上传') { message.error('您已上传应答文件,需撤销后再上传!') setUploadVisible(false) getList() } else { let strIndex = resumable.fileName.lastIndexOf(".") let fileSuffix = resumable.fileName.substring(strIndex + 1, resumable.fileName.length) // 判断文件类型 const fileTypes = fileT.split(',').map((type: string) => type.trim().toLowerCase()); // if (('.' + fileSuffix) != fileT) { if (!fileTypes.includes('.' + fileSuffix)) { message.error('请上传' + fileT + '类型的文件') } else if (fileSuffix == 'file' && resumable.file.size > 200 * 1024 * 1024) { message.error('文件最大为200MB') } else if (fileSuffix == 'zip' && resumable.file.size > 500 * 1024 * 1024) { message.error('文件最大为500MB') } else { message.error('上传失败!') } } switchBtn = false } const getCurrent = () => { getCurrentTime().then((res) => { if (res.code == 200) { let currentTiem = new Date(res.data.replace(/-/g, '/')).getTime() setTimestamp(currentTiem) } }) } const getList = () => { let data = { roomType: projectType } getUpload(projectId, data).then((res) => { if (res.code == 200) { getSupplierStatus(projectId) setDateList(res?.data) setUseIpass(res?.data[0]?.useIpass) getCode(res?.data[0]?.companyId) } }) } const handleTimeInterval = () => { // 倒计时 if (dateList.length > 0 && timestamp > 0) { setTimestamp(timestamp + 1000); let newTimeDateList: any = []; dateList.map((item: any, index: any) => { if (item?.endDate && item?.endDate != "" && item?.endDate != null) { newTimeDateList.push(showTimeDetail(item?.endDate)); } }) setCurrentDateList(new Date(timestamp).toLocaleString()) setTimeDateList(newTimeDateList); } } useEffect(() => { savedCallback.current = handleTimeInterval; }); useEffect(() => { if (isInit) { getList(); getCurrent(); timeInteval = setInterval(() => { // 倒计时 savedCallback.current(); }, 1000); } return () => { clearInterval(timeInteval); if (task) { clearInterval(task) } } }, [isInit]); const showTimeDetail = (endDate: any) => { let endtime = new Date(endDate.replace(/-/g, '/')); //定义结束时间 let lefttime = endtime.getTime() - timestamp; //距离结束时间的毫秒数 let returnResult = ""; if (lefttime > 0) { let leftd = Math.floor(lefttime / (1000 * 60 * 60 * 24)); //计算天数 let lefth = Math.floor(lefttime / (1000 * 60 * 60) % 24); //计算小时数 let leftm = Math.floor(lefttime / (1000 * 60) % 60); //计算分钟数 let lefts = Math.floor(lefttime / 1000 % 60); //计算秒数 returnResult = "距离递交结束还有 " + leftd + "天" + lefth + "时" + leftm + "分" + lefts + "秒"; } else { returnResult = "已超过截止时间"; } return returnResult; } return ( <>
分包分段信息
{ dateList.map((item: any, index: any) => { return ( <>
应答截止时间:{item.endDate} 国家授时中心标准时间:{currentDateList} {timeDateList.length > 0 ? timeDateList[index] : null} { item.state == '0' && timestamp > 0 && new Date(item.startDate.replaceAll("-", "/")).getTime() < timestamp && new Date(item.endDate.replaceAll("-", "/")).getTime() > timestamp ? : null }
{ item.tfileList.map((val: any, index: any) => { val.startDate = item.startDate val.endDate = item.endDate val.openTime = item.openTime val.signDateTime = item.signDateTime val.tpId = item.tpId val.sectionId = item.sectionId val.pathId = item.id val.companyId = item.companyId val.createYear = item.createYear val.openState = item.openState val.tendererName = item.tendererName }) } { item.state != '0' ? null :

温馨提示:您尚未完成投标文件上传!请上传投标客户端制作生成的文件,若您未安装客户端工具,可至系统菜单-【我的工作台】-【共享文档下载】进行下载和安装!

} ) }) } { uploadVisible ? closeModal()}>关闭]} > { onFileAdded(file, resumable) }} onPauseUpload={(file: any, resumable: any) => { onPauseUpload(file, resumable) }} onResumeUpload={(file: any, resumable: any) => { onResumeUpload(file, resumable) }} onCancelUpload={(file: any, resumable: any) => { onCancelUpload(file, resumable) }} service="/api/core-service-ebtp-updownload/v1/hulk/upload" /> : null } setWithdrawVisible(false)} onOk={() => getWithdraw()} > 确定撤回吗? setReceiptVisible(false)} onOk={() => setReceiptVisible(false)} centered style={{ maxHeight: modalHeight }} bodyStyle={{ maxHeight: modalHeight - 107, overflowY: 'auto' }} >
好的,我已知晓]} >

友情提示:您已被列入联通供应商黑名单,黑名单期间您可能被拒绝中标,请您谨慎操作。

{ setIsInit(true) }} /> ) } export default Index