This commit is contained in:
houjishuang
2025-05-28 17:23:05 +08:00
8 changed files with 3827 additions and 773 deletions

View File

@ -34,10 +34,15 @@ export default {
pathRewrite: { '/api/biz-service-ebtp-project': '' },
},
'/api/sys-manager-ebtp-project': {
target: 'http://localhost:18012',
target: 'http://localhost:18030',
changeOrigin: true,
pathRewrite: { '/api/sys-manager-ebtp-project': '' },
},
'/api/biz-service-ebtp-rsms': {
target: 'http://localhost:18014',
changeOrigin: true,
pathRewrite: { '/api/biz-service-ebtp-rsms': '' },
},
'/api/biz-service-ebtp-agency': {
target: 'http://localhost:18099',
changeOrigin: true,
@ -91,4 +96,3 @@ export default {
},
}
};

View File

@ -0,0 +1,971 @@
import React, { useEffect, useState } from 'react';
import { Avatar, Button, Col, Collapse, Form, Input, List, Modal, Image, Row, Space, Spin, message, Checkbox, Affix, Table, DatePicker, Anchor, BackTop } from 'antd';
import { UserSwitchOutlined, CarryOutOutlined, MinusCircleOutlined, PlusOutlined, ArrowUpOutlined } from '@ant-design/icons';
import moment from 'moment'
import logo from '@/assets/logo.svg';
import styles from './index.less';
import './index.less';
import { getProOpenTenderForm, getSessionUserData } from "@/utils/session";
import { isEmpty } from '@/utils/CommonUtils';
import { CheckboxItem, DatePickerItem, InputItem, InputNumberItem, RadioItem, TextAreaItem } from './fieldItem';
import { btnAuthority } from '@/utils/authority';
import Dating from '@/images/招标公告/dating.jpg';
import { getAnnoStructuralValue, getChooseRoom, saveAnnoStructuralFormData } from '../service';
import { UploadProps } from "antd/lib/upload/interface";
import { EditableProTable, ProColumns } from '@ant-design/pro-table';
import ExtendUpload from '@/utils/ExtendUpload';
import { SnowflakeID } from '@/services/untilService';
import { history } from 'umi';
import Medias from './Medias';
const { Panel } = Collapse;
const formLayout = { labelCol: { span: 8 }, wrapperCol: { span: 16 }, };
const form24Layout = { labelCol: { span: 4 }, wrapperCol: { span: 20 }, };
const form24LayoutWithOutLabel = { wrapperCol: { span: 20, offset: 4 }, };
const formFileWrapperCol = { wrapperCol: { span: 9 }, };
const { Link } = Anchor;
/**
* 采购复盘-回填表
* @param props
* @returns
*/
const BiddingAnnoStructureForm: React.FC<{}> = (props: any) => {
// 取项目id
const projectId = props?.location?.state?.projectId;
const search = props?.location?.state?.search;
const annoId = props?.location?.state?.annoId;
const editInformation = props?.location?.state?.editStatus;
// const annoId = "1732282646482624512";
// 取查询条件
const stucturalId = "1";
// 结构化信息
const [annoStructureData, setAnnoStructureData] = useState<any>([]);
// 取用户信息
let data = getSessionUserData();
// 招标公告---关联标段---当前选中的标段ids
const [sectionSelectIds, setSectionSelectIds] = useState<string[]>([]);
// 项目概况和招标范围---标包情况---返回的全部标段信息
const [sectionSelectData, setSectionSelectData] = useState<any>([]);
// 招标文件的获取---招标文件费用---返回的全部标段信息
const [expenses1AmountSectionData, setExpenses1AmountSectionData] = useState<any>([]);
// 投标人资格能力要求---投标人资格能力要求---返回的全部包的投标人资格能力要求
const [tenderAskData, setTenderAskData] = useState<any>([]);
// 当前展开的折叠面板
const [activeKey, setActiveKey] = useState<string[]>([]);
// loading
const [loading, setLoading] = useState<boolean>(false);
const [UploadID, setUploadID] = useState<any>(); //upload 业务id
// const [editInformation, setEditInformation] = useState<boolean>(props?.location?.state?.editStatus);//是否可编
/*20210112 新增 发布媒体限制*/
const [mediaType, setmediaType] = useState<any>();
// 2021-06-17 新增 发布媒体显示发布成功失败
const [mediaReleases, mediaReleasesSet] = useState<any>([]);
//右侧浮动层监听Dom
const [container, setContainer] = useState<HTMLDivElement | null>(null);
const UploadProps: UploadProps = {
name: "file",
disabled: editInformation
}
// Form
const [form] = Form.useForm();
/**
* 折叠面板选择
* @param key
*/
const onCollapseChange = (key: string | string[]) => {
setActiveKey(key as string[]);
};
const ReplyEndTimechange1 = (data?: any) => {
if (data != undefined) {
form.setFieldsValue({
"openingTime": moment(data, 'yyyy-MM-DD HH:mm:ss'),
});
}
};
/**
* 获取公告结构化信息
* @param id
*/
const getStructuralList = async (id: any) => {
try {
const result = await getAnnoStructuralValue({ tpId: projectId, stucturalId: stucturalId, annoId: annoId ? annoId : undefined });
if (result && result?.success) {
const offer = result?.data;
setAnnoStructureData(offer);
const linkKeys = offer?.groupVoList?.map((item: { id: any; }) => item?.id);
setActiveKey([...linkKeys]);
// 项目概况和招标范围---标包情况---返回的全部标段信息
const overviewRangeDate = offer?.groupVoList?.filter((item: any) => item?.code === "overview_range");
const sectionDate = overviewRangeDate[0]?.assemblyVoList?.filter((item: any) => item?.code === "sectionExpeses");
setSectionSelectData(JSON.parse(sectionDate[0]?.extend2))
{ sectionDate[0]?.value && form.setFieldsValue({ "sectionExpeses": JSON.parse(sectionDate[0]?.value) }) }
// 招标文件的获取---招标文件费用---返回的全部标段信息
const expesesDate = offer?.groupVoList?.filter((item: any) => item?.code === "expeses");
const expenses1Amount = expesesDate[0]?.assemblyVoList?.filter((item: any) => item?.code === "expenses1Amount");
setExpenses1AmountSectionData(JSON.parse(expenses1Amount[0]?.extend2))
{ expenses1Amount[0]?.value && form.setFieldsValue({ "expenses1Amount": JSON.parse(expenses1Amount[0]?.value) }) }
// 投标人资格能力要求---投标人资格能力要求---返回的全部包的投标人资格能力要求
const tenderAskDate = offer?.groupVoList?.filter((item: any) => item?.code === "tenderAsk");
const tenderAskProject = tenderAskDate[0]?.assemblyVoList?.filter((item: any) => item?.code === "tenderAskProject");
setTenderAskData(JSON.parse(tenderAskProject[0]?.extend2))
{ tenderAskProject[0]?.value && form.setFieldsValue({ "tenderAskProject": JSON.parse(tenderAskProject[0]?.value) }) }
// 附件---附件---fileId
const annexDate = offer?.groupVoList?.filter((item: any) => item?.code === "annex");
const fileId = annexDate[0]?.assemblyVoList?.filter((item: any) => item?.code === "fileId");
setUploadID(fileId[0]?.value);
}
} catch (error) {
}
}
const check = (data: any) => {
let msg = "false";
if (form.getFieldValue("docStartTime") < moment().startOf('day')) {
message.warn('招标文件获取开始时间需晚于当前时间');
} else if (moment(form.getFieldValue("docEndTime")).startOf('day').diff(moment(form.getFieldValue("docStartTime")).startOf('day'), "days") < 5) {
message.warn('招标文件获取截止时间需与文件获取开始时间间隔不少于5天');
} else if (moment(form.getFieldValue("replyEndTime")).startOf('day').diff(moment(form.getFieldValue("docStartTime")).startOf('day'), "days") < (getProOpenTenderForm() == "open_tender_form_1" ? 20 : 15)) {
message.warn('投标截止时间需与文件获取开始时间间隔不少于' + (getProOpenTenderForm() == "open_tender_form_1" ? 20 : 15) + '天');
} else if (form.getFieldValue("replyEndTime").format('YYYY-MM-DD HH:mm:ss') < form.getFieldValue("docEndTime").format('YYYY-MM-DD HH:mm:ss')) {
message.warn('投标截止时间需晚于或等于投标文件获取截止时间');
} else if (moment(form.getFieldValue("openingTime")).diff(moment(form.getFieldValue("replyEndTime")), "minutes") != 0) {
message.warn('开标时间(' + form.getFieldValue("openingTime").format("yyyy-MM-DD HH:mm") + ')需与投标截止时间(' + form.getFieldValue("replyEndTime").format("yyyy-MM-DD HH:mm") + ')相同');
} else if (form.getFieldValue("openhallTitle")?.substring(0, 10) != moment(form.getFieldValue("openingTime")).format('YYYY-MM-DD')) {
message.warn('开标大厅日期需与开标日期相同');
} else if (data?.sectionDivide === "划分" && !data?.sectionNumber) {
message.warn('标包数量不可为空');
} else {
msg = "true"
}
return msg;
}
/**
* 保存
*/
const onSave = async () => {
form.setFieldsValue({ "fileId": form.getFieldValue("fileId") ? form.getFieldValue("fileId") : UploadID });
form.validateFields().then(async values => {
if (check(values) === "true") {
let structuralDataList: any[] = [];
for (let i = 0, length = annoStructureData?.groupVoList?.length; i < length; i++) {
const item = annoStructureData?.groupVoList[i];
for (let j = 0, jlength = item?.assemblyVoList?.length; j < jlength; j++) {
const jitem = item?.assemblyVoList[j];
if (isEmpty(values?.[jitem?.code])) { // 空值或者类型为表格无需返回数据 || jitem?.type === 6 else
if (jitem?.code === "annoNature") {
structuralDataList.push({
assemblyId: jitem?.id,
assemblyCode: jitem?.code,
value: "1",
})
} else if (jitem?.code === "source") {
structuralDataList.push({
assemblyId: jitem?.id,
assemblyCode: jitem?.code,
value: "11",
})
}
} else if (jitem?.type === "0") { // 默认文本
// if (jitem?.ifShow === "1") {
structuralDataList.push({
assemblyId: jitem?.id,
assemblyCode: jitem?.code,
value: jitem.value ? jitem.value : values?.[jitem?.code],
})
// }
} else if (jitem?.type === "3" || jitem?.type === "31") { // 多选
structuralDataList.push({
assemblyId: jitem?.id,
assemblyCode: jitem?.code,
value: values[jitem?.code],
})
} else if (jitem?.type === "4" || jitem?.type === "5") { // 日期 需要格式化时间
structuralDataList.push({
assemblyId: jitem?.id,
assemblyCode: jitem?.code,
value: moment(values[jitem?.code]).format('yyyy-MM-DD HH:mm:ss'),
})
} else if (jitem?.type === "9") { // 表格
// if (jitem?.code === "sectionExpeses") {
structuralDataList.push({
assemblyId: jitem?.id,
assemblyCode: jitem?.code,
value: values[jitem?.code],
})
// }
} else if (jitem?.type === "10") { // 附件
structuralDataList.push({
assemblyId: jitem?.id,
assemblyCode: jitem?.code,
value: values[jitem?.code],
})
} else { //其他数值型字段放到contentValue上
structuralDataList.push({
assemblyId: jitem?.id,
assemblyCode: jitem?.code,
value: values[jitem?.code],
})
}
}
}
try {
let params = {
// ...offerData,
structuralDataList,
tpId: projectId,
stucturalId: stucturalId,
sections: sectionSelectIds,
}
setLoading(true);
const result = await saveAnnoStructuralFormData(params);
if (result && result?.success) {
message.success("保存成功!");
back();
}
setLoading(false);
} catch (error) {
setLoading(false);
}
}
})
}
const back = () => {
history.push({ pathname: "/ProjectLayout/biddingAnnouncement/BiddingAnnouncementList", state: { returnParams: search } })
}
useEffect(() => {
if (!annoId) {
SnowflakeID().then(res => {
setUploadID(res.id);
});
}
if (projectId) {
getStructuralList(projectId);
}
// isCheck()
return () => {
}
}, [])
useEffect(() => {
const selectData = sectionSelectData.filter((item: any) => sectionSelectIds.indexOf(item?.sectionId) !== -1);
const amountSelectData = expenses1AmountSectionData.filter((item: any) => sectionSelectIds.indexOf(item?.sectionId) !== -1);
const tenderAskProjectData = tenderAskData.filter((item: any) => sectionSelectIds.indexOf(item?.sectionId) !== -1);
form.setFieldsValue({ "sectionExpeses": selectData })
form.setFieldsValue({ "expenses1Amount": amountSelectData })
form.setFieldsValue({ "tenderAskProject": tenderAskProjectData })
form.setFieldsValue({ "sectionNumber": sectionSelectIds.length })
}, [sectionSelectIds])
const [spinning, setSping] = useState<boolean>(false);//加载遮罩
const [choiceHallType, setChoiceHallType] = useState<boolean>(false);//选择开标大厅窗口状态
const [choiceHallData, setChoiceHallData] = useState<any>([]);//选择开标大厅窗口状态
/* 选择开标大厅 */
const getChooseRoomList = async () => {
setSping(true);
//先获取开标时间 没有不打开modal
let openTime = form.getFieldValue('openingTime');
if (openTime) {//不为空
await getChooseRoom(openTime.format('YYYY-MM-DD')).then(res => {
if (res != null && res.message == "success") {
setChoiceHallData(res.data)
setChoiceHallType(true);
} else {
message.error(res.message);
}
})
} else {
message.error('请先录入开标时间!')
}
setSping(false);
}
const confirmChooseRoom = (data: any) => {
if (!(parseInt(data.num) < data.max)) {
message.error('所选大厅预约已满,请更换。')
} else {
setChoiceHallType(false);
form.setFieldsValue({
"openhallId": data.id,
"openhallTitle": data.openDate
});
}
}
//招标公告-关联标段-多选框
const SectionCheckDom = (field: any) => {
const { onChange, value } = field;
setSectionSelectIds(value)
return (
<Checkbox.Group
style={{ width: "90%" }}
onChange={onChange}
value={value}
disabled={editInformation}
>
{
field?.extend2 && JSON.parse(field?.extend2)?.map((item: any) => (
<Checkbox
value={Object.keys(item)[0]}
key={Object.keys(item)[0]}
>
{Object.values(item)[0]}
</Checkbox>
))
}
</Checkbox.Group>
)
};
//项目概况和招标范围-标包情况-表格
const columns: ProColumns<any>[] = [
{
title: '序号',
editable: false,
valueType: 'index',
width: "5%",
fixed: 'left',
},
{
title: '标包名称',
editable: false,
dataIndex: 'sectionName',
key: 'sectionName',
width: "20%",
},
{
title: '是否最高限价',
dataIndex: 'ifCeilingPrice',
key: 'ifCeilingPrice',
width: "10%",
valueType: 'radio',
valueEnum: {
"0": { text: '否' },
"1": { text: '是' },
},
},
{
title: '最高限价(元)',
dataIndex: 'ceilingPrice',
key: 'ceilingPrice',
width: "15%",
tooltip: "是否最高限价选择【是】,当前行的最高限价(元)必须填写",
formItemProps: {
rules: [{ pattern: /^[0-9]+(\.[0-9]{1,2})?$/, message: '请输入正确数值(最多2位小数)' },
{ pattern: /^.{0,21}$/, message: '超长' }],
}
},
{
title: '分配情况',
editable: false,
dataIndex: 'ratioValue',
key: 'ratioValue',
width: "40%",
},
];
//项目概况和招标范围-标包情况-表格
const SectionExpesesTableItem = (field: any) => {
const { value, onChange } = field;
//处理列头
return (
<EditableProTable
rowKey="sectionId"
style={{ width: "90%" }}
// 关闭默认的新建按钮
recordCreatorProps={false}
columns={columns}
value={value}
editable={{
type: 'multiple',
editableKeys: value && !editInformation ? value.map((item: any) => item.sectionId) : [],
onValuesChange: (record, recordList) => {
onChange(recordList)
},
}}
/>
)
}
//投标格式能力要求-投标格式能力要求-表格
const TenderAskColumns: ProColumns<any>[] = [
{
title: '序号',
editable: false,
valueType: 'index',
width: "5%",
fixed: 'left',
},
{
title: '资格条件',
dataIndex: 'condition',
key: 'condition',
width: "60%",
formItemProps: () => {
return {
rules: [{ required: true, message: '此项为必填项' }],
};
},
},
{
title: '操作',
valueType: 'option',
width: 200,
render: (text, record, _, action) => [
<a
key="editable"
hidden={editInformation}
onClick={() => {
action?.startEditable?.(record.id);
}}
>
</a>,
<a
key="delete"
hidden={editInformation}
onClick={() => {
const tableDataSource = form?.getFieldValue(
'tenderAsk'
);
form?.setFieldsValue({
tenderAsk: tableDataSource.filter((item: any) => item.id !== record.id),
});
}}
>
</a>,
],
},
];
//投标格式能力要求-投标格式能力要求-表格类型定义
type DataSourceType = {
id: number;
condition?: string;
};
//投标格式能力要求-投标格式能力要求-表格
const TenderAskTableItem = (field: any) => {
const { value, onChange } = field;
//处理列头
return (
<EditableProTable<DataSourceType>
rowKey="id"
style={{ width: "90%" }}
recordCreatorProps={{
newRecordType: 'dataSource',
hidden: editInformation,
creatorButtonText: '新增',
record: () => ({
id: Date.now(),
condition: "",
}),
}}
columns={TenderAskColumns}
value={value ? value : []}
editable={{
type: 'multiple',
onValuesChange: (record, recordList) => {
onChange(recordList)
},
actionRender: (row, config, defaultDom) => {
return [
defaultDom.save,
defaultDom.delete || defaultDom.cancel
];
},
}}
/>
)
}
//投标格式能力要求-投标格式能力要求-表格
const TenderAskProjectColumns: any[] = [
{
title: '序号',
valueType: 'index',
width: 100,
render: (text: any, _: any, index: any) => index + 1,
},
{
title: '资格条件',
dataIndex: 'condition',
key: 'condition',
// width: "60%",
},
];
//投标格式能力要求-投标格式能力要求-表格
const TenderAskProjectTableItem = (field: any) => {
const { value, onChange } = field;
//处理列头
return (
<Table
columns={TenderAskProjectColumns}
dataSource={value ? value : []}
rowKey="id"
size="small"
pagination={false}
style={{ width: '90%' }}
/>
)
}
//招标文件的获取-招标文件费用-表格
const expenses1AmountColumns: ProColumns<any>[] = [
{
title: '序号',
editable: false,
valueType: 'index',
width: "5%",
fixed: 'left',
},
{
title: '标包名称',
editable: false,
dataIndex: 'sectionName',
key: 'sectionName',
width: "20%",
},
{
title: '费用(元)',
dataIndex: 'amount',
key: 'amount',
width: "20%",
formItemProps: {
rules: [{ pattern: /^[0-9]+(\.[0-9]{1,2})?$/, message: '请输入正确数值(最多2位小数)' },
{ pattern: /^.{0,21}$/, message: '超长' }],
}
},
];
//招标文件的获取-招标文件费用-表格
const Expenses1AmountTableItem = (field: any) => {
const { value, onChange } = field;
//处理列头
return (
<EditableProTable
rowKey="sectionId"
style={{ width: "90%" }}
// 关闭默认的新建按钮
recordCreatorProps={false}
columns={expenses1AmountColumns}
value={value}
editable={{
type: 'multiple',
editableKeys: value && !editInformation ? value.map((item: any) => item.sectionId) : [],
onValuesChange: (record, recordList) => {
onChange(recordList)
},
}}
/>
)
}
//招标文件投递-投递文件数量-表格
const submitFileNumberColumns: ProColumns<any>[] = [
{
title: '序号',
editable: false,
valueType: 'index',
width: "5%",
fixed: 'left',
},
{
title: '文件类型',
editable: false,
dataIndex: 'name',
key: 'name',
width: "20%",
},
{
title: '份数(份)',
dataIndex: 'number',
key: 'number',
width: "20%",
formItemProps: {
rules: [{ pattern: /^[0-9]?$/, message: '请输入正确数值' },
{ pattern: /^.{0,21}$/, message: '超长' }],
}
},
];
const SubmitFileNumberTableItem = (field: any) => {
const { value, onChange } = field;
//处理列头
return (
<EditableProTable
rowKey="name"
style={{ width: "90%" }}
// 关闭默认的新建按钮
recordCreatorProps={false}
columns={submitFileNumberColumns}
value={value ? value : JSON.parse(field?.extend2)}
editable={{
type: 'multiple',
editableKeys: editInformation ? [] : value ? value.map((item: any) => item.name) : JSON.parse(field?.extend2).map((item: any) => item.name),
onValuesChange: (record, recordList) => {
onChange(recordList)
},
}}
/>
)
}
const ContactInformationFormItem = (fileds: any) => {
const assemblyVo = fileds?.assemblyVo
const icondition = JSON.parse(assemblyVo?.icondition)
//处理列头
return (
<Form.List
name={assemblyVo?.code}
rules={[
{
validator: async (_, names) => {
if (names.length > icondition?.number) {
return Promise.reject(new Error('数量超出'));
}
},
},
]}
initialValue={JSON.parse(assemblyVo?.value)}
>
{(fields, { add, remove }, { errors }) => {
if (fields.length === 0) {
add()
}
return <>
{fields.map((field, index) => (
<Form.Item
{...(index === 0 ? form24Layout : form24LayoutWithOutLabel)}
label={index === 0 ? assemblyVo?.name : ''}
required={assemblyVo?.ifRequired === "1"}
key={field.key}
>
<Form.Item
{...field}
validateTrigger={['onChange', 'onBlur']}
rules={
assemblyVo?.code === "agentContact_phone" ?
[{
pattern: /(^[1][3,4,5,6,7,8,9][0-9]{9}$)|(^(([0\+]\d{2,3}-)?(0\d{2,3})-)(\d{7,8})(-(\d{3,}))?$)/,
message: '输入的电话号码不正确',
}, { required: assemblyVo?.ifRequired === "1", message: "请填写此项.", }]
:
[{ required: assemblyVo?.ifRequired === "1", message: "请填写此项.", }]
}
noStyle
>
<Input style={{ width: '90%' }} disabled={editInformation} />
</Form.Item>
{fields.length > 1 ? (
<MinusCircleOutlined
className="dynamic-delete-button"
onClick={() => remove(field.name)}
hidden={editInformation}
/>
) : null}
</Form.Item>
))}
<Form.Item {...form24LayoutWithOutLabel}>
<Button
type="dashed"
onClick={() => add()}
style={{ width: '60%' }}
icon={<PlusOutlined />}
hidden={editInformation}
disabled={fields.length >= icondition?.number}
>
{assemblyVo?.name}
</Button>
<Form.ErrorList errors={errors} />
</Form.Item>
</>
}}
</Form.List>
)
}
//修改发布媒体 触发方法-邢书源
const medias9 = (dis: any) => {
if (dis) {
form.setFieldsValue({
"medias": ["9"],
});
}
setmediaType(dis);
}
const ShowComponent = (fileds: any) => {
const groupVo = fileds?.groupVo
const assemblyVo = fileds?.assemblyVo
return (
<Form.Item
label={assemblyVo?.name}
name={assemblyVo?.code}
rules={
assemblyVo?.type === "11" && assemblyVo?.code === "maxAmount" ? [
{ required: assemblyVo?.ifRequired === "1", message: '请填写此项' },
{ pattern: /^([1-9][0-9]*)+(\.[0-9]{1,2})?$/, message: '请输入正确数值(最多2位小数)' },
{ pattern: /^.{0,21}$/, message: '超长' }
] : assemblyVo?.type === "11" ? [
{ required: assemblyVo?.ifRequired === "1", message: '请填写此项' },
{ pattern: /^[0-9]+(\.[0-9]{1,2})?$/, message: '请输入正确数值(最多2位小数)' },
{ pattern: /^.{0,21}$/, message: '超长' }
] :
assemblyVo?.code === "agentContact_email" ?
[
{ required: assemblyVo?.ifRequired === "1", message: '请填写此项' },
{
type: 'email',
message: '输入的邮箱不正确',
},
]
:
[
{ required: assemblyVo?.ifRequired === "1", message: '请填写此项' },
]
}
wrapperCol={groupVo.code === "basic" ? formLayout.wrapperCol : assemblyVo?.type === "10" ? formFileWrapperCol.wrapperCol : form24Layout.wrapperCol}
labelCol={groupVo.code === "basic" ? formLayout.labelCol : form24Layout.labelCol}
extra={groupVo.code !== "medium" && assemblyVo?.remark}
hidden={assemblyVo?.ifShow === "0"}
initialValue={assemblyVo?.type === "3" || assemblyVo?.type === "31" ? (
isEmpty(assemblyVo?.value) ? [] : JSON.parse(assemblyVo?.value)
) : assemblyVo?.type === "4" || assemblyVo?.type === "5" ? (
assemblyVo?.value ? moment(assemblyVo?.value, "yyyy-MM-DD HH:mm:ss") : undefined
) : assemblyVo?.type === "9" ? (
assemblyVo?.value ? JSON.parse(assemblyVo?.value) : undefined
) : assemblyVo?.value
}
>
{(() => {
if (assemblyVo?.type === "0") { // 文本
return <Input style={{ width: "90%" }} bordered={false} readOnly />
} else if (assemblyVo?.type === "12") { // 文本域
return <TextAreaItem {...assemblyVo} disabled={editInformation} />
} else if (assemblyVo?.type === "1" || assemblyVo?.type === "11") { // 文本
return <InputItem {...assemblyVo} disabled={editInformation} />
} else if (assemblyVo?.type === "2" || assemblyVo?.type === "21") { // 2单选 21换行单选
return <RadioItem {...assemblyVo} disabled={editInformation} />
} else if (groupVo.code === "anno" || assemblyVo?.code === "sections") { // 关联标段
return <SectionCheckDom {...assemblyVo} />
} else if (assemblyVo?.type === "3") { // 3复选
return <CheckboxItem {...assemblyVo} disabled={editInformation} />
} else if (assemblyVo?.type === "31") { // 31换行复选
return <Medias
vis={true}
editInformation={editInformation}
mediaType={mediaType}
mediaData={JSON.parse(assemblyVo?.remark)}
mediaReleases={mediaReleases}
medias9={(dis: boolean) => medias9(dis)}
/>
} else if (assemblyVo?.type === "4" && assemblyVo?.code === "replyEndTime") { // 日期
return <DatePicker
showNow={false}
placeholder={assemblyVo?.ifRequired === 1 ? `请选择${assemblyVo?.name}` : undefined}
showTime={{ defaultValue: moment().startOf('minute') }}
disabled={editInformation}
format={"yyyy-MM-DD HH:mm"}
style={{ width: "90%" }}
onChange={(data: any) => ReplyEndTimechange1(data)}
/>
} else if (assemblyVo?.type === "4") { // 日期
return <DatePickerItem {...assemblyVo} disabled={editInformation} />
} else if (assemblyVo?.type === "5") { // 日期
return <DatePickerItem {...assemblyVo} disabled={editInformation} />
} else if (assemblyVo?.type === "7" && assemblyVo?.code === "openhallTitle") { // 选择框
return <Row>
<Col span={20}>
<Form.Item name={assemblyVo?.code}
// rules={[{ required: true, message: '当前项不可为空', },]}
>
<Input style={{ width: "90%" }} disabled={true} />
</Form.Item>
</Col>
<Col span={4}>
<Button type="primary" onClick={() => { getChooseRoomList() }} disabled={editInformation} style={{ marginLeft: "8px" }}></Button>
</Col>
</Row>
} else if (assemblyVo?.type === "8") { // 数字
return <InputNumberItem {...assemblyVo} disabled={editInformation} />
} else if (assemblyVo?.type === "9" && assemblyVo?.code === "sectionExpeses") { // 表格-标包情况
return <SectionExpesesTableItem {...assemblyVo} />
} else if (assemblyVo?.type === "9" && assemblyVo?.code === "tenderAsk") { // 表格-补充资格能力要求
return <TenderAskTableItem {...assemblyVo} />
} else if (assemblyVo?.type === "9" && assemblyVo?.code === "tenderAskProject") { // 表格-投标格式能力要求
return <TenderAskProjectTableItem {...assemblyVo} />
} else if (assemblyVo?.type === "9" && assemblyVo?.code === "expenses1Amount") { // 表格-招标文件费用
return <Expenses1AmountTableItem {...assemblyVo} />
} else if (assemblyVo?.type === "9" && assemblyVo?.code === "submitFileNumber") { // 表格-投递文件数量
return <SubmitFileNumberTableItem {...assemblyVo} />
} else if (assemblyVo?.type === "10") { // 附件
return UploadID != "empty" ?
<ExtendUpload uploadProps={UploadProps} maxCount={3} bid={UploadID} />
: null
} else if (assemblyVo?.type === "14") {
return <div style={{ border: '1px solid #c9d8db', padding: '16px', overflowX: 'auto', width: '90%' }} className='content-div'>
<div dangerouslySetInnerHTML={{ __html: assemblyVo?.value }}></div>
</div>
} else {
return <></>
}
})()}
</Form.Item>
);
}
const handleClick = (
e: React.MouseEvent<HTMLElement>,
link: {
title: React.ReactNode;
href: string;
},
) => {
e.preventDefault();
};
return (
<>
<div className={styles.header}>
<div className={styles.headerAlign} style={{ position: "relative", top: "2px", fontSize: "16px", fontWeight: "600" }}>
<img src={logo} style={{ height: "30px", marginRight: "10px", position: 'relative', top: '-2px' }} />
</div>
<ul className={styles.rightBtns}>
<li><CarryOutOutlined />{moment().format("YYYY-MM-DD")}</li>
{data?.organizationName == null ? null : (<li><UserSwitchOutlined />{data.organizationName}</li>)}
<li>
<Avatar size="small" src="https://gw.alipayobjects.com/zos/antfincdn/XAosXuNZyF/BiazfanxmamNRoxxVxka.png" style={{ width: '30px' }} />
<a className="antd-dropdown-link" style={{ color: "#fff", marginRight: "36px" }}>
{data.fullName}
</a>
</li>
</ul>
</div>
<div className="zjl-entrust confirm" style={{ height: window.innerHeight - 56, overflowY: 'auto', background: '#fff' }}>
<div style={{ display: 'flex', justifyContent: 'space-between', margin: '0 16px 16px' }}>
<Space>
<h3 className="first-title"></h3>
</Space>
<Affix offsetTop={70}>
<Space>
<Button key='save' type='primary' onClick={onSave} disabled={editInformation} loading={loading} hidden={btnAuthority(['ebtp-agency-project-manager', 'ebtp-purchase'])}></Button>
<Button key='back' type='default' onClick={() => { back() }}></Button>
</Space>
</Affix>
</div>
<div style={{ padding: '0px 24px' }} className="public-platform-header">
<div style={{ width: '15%', float: 'left' }}>
<div style={{ margin: '0px 16px', border: '1px solid rgb(179,0,0)', borderRadius: '8px', padding: '8px 0px', backgroundColor: 'white', width: '12%' }} className='anchor-father'>
{container && (
<>
<Anchor getContainer={() => container} style={{ overflow: 'hidden' }} onClick={handleClick}>
{annoStructureData?.groupVoList && annoStructureData?.groupVoList?.map((groupVo: any) => (
<Link href={"#" + groupVo?.code} title={groupVo?.name} />
))}
</Anchor>
</>
)}
</div>
<BackTop style={{ right: '100vh-40px' }}>
<div className='backtop'><ArrowUpOutlined /></div>
</BackTop>
</div>
<div style={{ width: '85%', float: 'right', border: '1px solid #f5f5f5' }}>
<div style={{ height: innerHeight - 100, overflowY: 'auto' }} className="public-platform" ref={setContainer}>
<Spin spinning={loading}>
<Collapse activeKey={activeKey} onChange={onCollapseChange}>
{
annoStructureData?.groupVoList && annoStructureData?.groupVoList?.map((groupVo: any) => (
<Panel header={groupVo?.name} key={groupVo?.id} id={groupVo?.code}>
<Form {...formLayout} form={form} >
<Row>
{
groupVo?.assemblyVoList && groupVo?.assemblyVoList?.map((assemblyVo: any) => {
const icondition = JSON.parse(assemblyVo?.icondition)
return <Col span={groupVo.code === "basic" ? 12 : 24} key={assemblyVo?.id}>
{assemblyVo?.icondition ?
<Form.Item
noStyle
shouldUpdate={(prevValues, currentValues) => prevValues[icondition?.key] !== currentValues[icondition?.key]}
>
{({ getFieldValue }) =>
(icondition?.type === "2" && getFieldValue(icondition?.key) === icondition?.value) ? //单选
(assemblyVo.type === "13") ?
(<ContactInformationFormItem assemblyVo={assemblyVo} />)
:
(<ShowComponent groupVo={groupVo} assemblyVo={assemblyVo} />
)
:
(icondition?.type === "3" && getFieldValue(icondition?.key)?.indexOf(icondition?.value) > -1) ? (//多选
<ShowComponent groupVo={groupVo} assemblyVo={assemblyVo} />
) : null
}
</Form.Item>
:
<ShowComponent groupVo={groupVo} assemblyVo={assemblyVo} />
}
</Col>
})
}
</Row>
</Form>
</Panel>
))
}
</Collapse></Spin>
</div>
</div>
</div>
{choiceHallType &&
<Modal
visible={choiceHallType}
destroyOnClose
title={`选择开标大厅`}
width={800}
bodyStyle={{ padding: '32px 40px 48px', overflowY: 'auto' }}
centered={true}
closable={false}
footer={(
<>
<Button onClick={() => setChoiceHallType(false)}></Button>
</>
)}
>
<p style={{ color: 'red', marginLeft: 12, fontSize: 16 }}>~</p>
<List
grid={{
gutter: 16,
xs: 3,
sm: 3,
md: 3,
lg: 3,
xl: 3,
xxl: 3,
}}
style={{ padding: 12 }}
dataSource={choiceHallData}
renderItem={(item: any) => (
<List.Item onClick={() => confirmChooseRoom(item)}>
<div className='card-onmouse' style={{ textAlign: 'center', position: 'relative', cursor: 'pointer', height: 113.42 }}>
<Image width='100%' src={Dating} preview={false} />
<div className='text-css'>
<div>{item.openDate}</div>
<div>{item.num}/{item.max}</div>
</div>
</div>
</List.Item>
)}
/>
</Modal>
}
</div>
</>
);
};
export default BiddingAnnoStructureForm;

