Commit e5a855d9 authored by 前端-钟卫鹏's avatar 前端-钟卫鹏

feat: 添加投标查询

parent 91523d3b
......@@ -47,8 +47,8 @@ const routeList = [
// commentRoutes,
// contentRoute,
// balancedRoute,
demandRoute,
procurementRoute,
// demandRoute,
// procurementRoute,
// demandQuoteOrderRoute,
// capitalAccount,
// messageRoute,
......
......@@ -42,7 +42,22 @@ const router = {
hideInMenu: true,
noMargin: true,
},
{
// 投标查询
path: '/procurement/tenderSearch',
name: '投标查询',
hidePageHeader: true,
component: '@/pages/procurement/tenderSearch',
},
{
// 投标 详情
path: '/procurement/tenderSearch/detail',
name: '投标详情',
component: '@/pages/procurement/tenderSearch/detail',
hidePageHeader: true,
hideInMenu: true,
noMargin: true,
},
]
}
......
import React, { useRef } from 'react'
import React from 'react'
import { useCallback, useState, useEffect } from 'react'
import { usePageStatus } from '@/hooks/usePageStatus'
import { PublicApi } from '@/services/api'
import { Link } from 'umi'
import { GlobalConfig } from '@/global/config'
import { formatTimeString } from '@/utils'
import { message } from 'antd'
import { history } from 'umi'
interface OrderDetailHookProps {
/** 招标,投标 */
type: 'callForBid' | 'tender'
/** 招标-招标详情,投标-投标详情,招标-投标详情,投标-招标详情 */
type: 'callForBid' | 'tender' | 'callForBidInTender' | 'tenderInCallForBid'
}
// 招标详情, 支持(招标、投标)两种模式
// 招标详情, 支持(招标-招标、投标-投标、招标-投标、投标-招标)两种模式
export const useBidDetail = (options: OrderDetailHookProps) => {
// 详情数据
const [formData, setFormData] = useState<any>(null)
// 流转记录数据(内/外)
const [interiorProcurementOrderLogResponses, setInteriorProcurementOrderLogResponses] = useState<any>(null)
const [externalProcurementOrderLogResponses, setExternalProcurementOrderLogResponses] = useState<any>(null)
// 流程状态数据(内/外)
const [interiorWorkflowFlowRecordLogResponses, setInteriorWorkflowFlowRecordLogResponses] = useState<any>(null)
const [externalWorkflowFlowRecordLogResponses, setExternalWorkflowFlowRecordLogResponses] = useState<any>(null)
// 地址
const [address, setAddress] = useState<string>(null)
const [address, setAddress] = useState<string>('')
// 内容元素距顶部距离数组
const [offsetTopList, setOffsetTopList] = useState<number[]>([])
......@@ -34,49 +33,100 @@ export const useBidDetail = (options: OrderDetailHookProps) => {
reloadFormData()
}, [])
const reloadFormData = useCallback(() => {
const switchApi = (type) => {
let _api: any = null;
switch (type) {
case 'callForBid':
_api = PublicApi.getPurchaseInviteTenderPlatformGetInviteTender;
break;
case 'tender':
_api = PublicApi.getPurchaseInviteTenderPlatformGetSubmitTender;
break;
// case 'callForBidInTender':
// _api = PublicApi.getPurchaseInviteTenderGetSubmitTender;
// break;
// case 'tenderInCallForBid':
// _api = PublicApi.getPurchaseSubmitTenderGetInviteTender;
// break;
default:
_api = null;
}
return _api
}
// const switchParamField = (type) => {
// let field: any = null;
// switch (type) {
// case 'callForBid':
// field = 'inviteTenderId'
// break;
// case 'tender':
// field = 'submitTenderId'
// break;
// // case 'callForBidInTender':
// // field = 'submitTenderId'
// // break;
// // case 'tenderInCallForBid':
// // field = 'inviteTenderId'
// // break;
// default:
// field = null;
// }
// return field
// }
const reloadFormData = useCallback(async () => {
if (id) {
// 详情
// @todo 需补充投标详情api
const fn = type === 'callForBid' ? PublicApi.getPurchaseInviteTenderGetInviteTender : PublicApi.getPurchaseSubmitTenderGetInviteTender
fn({ id }, { ctlType: "none" }).then(res => {
const { code, data, message: msg } = res
if (code === 1000) {
setFormData(data)
if(data?.deliverAddress) {
PublicApi.getLogisticsReceiverAddressGet({id: data.deliverAddress}).then(_res => {
const { data: _data } = _res
const { provinceName, cityName, districtName, address } = _data
if(res.code === 1000) {
setAddress(`${provinceName}/${cityName}/${districtName}/${address}`)
}
})
}
} else {
message.error(msg)
const fn = switchApi(type);
let params: any = {};
// params[switchParamField(type)] = id
params['id'] = id
const { code, data, message: msg } = await fn(params, { ctlType: "none" })
if (code === 1000) {
setFormData(data)
if(data?.deliverAddress) {
PublicApi.getLogisticsReceiverAddressGet({id: data.deliverAddress}).then(_res => {
const { data: _data } = _res
const { provinceName, cityName, districtName, address } = _data
if(code === 1000) {
setAddress(`${provinceName}/${cityName}/${districtName}/${address}`)
}
})
}
})
} else {
message.error(msg)
}
// 有投标模式的情况下提取招标id
const searchId = type.indexOf('ender') !== -1 ? data.inviteTender.id : id
// 流转记录(内/外)
// @todo 需补充投标记录api
const inCheckRecordFn = PublicApi.getPurchaseInviteTenderInCheckRecordGetInviteTenderInCheckRecord
inCheckRecordFn({ inviteTenderId: id }, { ctlType: "none" }).then(res => {
const { code, data, message: msg } = res
if (code === 1000) {
setInteriorProcurementOrderLogResponses(data)
} else {
message.error(msg)
}
})
// 招投标
const inCheckRecordFn = !type.indexOf('c')
?
PublicApi.getPurchaseInviteTenderInCheckRecordGetInviteTenderInCheckRecord
:
PublicApi.getPurchaseSubmitTenderInCheckRecordGetSubmitTenderInCheckRecord
const inReocrdRes = await inCheckRecordFn({ inviteTenderId: searchId })
if (inReocrdRes.code === 1000) {
setInteriorProcurementOrderLogResponses(inReocrdRes.data)
}
const outCheckRecordFn = PublicApi.getPurchaseTenderOutCheckRecordGetTenderOutCheckRecord
outCheckRecordFn({ inviteTenderId: id }, { ctlType: "none" }).then(res => {
const { code, data, message: msg } = res
if (code === 1000) {
setExternalProcurementOrderLogResponses(data)
} else {
message.error(msg)
}
})
const outRecordRes = await outCheckRecordFn({ inviteTenderId: searchId })
if (outRecordRes.code === 1000) {
setExternalProcurementOrderLogResponses(outRecordRes.data)
}
// 流程状态(内/外)
// 招投标
const processRes = await PublicApi.getPurchaseInviteTenderGetInviteTenderProcess({ inviteTenderId: searchId })
if(processRes.code === 1000 && processRes.data) {
setInteriorWorkflowFlowRecordLogResponses(processRes.data.subProcess.userTaskList)
setExternalWorkflowFlowRecordLogResponses(processRes.data.userTaskList)
}
}
}, [id])
......@@ -85,13 +135,16 @@ export const useBidDetail = (options: OrderDetailHookProps) => {
data: formData,
interiorProcurementOrderLogResponses,
externalProcurementOrderLogResponses,
interiorWorkflowFlowRecordLogResponses,
externalWorkflowFlowRecordLogResponses,
address,
offsetTopList,
ctl: {
setData: setFormData,
setOffsetTopList,
},
reloadFormData
reloadFormData,
apiType: type,
}
return {
......
......@@ -24,7 +24,6 @@ const callForBidsSearch: React.FC<{}> = () => {
return (
<PageHeaderWrapper>
<Card>
<StandardTable
fetchTableData={params => fetchTableData(params)}
......@@ -54,7 +53,6 @@ const callForBidsSearch: React.FC<{}> = () => {
}}
/>
</Card>
</PageHeaderWrapper>
)
}
......
......@@ -132,4 +132,4 @@ const BidDetailHeader: React.FC<BidDetailHeaderProps> = ({
BidDetailHeader.defaultProps = {}
export default BidDetailHeader
export default BidDetailHeader
\ No newline at end of file
......@@ -24,6 +24,13 @@ const mapColor = [
"rgb(101, 84, 192)", // 紫
"rgb(230, 63, 59)", // 红
"rgb(0, 179, 122)", // 绿
"rgb(96, 98, 102)", // 灰
"rgb(255, 153, 31)", // 黄
"rgb(63, 126, 210)", // 蓝
"rgb(101, 84, 192)", // 紫
"rgb(230, 63, 59)", // 红
"rgb(0, 179, 122)", // 绿
]
// 订单内部状态显示
......
......@@ -53,8 +53,7 @@ const FirstCheckedBid:React.FC<FirstCheckedBidProps> = (props) => {
message.error('只能批量提交外部状态为待平台审核招标的招标')
}
}
return <PageHeaderWrapper>
<Card>
return <Card>
<StandardTable
fetchTableData={params => fetchTableData(params)}
rowSelection={rowSelection}
......@@ -96,7 +95,6 @@ const FirstCheckedBid:React.FC<FirstCheckedBidProps> = (props) => {
}}
/>
</Card>
</PageHeaderWrapper>
}
FirstCheckedBid.defaultProps = {}
......
.anchorGap {
div {
&:target {
padding-top: 190px;
margin-top: -190px;
}
}
}
import React, { useState, useCallback, useRef } from 'react';
import { Button } from 'antd';
import PreLoading from '@/components/PreLoading';
import { BidDetailContext } from '@/pages/procurement/_public/bid/context';
import { useBidDetail } from '@/pages/procurement/_public/bid/effects/useBidDetail';
import BidDetailHeader from '@/pages/procurement/components/bidDetailHeader';
import BidDetailSection from '@/pages/procurement/components/bidDetailSection';
import OrderDetailWrapper from '@/pages/orderSystem/components/OrderDetailWrapper';
const TenderSearchDetail: React.FC = () => {
const { formContext, id } = useBidDetail({type: 'tender'})
const {data} = formContext
const anchorTitleList = [
{ title: '流转进度', id: 'transferProcess', componentName: "TransferProcess" },
{ title: '中标结果', id: 'bidResult', type: "bidResult" },
{ title: '中标明细', id: 'bidParticulars', componentName: "BidParticulars" },
{ title: '基本信息', id: 'baseicInfo', type: "basicInfo" },
{ title: '投标要求', id: 'tenderNeed', type: "bidNeed" },
{ title: '投标其他要求', id: 'tenderOtherNeed', type: "bidNeed" },
{ title: '投标商品', id: 'tenderParticulars', componentName: "BidParticulars" },
{ title: '流转记录', id: 'transferRecord', componentName: "BidTransformRecord" },
]
return (
<div>
<BidDetailContext.Provider value={formContext}>
<BidDetailHeader
formContext={formContext}
anchorList={anchorTitleList}
/>
<OrderDetailWrapper>
<PreLoading loading={!formContext.data} active paragraph={{rows: 6}}>
<BidDetailSection formContext={formContext} anchorList={anchorTitleList} type="tender" />
</PreLoading>
</OrderDetailWrapper>
</BidDetailContext.Provider>
</div>
);
};
export default TenderSearchDetail;
import React from 'react'
import { Card} from 'antd'
import { StandardTable } from 'god'
import { useStateFilterSearchLinkageEffect } from '@/formSchema/effects/useFilterSearch'
import { FORM_FILTER_PATH } from '@/formSchema/const'
import { useSelfTable } from './model/useSelfTable'
import { tableListSchema } from './schema'
import Submit from '@/components/NiceForm/components/Submit'
import DateRangePickerUnix from '@/components/NiceForm/components/DateRangePickerUnix'
import { PublicApi } from '@/services/api'
import { BidOuterWorkState } from '@/constants'
const TenderSearch: React.FC<{}> = () => {
const {
ref,
columns
} = useSelfTable()
const fetchTableData = async (params) => {
const { data } = await PublicApi.postPurchaseInviteTenderPlatformGetSubmitTenderList(params, { ctlType: "none" })
return data
}
return (
<Card>
<StandardTable
fetchTableData={params => fetchTableData(params)}
currentRef={ref}
columns={columns}
rowKey={'id'}
formilyLayouts={{
justify: 'space-between'
}}
formilyProps={{
ctx: {
inline: false,
schema: tableListSchema,
effects: ($, actions) => {
useStateFilterSearchLinkageEffect(
$,
actions,
'code',
FORM_FILTER_PATH,
);
},
components: {
DateRangePickerUnix,
Submit
}
}
}}
/>
</Card>
)
}
export default TenderSearch
import React, { useRef } from 'react'
import EyePreview from '@/components/EyePreview'
import { formatTimeString } from '@/utils'
import CustomTag from '@/pages/procurement/components/CustomTag'
// 投标查询
export const useSelfTable = () => {
const ref = useRef<any>({})
const callForBidColumns: any[] = [
{
title: '序号',
align: 'center',
dataIndex: 'id',
key: 'id',
render: (text, record, index) => index + 1
},
{
title: '招标编号/项目',
align: 'center',
dataIndex: 'memberId',
key: 'memberId',
render: (text, record) => <>
<EyePreview url={`/procurement/callForBidsSearch/detail?id=${record.inviteTender.id}`}>
{record.inviteTender.code}
</EyePreview>
<div>{record.inviteTender.projectName}</div>
</>
},
{
title: '投标编号/会员',
align: 'center',
dataIndex: 'code',
key: 'code',
render: (text, record) => <>
{text ? <EyePreview url={`/procurement/tenderSearch/detail?id=${record.id}`}>
{text}
</EyePreview> : null}
<div>{record.memberName}</div>
</>
},
{
title: '投标时间',
align: 'center',
dataIndex: 'inviteTender',
key: 'inviteTender',
render: (text, record) => formatTimeString(record.inviteTender.inviteTenderStartTime),
width: 200
},
{
title: '开标时间',
align: 'center',
dataIndex: 'inviteTender',
key: 'inviteTender',
render: (text, record) => formatTimeString(record.inviteTender.openTenderTime),
width: 200
},
{
title: '是否中标',
align: 'center',
dataIndex: 'isWin',
key: 'isWin',
render: (text) => text ? '是' : '否'
},
{
title: '外部状态',
align: 'center',
dataIndex: 'inviteTender',
key: 'inviteTender',
render: (text, record) => <CustomTag status={record.inviteTender.tenderOutStatus} type='out' />
},
// {
// title: '内部状态',
// align: 'center',
// dataIndex: 'interiorState',
// key: 'interiorState',
// render: (text) => <CustomBadge status={text} type='inside' />
// },
]
return {
ref,
columns: callForBidColumns
}
}
import { ISchema } from '@formily/antd';
import { FORM_FILTER_PATH } from '@/formSchema/const';
import { BidOutStateTexts } from '@/constants';
/**
* 招标查询列表高级筛选
*/
export const tableListSchema: ISchema = {
type: 'object',
properties: {
code: {
type: 'string',
"x-component": 'SearchFilter',
'x-component-props': {
placeholder: '请输入招标编号',
align: 'flex-start',
},
},
[FORM_FILTER_PATH]: {
type: 'object',
'x-component': 'flex-layout',
'x-component-props': {
inline: true,
rowStyle: {
justifyContent: 'start',
},
colStyle: {
marginRight: 20
}
},
properties: {
projectName: {
type: 'string',
'x-component-props': {
placeholder: '请输入投标项目',
}
},
tenderCode: {
type: 'string',
'x-component-props': {
placeholder: '请输入投标编号',
}
},
openTenderTime: {
type: 'string',
"x-component": 'data',
'x-component-props': {
placeholder: '开标开始时间',
showTime: true,
},
},
memberName: {
type: 'string',
'x-component-props': {
placeholder: '请输入投标会员',
}
},
tenderOutStatusList: {
type: 'string',
"x-component-props": {
placeholder: '请选择外部状态'
},
enum: Object.keys(BidOutStateTexts).map(item => ({
label: BidOutStateTexts[item],
value: item,
}))
},
// "interiorState": {
// type: 'string',
// "x-component-props": {
// placeholder: '请选择内部状态'
// },
// enum: Object.keys(PurchaseOrderInsideWorkStateTexts).map(item => ({
// label: PurchaseOrderInsideWorkStateTexts[item],
// value: item,
// }))
// },
submit: {
'x-component': 'Submit',
'x-component-props': {
children: '查询',
},
},
},
},
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment