3.10 工程代码同步master
This commit is contained in:
237
src/pages/Bid/ReviewConfig/Config/components/commonFunc.ts
Normal file
237
src/pages/Bid/ReviewConfig/Config/components/commonFunc.ts
Normal file
@ -0,0 +1,237 @@
|
||||
import { message } from "antd";
|
||||
import { getSessionProjectData } from '@/utils/session';
|
||||
//获取url参数
|
||||
export function getQueryString(name: any) {
|
||||
let reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)", "i");
|
||||
let r = window.location.search.substr(1).match(reg);
|
||||
return r !== null ? unescape(r[2]) : null;
|
||||
}
|
||||
//判断undefined ''
|
||||
export const checkUnEmp = (val: any) => {
|
||||
if (val != undefined && val != "") {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
};
|
||||
|
||||
//计算一个table的最高分
|
||||
export const subCountScore = (subData: any) => {
|
||||
return subData?.detailList?.reduce((preValue: any, item: any) => { return preValue + parseFloat(item.highScore) }, 0)
|
||||
}
|
||||
|
||||
//单选取最大
|
||||
export function chooseOne(data: any) {
|
||||
let max = 0;
|
||||
if (data != undefined && data.length > 0) {
|
||||
data.map((item: any) => {
|
||||
parseFloat(item.standardDetailScore) > max ? max = parseFloat(item.standardDetailScore) : null;
|
||||
})
|
||||
}
|
||||
return max;
|
||||
}
|
||||
//多选加和
|
||||
export function chooseMany(data: any) {
|
||||
let max = 0;
|
||||
if (data != undefined && data.length > 0) {
|
||||
max = data.reduce((preVal: any, item: any) => {
|
||||
if (item.standardDetailScore != '') {
|
||||
return preVal + parseFloat(item.standardDetailScore)
|
||||
} else {
|
||||
return preVal
|
||||
}
|
||||
}, 0)
|
||||
}
|
||||
return max;
|
||||
}
|
||||
//修改最大值
|
||||
export function changeHighScore(method: any, list: any) {
|
||||
if (method == 0) {
|
||||
return chooseOne(list)
|
||||
}
|
||||
if (method == 1) {
|
||||
return chooseMany(list)
|
||||
}
|
||||
if (method == 2) {
|
||||
return 0
|
||||
}
|
||||
return 0
|
||||
}
|
||||
//大于0反true
|
||||
export function lessThan0(val: any) {
|
||||
if (val != "--" && val != "++" && !(parseInt(val) < 0)) { return true } else { return false }
|
||||
}
|
||||
|
||||
//校验空数据-详审
|
||||
export function checkEmpty(data: any, type: any, name: any) {//校验类别里的空数据
|
||||
let pass = true;
|
||||
let reg = /(^-?(?:\d+|\d{1,3}(?:,\d{3})+)(?:\.\d{1,2})?$)/;
|
||||
if (data != undefined && data.length > 0) {
|
||||
let index = 1;
|
||||
for (const item of data) {
|
||||
if (item.scoreItem === '') {//评分项
|
||||
message.error(`${type}-${name},第${index}行,评分项不能为空!`)
|
||||
return false;
|
||||
}
|
||||
if (item.rvwStandard === '') {//评分标准
|
||||
message.error(`${type}-${name},第${index}行,评分标准不能为空!`)
|
||||
return false;
|
||||
}
|
||||
if (item.scoreMethod == 0 || item.scoreMethod == 1) {// 单选、多选的 详细评分标准
|
||||
if (item.standardList) {
|
||||
for (const item2 of item.standardList) {
|
||||
if (!reg.test(item2.standardDetailScore) || item2.standardName == '') {
|
||||
message.error(`${type}-${name},第${index}行,详细评分标准有未填项!`)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
message.error(`${type}-${name},第${index}行,详细评分标准有未填项!`)
|
||||
return false;
|
||||
}
|
||||
} else if (item.scoreMethod == 2) {// 人工录入的 最低分
|
||||
if (item.lowScore === '') {// || !lessThan0(item.lowScore)
|
||||
message.error(`${type}-${name},第${index}行,最低分不能为空!`)
|
||||
return false;
|
||||
}
|
||||
if (parseFloat(item.highScore) < parseFloat(item.lowScore)) {//最高分不小于最低分
|
||||
message.error(`${type}-${name},第${index}行,最高分不能小于最低分!`)
|
||||
return false;
|
||||
}
|
||||
} else if (item.scoreMethod == 4) {// 步长法的 每步分值
|
||||
if (item.stepScore == '') {
|
||||
message.error(`${type}-${name},第${index}行,每步分值不能为空!`)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (item.highScore === '') {//最高分 || !lessThan0(item.highScore)
|
||||
message.error(`${type}-${name},第${index}行,最高分不能为空!`)
|
||||
return false;
|
||||
}
|
||||
|
||||
index++;
|
||||
}
|
||||
} else {
|
||||
const method = getSessionProjectData().bidMethodDict;
|
||||
if (method === '5' || method === '6') {
|
||||
pass = true;
|
||||
} else {
|
||||
message.error(`${type}类不能为空!`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return pass;
|
||||
}
|
||||
//校验空数据-初审
|
||||
export function checkEmptyFirst(data: any, type: any, name: any) {//校验类别里的空数据
|
||||
let pass = true;
|
||||
if (data != undefined && data.length > 0) {
|
||||
let index = 1;
|
||||
for (const item of data) {
|
||||
if (item.scoreItem == '') {
|
||||
message.error(`${type}-${name},第${index}行,审查因素不能为空!`)
|
||||
return false;
|
||||
}
|
||||
if (item.rvwStandard == '') {
|
||||
message.error(`${type}-${name},第${index}行,审查标准不能为空!`)
|
||||
return false;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
} else {
|
||||
message.error(`${type}不能为空!`)
|
||||
return false;
|
||||
}
|
||||
return pass;
|
||||
}
|
||||
//校验报价
|
||||
export function checkBj(dataT: any, tanpan?: boolean) {//tanpan 是否评审流程里的报价节点
|
||||
let pass = true;
|
||||
let data;
|
||||
if (dataT[0] == undefined) {
|
||||
pass = false;
|
||||
message.error(`报价类不能为空!`)
|
||||
}
|
||||
if (tanpan && pass) {
|
||||
data = dataT[0]
|
||||
} else {
|
||||
data = dataT[0]?.detailList[0];
|
||||
}
|
||||
if (data != undefined && pass) {
|
||||
if (data.scoreMethod == 3) {//自动计算
|
||||
if (data.highScore === '') {//最高分 || !lessThan0(data.highScore)
|
||||
pass = false;
|
||||
message.error(`报价类,最高分不能为空!`)
|
||||
}
|
||||
if (data.effectiveType == 6) {//有效报价
|
||||
if (data.includeHighPrice === '' || data.includeHighPrice === undefined) {//|| !lessThan0(data.includeHighPrice)
|
||||
pass = false;
|
||||
message.error(`报价类,有效报价最高价不能为空,不能小于0!`)
|
||||
}
|
||||
if (data.includeLowPrice === '' || data.includeLowPrice === undefined) {//|| !lessThan0(data.includeLowPrice)
|
||||
pass = false;
|
||||
message.error(`报价类,有效报价最低价不能为空,不能小于0!`)
|
||||
}
|
||||
}
|
||||
if (data.baseType == 3) {//评标基准价 平均报价系数
|
||||
if (data.avgPriceMultiplier === '') {//|| !lessThan0(data.avgPriceMultiplier)
|
||||
pass = false;
|
||||
message.error(`报价类,平均报价系数不能为空,不能小于0!`)
|
||||
}
|
||||
}
|
||||
if (data.priceType == 1) {//报价分
|
||||
if (data.priceMultiplier === '' || data.priceMultiplierSecond === '') {//|| !lessThan0(data.priceMultiplier) || !lessThan0(data.priceMultiplierSecond)
|
||||
pass = false;
|
||||
message.error(`报价类,报价分,评标基准价系数不能为空,不能小于0!`)
|
||||
}
|
||||
if (
|
||||
data.lowScore === '' ||
|
||||
// !lessThan0(data.lowScore) ||
|
||||
data.lowScoreSecond === '' ||
|
||||
// !lessThan0(data.lowScoreSecond) ||
|
||||
parseFloat(data.lowScore) > parseFloat(data.highScore) ||
|
||||
parseFloat(data.lowScoreSecond) > parseFloat(data.highScore)
|
||||
) {
|
||||
pass = false;
|
||||
message.error(`报价类,报价分,最低分不能为空,不能小于0,不能大于最高分!`)
|
||||
}
|
||||
}
|
||||
if (data.priceType == 2) {//报价分
|
||||
if (
|
||||
data.lowScore === '' ||
|
||||
// !lessThan0(data.lowScore) ||
|
||||
data.lowScoreSecond === '' ||
|
||||
// !lessThan0(data.lowScoreSecond) ||
|
||||
parseFloat(data.lowScore) > parseFloat(data.highScore) ||
|
||||
parseFloat(data.lowScoreSecond) > parseFloat(data.highScore)
|
||||
) {
|
||||
pass = false;
|
||||
message.error(`报价类,报价分,最低分不能为空,不能小于0,不能大于最高分!`)
|
||||
}
|
||||
}
|
||||
if (data.priceType == 3 || data.priceType == 4 || data.priceType == 5) {//报价分
|
||||
if (data.priceMultiplier === '') {//|| !lessThan0(data.priceMultiplier)
|
||||
pass = false;
|
||||
message.error(`报价类,报价分,评标基准价系数不能为空,不能小于0!`)
|
||||
}
|
||||
}
|
||||
} else if (data.scoreMethod == 2) {//手动计算
|
||||
pass = true;
|
||||
} else {
|
||||
pass = false;
|
||||
message.error(`请选择计算方式!`)
|
||||
}
|
||||
}
|
||||
return pass;
|
||||
}
|
||||
|
||||
//去重
|
||||
export function unique1(arr: any) {
|
||||
var hash = [];
|
||||
for (var i = 0; i < arr.length; i++) {
|
||||
if (hash.indexOf(arr[i]) == -1) {
|
||||
hash.push(arr[i]);
|
||||
}
|
||||
}
|
||||
return hash;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
1356
src/pages/Bid/ReviewConfig/Config/components/detailedMain.tsx
Normal file
1356
src/pages/Bid/ReviewConfig/Config/components/detailedMain.tsx
Normal file
File diff suppressed because it is too large
Load Diff
@ -33,13 +33,7 @@
|
||||
.blue{
|
||||
color: rgb(0, 64, 201);
|
||||
}
|
||||
:global {
|
||||
.ant-radio{
|
||||
vertical-align: top !important;
|
||||
margin-top: 4px !important;
|
||||
}
|
||||
.ant-checkbox{
|
||||
vertical-align: top !important;
|
||||
margin-top: 4px !important;
|
||||
}
|
||||
}
|
||||
// .ant-btn-dashed{
|
||||
// margin:0 !important;
|
||||
// }
|
||||
|
||||
|
277
src/pages/Bid/ReviewConfig/Config/components/fileTree.tsx
Normal file
277
src/pages/Bid/ReviewConfig/Config/components/fileTree.tsx
Normal file
@ -0,0 +1,277 @@
|
||||
import { getProMethod } from "@/utils/session";
|
||||
import ProTable, { ActionType, ProColumns } from "@ant-design/pro-table";
|
||||
import { Button, Modal, Spin, Tree } from "antd";
|
||||
import React, { useEffect, useRef, useState } from "react";
|
||||
import { unique1 } from "./commonFunc";
|
||||
import { getAllFile, getGlfile, getTree, saveF } from "./service";
|
||||
type FileTreeType = {
|
||||
record?: any,//关联文件当前行数据\
|
||||
childs: any,
|
||||
roots: any,
|
||||
treeData: any,
|
||||
type: string,//check 查看关联应答文件; option--关联文件
|
||||
id?: string,//detId 详审id firstId 初审id
|
||||
rePage: () => {},//执行父组件刷新页面的方法
|
||||
parentSpin: (value: any) => {},//控制父组件 spin
|
||||
}
|
||||
const FileTree: React.FC<FileTreeType> = (props) => {
|
||||
//==============================================================state
|
||||
const {
|
||||
record,
|
||||
type,
|
||||
id,
|
||||
childs,
|
||||
roots,
|
||||
treeData,
|
||||
rePage,
|
||||
parentSpin
|
||||
} = props;
|
||||
const checkRelationRef = useRef<ActionType>();
|
||||
//根据评审室id和轮次数查应答文件格式
|
||||
const [spin, setSpin] = useState<boolean>(false);//蒙层
|
||||
const [glfile, setGlfile] = useState<boolean>(false);//关联应答文件
|
||||
const [checkRelation, setCheckRelation] = useState<boolean>(false); //查看关联应答文件
|
||||
// const [childs, childsSet] = useState<any>([]);//子节点
|
||||
// const [roots, rootsSet] = useState<any>([]);//根节点
|
||||
const [pIds, pIdsSet] = useState<any>([]);//根节点(保存时用)
|
||||
const [checkedKeys, setCheckedKeys] = useState<any>([]);//树被选中节点
|
||||
// const [treeData, setTreeData] = useState<any>([]);//应答文件树
|
||||
const [choosedId, setChoosedId] = useState<any>();//关联应答文件的对应的一条数据的id
|
||||
const [hide, hideSet] = useState(false);
|
||||
|
||||
const treeOneClass = {};// 子节点id:父节点id
|
||||
treeData?.map((item: any) => {
|
||||
item?.children?.map((item2: any) => {
|
||||
treeOneClass[item2.key] = item2.pId
|
||||
})
|
||||
})
|
||||
|
||||
//页面文字显示
|
||||
const method = getProMethod();
|
||||
let showNameT: any = { tb: '应答' }//应答
|
||||
if (method === 'procurement_mode_1' || method === 'procurement_mode_2') {//招标
|
||||
showNameT = { tb: '投标' }
|
||||
}
|
||||
|
||||
//查看关联应答文件表格
|
||||
const columnsCheckRelation: ProColumns<any>[] = [
|
||||
{ title: '序号', valueType: 'index', width: 50 },
|
||||
{ title: '类别名称', dataIndex: 'name', width: 150, },
|
||||
{ title: '评分项', dataIndex: 'scoreItem', width: 300, },
|
||||
{ title: '关联资料', dataIndex: 'documentNames', },
|
||||
];
|
||||
//==============================================================func
|
||||
//获取关联的文件用来选中
|
||||
const getGlFile = async (detailId: any) => {
|
||||
let data: any = [];
|
||||
let pIdsT: any = [];
|
||||
await getGlfile({ detailId: detailId }).then((res) => {
|
||||
if (res.data != undefined) {
|
||||
res.data.map((it: any) => {
|
||||
//如果是子节点的 追加
|
||||
let index = childs.findIndex((item: any) => item === it.documentId);
|
||||
index != -1 ? data.push(it.documentId) : null;
|
||||
if (index != -1) {
|
||||
data.push(it.documentId);
|
||||
pIdsT.push(treeOneClass[it.documentId]);
|
||||
}
|
||||
});
|
||||
}
|
||||
pIdsSet(pIdsT);
|
||||
setCheckedKeys(data);
|
||||
});
|
||||
setGlfile(true);
|
||||
setSpin(false);
|
||||
parentSpin(false);
|
||||
}
|
||||
//树
|
||||
const onCheck = (checkedKeys: any, e: any) => {
|
||||
let pIdsT = [...pIds];//根节点
|
||||
let index = pIdsT.findIndex(item => item === e.node.pId);
|
||||
if (e.checked) {//选中
|
||||
//pids加根节点 有就不加
|
||||
if (e.node.pId != null) {//!=null为子节点
|
||||
pIdsT.push(e.node.pId);
|
||||
} else {
|
||||
pIdsT.push(e.node.key);//添加根节点
|
||||
}
|
||||
} else {//取消选中
|
||||
//pids删根节点
|
||||
if (e.node.pId != null) {//!=null为子节点
|
||||
if (index != -1) {//-1 没有
|
||||
pIdsT.splice(index, 1);
|
||||
}
|
||||
} else {
|
||||
//清空暂存的 选中的根节点 数组
|
||||
pIdsT = pIdsT.filter(item => item != e.node.key)
|
||||
}
|
||||
}
|
||||
pIdsSet(pIdsT);
|
||||
setCheckedKeys(checkedKeys);
|
||||
};
|
||||
//关联文件 表格内操作
|
||||
function relevanceFile() {
|
||||
return (
|
||||
<>
|
||||
<Button type='text' hidden={hide} onClick={async () => {
|
||||
setSpin(true);
|
||||
parentSpin(true);
|
||||
// await getTreeData(assessRoomId, turnSort);
|
||||
await getGlFile(record.id);
|
||||
setChoosedId(record.id);
|
||||
}}>关联文件</Button>
|
||||
<Modal
|
||||
visible={glfile}
|
||||
title={`关联${showNameT.tb}文件`}
|
||||
width={"20%"}
|
||||
centered
|
||||
okButtonProps={{
|
||||
loading: spin
|
||||
}}
|
||||
onCancel={() => setGlfile(false)}
|
||||
onOk={async () => {
|
||||
setSpin(true);
|
||||
parentSpin(true);
|
||||
hideSet(true);
|
||||
if (treeData.length > 0) {
|
||||
let checkedKeysT = unique1([...checkedKeys, ...pIds]);
|
||||
const success = await saveF({ detailId: choosedId, documentIdList: checkedKeysT });
|
||||
if (success) {
|
||||
rePage();
|
||||
}
|
||||
}
|
||||
setSpin(false);
|
||||
parentSpin(false);
|
||||
setGlfile(false);
|
||||
setCheckedKeys([]);
|
||||
}}
|
||||
>
|
||||
<Spin spinning={spin}>
|
||||
{
|
||||
treeData.length != 0 ?
|
||||
<Tree
|
||||
checkable
|
||||
autoExpandParent={true}
|
||||
onCheck={onCheck}
|
||||
checkedKeys={checkedKeys}
|
||||
treeData={treeData}
|
||||
selectable={false}
|
||||
height={300}
|
||||
defaultExpandAll={true}
|
||||
/>
|
||||
: '没有应答格式'
|
||||
}
|
||||
</Spin>
|
||||
</Modal>
|
||||
</>
|
||||
)
|
||||
}
|
||||
//查看关联应答文件
|
||||
function checkRelevanceFile() {
|
||||
return (
|
||||
<>
|
||||
<Button style={{ marginRight: '10px' }} key="3" onClick={async () => {
|
||||
// await getTreeData(assessRoomId, turnSort);
|
||||
checkRelationRef.current?.reload();
|
||||
setCheckRelation(true);
|
||||
}}>查看关联{showNameT.tb}文件</Button>
|
||||
<Modal
|
||||
visible={checkRelation} width={'80%'} centered title={`查看关联${showNameT.tb}文件`} onCancel={() => setCheckRelation(false)}
|
||||
footer={renderFooter()}
|
||||
>
|
||||
<ProTable
|
||||
actionRef={checkRelationRef}
|
||||
columns={columnsCheckRelation}//表格
|
||||
options={false}
|
||||
search={false}
|
||||
tableAlertRender={false}
|
||||
request={(params) => getAllFile({ pageNo: params.current, pageSize: params.pageSize, configId: id }).then((res) => {
|
||||
let dataT: any = [...res.data.records];
|
||||
let documentIds: any = [];
|
||||
let documentNames: any = [];
|
||||
dataT.map((item: any) => {
|
||||
if (item.documentIds != null) {
|
||||
documentIds = [...item.documentIds.split(',')];
|
||||
documentNames = [...item.documentNames.split(',')];
|
||||
for (var i = 0; i < roots.length; i++) {
|
||||
for (var j = 0; j < documentIds.length; j++) {
|
||||
if (documentIds[j] == roots[i]) {
|
||||
documentIds.splice(j, 1);
|
||||
documentNames.splice(j, 1);
|
||||
j = j - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
item.documentIds = documentIds.join(',');
|
||||
item.documentNames = documentNames.join(',');
|
||||
}
|
||||
});
|
||||
const result = {
|
||||
data: dataT,
|
||||
total: res.data.total,
|
||||
success: res.success,
|
||||
pageSize: res.pageSize,
|
||||
current: res.current
|
||||
};
|
||||
return result;
|
||||
})}
|
||||
pagination={{ defaultPageSize: 10, showSizeChanger: false, }}//默认显示条数
|
||||
/>
|
||||
</Modal>
|
||||
</>
|
||||
)
|
||||
}
|
||||
//查看关联页脚
|
||||
function renderFooter() {
|
||||
return (
|
||||
<Button type='primary' onClick={() => setCheckRelation(false)}>关闭</Button>
|
||||
)
|
||||
}
|
||||
//==============================================================dom
|
||||
return (
|
||||
<>
|
||||
{type === 'option' && relevanceFile()}
|
||||
{type === 'check' && checkRelevanceFile()}
|
||||
</>
|
||||
)
|
||||
}
|
||||
//获取关联文件树
|
||||
export const getTreeDataOut = async (assessRoomId: any, turnSort: any) => {
|
||||
let data: any = [];
|
||||
let rootT: any = [];
|
||||
let childT: any = [];
|
||||
await getTree({ assessRoomId: assessRoomId, turnSort: turnSort }).then((res) => {
|
||||
if (res.data != undefined) {
|
||||
res.data.map((item: any, index: any) => {
|
||||
const title1 = item.name;
|
||||
const key1 = item.id;
|
||||
let children1: any = [];
|
||||
if (item.children != undefined) {
|
||||
const children = item.children.map((item: any, index: any) => {
|
||||
const title2 = item.name;
|
||||
const key2 = item.id;
|
||||
let children2: any = [];
|
||||
if (item.children != undefined) {
|
||||
const children = item.children.map((item: any, index: any) => {
|
||||
const title3 = item.name;
|
||||
const key3 = item.id;
|
||||
childT.push(key3)
|
||||
return { title: title3, key: key3, pId: key2 }
|
||||
});
|
||||
children2 = children;
|
||||
}
|
||||
childT.push(key2)
|
||||
return { title: title2, key: key2, children: children2, pId: key1 }
|
||||
});
|
||||
children1 = children;
|
||||
}
|
||||
const first = { title: title1, key: key1, children: children1, pId: null }
|
||||
rootT.push(key1)
|
||||
data.push(first);
|
||||
});
|
||||
}
|
||||
})
|
||||
return { roots: rootT, childs: childT, treeData: data }
|
||||
}
|
||||
export default FileTree;
|
||||
|
File diff suppressed because it is too large
Load Diff
810
src/pages/Bid/ReviewConfig/Config/components/firstMain.tsx
Normal file
810
src/pages/Bid/ReviewConfig/Config/components/firstMain.tsx
Normal file
@ -0,0 +1,810 @@
|
||||
import React, { useEffect, useMemo, useRef, useState, } from 'react';
|
||||
import { Button, Radio, Input, Modal, Form, Row, Col, Select, Collapse, message, Spin, Popconfirm } from 'antd';
|
||||
import ProTable, { ProColumns } from '@ant-design/pro-table';
|
||||
import { PlusOutlined, EditOutlined, DeleteOutlined, ExclamationCircleOutlined } from '@ant-design/icons';
|
||||
import { getPage, saveData, delDet, delCate, firstTem } from './service'
|
||||
import { getURLInformation } from '@/utils/CommonUtils'
|
||||
import '@/assets/xsy_style.less'
|
||||
import { btnAuthority } from '@/utils/authority';
|
||||
import { checkEmptyFirst, checkUnEmp } from './commonFunc';
|
||||
import FileTree, { getTreeDataOut } from './fileTree';
|
||||
import TempleteBtns from './templeteBtns';
|
||||
import Preview from './preview';
|
||||
import { getParentConfig } from '@/pages/ZBiXuan/EvaluationRoom/Config/FirstLimited/service';
|
||||
|
||||
type FirstType = {
|
||||
show: string,
|
||||
}
|
||||
const FirstMain: React.FC<FirstType> = (props) => {
|
||||
//===========================================================================================================state
|
||||
const formLayout = {
|
||||
labelCol: { span: 6 },
|
||||
wrapperCol: { span: 18 },
|
||||
};
|
||||
const { show } = props
|
||||
const FormItem = Form.Item;
|
||||
const [form] = Form.useForm();
|
||||
const [formModal] = Form.useForm();
|
||||
const { Option } = Select;
|
||||
const { Panel } = Collapse;
|
||||
const { TextArea } = Input;
|
||||
const { confirm } = Modal;
|
||||
const [assessRoomId, setAssessRoomId] = useState<any>();//,评标室id
|
||||
const [turnSort, setTurnSort] = useState<any>();//轮次号
|
||||
const [spin, setSpin] = useState<boolean>(true);//加载
|
||||
const [dis, setDis] = useState<boolean>(true);//是否可以更改
|
||||
//形式评审---包含商务子类
|
||||
const [data1, setData1] = useState<any>([]);
|
||||
//资格审查项
|
||||
const [data2, setData2] = useState<any>([]);
|
||||
//响应性评审
|
||||
const [data3, setData3] = useState<any>([]);
|
||||
//符合性审查
|
||||
const [data4, setData4] = useState<any>([]);
|
||||
const [category, setCategory] = useState<boolean>(false);//新增、修改类别窗口
|
||||
const [isUpdateCate, isUpdateCateSet] = useState<boolean>(false);//是否修改类别
|
||||
const [upData, updataSet] = useState<any>([]);//正在修改的数据
|
||||
const [principleStatus, setPrincipleStatus] = useState<number>();//评判原则
|
||||
const [deviatedStatus, setDeviatedStatus] = useState<any>();//偏离
|
||||
const [commonId, setCommonId] = useState<any>();//初审详审公共id
|
||||
const [firstId, setFirstId] = useState<any>();//初审整体data id
|
||||
const [nodeId, setNodeId] = useState<any>();//包id
|
||||
const [oid, oidSet] = useState<any>('')//下载excel oid
|
||||
const mainDiv = useRef<HTMLDivElement>(null);
|
||||
const [childs, childsSet] = useState<any>([]);//子节点
|
||||
const [roots, rootsSet] = useState<any>([]);//根节点
|
||||
const [treeData, setTreeData] = useState<any>([]);//应答文件树
|
||||
|
||||
//鼠标移入行大类别名称
|
||||
const [onRowCateName, onRowCateNameSet] = useState<any>('');
|
||||
//公共表格
|
||||
const commonColumns: ProColumns<any>[] = [
|
||||
{ title: '序号', valueType: 'index', width: 50 },
|
||||
{
|
||||
title: '审查因素', dataIndex: 'scoreItem', width: 300,
|
||||
render: (_, record) => {
|
||||
const idT = record.id != undefined ? record.id : record.tableId
|
||||
return (
|
||||
<Form form={form}>
|
||||
<FormItem style={{ margin: 0 }} name={`scoreItem${idT}${record.key}`} rules={[{ type: 'string', message: '请输入正确内容' }, { max: 255, message: '超过内容最大长度:255' }]}>
|
||||
<TextArea autoSize readOnly={dis} defaultValue={record.scoreItem}
|
||||
onBlur={(event) => {
|
||||
record.scoreItem = event.target.value;
|
||||
reTable()
|
||||
}} placeholder="请输入审查因素" />
|
||||
</FormItem>
|
||||
</Form>
|
||||
)
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '审查标准', dataIndex: 'rvwStandard',
|
||||
render: (_, record) => {
|
||||
const idT = record.id != undefined ? record.id : record.tableId
|
||||
return (
|
||||
<Form form={form}>
|
||||
<FormItem style={{ margin: 0 }} name={`rvwStandard${idT}${record.key}`} rules={[{ type: 'string', message: '请输入正确内容' }, { max: 2000, message: '超过内容最大长度:2000' }]}>
|
||||
<TextArea autoSize readOnly={dis} defaultValue={record.rvwStandard}
|
||||
onBlur={(event) => {
|
||||
record.rvwStandard = event.target.value;
|
||||
reTable();
|
||||
}} placeholder="请输入审查标准" />
|
||||
</FormItem>
|
||||
</Form>
|
||||
)
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '初审项性质', dataIndex: 'deviationStatus', width: 200,
|
||||
render: (_, record) => {
|
||||
return (
|
||||
<Radio.Group disabled={dis} onChange={(event) => {
|
||||
event.target.value === 1 && deviatedStatus === 0 && setDeviatedStatus(1)
|
||||
record.deviationStatus = event.target.value;
|
||||
reTable();
|
||||
}} value={deviatedStatus === 1 ? record.deviationStatus : 0}>
|
||||
<Radio value={1}>可偏离</Radio>
|
||||
<Radio value={0}>不可偏离</Radio>
|
||||
</Radio.Group>
|
||||
)
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '操作', dataIndex: 'option', width: 150,
|
||||
valueType: 'option',
|
||||
render: (_, record, index) => {
|
||||
if (!dis) {
|
||||
return ([
|
||||
<>
|
||||
{
|
||||
checkUnEmp(record.id) &&
|
||||
<>
|
||||
<FileTree
|
||||
record={record}
|
||||
type='option'
|
||||
roots={roots}
|
||||
childs={childs}
|
||||
treeData={treeData}
|
||||
rePage={() => queryFirstData()}
|
||||
parentSpin={async (value) => setSpin(value)}
|
||||
/>
|
||||
<br />
|
||||
</>
|
||||
}
|
||||
{index != 0 && conmmonDelConfirm(record)}
|
||||
</>
|
||||
]);
|
||||
} else {
|
||||
return <></>
|
||||
}
|
||||
}
|
||||
},
|
||||
];
|
||||
//公共子类表格-删除气泡提示框
|
||||
function conmmonDelConfirm(record: any) {
|
||||
let id = record.id;
|
||||
const idT = record.id != undefined ? record.id : record.tableId;
|
||||
const confirm = async () => {
|
||||
setSpin(true);
|
||||
let success = false;
|
||||
form.setFieldsValue({
|
||||
[`scoreItem${idT}${record.key}`]: '',
|
||||
[`rvwStandard${idT}${record.key}`]: '',
|
||||
});
|
||||
checkUnEmp(id) ? success = await delDet({ id }) : null;
|
||||
if (success) {
|
||||
queryFirstData();
|
||||
}
|
||||
if (!checkUnEmp(id)) {
|
||||
let dataT: any = []
|
||||
record.categoryName == '形式评审' && (dataT = [...data1])
|
||||
record.categoryName == '资格审查项' && (dataT = [...data2])
|
||||
record.categoryName == '响应性评审' && (dataT = [...data3])
|
||||
record.categoryName == '符合性审查' && (dataT = [...data4])
|
||||
dataT?.map((item: any, index: any) => {
|
||||
if (item.id == record.tableId || item.tableId == record.tableId) {
|
||||
dataT[index].detailList = item.detailList.filter((item2: any) => item2.key != record.key)
|
||||
}
|
||||
})
|
||||
record.categoryName == '形式评审' && setData1(dataT)
|
||||
record.categoryName == '资格审查项' && setData2(dataT)
|
||||
record.categoryName == '响应性评审' && setData3(dataT)
|
||||
record.categoryName == '符合性审查' && setData4(dataT)
|
||||
message.success('删除成功');
|
||||
}
|
||||
setSpin(false);
|
||||
}
|
||||
return (
|
||||
<Popconfirm
|
||||
title={checkUnEmp(id) ? '确认删除已保存数据么?' : '确认删除未保存数据么?'}
|
||||
onConfirm={confirm}
|
||||
okText="确认"
|
||||
cancelText="取消"
|
||||
>
|
||||
<Button type='text'>删除</Button>
|
||||
</Popconfirm>
|
||||
)
|
||||
}
|
||||
//============================================================================================================组件
|
||||
|
||||
const rePreview = useMemo(() => {//预览页面
|
||||
return <Preview data={{ data1, data2, data3, data4 }} rvwType={1} />
|
||||
}, [data1, data2, data3, data4])
|
||||
const btnAttr = {
|
||||
hidden: btnAuthority(['ebtp-agency-project-manager', 'ebtp-purchase']),
|
||||
style: { marginRight: '10px' },
|
||||
disabled: dis,
|
||||
}
|
||||
const returnTem = useMemo(() => {//模板
|
||||
let tem = null;
|
||||
if (nodeId && oid) {
|
||||
tem = <TempleteBtns
|
||||
rvwType={1}
|
||||
commonId={commonId}
|
||||
nodeId={nodeId}
|
||||
assessRoomId={assessRoomId}
|
||||
dis={dis}
|
||||
oid={oid}
|
||||
purchaseMethod={1}
|
||||
reviewId={firstId}
|
||||
rePage={() => queryFirstData()}
|
||||
parentSpin={async (value) => setSpin(value)}
|
||||
processData={(data) => processingData(data)}
|
||||
/>
|
||||
}
|
||||
return tem
|
||||
}, [assessRoomId, commonId, nodeId, firstId, dis, oid]);
|
||||
function detailButtons() {//业务按钮组
|
||||
return (
|
||||
<>
|
||||
<Button
|
||||
hidden={btnAuthority(['ebtp-agency-project-manager', 'ebtp-purchase'])}
|
||||
style={{ marginRight: '10px' }}
|
||||
disabled={dis}
|
||||
key="saveBtn"
|
||||
type="primary"
|
||||
onClick={() => saveFunc()}
|
||||
>保存</Button>
|
||||
<Button
|
||||
hidden={btnAuthority(['ebtp-agency-project-manager', 'ebtp-purchase'])}
|
||||
style={{ marginRight: '10px' }}
|
||||
disabled={dis}
|
||||
key="addCategoryBtn"
|
||||
type="primary"
|
||||
onClick={() => {
|
||||
setCategory(true);//控制新增类别窗口
|
||||
isUpdateCateSet(false);
|
||||
formModal.setFieldsValue({ name: '', type: '请选择', weights: '' });
|
||||
}}
|
||||
>新增类别</Button>
|
||||
{
|
||||
getURLInformation("readStatus") != null &&
|
||||
<Button
|
||||
{...btnAttr}
|
||||
type="primary"
|
||||
key="parent"
|
||||
onClick={showConfirm}
|
||||
>
|
||||
继承上轮
|
||||
</Button>
|
||||
|
||||
}
|
||||
<FileTree
|
||||
type='check'
|
||||
id={firstId}
|
||||
roots={roots}
|
||||
childs={childs}
|
||||
treeData={treeData}
|
||||
rePage={() => queryFirstData()}
|
||||
parentSpin={async (value) => setSpin(value)}
|
||||
/>
|
||||
{rePreview}
|
||||
{returnTem}
|
||||
{
|
||||
getURLInformation("readStatus") != null ?
|
||||
<Button style={{ marginLeft: '10px' }} onClick={() => { history.back() }}>返回</Button>
|
||||
: null
|
||||
}
|
||||
</>
|
||||
)
|
||||
}
|
||||
//新增类别Modal
|
||||
function addCategoryModal() {
|
||||
return (
|
||||
<Modal
|
||||
centered
|
||||
title={isUpdateCate ? '修改类别' : '新增类别'}
|
||||
visible={category}
|
||||
width={500}
|
||||
onCancel={() => { setCategory(false); formModal.resetFields() }}
|
||||
onOk={() => {
|
||||
formModal.validateFields().then(() => {
|
||||
if (formModal.getFieldsValue().type === '请选择') {
|
||||
message.error('请选择类别');
|
||||
} else {
|
||||
setCategory(false);
|
||||
setSpin(true);
|
||||
setTimeout(() => {
|
||||
typeControl(formModal.getFieldsValue());
|
||||
formModal.resetFields();
|
||||
//mainDiv.current.scrollTop = mainDiv.current.scrollHeight;
|
||||
}, 100);
|
||||
}
|
||||
})
|
||||
}}
|
||||
>
|
||||
<Form {...formLayout} form={formModal}>
|
||||
<Row>
|
||||
<Col span={24}><FormItem
|
||||
key="addName"
|
||||
name="name"
|
||||
label="类别名称"
|
||||
rules={[{ required: true, message: '请输入名称' }]}
|
||||
>
|
||||
<Input readOnly={dis} style={{ width: "80%" }} />
|
||||
</FormItem></Col>
|
||||
</Row>
|
||||
<Row>
|
||||
<Col span={24}><FormItem
|
||||
name="type"
|
||||
label="类型"
|
||||
initialValue="请选择"
|
||||
rules={[{ required: true, message: '请选择类别' }]}
|
||||
>
|
||||
<Select style={{ width: "80%" }}>
|
||||
<Option value="形式评审" key="addCateKey1">形式评审</Option>
|
||||
<Option value="资格审查项" key="addCateKey2">资格审查项</Option>
|
||||
<Option value="响应性评审" key="addCateKey3">响应性评审</Option>
|
||||
<Option value="符合性审查" key="addCateKey4">符合性审查</Option>
|
||||
</Select>
|
||||
</FormItem></Col>
|
||||
</Row>
|
||||
</Form>
|
||||
</Modal>
|
||||
)
|
||||
}
|
||||
//返回单选按钮组
|
||||
const returnRadios = () => {
|
||||
return (
|
||||
<Form style={{ marginLeft: '24px', }} form={form}>
|
||||
<Row>
|
||||
<Col span={8}>
|
||||
<FormItem label="初审项评判原则">
|
||||
<Radio.Group disabled={dis} name="radiogroup" onChange={(e) => setPrincipleStatus(e.target.value)} value={principleStatus}>
|
||||
<Radio value={1}>全数通过</Radio>
|
||||
<Radio value={0}>简单多数</Radio>
|
||||
</Radio.Group>
|
||||
</FormItem>
|
||||
</Col>
|
||||
<Col span={8}>
|
||||
<FormItem label="是否可偏离">
|
||||
<Radio.Group disabled={dis} onChange={(e) => {
|
||||
setDeviatedStatus(e.target.value);
|
||||
}} value={deviatedStatus}>
|
||||
<Radio value={1}>可偏离</Radio>
|
||||
<Radio value={0}>不可偏离</Radio>
|
||||
</Radio.Group>
|
||||
</FormItem>
|
||||
</Col>
|
||||
<Col span={8}>
|
||||
<FormItem
|
||||
hidden={deviatedStatus != 1}
|
||||
label="偏离数量"
|
||||
name='deviationNumber1'
|
||||
rules={[
|
||||
{ required: deviatedStatus == 1, message: '请填写偏离数量' },
|
||||
{ pattern: /^([1-9][0-9]{0,1}|100)$/, message: '请填写100以内正整数' },
|
||||
]}>
|
||||
<Input readOnly={dis} style={{ width: "30%", position: 'relative', }} />
|
||||
</FormItem>
|
||||
</Col>
|
||||
</Row>
|
||||
</Form>
|
||||
)
|
||||
};
|
||||
//返回折叠面板
|
||||
const returnPanel = () => {
|
||||
return (
|
||||
<Collapse defaultActiveKey={['Panel1', 'Panel2', 'Panel3', 'Panel4']}>
|
||||
{
|
||||
data1.length != 0 &&
|
||||
<Panel header='形式评审' key='Panel1'>
|
||||
{data1?.map((item: any, mapindex: any) => { return returnTable(item, mapindex) })}
|
||||
</Panel>
|
||||
}
|
||||
{
|
||||
data2.length != 0 &&
|
||||
<Panel header='资格审查项' key='Panel2'>
|
||||
{data2?.map((item: any, mapindex: any) => { return returnTable(item, mapindex) })}
|
||||
</Panel>
|
||||
}
|
||||
{
|
||||
data3.length != 0 &&
|
||||
<Panel header='响应性评审' key='Panel3'>
|
||||
{data3?.map((item: any, mapindex: any) => { return returnTable(item, mapindex) })}
|
||||
</Panel>
|
||||
}
|
||||
{
|
||||
data4.length != 0 &&
|
||||
<Panel header='符合性审查' key='Panel4'>
|
||||
{data4?.map((item: any, mapindex: any) => { return returnTable(item, mapindex, true) })}
|
||||
</Panel>
|
||||
}
|
||||
</Collapse>
|
||||
)
|
||||
};
|
||||
//返回子类表格
|
||||
function returnTable(subData: any, mapindex: number, isBaojia?: boolean) {
|
||||
//删除子表格
|
||||
const confirm = async () => {
|
||||
const categoryName = subData.categoryName;
|
||||
setSpin(true);
|
||||
if (subData.id != undefined) {
|
||||
//走接口删除
|
||||
let success = await delCate(subData.id);
|
||||
if (success) {
|
||||
await queryFirstData();
|
||||
}
|
||||
} else {
|
||||
categoryName == '形式评审' && setData1(data1.filter((item: any) => item.key != subData.key));
|
||||
categoryName == '资格审查项' && setData2(data2.filter((item: any) => item.key != subData.key));
|
||||
categoryName == '响应性评审' && setData3(data3.filter((item: any) => item.key != subData.key));
|
||||
categoryName == '符合性审查' && setData4(data4.filter((item: any) => item.key != subData.key));
|
||||
message.success('删除成功');
|
||||
}
|
||||
setSpin(false);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className='xsy-config-table' id={`${subData.name}${subData.key}`}>
|
||||
<div style={{ height: '42px', lineHeight: '42px' }}>
|
||||
<h3 className='scd-title' style={{ float: 'left' }}>{subData.name}</h3>
|
||||
{
|
||||
!dis &&
|
||||
<div style={{ float: 'right' }}>
|
||||
<Button
|
||||
hidden={btnAuthority(['ebtp-agency-project-manager', 'ebtp-purchase'])}
|
||||
type='dashed'
|
||||
style={{ marginRight: '10px' }}
|
||||
// className='xsyBtn'
|
||||
onClick={() => {
|
||||
setCategory(true);//控制新增、修改类别窗口
|
||||
isUpdateCateSet(true);
|
||||
updataSet(subData);
|
||||
onRowCateNameSet(subData.categoryName);
|
||||
formModal.setFieldsValue({ name: subData.name, type: subData.categoryName, weights: subData.weights });
|
||||
}}
|
||||
>
|
||||
<EditOutlined />{`修改`}
|
||||
</Button>
|
||||
<Popconfirm
|
||||
title="确认删除么?"
|
||||
onConfirm={confirm}
|
||||
okText="确认"
|
||||
cancelText="取消"
|
||||
>
|
||||
<Button
|
||||
hidden={btnAuthority(['ebtp-agency-project-manager', 'ebtp-purchase'])}
|
||||
type='dashed'
|
||||
>
|
||||
<DeleteOutlined />{`删除`}
|
||||
</Button>
|
||||
</Popconfirm>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<ProTable
|
||||
columns={commonColumns}
|
||||
size="small"
|
||||
dataSource={subData.detailList}
|
||||
options={false}
|
||||
search={false}
|
||||
tableAlertRender={false}
|
||||
pagination={false}//分页
|
||||
onRow={record => {
|
||||
return {
|
||||
onMouseEnter: event => { onRowCateNameSet(subData.categoryName) }, // 鼠标移入行
|
||||
};
|
||||
}}
|
||||
/>
|
||||
{
|
||||
!dis && subData.categoryName !== '报价' &&
|
||||
<Button
|
||||
hidden={btnAuthority(['ebtp-agency-project-manager', 'ebtp-purchase'])}
|
||||
type='dashed'
|
||||
// className='xsyBtn'
|
||||
style={{ width: '100%' }}
|
||||
key={subData.categoryName + mapindex + 'Btn1'}
|
||||
onClick={() => addOneRow(subData.categoryName, mapindex, subData.tableId, subData.id)}
|
||||
>
|
||||
<PlusOutlined />新增评分项
|
||||
</Button>
|
||||
}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
//继承上轮确认提示框
|
||||
function showConfirm() {
|
||||
confirm({
|
||||
title: '即将继承上一轮初审配置(如上一轮无数据,则无法继承),是否继承?',
|
||||
icon: <ExclamationCircleOutlined />,
|
||||
centered: true,
|
||||
okText: '继承',
|
||||
onOk() {
|
||||
setSpin(true);
|
||||
getParentConfig({ nodeId, rvwType: 1 }).then((res) => {
|
||||
res?.code == 200 ? queryFirstData() : setSpin(false);
|
||||
}).catch(() => setSpin(false))
|
||||
},
|
||||
});
|
||||
}
|
||||
//===========================================================================================================FUNC
|
||||
useEffect(() => {
|
||||
if (show !== '2') {
|
||||
queryFirstData();
|
||||
firstTem().then(res => {
|
||||
res?.code == 200 ? oidSet(res.data.documentCenterId) : null;
|
||||
});
|
||||
}
|
||||
}, [show]);
|
||||
//新增、修改类别
|
||||
const typeControl = async (values: any) => {
|
||||
const { name, type, weights } = values;
|
||||
let tableId = Date.now();
|
||||
let subCate = {
|
||||
categoryName: type,//大类别名称
|
||||
name: name,//字类名
|
||||
tableId: tableId,
|
||||
key: 0,
|
||||
detailList: [{//初始值---新增用
|
||||
key: 0,
|
||||
tableId: tableId,
|
||||
scoreItem: "",//评分项
|
||||
categoryName: type,//大类别名称
|
||||
rvwStandard: "",//评分标准
|
||||
deviationStatus: 0,//是否可偏离
|
||||
}]
|
||||
}
|
||||
let [data1T, data2T, data3T, data4T] = [[...data1], [...data2], [...data3], [...data4]];
|
||||
|
||||
const add = (type: any) => {
|
||||
//新增
|
||||
if (type == '形式评审') {
|
||||
subCate['key'] = data1.length;
|
||||
subCate['category'] = '0';
|
||||
setData1([...data1T, subCate])
|
||||
} else if (type == '资格审查项') {
|
||||
subCate['key'] = data2.length;
|
||||
subCate['category'] = '1';
|
||||
setData2([...data2T, subCate])
|
||||
} else if (type == '响应性评审') {
|
||||
subCate['key'] = data3.length;
|
||||
subCate['category'] = '2';
|
||||
setData3([...data3T, subCate])
|
||||
} else if (type == '符合性审查') {
|
||||
subCate['key'] = data4.length;
|
||||
subCate['category'] = '7';
|
||||
setData4([...data4T, subCate])
|
||||
}
|
||||
}
|
||||
if (isUpdateCate) {//修改
|
||||
const oldCategoryName = upData.categoryName;
|
||||
subCate = upData.key;
|
||||
upData.name = name;
|
||||
upData.categoryName = type;
|
||||
upData.weights = weights == undefined ? 100 : weights;
|
||||
//修改
|
||||
if (oldCategoryName == '形式评审') {
|
||||
if (oldCategoryName != type) {
|
||||
data1T = data1T.filter((item: any) => item.key != undefined ? item.key != upData.key : item.id != upData.id);
|
||||
} else {
|
||||
let index = data1T.findIndex((item: any) => item.key != undefined ? item.key == upData.key : item.id == upData.id)
|
||||
data1T[index] = upData;
|
||||
}
|
||||
setData1(data1T)
|
||||
}
|
||||
if (oldCategoryName == '资格审查项') {
|
||||
if (oldCategoryName != type) {
|
||||
data2T = data2T.filter((item: any) => item.key != undefined ? item.key != upData.key : item.id != upData.id);
|
||||
} else {
|
||||
let index = data2T.findIndex((item: any) => item.key != undefined ? item.key == upData.key : item.id == upData.id)
|
||||
data2T[index] = upData;
|
||||
}
|
||||
setData2(data2T)
|
||||
}
|
||||
if (oldCategoryName == '响应性评审') {
|
||||
if (oldCategoryName != type) {
|
||||
data3T = data3T.filter((item: any) => item.key != undefined ? item.key != upData.key : item.id != upData.id);
|
||||
} else {
|
||||
let index = data3T.findIndex((item: any) => item.key != undefined ? item.key == upData.key : item.id == upData.id)
|
||||
data3T[index] = upData;
|
||||
}
|
||||
setData3(data3T)
|
||||
}
|
||||
if (oldCategoryName == '符合性审查') {
|
||||
if (oldCategoryName != type) {
|
||||
data4T = data4T.filter((item: any) => item.key != undefined ? item.key != upData.key : item.id != upData.id);
|
||||
} else {
|
||||
let index = data4T.findIndex((item: any) => item.key != undefined ? item.key == upData.key : item.id == upData.id)
|
||||
data4T[index] = upData;
|
||||
}
|
||||
setData4(data4T)
|
||||
}
|
||||
subCate = upData;
|
||||
oldCategoryName != type && add(type);
|
||||
} else {
|
||||
add(type);
|
||||
}
|
||||
scrollToAnchor(subCate.name + subCate.key)
|
||||
setSpin(false);
|
||||
}
|
||||
//表格新增一行
|
||||
function addOneRow(categoryName: string, key: number, tableId: any, id: any) {
|
||||
const oneRow = {//初始值---新增用
|
||||
tableId: tableId ? tableId : id,
|
||||
scoreItem: "",//评分项
|
||||
rvwStandard: "",//评分标准
|
||||
categoryName: categoryName,
|
||||
deviationStatus: 0,//是否可偏离
|
||||
};
|
||||
|
||||
const setData = (data: any) => {
|
||||
let dataFirst: any[] = [];
|
||||
data.map((item: any, index: any) => {//大类 含子表格数据[]
|
||||
let dataSecond: any[] = [];
|
||||
item.detailList.map((item2: any) => {
|
||||
dataSecond.push(item2)
|
||||
})
|
||||
if (index == key) {
|
||||
oneRow['key'] = dataSecond[dataSecond.length - 1] ? dataSecond[dataSecond.length - 1].key + 1 : 0;
|
||||
dataSecond.push(oneRow)
|
||||
}
|
||||
item.detailList = dataSecond;
|
||||
dataFirst.push(item);
|
||||
})
|
||||
return dataFirst;
|
||||
}
|
||||
if (categoryName == '形式评审') {
|
||||
setData1(setData(data1))
|
||||
} else if (categoryName == '资格审查项') {
|
||||
setData2(setData(data2))
|
||||
} else if (categoryName == '响应性评审') {
|
||||
setData3(setData(data3))
|
||||
} else if (categoryName == '符合性审查') {
|
||||
setData4(setData(data4))
|
||||
}
|
||||
}
|
||||
//根据name subname 定位表格、数据并重新赋值
|
||||
function reTable() {
|
||||
if (onRowCateName === '形式评审') {
|
||||
setData1([...data1]);
|
||||
} else if (onRowCateName === '资格审查项') {
|
||||
setData2([...data2]);
|
||||
} else if (onRowCateName === '响应性评审') {
|
||||
setData3([...data3]);
|
||||
} else if (onRowCateName === '符合性审查') {
|
||||
setData4([...data4]);
|
||||
}
|
||||
}
|
||||
//保存页面
|
||||
async function saveFunc() {
|
||||
setSpin(true);
|
||||
const id = firstId;
|
||||
const rvwType = "1";
|
||||
let categoryList: any[] = [];
|
||||
let pass = true;
|
||||
let [data1t, data2t, data3t, data4t] = [[...data1], [...data2], [...data3], [...data4]]
|
||||
if (data1t.length == 0 && data2t.length == 0 && data3t.length == 0 && data4t.length == 0) {
|
||||
pass = false;
|
||||
message.error('请新增类别');
|
||||
}
|
||||
pass && await form.validateFields().catch((errorInfo) => {
|
||||
pass = false;
|
||||
message.error(errorInfo.errorFields[0].errors);
|
||||
})
|
||||
if (data1t.length > 0 && pass) {
|
||||
data1t.map((item: any) => {
|
||||
!checkEmptyFirst(item.detailList, '形式评审', item.name) && (pass = false);
|
||||
pass && deviatedStatus === 0 && (item.detailList.map((item2: any) => item2.deviationStatus = 0))
|
||||
})
|
||||
}
|
||||
if (data2t.length > 0 && pass) {
|
||||
data2t.map((item: any) => {
|
||||
!checkEmptyFirst(item.detailList, '资格审查项', item.name) && (pass = false);
|
||||
pass && deviatedStatus === 0 && (item.detailList.map((item2: any) => item2.deviationStatus = 0))
|
||||
})
|
||||
}
|
||||
if (data3t.length > 0 && pass) {
|
||||
data3t.map((item: any) => {
|
||||
!checkEmptyFirst(item.detailList, '响应性评审', item.name) && (pass = false);
|
||||
pass && deviatedStatus === 0 && (item.detailList.map((item2: any) => item2.deviationStatus = 0))
|
||||
})
|
||||
}
|
||||
if (data4t.length > 0 && pass) {
|
||||
data4t.map((item: any) => {
|
||||
!checkEmptyFirst(item.detailList, '符合性审查', item.name) && (pass = false);
|
||||
pass && deviatedStatus === 0 && (item.detailList.map((item2: any) => item2.deviationStatus = 0))
|
||||
})
|
||||
};
|
||||
if (pass) {//合数据
|
||||
categoryList = [...data1t, ...data2t, ...data3t, ...data4t,]
|
||||
let allData = {
|
||||
id,
|
||||
commonId,
|
||||
principleStatus,
|
||||
deviatedStatus,
|
||||
rvwType,
|
||||
categoryList,
|
||||
nodeId,
|
||||
deviationNumber: form.getFieldValue('deviationNumber1'),
|
||||
}
|
||||
const success = await saveData(allData);
|
||||
if (success) {
|
||||
message.success('保存成功');
|
||||
queryFirstData();
|
||||
}
|
||||
} else {
|
||||
setSpin(false);
|
||||
}
|
||||
}
|
||||
//获取初审数据
|
||||
const queryFirstData = async () => {
|
||||
let commonId: any = "";
|
||||
if (getURLInformation("id") != null) {
|
||||
commonId = getURLInformation("id")
|
||||
}
|
||||
let nodeId: any = '';
|
||||
if (getURLInformation("nodeId") != null) {
|
||||
nodeId = getURLInformation("nodeId")
|
||||
}
|
||||
setCommonId(commonId);
|
||||
setNodeId(nodeId);
|
||||
const rvwType = 1;
|
||||
setSpin(true);
|
||||
await getPage({ commonId, rvwType, nodeId }).then((res) => {
|
||||
if (res.code == 200) {
|
||||
processingData(res);
|
||||
}
|
||||
})
|
||||
}
|
||||
//处理数据
|
||||
async function processingData(res: any) {
|
||||
setData1([]);
|
||||
setData2([]);
|
||||
setData3([]);
|
||||
setData4([]);
|
||||
// let data1T: any = [];
|
||||
setSpin(true);
|
||||
let [data1T, data2T, data3T, data4T]: any = [[], [], [], []];
|
||||
let dis: any = true;
|
||||
let deviatedStatus: any, principleStatus: any, deviationNumber: any = "";
|
||||
let firstId = "";
|
||||
let assessRoomId: any, turnSort: any = 0;
|
||||
const data = res.data;
|
||||
deviatedStatus = data.deviatedStatus != null ? data.deviatedStatus : 0;
|
||||
principleStatus = data.principleStatus != null ? data.principleStatus : 0;
|
||||
deviationNumber = data.deviationNumber;
|
||||
assessRoomId = data.assessRoomId;
|
||||
turnSort = data.reviewTurnSort;
|
||||
data.categoryList.map((item: any) => {
|
||||
const cate = item.category
|
||||
cate === '0' && data1T.push(item);
|
||||
cate === '1' && data2T.push(item);
|
||||
cate === '2' && data3T.push(item);
|
||||
cate === '7' && data4T.push(item);
|
||||
});
|
||||
if (data.status == 0 || data.status == null) {
|
||||
dis = false;
|
||||
}
|
||||
if (data.id != null) {
|
||||
firstId = data.id;
|
||||
}
|
||||
let tree = await getTreeDataOut(assessRoomId, turnSort);
|
||||
rootsSet(tree.roots);
|
||||
childsSet(tree.childs);
|
||||
setTreeData(tree.treeData);
|
||||
|
||||
setFirstId(firstId);
|
||||
setAssessRoomId(assessRoomId);
|
||||
setTurnSort(turnSort);
|
||||
setData1(data1T); setData2(data2T); setData3(data3T); setData4(data4T);
|
||||
setDeviatedStatus(deviatedStatus);
|
||||
setPrincipleStatus(principleStatus);
|
||||
form.setFieldsValue({
|
||||
deviationNumber1: deviationNumber,
|
||||
})
|
||||
setDis(dis);
|
||||
setSpin(false);
|
||||
}
|
||||
//缓慢滚动
|
||||
const scrollToAnchor = (anchorName: any) => {
|
||||
if (anchorName) {
|
||||
let anchorElement = document.getElementById(anchorName);
|
||||
if (anchorElement) {
|
||||
anchorElement.scrollIntoView(
|
||||
{ behavior: 'smooth' }
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
return (
|
||||
<div className='bgCWhite'>
|
||||
<Spin spinning={spin}>
|
||||
<div style={{ marginTop: '16px', padding: '0px 24px', height: '32px', lineHeight: '32px' }}>
|
||||
<h3 className='first-title' style={{ float: 'left' }}>编辑初审细则</h3>
|
||||
<div style={{ float: 'right' }}>
|
||||
{detailButtons()}{/* 业务按钮组 */}
|
||||
</div>
|
||||
</div>
|
||||
<div style={{ clear: 'both' }} />
|
||||
{returnRadios()}{/* 单选按钮组 */}
|
||||
<div className='xsy-scroll-hidden' style={{ height: innerHeight - 400, overflow: 'auto', borderTop: '1px', borderTopStyle: 'solid', borderColor: 'rgb(217,217,217)' }} ref={mainDiv}>
|
||||
{returnPanel()}{/* 折叠面板 */}
|
||||
</div>
|
||||
</Spin>
|
||||
{/* 新增类别Modal */}
|
||||
{addCategoryModal()}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
export default FirstMain;
|
@ -8,16 +8,13 @@
|
||||
border-width: 1px;
|
||||
}
|
||||
}
|
||||
|
||||
// :global {
|
||||
// .pageHeaderStyle {
|
||||
// .ant-page-header {
|
||||
// position: relative;
|
||||
// font-size: 0px;
|
||||
// padding: 0px;
|
||||
// border-bottom: solid;
|
||||
// border-bottom-color: rgb(208,1,0);
|
||||
// border-width: 1px;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
.xsyBtn {
|
||||
color:#1890ff;
|
||||
margin-right: 8px;
|
||||
:hover{
|
||||
color:#1890ff;
|
||||
}
|
||||
}
|
||||
// .firstTabs{
|
||||
// padding: 0px 24px 0px 24px;
|
||||
// }
|
211
src/pages/Bid/ReviewConfig/Config/components/preview.tsx
Normal file
211
src/pages/Bid/ReviewConfig/Config/components/preview.tsx
Normal file
@ -0,0 +1,211 @@
|
||||
import { getProMethod } from "@/utils/session";
|
||||
import ProTable, { ProColumns } from "@ant-design/pro-table";
|
||||
import { Button, Checkbox, Col, InputNumber, Modal, Radio, Tabs, } from "antd";
|
||||
import React, { useState } from "react";
|
||||
import styles from './detailedStyles.less';
|
||||
type PreviewType = {
|
||||
data: any,
|
||||
rvwType: number,//初审1详审2
|
||||
}
|
||||
const Preview: React.FC<PreviewType> = (props) => {
|
||||
const { TabPane } = Tabs;
|
||||
const { data, rvwType } = props;
|
||||
const { data1, data2, data3, data4 } = data;
|
||||
|
||||
//==========================================================state
|
||||
const [preview, setPreview] = useState<boolean>(false);//预览显隐
|
||||
|
||||
//页面文字显示
|
||||
const method = getProMethod();
|
||||
let showNameT: any = { tbr: '供应商' }//应答
|
||||
if (method === 'procurement_mode_1' || method === 'procurement_mode_2') {//招标
|
||||
showNameT = { tbr: '投标人' }
|
||||
}
|
||||
|
||||
//预览表格
|
||||
const columnsPreview: ProColumns<any>[] = [
|
||||
{
|
||||
title: '类别名称', width: 130, dataIndex: 'name',
|
||||
render: (_: any, record: any, index: number) => {
|
||||
return {
|
||||
children: _,
|
||||
props: {
|
||||
rowSpan: record.rowSpan,
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{ title: '评分项', dataIndex: "scoreItem" },
|
||||
{
|
||||
title: showNameT.tbr + 'XXX', dataIndex: "cate", width: 400,
|
||||
render: (_, record) => {
|
||||
return (
|
||||
<>
|
||||
{
|
||||
rvwType === 1 &&
|
||||
<Radio.Group >
|
||||
<Radio value={1}>合格</Radio>
|
||||
<Radio value={0}>不合格</Radio>
|
||||
</Radio.Group>
|
||||
}
|
||||
{
|
||||
rvwType === 2 && record.scoreMethod == 0 &&
|
||||
record?.standardList?.map((item: any, index: any) => {
|
||||
return (
|
||||
<Radio value={index} className={styles.radioStyle}>
|
||||
<label className={styles.labelStyle} style={{ width: '400px' }}>
|
||||
{item.standardDetailScore}分({item.standardName})
|
||||
</label>
|
||||
</Radio>
|
||||
)
|
||||
})
|
||||
}
|
||||
{
|
||||
rvwType === 2 && record.scoreMethod == 1 &&
|
||||
record.standardList.map((item: any, index: any) => {
|
||||
return (
|
||||
<Col span={24}>
|
||||
<Checkbox value={index} className={styles.radioStyle}>
|
||||
<label className={styles.labelStyle} style={{ width: '400px' }}>
|
||||
{item.standardDetailScore}分({item.standardName})
|
||||
</label>
|
||||
</Checkbox>
|
||||
</Col>
|
||||
)
|
||||
})
|
||||
}
|
||||
{
|
||||
rvwType === 2 && record.scoreMethod == 3 &&
|
||||
<><InputNumber min={record.lowScore} max={record.highScore} defaultValue={record.lowScore} /> 分</>
|
||||
}
|
||||
{
|
||||
rvwType === 2 && record.scoreMethod == 4 &&
|
||||
<><InputNumber min={record.lowScore} max={record.highScore} defaultValue={record.lowScore} step={record.lowScore} /> 每步:{record.lowScore}分</>
|
||||
}
|
||||
</>
|
||||
)
|
||||
|
||||
}
|
||||
},
|
||||
];
|
||||
//==========================================================func
|
||||
/**
|
||||
* 合并table单元格
|
||||
* @param data
|
||||
* @param fieldName
|
||||
*/
|
||||
const createNewArr = (data: any[], fieldName: string) => {
|
||||
return data.reduce((result: any[], item: any) => {
|
||||
//首先将name字段作为新数组result取出
|
||||
if (result.indexOf(item[fieldName]) < 0) {
|
||||
result.push(item[fieldName]);
|
||||
}
|
||||
return result
|
||||
}, []).reduce((result: any[], name: any) => {
|
||||
//将name相同的数据作为新数组取出,并在其内部添加新字段**rowSpan**
|
||||
const children = data.filter(item => item[fieldName] === name);
|
||||
result = result.concat(
|
||||
children.map((item: any, index: number) => ({
|
||||
...item,
|
||||
rowSpan: index === 0 ? children.length : 0,//将第一行数据添加rowSpan字段
|
||||
}))
|
||||
)
|
||||
return result;
|
||||
}, [])
|
||||
}
|
||||
//处理数据
|
||||
function makeData(data: any) {
|
||||
let datat: any = [];
|
||||
data?.map((item: any) => {
|
||||
item?.detailList?.map((item2: any) => {
|
||||
item2['name'] = item.name;
|
||||
datat.push(item2)
|
||||
})
|
||||
})
|
||||
return datat;
|
||||
}
|
||||
let [data1t, data2t, data3t, data4t] = [
|
||||
createNewArr(makeData(data1), 'name'),
|
||||
createNewArr(makeData(data2), 'name'),
|
||||
createNewArr(makeData(data3), 'name'),
|
||||
createNewArr(makeData(data4), 'name'),
|
||||
];
|
||||
|
||||
|
||||
//==========================================================dom
|
||||
const PreViewModal = () => {
|
||||
return (
|
||||
<Modal
|
||||
visible={preview}
|
||||
title="预览"
|
||||
width={"60%"}
|
||||
centered
|
||||
bodyStyle={{ maxHeight: "500px", overflow: 'auto' }}
|
||||
onCancel={() => setPreview(false)}
|
||||
footer={renderFooter()}
|
||||
>
|
||||
{tabs()}
|
||||
</Modal>
|
||||
)
|
||||
}
|
||||
function tabs() {//页签
|
||||
return (
|
||||
<Tabs>
|
||||
{
|
||||
data1t.length > 0 &&
|
||||
<TabPane tab={data1[0].categoryName} key="1">
|
||||
{table(data1t)}
|
||||
</TabPane>
|
||||
}
|
||||
{
|
||||
data2t.length > 0 &&
|
||||
<TabPane tab={data2[0].categoryName} key="2">
|
||||
{table(data2t)}
|
||||
</TabPane>
|
||||
}
|
||||
{
|
||||
data3t.length > 0 &&
|
||||
<TabPane tab={data3[0].categoryName} key="3">
|
||||
{table(data3t)}
|
||||
</TabPane>
|
||||
}
|
||||
{
|
||||
data4t.length > 0 &&
|
||||
<TabPane tab={data4[0].categoryName} key="4">
|
||||
{table(data4t)}
|
||||
</TabPane>
|
||||
}
|
||||
</Tabs>
|
||||
)
|
||||
}
|
||||
function table(data: any) {
|
||||
return (
|
||||
<ProTable
|
||||
columns={columnsPreview}
|
||||
dataSource={data}
|
||||
options={false}
|
||||
search={false}
|
||||
pagination={false}
|
||||
bordered
|
||||
/>
|
||||
)
|
||||
}
|
||||
//页脚
|
||||
function renderFooter() {
|
||||
return (
|
||||
<Button type='primary' onClick={() => setPreview(false)}>关闭</Button>
|
||||
)
|
||||
}
|
||||
return (
|
||||
<>
|
||||
<Button
|
||||
key="4"
|
||||
style={{ marginRight: '10px' }}
|
||||
onClick={() => {
|
||||
setPreview(true);
|
||||
}}>预览</Button>
|
||||
<PreViewModal />
|
||||
</>
|
||||
)
|
||||
}
|
||||
export default Preview;
|
@ -1,4 +1,5 @@
|
||||
import request from '@/utils/request';
|
||||
import { message } from 'antd';
|
||||
|
||||
|
||||
//查询
|
||||
@ -22,6 +23,25 @@ export async function useTem(params?: any) {
|
||||
params,
|
||||
});
|
||||
};
|
||||
//使用模板
|
||||
export const useT = async (fields: any) => {
|
||||
const hide = message.loading('正在配置');
|
||||
try {
|
||||
const success = await useTem({ ...fields }).then(res => { return res.success });
|
||||
hide();
|
||||
if (success) {
|
||||
message.success('配置成功');
|
||||
return true;
|
||||
} else {
|
||||
message.error('配置失败');
|
||||
return false;
|
||||
}
|
||||
} catch (error) {
|
||||
hide();
|
||||
message.error('配置失败请重试!');
|
||||
return false;
|
||||
}
|
||||
};
|
||||
//查询应答文件格式
|
||||
export async function getTree(params?: any) {
|
||||
return request(`/api/biz-service-ebtp-resps/v1/tdoccatalog/treelistForRsms`, {
|
||||
@ -54,6 +74,24 @@ export async function glFile(params?: any) {
|
||||
},
|
||||
});
|
||||
};
|
||||
//保存关联文件
|
||||
export const saveF = async (fields: any) => {
|
||||
const hide = message.loading('正在保存');
|
||||
try {
|
||||
const success = await glFile({ ...fields }).then(res => { return res.success });
|
||||
hide();
|
||||
if (success) {
|
||||
message.success('保存成功');
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} catch (error) {
|
||||
hide();
|
||||
message.error('保存失败请重试!');
|
||||
return false;
|
||||
}
|
||||
};
|
||||
//保存
|
||||
export async function saveData(params: any) {
|
||||
return request(`/api/biz-service-ebtp-rsms/v1/review/config/detail`, {
|
||||
@ -63,7 +101,25 @@ export async function saveData(params: any) {
|
||||
},
|
||||
});
|
||||
}
|
||||
//保存模板
|
||||
//新增、保存对
|
||||
export const save = async (fields: any) => {
|
||||
const hide = message.loading('正在保存');
|
||||
try {
|
||||
const success = await saveData({ ...fields }).then(res => { return res.success });
|
||||
hide();
|
||||
if (success) {
|
||||
message.success('保存成功');
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} catch (error) {
|
||||
hide();
|
||||
message.error('保存失败请重试!');
|
||||
return false;
|
||||
}
|
||||
};
|
||||
//保存模板--接口
|
||||
export async function saveTem(params: any) {
|
||||
return request(`/api/biz-service-ebtp-rsms/v1/review/config/template/save`, {
|
||||
method: 'POST',
|
||||
@ -72,22 +128,108 @@ export async function saveTem(params: any) {
|
||||
},
|
||||
});
|
||||
}
|
||||
//删除单项
|
||||
//保存模板--方法
|
||||
export const saveT = async (fields: any) => {
|
||||
const hide = message.loading('正在保存');
|
||||
try {
|
||||
const success = await saveTem({ ...fields }).then(res => { return res.success });
|
||||
hide();
|
||||
if (success) {
|
||||
message.success('保存成功');
|
||||
return true;
|
||||
} else {
|
||||
message.error('保存失败');
|
||||
return false;
|
||||
}
|
||||
} catch (error) {
|
||||
hide();
|
||||
message.error('保存失败请重试!');
|
||||
return false;
|
||||
}
|
||||
};
|
||||
// 删除评审项接口
|
||||
export async function delDetail(params?: any) {
|
||||
return request(`/api/biz-service-ebtp-rsms/v1/review/config/detail/${params.id}`, {
|
||||
method: 'DELETE'
|
||||
});
|
||||
};
|
||||
//删除类别
|
||||
export async function delCategory(params?: any) {
|
||||
return request(`/api/biz-service-ebtp-rsms/v1/review/config/category/${params.id}`, {
|
||||
|
||||
//删除评审项方法
|
||||
export const delDet = async (fields: any) => {
|
||||
const hide = message.loading('正在删除');
|
||||
try {
|
||||
const success = await delDetail({ ...fields }).then(res => { return res.success });
|
||||
hide();
|
||||
if (success) {
|
||||
message.success('删除成功');
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} catch (error) {
|
||||
hide();
|
||||
message.error('配置失败请重试!');
|
||||
return false;
|
||||
}
|
||||
};
|
||||
//删除类别接口
|
||||
export async function delCategory(id?: any) {
|
||||
return request(`/api/biz-service-ebtp-rsms/v1/review/config/category/${id}`, {
|
||||
method: 'DELETE'
|
||||
});
|
||||
};
|
||||
//删除打分最小项细则
|
||||
//删除类别方法
|
||||
export const delCate = async (id: any) => {
|
||||
const hide = message.loading('正在删除');
|
||||
try {
|
||||
const success = await delCategory(id).then(res => { return res.success });
|
||||
hide();
|
||||
if (success) {
|
||||
message.success('删除成功');
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} catch (error) {
|
||||
hide();
|
||||
message.error('删除失败请重试!');
|
||||
return false;
|
||||
}
|
||||
};
|
||||
//删除详细评分标准-接口
|
||||
export async function delStandard(params?: any) {
|
||||
return request(`/api/biz-service-ebtp-rsms/v1/review/config/standard/${params.id}`, {
|
||||
method: 'DELETE'
|
||||
// return request(`/api/biz-service-ebtp-rsms/v1/review/config/standard/${params.id}`, {
|
||||
// method: 'DELETE'
|
||||
|
||||
return request(`/api/biz-service-ebtp-rsms/v1/review/config/standard`, {
|
||||
method: 'POST',
|
||||
data:params,
|
||||
});
|
||||
};
|
||||
//删除详细评分标准方法
|
||||
export const delStan = async (fields: any) => {
|
||||
const hide = message.loading('正在删除');
|
||||
try {
|
||||
const success = await delStandard(fields).then(res => { return res.success });
|
||||
hide();
|
||||
if (success) {
|
||||
// message.success('删除成功');
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} catch (error) {
|
||||
hide();
|
||||
message.error('删除失败请重试!');
|
||||
return false;
|
||||
}
|
||||
};
|
||||
//初审EXCEL模板
|
||||
export async function firstTem() {
|
||||
return request(`/api/biz-service-ebtp-extend/v1/template/warehouse/fhxsc`);
|
||||
};
|
||||
//详审EXCEL模板
|
||||
export async function detailTem() {
|
||||
return request(`/api/biz-service-ebtp-extend/v1/template/warehouse/pfbz`);
|
||||
};
|
||||
|
||||
|
264
src/pages/Bid/ReviewConfig/Config/components/templeteBtns.tsx
Normal file
264
src/pages/Bid/ReviewConfig/Config/components/templeteBtns.tsx
Normal file
@ -0,0 +1,264 @@
|
||||
import { btnAuthority } from "@/utils/authority";
|
||||
import FileDown from "@/utils/Download";
|
||||
import { UploadOutlined } from "@ant-design/icons";
|
||||
import ProTable, { ActionType, ProColumns } from "@ant-design/pro-table";
|
||||
import { Button, Col, Dropdown, Form, Input, Menu, message, Modal, Row, Spin, Upload } from "antd";
|
||||
import React, { useRef, useState } from "react";
|
||||
import { getTemPage, saveT, useT } from "./service";
|
||||
import '@/assets/xsy_style.less'
|
||||
type TemType = {
|
||||
rvwType: number,//初审1 详审2
|
||||
commonId: string,//公共id
|
||||
assessRoomId: string,//评审室id
|
||||
nodeId: string,//节点id
|
||||
dis: boolean,
|
||||
oid: string,//文件id
|
||||
purchaseMethod: number,//1234 初审 详审 初审有限数量制 详审无报价
|
||||
reviewId?: string,//detId 详审id firstId 初审id
|
||||
rePage: () => {},//执行父组件刷新页面的方法
|
||||
processData: (data: any) => {}//处理数据
|
||||
parentSpin: (value: any) => {},//控制父组件 spin
|
||||
}
|
||||
const TempleteBtns: React.FC<TemType> = (props) => {
|
||||
//=====================================================================state
|
||||
const { reviewId, rvwType, assessRoomId, commonId, nodeId, dis, oid, purchaseMethod, rePage, processData, parentSpin } = props;
|
||||
const FormItem = Form.Item;
|
||||
const [form] = Form.useForm();
|
||||
const ref = useRef<ActionType>();
|
||||
//模板
|
||||
const [temSave, setTemSave] = useState<boolean>(false);//保存模板
|
||||
const [temUse, setTemUse] = useState<boolean>(false);//使用模板
|
||||
const [modalSpin, modalSpinSet] = useState<boolean>(false);//保存模板Spin
|
||||
const [pageTemData, setPageTemData] = useState<any>({ pageNo: 1, pageSize: 10, rvwType, templateName: "", purchaseMethod }); //查询模板分页数据
|
||||
const upProps = {
|
||||
name: 'file',
|
||||
action: '/api/biz-service-ebtp-rsms/v1/review/config/template/importTemplate',
|
||||
data: {
|
||||
id: reviewId, rvwType: rvwType, commonId: commonId, nodeId: nodeId
|
||||
},
|
||||
accept: ".xls,.xlsx",
|
||||
itemRender: () => { return null },
|
||||
onChange(info: any) {
|
||||
parentSpin(true);
|
||||
if (info.file.status === 'done') {
|
||||
if (info.file?.response?.code == 200) {
|
||||
message.success(`${info.file.name} 导入成功,保存生效`);
|
||||
//给表格加key
|
||||
info.file?.response?.data.categoryList.map((item: any, index: number) => {
|
||||
item.key = index;
|
||||
})
|
||||
processData(info.file?.response);
|
||||
info2();
|
||||
} else {
|
||||
message.error(info.file?.response?.message);
|
||||
}
|
||||
} else if (info.file.status === 'error') {
|
||||
message.error(`${info.file.name} 上传失败`);
|
||||
rePage();
|
||||
}
|
||||
parentSpin(false);
|
||||
},
|
||||
};
|
||||
//模板列表表格
|
||||
const columnsTemUse: ProColumns<any>[] = [
|
||||
{ title: '序号', valueType: 'index', },
|
||||
{ title: '模板名称', dataIndex: 'templateName', },
|
||||
{ title: '制作人', dataIndex: 'name', },
|
||||
{ title: '制作时间', width: 200, dataIndex: 'createDate', valueType: 'dateTime' },
|
||||
{
|
||||
title: '操作', dataIndex: 'option', width: 100, valueType: 'option',
|
||||
render: (_, record) => {
|
||||
return (
|
||||
<Button
|
||||
hidden={btnAuthority(['ebtp-agency-project-manager', 'ebtp-purchase'])}
|
||||
type='text'
|
||||
className='xsyBtn'
|
||||
onClick={async () => {
|
||||
modalSpinSet(true);
|
||||
const configId = reviewId;
|
||||
const id = record.id;
|
||||
const success = await useT({ configId, id, commonId, nodeId });
|
||||
if (success) {
|
||||
setTemUse(false);
|
||||
parentSpin(true);
|
||||
info();
|
||||
rePage();
|
||||
}
|
||||
modalSpinSet(false);
|
||||
}}>使用</Button>
|
||||
)
|
||||
}
|
||||
},
|
||||
];
|
||||
//=====================================================================func
|
||||
function info() {
|
||||
Modal.info({
|
||||
centered: true,
|
||||
title: '使用模板后,需重新保存,数据方可留存。',
|
||||
});
|
||||
}
|
||||
function info2() {
|
||||
Modal.info({
|
||||
centered: true,
|
||||
title: '导入EXCEL成功后,需重新保存,数据方可留存。',
|
||||
});
|
||||
}
|
||||
|
||||
//=====================================================================dom
|
||||
const menu = (
|
||||
<Menu style={{ backgroundColor: "white" }}>
|
||||
<Button
|
||||
hidden={btnAuthority(['ebtp-agency-project-manager', 'ebtp-purchase'])}
|
||||
disabled={dis}
|
||||
type="primary"
|
||||
key="menuBtnSave"
|
||||
style={{ margin: '2px 5px' }}
|
||||
onClick={() => {
|
||||
assessRoomId != null ?
|
||||
setTemSave(true)
|
||||
: message.info('请先保存配置')
|
||||
}}
|
||||
>保存模板</Button>
|
||||
<Button
|
||||
hidden={btnAuthority(['ebtp-agency-project-manager', 'ebtp-purchase'])}
|
||||
disabled={dis}
|
||||
type="primary"
|
||||
key="menuBtnUse"
|
||||
style={{ margin: '2px 5px' }}
|
||||
onClick={() => {
|
||||
ref.current?.reload();
|
||||
setTemUse(true);
|
||||
}}
|
||||
>使用模板</Button>
|
||||
<FileDown
|
||||
apiUrl={`/api/core-service-ebtp-updownload/v1/attachment/download/oid/${oid}`}
|
||||
btnName={'下载EXCEL模板'}
|
||||
style={{ margin: '2px 5px' }}
|
||||
/>
|
||||
<Upload {...upProps}>
|
||||
<Button
|
||||
hidden={btnAuthority(['ebtp-agency-project-manager', 'ebtp-purchase'])}
|
||||
icon={<UploadOutlined />}
|
||||
disabled={dis}
|
||||
type="primary"
|
||||
key="menuBtnImport"
|
||||
style={{ margin: '2px 5px' }}
|
||||
>导入EXCEL</Button>
|
||||
</Upload>
|
||||
</Menu>
|
||||
);
|
||||
//表格按钮
|
||||
const tools = [
|
||||
<Input placeholder="模板全名或关键字" onChange={(event) => {
|
||||
let data = pageTemData;
|
||||
data.templateName = event.target.value;
|
||||
setPageTemData(data);
|
||||
}} />,
|
||||
<Button type="primary" loading={modalSpin} onClick={() => {
|
||||
if (ref.current) {
|
||||
ref.current.reload();
|
||||
}
|
||||
}}>查询</Button>,
|
||||
];
|
||||
return (
|
||||
<>
|
||||
<Dropdown.Button overlay={menu}>模板→</Dropdown.Button>
|
||||
<Modal
|
||||
visible={temSave}
|
||||
width={"40%"}
|
||||
onCancel={() => setTemSave(false)}
|
||||
okButtonProps={{ loading: modalSpin }}
|
||||
onOk={async () => {
|
||||
parentSpin(true);
|
||||
modalSpinSet(true);
|
||||
const configId = reviewId;
|
||||
const templateName = form.getFieldsValue().temName;
|
||||
const allData = { configId, templateName, rvwType, purchaseMethod };
|
||||
let success = false;
|
||||
if (configId != '') {
|
||||
if (templateName != "") {
|
||||
success = await saveT(allData);
|
||||
}
|
||||
} else {
|
||||
message.error('请先保存页面数据!')
|
||||
}
|
||||
|
||||
if (success) {
|
||||
setTemSave(false);
|
||||
rePage();
|
||||
}
|
||||
modalSpinSet(false);
|
||||
parentSpin(false);
|
||||
}}
|
||||
centered
|
||||
title="保存模板"
|
||||
>
|
||||
<Spin spinning={modalSpin}>
|
||||
<Form
|
||||
labelCol={{ span: 6 }}
|
||||
wrapperCol={{ span: 16 }}
|
||||
form={form}
|
||||
>
|
||||
<Row>
|
||||
<Col span={24}><FormItem
|
||||
name="temName"
|
||||
label="模板名称"
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: '请输入模板名称',
|
||||
},
|
||||
]}
|
||||
>
|
||||
<Input placeholder="请输入模板名称" />
|
||||
</FormItem>
|
||||
</Col>
|
||||
</Row>
|
||||
</Form>
|
||||
</Spin>
|
||||
</Modal>
|
||||
<Modal
|
||||
visible={temUse}
|
||||
centered
|
||||
title="使用模板"
|
||||
width={1000}
|
||||
okButtonProps={{ loading: modalSpin }}
|
||||
onCancel={() => setTemUse(false)}
|
||||
footer={[<Button type='primary' onClick={() => setTemUse(false)}>关闭 </Button>]}
|
||||
>
|
||||
<Spin spinning={modalSpin}>
|
||||
<ProTable
|
||||
actionRef={ref}
|
||||
columns={columnsTemUse}//表格
|
||||
options={false}
|
||||
search={false}
|
||||
toolBarRender={() => tools}
|
||||
request={() =>
|
||||
getTemPage({ ...pageTemData }).then((res) => {
|
||||
const result = {
|
||||
data: res.data.records,
|
||||
total: res.data.total,
|
||||
success: res.success,
|
||||
pageSize: res.pageSize,
|
||||
current: res.current
|
||||
};
|
||||
return result;
|
||||
})
|
||||
}
|
||||
pagination={{
|
||||
defaultPageSize: 10,
|
||||
showSizeChanger: false,
|
||||
onChange: (page, pageSize) => {
|
||||
let data = pageTemData;
|
||||
data.pageNo = page;
|
||||
data.pageSize = pageSize;
|
||||
setPageTemData(data);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</Spin>
|
||||
</Modal>
|
||||
</>
|
||||
)
|
||||
}
|
||||
export default TempleteBtns;
|
@ -1,16 +0,0 @@
|
||||
import { Card, Tree } from 'antd';
|
||||
import React, {} from 'react';
|
||||
|
||||
const TreeTem: React.FC<{}> = () => {
|
||||
const roomId = "111"
|
||||
return (
|
||||
<>
|
||||
<Card>
|
||||
<Tree>
|
||||
|
||||
</Tree>
|
||||
</Card>
|
||||
</>
|
||||
)
|
||||
};
|
||||
export default TreeTem ;
|
Reference in New Issue
Block a user