View File

@ -0,0 +1,106 @@
import { getDefId } from "@/utils/session";
import { Checkbox, Col, Form, Row, Typography } from "antd";
import React, { useEffect, useState } from "react"
import { getMediaService } from "../service";
//公告发布媒体
interface MediaProps {
vis: boolean,
editInformation: boolean,
mediaType: boolean,
mediaData: any[],
mediaReleases: any,
medias9: (dis: any) => void,
label?: string,
}
const Media: React.FC<MediaProps> = (props) => {
const {
vis,
editInformation,
mediaType,
mediaData,
mediaReleases,
medias9,
label
} = props;
//============================================================state
const [medias, mediasSet] = useState<any>([]);
const { Text } = Typography
const defId = getDefId(); //流程id
//mediaReleases: [{mediaId: "9", status: 1}] 9-无需推送外网; 0没发 1发布成功 2发布失败
let mediaStatus = {};//媒体对应发布状态
mediaReleases?.length > 0 && mediaReleases.map((item: any) => {
let state = ''
item.status == '0' && (state = '暂未发送');
item.status == '1' && (state = '发布成功');
item.status == '2' && (state = '发布失败');
mediaStatus[item.mediaId] = state;
});
//============================================================func
useEffect(() => {
getMedias()
}, [vis]);
//取媒体数据
async function getMedias() {
if (vis) {
// let data: never[] = [];
// await getMediaService().then((res: any) => {
// if (res.code == 200) {
// data = res.data;
// }
// })
// mediasSet(data);
mediasSet(mediaData);
}
}
const changeMedia = (checkedParam: any) => {
medias9(checkedParam.indexOf("9") > -1);
}
//============================================================dom
return (
<>
<Form.Item
name="medias"
label={label ? label : ''}
rules={[
{
required: true,
message: '当前项不可为空',
},
]}
>
<Checkbox.Group
style={{ width: '90%' }}
onChange={changeMedia}
disabled={editInformation}
>
<Row>
{
medias?.length != 0 &&
medias.map((item: any) => {
return (
<Col span={24} key={item.id + 'Col'}>
<Checkbox disabled={item.id != '9' && mediaType} key={item.id} value={item.id}>
{item.webName}
<span style={{ color: 'red' }}>
{item?.remark}
</span>
<span style={{ color: mediaStatus[item.id] == '发布成功' ? 'rgb(7,193,96)' : 'red' }}>
{
mediaReleases?.length > 0 && mediaStatus[item.id] != undefined && item.id != '9' &&
`${mediaStatus[item.id]}`
}
</span>
</Checkbox>
</Col>
)
})
}
</Row>
</Checkbox.Group>
</Form.Item>
{/* {defId != "recruit_multi" && <Text type="secondary">如选择发布到【中国招标投标公共服务平台】,在发布前需填写【公共服务平台】信息</Text>} */}
</>
)
}
export default Media

