手写签名,线下评审,预审评委会
This commit is contained in:
@ -38,6 +38,11 @@ export default [//评标
|
||||
path: '/EvaRoom/Evaluation/projectManager/ReviewResults/Manager',
|
||||
component: './Evaluation/projectManager/ReviewResults/Manager',
|
||||
},
|
||||
//评审结果-线下评审-项目经理
|
||||
{
|
||||
path: '/EvaRoom/Evaluation/projectManager/ReviewResults/ManagerEntry',
|
||||
component: './Evaluation/projectManager/ReviewResults/ManagerEntry',
|
||||
},
|
||||
//评审结果-组长
|
||||
{
|
||||
path: '/EvaRoom/Evaluation/expert/ReviewResults/GroupLeader',
|
||||
|
@ -39,7 +39,7 @@ export default
|
||||
//评委会设置 资审发售 项目经理
|
||||
{
|
||||
path: '/ProjectLayout/ZYuShen/Tender/ProjectManager/JudgingPanel',
|
||||
component: './Tender/ProjectManager/JudgingPanel/List'
|
||||
component: './Tender/ProjectManager/JudgingPanel/List/preIndex'
|
||||
},
|
||||
//澄清 资审发售 项目经理
|
||||
{
|
||||
|
BIN
src/assets/signPen/signPen.png
Normal file
BIN
src/assets/signPen/signPen.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 18 KiB |
31
src/assets/styles.module.less
Normal file
31
src/assets/styles.module.less
Normal file
@ -0,0 +1,31 @@
|
||||
/**
|
||||
* 手写签名用
|
||||
*/
|
||||
.container {
|
||||
top: 10%;
|
||||
left: 10%;
|
||||
width: 100%;
|
||||
height: 50vh;
|
||||
}
|
||||
|
||||
.sigContainer {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin: 0 auto;
|
||||
background-color: #fff;
|
||||
cursor: auto;
|
||||
}
|
||||
|
||||
.sigPointer {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin: 0 auto;
|
||||
background-color: #fff;
|
||||
cursor: url("./signPen/signPen.png"),Crosshair;
|
||||
}
|
||||
|
||||
.sigPad {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: #fff;
|
||||
}
|
@ -5,7 +5,7 @@ import styles from './index.less';
|
||||
import { connect } from "dva";
|
||||
import { routerRedux } from 'dva/router';
|
||||
import React, { useState, useEffect, useReducer } from 'react';
|
||||
import { getSessionUserData, getRoomId, getProMethod, getSessionRoleData, getIPassDecode, getDefId, getProId } from '@/utils/session';
|
||||
import { getSessionUserData, getRoomId, getRoomStatus, getProMethod, getSessionRoleData, getIPassDecode, getDefId, getProId, getOfflineStatusById } from '@/utils/session';
|
||||
import { getURLInformation } from '@/utils/CommonUtils';
|
||||
import { getLeader, isShowResult, isShowCount, getErrorStatus, getRiskStatus, isShowRiskModal, saveConfirm, isLeaderConfirm } from './service';
|
||||
import logo from '@/images/opening/logo.svg'
|
||||
@ -34,8 +34,13 @@ const BiddingRoom = (props) => {
|
||||
let data = getSessionUserData();
|
||||
//获取比选一阶段二次项目,自定义流程,当前供应商
|
||||
const isBxOneSecondCustom = sessionStorage.getItem("isBxOneSecondCustom");
|
||||
//评审方式:状态:0-默认,1-已确认配置分工及组长
|
||||
const roomJuryConfigStatus = sessionStorage.getItem("roomJuryConfigStatus");
|
||||
//评审方式:0-线上、1-线下
|
||||
const roomReviewMethod = sessionStorage.getItem("roomReviewMethod");
|
||||
//获取评审室id
|
||||
const roomId = getRoomId();
|
||||
const roomStatus = getRoomStatus();
|
||||
const [list, setList] = useState();
|
||||
//风险提示文字弹窗控制
|
||||
const [riskVisible, setRiskVisible] = useState(false);
|
||||
@ -96,6 +101,28 @@ const BiddingRoom = (props) => {
|
||||
path: "/EvaRoom/Evaluation/projectManager/ReviewResults/Manager",
|
||||
text: "评审结果"
|
||||
}]
|
||||
//项目经理角色
|
||||
let managerOffList = [
|
||||
{
|
||||
id: 1,
|
||||
path: "/EvaRoom",
|
||||
text: "基本信息"
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
path: "/EvaRoom/BiddingDocumentsDecrypt",
|
||||
text: `${responseType}文件查看`
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
path: "/EvaRoom/Evaluation/BidControl/BidControlManager",
|
||||
text: "风险点展示"
|
||||
},
|
||||
{
|
||||
id: 8,
|
||||
path: "/EvaRoom/Evaluation/projectManager/ReviewResults/ManagerEntry",
|
||||
text: "评审结果录入"
|
||||
}]
|
||||
let JuryList = [
|
||||
{
|
||||
id: 1,
|
||||
@ -179,13 +206,25 @@ const BiddingRoom = (props) => {
|
||||
|
||||
//评审结果页签点击事件
|
||||
const onclick = async (path, id) => {
|
||||
await getOfflineStatusById(roomId)
|
||||
if ((role == 'ebtp-agency-project-manager' || role == 'ebtp-purchase') && id == 8) { //代理&采购经理进入评审结果
|
||||
const success = await isClickResult();
|
||||
if (success) {
|
||||
history.push({ pathname: path });
|
||||
setSelectedPath(path);
|
||||
if (roomReviewMethod == 0){
|
||||
const success = await isClickResult();
|
||||
if (success) {
|
||||
history.push({ pathname: path });
|
||||
setSelectedPath(path);
|
||||
} else {
|
||||
message.info("未到评审结果环节,无法进入评审结果")
|
||||
}
|
||||
} else {
|
||||
message.info("未到评审结果环节,无法进入评审结果")
|
||||
console.log("roomJuryConfigStatus", roomJuryConfigStatus)
|
||||
|
||||
if (roomJuryConfigStatus == 1) {
|
||||
history.push({ pathname: path });
|
||||
setSelectedPath(path);
|
||||
} else {
|
||||
message.info("未到评审结果环节,无法进入评审结果")
|
||||
}
|
||||
}
|
||||
} else if (role == 'ebtp-expert' && id == 8) {//专家进入评审结果
|
||||
const success = await isClickResult();
|
||||
@ -246,14 +285,14 @@ const BiddingRoom = (props) => {
|
||||
if (res?.data == "Review") {
|
||||
return "/EvaRoom/Evaluation/expert/ReviewResults/Jury"
|
||||
} else {
|
||||
const result = await isLeaderConfirm({ assessRoomId: roomId });//供应商股权关系-专家组长是否确认风险
|
||||
if (result?.success && result?.data) {
|
||||
//TODO zyx暂时不需要const result = await isLeaderConfirm({ assessRoomId: roomId });//供应商股权关系-专家组长是否确认风险
|
||||
//TODO zyx暂时不需要if (result?.success && result?.data) {
|
||||
return "/EvaRoom/Evaluation/expert/ReviewResults/GroupLeader"
|
||||
} else {
|
||||
setIsResult(true)
|
||||
setRiskVisible(true)
|
||||
return false;
|
||||
}
|
||||
//TODO zyx暂时不需要} else {
|
||||
//TODO zyx暂时不需要 setIsResult(true)
|
||||
//TODO zyx暂时不需要 setRiskVisible(true)
|
||||
//TODO zyx暂时不需要 return false;
|
||||
//TODO zyx暂时不需要}
|
||||
}
|
||||
} else {
|
||||
return false
|
||||
@ -347,7 +386,11 @@ const BiddingRoom = (props) => {
|
||||
}
|
||||
//代理&项目经理
|
||||
if (role == "ebtp-agency-project-manager" || role == "ebtp-purchase") {//代理和采购经理
|
||||
setList(managerList);
|
||||
if(true){
|
||||
setList(managerOffList);
|
||||
}else {
|
||||
setList(managerList);
|
||||
}
|
||||
} else if (role == "ebtp-expert") {//专家
|
||||
setList(JuryList)
|
||||
} else if (role == "ebtp-supplier") {//供应商
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { fetchManagerList,openBizassessroom,resetVerificationCode,fetchJuryList,fetchSupplierList
|
||||
import { fetchManagerList,openBizassessroom,openOffBizassessroom,resetVerificationCode,fetchJuryList,fetchSupplierList
|
||||
,fetchJuryMemInfo,updateJuryMemInfo,validateVerificationCode,fetchbidslist
|
||||
,fetchPreSupplierList,fetchPreList,fetchPreListt,bxmultifetchPreListt,pushRedirectRe,getCheckedByRoomId,checkOpenBidSupplier,zmmultiOpenBizassessroom } from '../services/bidev';
|
||||
import { message } from 'antd';
|
||||
@ -43,6 +43,23 @@ export default {
|
||||
}
|
||||
callback();
|
||||
},
|
||||
// 开启线下评审室
|
||||
*openOffBizassessroom({payload,callback}, { call, put }){
|
||||
const response =yield call(openOffBizassessroom,payload)
|
||||
if(response?.code==200){
|
||||
// 查询招标代理列表
|
||||
const params={
|
||||
pageNo:1,
|
||||
pageSize:10,
|
||||
reviewMethod:1,
|
||||
roomType: getURLInformation('roomType'),
|
||||
tpId:getProId()//项目id
|
||||
}
|
||||
yield put({ type: 'fetchManagerList', payload: {...params} });
|
||||
message.success("开启成功!")
|
||||
}
|
||||
callback();
|
||||
},
|
||||
// 开启评审室(多轮招募)
|
||||
*zmmultiOpenBizassessroom({payload,callback}, { call, put }){
|
||||
const response =yield call(zmmultiOpenBizassessroom,payload)
|
||||
|
@ -11,6 +11,8 @@ import { reviewReportExpertsConfirmed } from '../../Jury/service';
|
||||
import { getDicData, getProMethod, getRoomId } from '@/utils/session';
|
||||
import { btnAuthority } from '@/utils/authority';
|
||||
import WebOffice0609, { WebOfficeRefProps } from '@/pages/webOffice/weboffice0609';
|
||||
import styles from '@/assets/styles.module.less'
|
||||
import SignaturePad from 'react-signature-canvas'
|
||||
import SortEditableTable from './SortEditableTable';
|
||||
import ReviewReportUpload from '@/utils/ReviewReportUpload';
|
||||
import { ExclamationCircleOutlined } from '@ant-design/icons';
|
||||
@ -111,6 +113,10 @@ const GroupLeader: React.FC = () => {
|
||||
const [resultDisabledStatus, setResultDisabledStatus] = useState<boolean>(false);
|
||||
//报价类型 true-百分比类型(折扣率,优惠率)false-数值类型(总价,单价)
|
||||
const [quotationMethod, setQuotationMethod] = useState<boolean>(false);
|
||||
//评审报告确认无误弹出窗
|
||||
const [visibleConfirm, setVisibleConfirm] = useState<boolean>(false);
|
||||
//鼠标指针ref
|
||||
const pointRef = useRef<any>()
|
||||
//评价方法 eval_method_1 最低价法 eval_method_2 综合评估法
|
||||
const [evalMethodDict, setEvalMethodDict] = useState<string>('');
|
||||
//评审结果排序弹窗
|
||||
@ -1446,6 +1452,142 @@ const GroupLeader: React.FC = () => {
|
||||
setSpinning(false);
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 评审报告确认无误(签字面板)
|
||||
* zhoujianlong 2021.8.19
|
||||
* @returns
|
||||
*/
|
||||
const modalConfirm = () => {
|
||||
//保存loading
|
||||
const [loading, setLoading] = useState<boolean>(false);
|
||||
//关闭modal
|
||||
const onCancel = () => {
|
||||
init();
|
||||
setVisibleConfirm(false);
|
||||
}
|
||||
//canvas ref
|
||||
let sigPad: any = {}
|
||||
//手写签名存储
|
||||
const [saveTrimCanvas, setSaveTrimCanvas] = useState<string>('')
|
||||
const canvasBase64 = reviewReportData?.expertList?.[0]?.expertSign
|
||||
useEffect(() => {
|
||||
if(canvasBase64 != undefined){
|
||||
setSaveTrimCanvas(canvasBase64)
|
||||
}
|
||||
}, [canvasBase64])
|
||||
|
||||
/**
|
||||
* 保存或发送调用接口
|
||||
* @params expertSign 签名产生的base64值
|
||||
* status true-保存 false-发送
|
||||
*/
|
||||
const toSaveOrSend = (expertSign: string,status: boolean) => {
|
||||
let params = {
|
||||
expertOpinion: 1,
|
||||
reportId: reviewReportData.id,
|
||||
expertSign: expertSign
|
||||
};
|
||||
if(status){ //判断是保存还是发送
|
||||
params["status"] = 0
|
||||
}
|
||||
setLoading(true)
|
||||
reviewReportExpertsConfirmed(params).then(res => {
|
||||
if(res?.code == 200 && res?.success === true) {
|
||||
commonMessage(res);
|
||||
if(status) {} else {
|
||||
onCancel();
|
||||
}
|
||||
}
|
||||
}).finally(() => {
|
||||
setLoading(false)
|
||||
})
|
||||
}
|
||||
//提交 status true-保存 false-发送
|
||||
const submit = (status: boolean) => {
|
||||
let emptyStatus = sigPad.isEmpty();
|
||||
if(emptyStatus) {
|
||||
message.error("当前无签名内容,请先签名");
|
||||
return;
|
||||
}
|
||||
//得到画布
|
||||
let canvas = sigPad._canvas;
|
||||
if (canvas.getContext) {
|
||||
let ctx = canvas.getContext('2d');
|
||||
// 将canvas的透明背景设置成白色
|
||||
let imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
|
||||
for(var i = 0; i < imageData.data.length; i += 4) {
|
||||
// 当该像素是透明的,则设置成白色
|
||||
if(imageData.data[i + 3] == 0) {
|
||||
imageData.data[i] = 255;
|
||||
imageData.data[i + 1] = 255;
|
||||
imageData.data[i + 2] = 255;
|
||||
imageData.data[i + 3] = 255;
|
||||
}
|
||||
}
|
||||
ctx.putImageData(imageData, 0, 0);
|
||||
}
|
||||
let imgUrl = sigPad.toDataURL('image/png',1);
|
||||
setSaveTrimCanvas(imgUrl)
|
||||
toSaveOrSend(imgUrl,status)
|
||||
}
|
||||
//clear
|
||||
const clear = () => {
|
||||
sigPad.clear();
|
||||
}
|
||||
//SignaturePad ref
|
||||
const refRender = (ref: any) => {
|
||||
sigPad = ref //存储ref
|
||||
if(ref != null) {
|
||||
ref?.clear()
|
||||
ref?.fromDataURL(saveTrimCanvas)
|
||||
}
|
||||
}
|
||||
return (
|
||||
<>
|
||||
<Modal
|
||||
destroyOnClose
|
||||
visible={visibleConfirm}
|
||||
title="专家签字"
|
||||
onCancel={onCancel}
|
||||
maskClosable={false}
|
||||
centered
|
||||
width={'60%'}
|
||||
bodyStyle={{
|
||||
backgroundColor: '#f0f0f0',
|
||||
userSelect: 'none', //用来禁止选中,复制
|
||||
MozUserSelect: 'none',
|
||||
WebkitUserSelect: 'none',
|
||||
msUserSelect: 'none',
|
||||
}}
|
||||
footer={[
|
||||
<Button key="send" type="primary" loading={loading} onClick={() => submit(false)}>
|
||||
发送
|
||||
</Button>,
|
||||
<Button key="submit" type="primary" loading={loading} onClick={() => submit(true)}>
|
||||
保存
|
||||
</Button>,
|
||||
<Button key="clear" loading={loading} onClick={() => clear()}>
|
||||
清空
|
||||
</Button>,
|
||||
<Button key="back" onClick={onCancel}>
|
||||
取消
|
||||
</Button>,
|
||||
<span style={{color: '#b30000',lineHeight: '32px'}}>提示:按住鼠标左键进行签名</span>
|
||||
]}
|
||||
>
|
||||
<Spin spinning={loading} delay={300}>
|
||||
<div className={styles.container}>
|
||||
<div className={styles.sigContainer} ref={pointRef} onMouseDown={() => pointRef.current.className = styles.sigPointer} onMouseUp={() => pointRef.current.className = styles.sigContainer}>
|
||||
<SignaturePad canvasProps={{className: styles.sigPad}} maxWidth={3.5} minWidth={1}
|
||||
ref={refRender} penColor="#000"/>
|
||||
</div>
|
||||
</div>
|
||||
</Spin>
|
||||
</Modal>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* 评审报告存在问题
|
||||
@ -1529,7 +1671,7 @@ const GroupLeader: React.FC = () => {
|
||||
)
|
||||
}
|
||||
/**
|
||||
* 评审报告确认无误
|
||||
* 评审报告确认无误(无需手写签名)
|
||||
*/
|
||||
const beConfirmed = () => {
|
||||
setReviewReportLoading(true);
|
||||
@ -1544,6 +1686,14 @@ const GroupLeader: React.FC = () => {
|
||||
})
|
||||
}
|
||||
|
||||
//确认无误的手写签名判断方法
|
||||
const toReportConfirm = () => {
|
||||
if(String(reviewReportData?.signStatus) == '1') {//判断是否启用手写签名 1-是 0-否
|
||||
setVisibleConfirm(true);
|
||||
} else {
|
||||
beConfirmed();
|
||||
}
|
||||
}
|
||||
const saveTable = (data: any, config: any) => {
|
||||
let form = config?.form;
|
||||
form.validateFields().then((res: any) => {
|
||||
@ -1606,11 +1756,12 @@ const GroupLeader: React.FC = () => {
|
||||
value={supplierTableData}
|
||||
onChange={setSupplierTableData}
|
||||
scroll={{ x: 1300 }}
|
||||
onRow={record => {
|
||||
onRow={(record, index) => {
|
||||
return {
|
||||
// 鼠标移入行
|
||||
onMouseEnter: () => {
|
||||
setEditableRowKeys(resultDisabledStatus ? [] : [record.id])
|
||||
setEditableRowKeys((resultDisabledStatus || (assessId == "1558990153220034560" && index == 0)) ? [] : [record.id])
|
||||
},
|
||||
onMouseLeave: () => {
|
||||
setEditableRowKeys([]);
|
||||
@ -1633,12 +1784,12 @@ const GroupLeader: React.FC = () => {
|
||||
</Panel>
|
||||
{isNotEmpty(reviewReportData.id) && (
|
||||
<Panel header="评审报告确认" key="2">
|
||||
<Row justify="end">
|
||||
<Row justify="end" style={{marginTop: '-8px',marginBottom: '8px'}}>
|
||||
<Col>
|
||||
<Space>
|
||||
{reportFileList.length == 0 ? null : <Button key="upload" onClick={() => setReportUploadVisible(true)}>查看附件</Button>}
|
||||
<Button type="primary" hidden={btnAuthority(['ebtp-expert'])} disabled={!reviewReportStatus} loading={reviewReportLoading} onClick={beConfirmed}>确认无误</Button>
|
||||
<Button type="primary" hidden={btnAuthority(['ebtp-expert'])} disabled={!reviewReportStatus} onClick={() => setVisibleIssue(true)}>我有问题</Button>
|
||||
<Button type="primary" hidden={btnAuthority(['ebtp-expert'])} key="confirm" disabled={!reviewReportStatus} loading={reviewReportLoading} onClick={() => toReportConfirm()}>确认无误</Button>
|
||||
<Button type="primary" hidden={btnAuthority(['ebtp-expert'])} key="problem" disabled={!reviewReportStatus} onClick={() => setVisibleIssue(true)}>我有问题</Button>
|
||||
</Space>
|
||||
</Col>
|
||||
</Row>
|
||||
@ -1664,6 +1815,7 @@ const GroupLeader: React.FC = () => {
|
||||
)}
|
||||
</Collapse>
|
||||
{modelIssue()}
|
||||
{modalConfirm()}
|
||||
{sortTableVisible && <SortEditableTable
|
||||
modalVisible={sortTableVisible}
|
||||
onCancel={() => setSortTableVisible(false)}
|
||||
|
@ -10,6 +10,8 @@ import Weboffice from "@/pages/webOffice/weboffice";
|
||||
import { getDicData, getProMethod, getRoomId } from '@/utils/session';
|
||||
import { btnAuthority } from '@/utils/authority';
|
||||
import WebOffice0609, { WebOfficeRefProps } from '@/pages/webOffice/weboffice0609';
|
||||
import styles from '@/assets/styles.module.less'
|
||||
import SignaturePad from 'react-signature-canvas'
|
||||
import ReviewReportUpload from '@/utils/ReviewReportUpload';
|
||||
import { getFileListByBid } from '@/utils/DownloadUtils';
|
||||
import MACAddressPrompt from '@/pages/Evaluation/BidControl/BidControlManager/components/MACAddressPrompt';
|
||||
@ -53,6 +55,10 @@ const Jury: React.FC = () => {
|
||||
const [ptcpMode, setPtcpMode] = useState<string>();
|
||||
//报价类型 %-百分比类型(折扣率,优惠率)元-数值类型(总价,单价)
|
||||
const [quotationMethod, setQuotationMethod] = useState<string>('元');
|
||||
//评审报告确认无误弹出窗
|
||||
const [visibleConfirm, setVisibleConfirm] = useState<boolean>(false);
|
||||
//鼠标指针ref
|
||||
const pointRef = useRef<any>()
|
||||
//初始化显示字段
|
||||
const candidateType = bidMethodDict == 'procurement_mode_1' || bidMethodDict == 'procurement_mode_2' ? '中标' : '中选';//初始化中标中选字段
|
||||
//评审报告附件modal visible
|
||||
@ -663,6 +669,143 @@ const Jury: React.FC = () => {
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 评审报告确认无误(签字面板)
|
||||
* zhoujianlong 2021.8.19
|
||||
* @returns
|
||||
*/
|
||||
const modalConfirm = () => {
|
||||
//保存loading
|
||||
const [loading, setLoading] = useState<boolean>(false);
|
||||
//关闭modal
|
||||
const onCancel = () => {
|
||||
init();
|
||||
setVisibleConfirm(false);
|
||||
}
|
||||
//canvas ref
|
||||
let sigPad: any = {}
|
||||
//手写签名存储
|
||||
const [saveTrimCanvas, setSaveTrimCanvas] = useState<string>('')
|
||||
const canvasBase64 = reviewReportData?.expertList?.[0]?.expertSign
|
||||
useEffect(() => {
|
||||
if(canvasBase64 != undefined){
|
||||
setSaveTrimCanvas(canvasBase64)
|
||||
}
|
||||
}, [canvasBase64])
|
||||
|
||||
/**
|
||||
* 保存或发送调用接口
|
||||
* @params expertSign 签名产生的base64值
|
||||
* status true-保存 false-发送
|
||||
*/
|
||||
const toSaveOrSend = (expertSign: string,status: boolean) => {
|
||||
let params = {
|
||||
expertOpinion: 1,
|
||||
reportId: reviewReportData.id,
|
||||
expertSign: expertSign
|
||||
};
|
||||
if(status){ //判断是保存还是发送
|
||||
params["status"] = 0
|
||||
}
|
||||
setLoading(true)
|
||||
reviewReportExpertsConfirmed(params).then(res => {
|
||||
if(res?.code == 200 && res?.success === true) {
|
||||
commonMessage(res);
|
||||
if(status) {} else {
|
||||
onCancel();
|
||||
}
|
||||
}
|
||||
}).finally(() => {
|
||||
setLoading(false)
|
||||
})
|
||||
}
|
||||
//提交 status true-保存 false-发送
|
||||
const submit = (status: boolean) => {
|
||||
let emptyStatus = sigPad.isEmpty();
|
||||
if(emptyStatus) {
|
||||
message.error("当前无签名内容,请先签名");
|
||||
return;
|
||||
}
|
||||
//得到画布
|
||||
let canvas = sigPad._canvas;
|
||||
if (canvas.getContext) {
|
||||
let ctx = canvas.getContext('2d');
|
||||
// 将canvas的透明背景设置成白色
|
||||
let imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
|
||||
for(var i = 0; i < imageData.data.length; i += 4) {
|
||||
// 当该像素是透明的,则设置成白色
|
||||
if(imageData.data[i + 3] == 0) {
|
||||
imageData.data[i] = 255;
|
||||
imageData.data[i + 1] = 255;
|
||||
imageData.data[i + 2] = 255;
|
||||
imageData.data[i + 3] = 255;
|
||||
}
|
||||
}
|
||||
ctx.putImageData(imageData, 0, 0);
|
||||
}
|
||||
let imgUrl = sigPad.toDataURL('image/png',1);
|
||||
setSaveTrimCanvas(imgUrl)
|
||||
toSaveOrSend(imgUrl,status)
|
||||
}
|
||||
//clear
|
||||
const clear = () => {
|
||||
sigPad.clear();
|
||||
}
|
||||
//SignaturePad ref
|
||||
const refRender = (ref: any) => {
|
||||
sigPad = ref //存储ref
|
||||
if(ref != null) {
|
||||
ref?.clear()
|
||||
ref?.fromDataURL(saveTrimCanvas)
|
||||
}
|
||||
}
|
||||
return (
|
||||
<>
|
||||
<Modal
|
||||
destroyOnClose
|
||||
visible={visibleConfirm}
|
||||
title="专家签字"
|
||||
onCancel={onCancel}
|
||||
maskClosable={false}
|
||||
centered
|
||||
width={'60%'}
|
||||
bodyStyle={{
|
||||
backgroundColor: '#f0f0f0',
|
||||
userSelect: 'none', //用来禁止选中,复制
|
||||
MozUserSelect: 'none',
|
||||
WebkitUserSelect: 'none',
|
||||
msUserSelect: 'none',
|
||||
}}
|
||||
footer={[
|
||||
<Button key="send" type="primary" loading={loading} onClick={() => submit(false)}>
|
||||
发送
|
||||
</Button>,
|
||||
<Button key="submit" type="primary" loading={loading} onClick={() => submit(true)}>
|
||||
保存
|
||||
</Button>,
|
||||
<Button key="clear" loading={loading} onClick={() => clear()}>
|
||||
清空
|
||||
</Button>,
|
||||
<Button key="back" onClick={onCancel}>
|
||||
取消
|
||||
</Button>,
|
||||
<span style={{color: '#b30000',lineHeight: '32px'}}>提示:按住鼠标左键进行签名</span>
|
||||
]}
|
||||
>
|
||||
<Spin spinning={loading} delay={300}>
|
||||
<div className={styles.container}>
|
||||
<div className={styles.sigContainer} ref={pointRef} onMouseDown={() => pointRef.current.className = styles.sigPointer} onMouseUp={() => pointRef.current.className = styles.sigContainer}>
|
||||
<SignaturePad canvasProps={{className: styles.sigPad}} maxWidth={3.5} minWidth={1}
|
||||
ref={refRender} penColor="#000"/>
|
||||
</div>
|
||||
</div>
|
||||
</Spin>
|
||||
</Modal>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* 评审报告 我有问题
|
||||
*/
|
||||
@ -783,7 +926,7 @@ const Jury: React.FC = () => {
|
||||
)
|
||||
}
|
||||
/**
|
||||
* 确认无误
|
||||
* 确认无误(无需手写签名)
|
||||
*/
|
||||
const submitReviewReport = () => {
|
||||
setReviewReportLoading(true);
|
||||
@ -797,6 +940,15 @@ const Jury: React.FC = () => {
|
||||
init();
|
||||
})
|
||||
}
|
||||
//确认无误的手写签名判断方法
|
||||
const toReportConfirm = () => {
|
||||
console.log(String(reviewReportData?.signStatus))
|
||||
if(String(reviewReportData?.signStatus) == '1') {//判断是否启用手写签名 1-是 0-否
|
||||
setVisibleConfirm(true);
|
||||
} else {
|
||||
submitReviewReport();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 获取表头
|
||||
*/
|
||||
@ -844,12 +996,14 @@ const Jury: React.FC = () => {
|
||||
{
|
||||
(isNotEmpty(reviewReportData) && isNotEmpty(reviewReportData.id)) && (
|
||||
<Panel header="评审报告确认" key="2">
|
||||
<Row justify="end">
|
||||
<Row justify="end" style={{marginTop: '-8px',marginBottom: '8px'}}>
|
||||
<Col>
|
||||
<Space>
|
||||
{reportFileList.length == 0 ? null : <Button key="upload" onClick={() => setReportUploadVisible(true)}>查看附件</Button>}
|
||||
<Button type="primary" hidden={btnAuthority(["ebtp-expert"])} disabled={!reviewReportStatus} loading={reviewReportLoading} onClick={() => submitReviewReport()}>确认无误</Button>
|
||||
<Button type="primary" hidden={btnAuthority(["ebtp-expert"])} disabled={!reviewReportStatus} onClick={() => setVisibleProblem(true)}>我有问题</Button>
|
||||
{/* <Button type="primary" hidden={btnAuthority(["ebtp-expert"])} disabled={!reviewReportStatus} loading={reviewReportLoading} onClick={() => submitReviewReport()}>确认无误</Button>
|
||||
<Button type="primary" hidden={btnAuthority(["ebtp-expert"])} disabled={!reviewReportStatus} onClick={() => setVisibleProblem(true)}>我有问题</Button> */}
|
||||
<Button type="primary" hidden={btnAuthority(["ebtp-expert"])} key="confirm" disabled={!reviewReportStatus} loading={reviewReportLoading} onClick={() => toReportConfirm()}>确认无误</Button>
|
||||
<Button type="primary" hidden={btnAuthority(["ebtp-expert"])} key="problem" disabled={!reviewReportStatus} onClick={() => setVisibleProblem(true)}>我有问题</Button>
|
||||
</Space>
|
||||
</Col>
|
||||
</Row>
|
||||
@ -876,6 +1030,7 @@ const Jury: React.FC = () => {
|
||||
</Collapse>
|
||||
{modelIssue()}
|
||||
{modelProblem()}
|
||||
{modalConfirm()}
|
||||
{reportUploadVisible && <ReviewReportUpload
|
||||
modalVisible={reportUploadVisible}
|
||||
onCancel={() => setReportUploadVisible(false)}
|
||||
|
@ -0,0 +1,13 @@
|
||||
import React from 'react';
|
||||
import Manager from './components/Manager';
|
||||
/**
|
||||
* 项目经理
|
||||
*/
|
||||
const Index: React.FC = () => {
|
||||
return (
|
||||
<>
|
||||
<Manager />
|
||||
</>
|
||||
);
|
||||
}
|
||||
export default Index;
|
@ -51,3 +51,10 @@ export function finishFlow(id: any) {
|
||||
export function getAssessRoomStatus(id: any) {
|
||||
return request('/api/biz-service-ebtp-process/v1/bizassessroom/info/' + id);
|
||||
}
|
||||
/**
|
||||
* 生成签名报告
|
||||
* @param id
|
||||
*/
|
||||
export function saveSignPdfReport(id: any) {
|
||||
return request('/api/biz-service-ebtp-evaluation/v1/review/report/signpdf/' + id);
|
||||
}
|
||||
|
1730
src/pages/Tender/ProjectManager/JudgingPanel/List/preIndex.tsx
Normal file
1730
src/pages/Tender/ProjectManager/JudgingPanel/List/preIndex.tsx
Normal file
File diff suppressed because it is too large
Load Diff
@ -10,6 +10,11 @@ export async function openBizassessroom(params) {
|
||||
return request(`/api/biz-service-ebtp-process/v1/bizassessroom/openRoom/${params.id}`,
|
||||
{ method: 'POST' });
|
||||
}
|
||||
// 开启评审
|
||||
export async function openOffBizassessroom(params) {
|
||||
return request(`/api/biz-service-ebtp-process/v1/bizassessroom/openOffRoom/${params.id}`,
|
||||
{ method: 'POST' });
|
||||
}
|
||||
// 开启评审多轮招募
|
||||
export async function zmmultiOpenBizassessroom(params) {
|
||||
return request(`/api/biz-service-ebtp-process/v1/assessroom/zmmulti/openRoom/${params.id}`,
|
||||
|
Reference in New Issue
Block a user