View File

@ -0,0 +1,177 @@
import React from "react"
import { Checkbox, Col, DatePicker, Input, InputNumber, Radio, Row } from "antd"
import moment from "moment"
import TextArea from "antd/lib/input/TextArea";
/**
* Input 文本
* @param field
* @returns
*/
export const InputItem = (field: any) => {
const { onChange, value } = field;
return (
<Input
style={{ width: "90%" }}
placeholder={field?.requiredFlag === 1 ? `请填写${field?.fieldName}` : undefined}
onChange={onChange}
disabled={field?.disabled}
value={value}
/>
)
}
/**
* TextArea 文本
* @param field
* @returns
*/
export const TextAreaItem = (field: any) => {
const { onChange, value } = field;
return (
<TextArea
autoSize={{ minRows: 3 }}
style={{ width: "90%" }}
bordered={field?.ifEditable === "0" ? false : true}
placeholder={field?.requiredFlag === 1 ? `请填写${field?.fieldName}` : undefined}
onChange={onChange}
disabled={field?.disabled}
value={value}
/>
)
}
/**
* DatePicker 日期
* @param field
* @returns
*/
export const DatePickerItem = (field: any) => {
const { onChange, value } = field;
return (
<DatePicker
showNow={false}
placeholder={field?.ifRequired === 1 ? `请选择${field?.name}` : undefined}
showTime={{ defaultValue: moment().startOf('minute') }}
disabled={field?.disabled}
disabledDate={(current) => current && current < moment().startOf('day')}
format={field?.type === "5" ? "yyyy-MM-DD" : "yyyy-MM-DD HH:mm"}
style={{ width: "90%" }}
onChange={onChange}
value={value}
/>
)
}
/**
* Radio 单选
* @param field
* @returns
*/
export const RadioItem = (field: any) => {
const { onChange, value } = field;
return (
<Radio.Group
style={{ width: "90%" }}
onChange={onChange}
value={value}
disabled={field?.disabled}
>
{
field?.type === "2" ? ( // 选项在一行
field?.extend2 && JSON.parse(field?.extend2)?.map((item: any) => (
<Radio
value={Object.keys(item)[0]}
key={Object.keys(item)[0]}
>
{Object.values(item)[0]}
</Radio>
))
) : (
<Row>
{
field?.extend2 && JSON.parse(field?.extend2)?.map((item: any) => (
<Col span={24} key={item?.id}>
<Radio
value={Object.keys(item)[0]}
key={Object.keys(item)[0]}
>
{Object.values(item)[0]}
</Radio>
</Col>
))
}
</Row>
)
}
</Radio.Group>
)
}
/**
* Checkbox 多选
* @param field
* @returns
*/
export const CheckboxItem = (field: any) => {
const { onChange, value } = field;
return (
<Checkbox.Group
style={{ width: "90%" }}
onChange={onChange}
value={value}
disabled={field?.disabled}
>
{
field?.type === "3" ? ( // 选项在一行
field?.extend2 && JSON.parse(field?.extend2)?.map((item: any) => {
return <Checkbox
value={Object.keys(item)[0]}
key={Object.keys(item)[0]}
disabled={((field?.code === "expesesAccess" || field?.code === "docSubmitMethod") && Object.keys(item)[0] === "1")}
>
{Object.values(item)[0]}
</Checkbox>
})
) : (
<Row>
{field?.extend2 && JSON.parse(field?.extend2)?.map((item: any) => {
return <>
{!field?.name && <Col span={4}></Col>}
<Col span={20} key={Object.keys(item)[0]}>
<Checkbox
value={Object.keys(item)[0]}
key={Object.keys(item)[0]}
>
{Object.values(item)[0]}
</Checkbox>
</Col>
</>
})}
</Row>
)
}
</Checkbox.Group>
)
}
/**
* InputNumber 数字
* @param field
* @returns
*/
export const InputNumberItem = (field: any) => {
const { onChange, value } = field;
return (
<InputNumber
min={0}
max={9999}
onChange={onChange}
disabled={field?.disabled}
readOnly={field?.ifEditable === "0"}
bordered={field?.ifEditable === "0" ? false : true}
value={value}
/>
)
}

View File

@ -0,0 +1,42 @@
.header {
background-color: #b30000;
color: white;
font-size: 20px;
height: 56px;
display: flex;
.headerAlign {
align-self: center;
margin-left: 20px;
font-weight: 400;
}
.rightBtns {
position: absolute;
right: 0;
li {
float: left;
line-height: 56px;
font-size: 14px;
color: #fff;
padding: 0 14px;
font-weight: 400 !important;
list-style: none;
span {
padding-right: 6px;
font-size: 16px;
}
a {
color: #fff;
}
}
}
}
.topic-manager-tabs .ant-tabs-nav {
background: #fff;
margin: 0 0 0 24px
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -16,7 +16,7 @@ export async function getSecs(params?: any) {
}
//删除
export async function delOne(params?: any) {
return request(`/api/biz-service-ebtp-rsms/v1/jury/info/${params.id}`, {
return request(`/api/biz-service-ebtp-rsms/v1/jury/info/del/${params.id}`, {
method: 'POST'
});
}
@ -122,4 +122,9 @@ export async function saveAssistPeople(data: any) {
method: 'POST',
data
});
};
};
export async function getCrotchListUsingGET() {
return request("/api/biz-service-ebtp-rsms/v1/specialitydict/getCrotchList", {
method: 'GET',
});
};