Commit b33a1f06 authored by 卢均锐's avatar 卢均锐

feat:采购竞价相关页面 90%

parent 9c82004f
......@@ -67,6 +67,14 @@ export const purchaseBidRoute = [
name: '待竞价',
component: '@/pages/transaction/purchaseAbility/purchaseBid/readyBid'
},
// 竞价管理
{
path: '/memberCenter/procurementAbility/purchaseBid/readyBid/management',
name: '竞价管理',
component: '@/pages/transaction/purchaseAbility/purchaseBid/readyBid/management',
hideInMenu: true,
noMargin: true,
},
// 待提交审核竞价结果
{
path: '/memberCenter/procurementAbility/purchaseBid/readySubmitExamineResult',
......
<?xml version="1.0" encoding="UTF-8"?>
<svg width="14px" height="13px" viewBox="0 0 14 13" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>message-square</title>
<defs>
<path d="M8,6 C8.368,6 8.66666667,6.29866667 8.66666667,6.66666667 C8.66666667,7.03466667 8.368,7.33333333 8,7.33333333 C7.632,7.33333333 7.33333333,7.03466667 7.33333333,6.66666667 C7.33333333,6.29866667 7.632,6 8,6 Z M10.6666667,6 C11.0346667,6 11.3333333,6.29866667 11.3333333,6.66666667 C11.3333333,7.03466667 11.0346667,7.33333333 10.6666667,7.33333333 C10.2986667,7.33333333 10,7.03466667 10,6.66666667 C10,6.29866667 10.2986667,6 10.6666667,6 Z M5.33333333,6 C5.70133333,6 6,6.29866667 6,6.66666667 C6,7.03466667 5.70133333,7.33333333 5.33333333,7.33333333 C4.96533333,7.33333333 4.66666667,7.03466667 4.66666667,6.66666667 C4.66666667,6.29866667 4.96533333,6 5.33333333,6 Z M13.3333333,10 C13.3333333,10.3673333 13.034,10.6666667 12.6666667,10.6666667 L5.70266667,10.6666667 C5.34066667,10.6666667 4.98466667,10.7653333 4.67333333,10.952 L2.66666667,12.156 L2.66666667,3.33333333 C2.66666667,2.966 2.966,2.66666667 3.33333333,2.66666667 L12.6666667,2.66666667 C13.034,2.66666667 13.3333333,2.966 13.3333333,3.33333333 L13.3333333,10 Z M12.6666667,1.33333333 L3.33333333,1.33333333 C2.23066667,1.33333333 1.33333333,2.23066667 1.33333333,3.33333333 L1.33333333,13.3333333 C1.33333333,13.5733333 1.46266667,13.7953333 1.67133333,13.9133333 C1.77333333,13.9713333 1.88666667,14 2,14 C2.11866667,14 2.23733333,13.9686667 2.34333333,13.9046667 L5.35933333,12.0953333 C5.46333333,12.0326667 5.582,12 5.70266667,12 L12.6666667,12 C13.7693333,12 14.6666667,11.1026667 14.6666667,10 L14.6666667,3.33333333 C14.6666667,2.23066667 13.7693333,1.33333333 12.6666667,1.33333333 L12.6666667,1.33333333 Z" id="path-1"></path>
</defs>
<g id="控件" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="聊天" transform="translate(-5.000000, -6.000000)">
<g id="message-square" transform="translate(4.000000, 5.000000)">
<mask id="mask-2" fill="white">
<use xlink:href="#path-1"></use>
</mask>
<use id="🎨-Icon-Сolor" fill="#00B37A" xlink:href="#path-1"></use>
</g>
</g>
</g>
</svg>
\ No newline at end of file
......@@ -19,11 +19,12 @@ export interface BidCommonLayoutProps {
layoutId: string,
title: string,
layoutType?: string,
extra?: React.ReactNode
extra?: React.ReactNode,
checkDetailFunc?: Function
}
const BidCommonLayout: React.FC<BidCommonLayoutProps> = (props: any) => {
const { layoutId, title, effect, layoutType, extra } = props;
const { layoutId, title, effect, layoutType, extra, checkDetailFunc } = props;
const _returnChild = (child, key) => {
if (child.type === 'text') {
return (
......@@ -61,7 +62,7 @@ const BidCommonLayout: React.FC<BidCommonLayoutProps> = (props: any) => {
<Row gutter={[8, 8]}>
{effect.map((item, index) => (
<Col span={5} key={`effect_result_${index}`}>
<ResultItem itemIndex={index} />
<ResultItem itemIndex={index} checkDetailFunc={checkDetailFunc} />
</Col>
))}
</Row>
......
......@@ -20,15 +20,16 @@
}
.badge {
width: 16px;
height: 16px;
width: 24px;
height: 24px;
background: #EBECF0;
border-radius: 8px;
border-radius: 12px;
text-align: center;
line-height: 16px;
line-height: 24px;
color: #909399;
font-size: 12px;
margin-right: 4px;
margin-left: 4px;
display: inline-block;
}
.title {
......@@ -40,6 +41,9 @@
white-space: nowrap;
word-break: break-all;
}
.label{
width: 40%;
}
}
}
......@@ -5,28 +5,24 @@ import styles from './index.less';
export interface ResultItemPrpos {
itemIndex: number,
detail?: any
detail?: any,
checkDetailFunc? : Function
}
const ResultItem: React.FC<ResultItemPrpos> = (props: any) => {
const { itemIndex, detial } = props;
const { itemIndex, detial, checkDetailFunc } = props;
return (
<div key={`msgItem_key_${itemIndex}`} className={styles.resultItem}>
<div className={styles.resultItemRow}>
<div className={styles.title}>广州白马皮具交易中心</div>
<div className={styles.badge}>1</div>
<div className={styles.title}>广州白马皮具交易中心<div className={styles.badge}>1</div></div>
</div>
<div className={styles.resultItemRow}>
<div className={styles.money}>¥900.00<span>(含税)</span></div>
<Button
type='link'
>
查看报价明细
</Button>
<Button type='link' onClick={checkDetailFunc}>查看报价明细</Button>
</div>
<Divider dashed style={{color: '#EBECF0',margin: '6px 0' }} />
<div className={styles.resultItemRow}>联系人姓名:<div className={styles.title}>小王</div></div>
<div className={styles.resultItemRow}>联系人手机:<div className={styles.title}>185 2929 6758</div></div>
<Divider dashed style={{ color: '#EBECF0', margin: '6px 0' }} />
<div className={styles.resultItemRow}><div className={styles.label}>联系人姓名:</div><div className={styles.title}>小王</div></div>
<div className={styles.resultItemRow}><div className={styles.label}>联系人手机:</div><div className={styles.title}>185 2929 6758</div></div>
</div>
)
}
......
.btnItem {
border: 1px solid #F4F5F7;
padding: 16px 12px;
font-size: 12px;
cursor: pointer;
.btnItemTitle {
display: flex;
flex-direction: row;
color: #909399;
margin-bottom: 16px;
div {
flex: 1;
color: #303133;
}
}
.btnItemPrice {
color: #303133;
display: flex;
flex-direction: row;
div {
flex: 1;
font-size: 16px;
span {
color: #909399;
}
}
}
}
import React, { useContext, useEffect, useState } from 'react';
import style from './index.less';
interface BtnItemProps {
btnType?: number,
active?: boolean
}
const BtnItem: React.FC<BtnItemProps> = (props: any) => {
const { btnType, active } = props;
const _returnBtn = () => {
if (btnType === 1) {
return (
<div className={style.btnItem} style={{borderColor: active ? '#00B37A' : '#F4F5F7'}}>
<div className={style.btnItemTitle}>
<div>广州白马皮具交易中心</div>
第2次</div>
<div className={style.btnItemPrice}>
<div>
¥900.00
<span>(含税)</span>
</div>
10:43:56
</div>
</div>
)
}
}
return (
_returnBtn()
)
}
BtnItem.defaultProps = {
btnType: 1
}
export default BtnItem;
\ No newline at end of file
import React, { useContext, useEffect, useState } from 'react';
import { Row, Col, Table, Button } from 'antd';
import Card from '../../../card';
import BtnItem from './btnItem';
const BidDetailLayout = () => {
const columns = [
{ title: '物料编号/名称', dataIndex: 'materielNo', align: 'center', },
{ title: '规格型号', dataIndex: 'type', align: 'center', },
{ title: '品类', dataIndex: 'category', align: 'center', },
{ title: '品牌', dataIndex: 'brand', align: 'center', },
{ title: '采购数量/单位', dataIndex: 'unit', align: 'center', },
{ title: '含税/税率', dataIndex: 'isHasTaxName', align: 'center', },
{ title: '单价(含税)', dataIndex: 'price', align: 'center', },
{ title: '金额(含税)', dataIndex: 'price', align: 'center', },
]
const dataSource = [
{
key: '1',
materielNo: 'Q89YTE1',
},
]
return (
<div style={{ width: '100%' }}>
<Card
id={'BidDetailLayout'}
title={'竞价详情'}
>
<Row gutter={[8, 8]}>
<Col span={7}>
<BtnItem />
</Col>
</Row>
{/* <Table dataSource={dataSource} columns={columns} />; */}
<Button type="link" block>显示更多</Button>
</Card>
</div>
)
}
export default BidDetailLayout
\ No newline at end of file
.iMBtn{
width: 24px;
height: 24px;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
border-radius: 12px;
background-color: #E4F7EF;
img{
width: 16px;
}
}
\ No newline at end of file
import React, { useEffect, useState } from 'react';
import Icon from '@ant-design/icons';
import ImIcon from '@/assets/icons/message_square.svg';
import styles from './index.less';
interface IMBtnProps {
func: Function,
btnStyle?: React.CSSProperties
}
const IMBtn: React.FC<IMBtnProps> = (props: any) => {
const { func, btnStyle } = props;
return (
<div className={styles.iMBtn} style={btnStyle} onClick={func}>
<img src={ImIcon} alt="" />
</div>
)
}
IMBtn.defaultProps = {
btnStyle: {
marginLeft: '6px'
}
}
export default IMBtn
\ No newline at end of file
import React, { useState, useEffect } from 'react';
import { Chart, Tooltip, Axis } from 'bizcharts';
import Point from 'bizcharts/lib/geometry/Point';
import Line from 'bizcharts/lib/geometry/Line';
import Card from '../../../card';
interface QuotationDeskProps {
title?: string,
extra?: React.ReactNode
}
const data = [
{
year: "1991",
value: 3,
},
{
year: "1992",
value: 4,
},
{
year: "1993",
value: 3.5,
},
{
year: "1994",
value: 5,
},
{
year: "1995",
value: 4.9,
},
{
year: "1996",
value: 6,
},
{
year: "1997",
value: 7,
},
{
year: "1998",
value: 9,
},
{
year: "1999",
value: 13,
},
];
const QuotationDesk: React.FC<QuotationDeskProps> = (props: any) => {
const { title, extra } = props;
// const [data] = useState({
// year: "1991",
// value: 3,
// })
return (
<Card
id={'QuotationDesk'}
title={title}
extra={extra}
>
<Chart
appendPadding={[10, 0, 0, 10]}
autoFit
height={375}
data={data}
scale={{ value: { min: 0, alias: '', type: 'linear-strict' }, year: { range: [0, 1] } }}
>
<Axis
title={{text: '金额(元)'}}
// visible={false}
name='value'
// line={{ style: { stroke: "#ff0000" } }}
tickLine={{ style: { lineWidth: 1 }, length: 5 }}
/>
<Line position="year*value" />
<Point position="year*value" />
<Tooltip showCrosshairs />
</Chart>
</Card>
)
}
QuotationDesk.defaultProps = {
title: '报价台'
}
export default QuotationDesk;
\ No newline at end of file
.wrap{
:global{
.ant-modal-body {
padding-top: 0;
padding-left: 0;
padding-bottom: 0;
.ant-tabs-ink-bar{
left: 0;
}
.ant-tabs-content{
min-height: 300px;
}
}
}
}
import React, { useEffect } from 'react';
import { Modal, Tabs, Form, Checkbox, Input } from 'antd';
const { TabPane } = Tabs;
const { TextArea } = Input;
import styles from './index.less';
const ConfirmBidResultModal = (props: any) => {
const [form] = Form.useForm();
const { title, visible, onCancel } = props;
return (
<Modal
width={600}
title={title}
visible={visible}
onCancel={onCancel}
wrapClassName={styles.wrap}
// onOk={() => actions.submit()}
// afterClose={() => actions.reset()}
>
<Form
form={form}
>
<Tabs tabPosition='left'>
<TabPane tab="中标公示" key="1">
<Form.Item name="offer">
<Checkbox>发送中标公示</Checkbox>
</Form.Item>
<Form.Item name="offer">
<TextArea rows={3} maxLength={100} placeholder="最长100个字符,50个汉字" />
</Form.Item>
</TabPane>
<TabPane tab="中标通知" key="2">
<Form.Item name="offer">
<Checkbox>发送中标通知</Checkbox>
</Form.Item>
<Form.Item name="offer">
<TextArea rows={3} maxLength={100} placeholder="最长100个字符,50个汉字" />
</Form.Item>
</TabPane>
<TabPane tab="感谢函" key="3">
<Form.Item name="offer">
<Checkbox>发送感谢函</Checkbox>
</Form.Item>
<Form.Item name="offer">
<TextArea rows={3} maxLength={100} placeholder="最长100个字符,50个汉字" />
</Form.Item>
</TabPane>
</Tabs>
</Form>
</Modal>
)
}
export default ConfirmBidResultModal
\ No newline at end of file
import React, { useRef, useImperativeHandle } from 'react';
import { StandardTable } from 'god';
import { ColumnType } from 'antd/lib/table/interface';
import NiceForm from '@/components/NiceForm';
import { createFormActions, FormEffectHooks } from '@formily/antd';
import { FORM_FILTER_PATH } from '@/formSchema/const';
import { useStateFilterSearchLinkageEffect } from '@/formSchema/effects/useFilterSearch';
import { searchSelectGetSelectCategoryOptionEffect } from '@/pages/transaction/effect/index';
import { PublicApi } from '@/services/api';
import { Row, Col, Space, Button, Typography, Popconfirm, Badge, Tag, Menu, Drawer } from 'antd';
const { Text } = Typography;
const formActions = createFormActions();
const QuotationDetailsDrawer = (props: any) => {
const { visible, onClose, schemaType, effects, reload } = props;
const tableRef = useRef<any>({});
const columns: ColumnType<any>[] = [{
title: '序号',
align: 'center',
dataIndex: 'id',
key: 'id',
render: (t, r, i) => ++i
}, {
title: '物料编号/摘要',
key: 'quotedPriceNo',
dataIndex: 'quotedPriceNo',
render: (text: any, record: any) => (
<Space direction='vertical'>
<Text type='secondary'>{record.quotedPriceNo}</Text>
<Text type='secondary'>{record.details}</Text>
</Space>
)
}, {
title: '规格型号',
key: 'createTime',
dataIndex: 'createTime',
render: (text: any, record: any) => text,
}, {
title: '品类',
key: 'createTime',
dataIndex: 'createTime',
render: (text: any, record: any) => text,
}, {
title: '品牌',
key: 'createTime',
dataIndex: 'createTime',
render: (text: any, record: any) => text,
}, {
title: '采购数量/单位',
key: 'createTime',
dataIndex: 'createTime',
render: (text: any, record: any) => text,
}, {
title: '含税/税率',
key: 'createTime',
dataIndex: 'createTime',
render: (text: any, record: any) => text,
}, {
title: '单价(含税)',
key: 'createTime',
dataIndex: 'createTime',
render: (text: any, record: any) => text,
}, {
title: '金额(含税)',
key: 'createTime',
dataIndex: 'createTime',
render: (text: any, record: any) => text,
}];
/** 列表数据 */
const fetchData = (params?: any) => {
return new Promise((resolve, reject) => {
fetch({ ...params }).then(res => {
resolve(res.data)
})
})
}
useImperativeHandle(reload, () => ({
reload: () => {
tableRef.current.reload();
}
}));
// 搜索
const search = (values: any) => {
tableRef.current.reload(values)
}
return (
<Drawer
title="报价明细"
width={1000}
onClose={onClose}
visible={visible}
bodyStyle={{ paddingBottom: 80 }}
footer={
<div style={{ textAlign: 'right', }}>
<Button onClick={onClose} style={{ marginRight: 8 }}>取消</Button>
<Button onClick={onClose} type="primary">确认</Button>
</div>
}
>
<StandardTable
currentRef={tableRef}
columns={columns}
tableProps={{ rowKew: 'id' }}
fetchTableData={(params: any) => fetchData(params)}
controlRender={
<NiceForm
actions={formActions}
onSubmit={values => search(values)}
effects={($, actions) => {
useStateFilterSearchLinkageEffect($, actions, effects, FORM_FILTER_PATH)
FormEffectHooks.onFieldChange$('category').subscribe(state => {
searchSelectGetSelectCategoryOptionEffect(actions, 'category')
})
}}
schema={
schemaType && SchemaRender()
}
>
</NiceForm>
}
/>
</Drawer>
)
}
export default QuotationDetailsDrawer
import React, { useState } from 'react';
import { Modal, Tabs, Form, Button, Input, Upload, message } from 'antd';
import { UPLOAD_TYPE } from '@/constants'
import { UploadOutlined } from '@ant-design/icons';
const { TabPane } = Tabs;
const { TextArea } = Input;
import styles from './index.less';
const UploadBidResultModal = (props: any) => {
const { title, visible, onCancel } = props;
const [files, setFiles] = useState<any>([]);
const [form] = Form.useForm();
const [loading, setloading] = useState(false);
/**判断文件类型和大小 */
const beforeDocUpload = (file: any) => {
const isLt20M = file.size / 1024 / 1024 < 20;
if (!isLt20M) {
message.error('上传文件大小不超过 20M!');
}
return isLt20M;
}
// 上传回调
const handleChange = ({ file }) => {
const arr: any = files;
setloading(true);
if (file.response) {
if (file.response.code === 1000) {
arr.push({
name: file.name,
url: file.response.data
})
setloading(false);
}
}
setFiles([...arr])
}
return (
<Modal
width={600}
title={title}
visible={visible}
onCancel={onCancel}
wrapClassName={styles.wrap}
// onOk={() => actions.submit()}
// afterClose={() => actions.reset()}
>
<Form
form={form}
layout="vertical"
>
<Form.Item name="offer" label="授标意见" rules={[{ required: true, message: '请输入授标意见' }]}>
<TextArea rows={3} maxLength={200} placeholder="最长200个字符,100个汉字" />
</Form.Item>
<Form.Item
label="报名要求附件"
name="file"
rules={[{ required: true, message: '请选择报名要求附件' }]}
>
<Upload
action="/api/file/file/upload"
data={{ fileType: UPLOAD_TYPE }}
showUploadList={false}
accept='.doc,.docx,.pdf,.ppt,.pptx,.xls,.xlsx'
beforeUpload={beforeDocUpload}
onChange={handleChange}
>
<Button loading={loading} icon={<UploadOutlined />}>上传文件</Button>
<div style={{ marginTop: '8px' }}>一次上传一个文件,每个附件大小不能超过 20M</div>
</Upload>
</Form.Item>
</Form>
</Modal>
)
}
export default UploadBidResultModal
\ No newline at end of file
.rank {
border-radius: 8px;
overflow: hidden;
.rankHeader {
height: 209px;
background: -webkit-linear-gradient(top, rgba(0, 179, 122, 1), #FFFFFF);
padding: 16px;
h5 {
font-size: 14px;
color: #FFFFFF;
margin-bottom: 24px;
}
.rankHeaderBox {
background-color: #FFFFFF;
border-radius: 5px;
padding: 16px;
img {
margin-bottom: 6px;
width: 24px;
}
h4 {
font-size: 16px;
color: #303133;
text-align: center;
position: relative;
}
.rankHeaderBoxInfo {
display: flex;
flex-direction: row;
font-size: 12px;
color: #909399;
span {
color: #303133;
}
.rankHeaderBoxInfoChild {
flex: 1;
align-items: center;
box-sizing: border-box;
text-align: center;
&:first-child{
border-right: 1px solid #EBECF0;
}
}
}
}
}
:global {
.ant-tabs-nav {
padding-left: 16px;
&::before{
border-bottom: 0;
}
}
.ant-tabs {
background-color: #FFFFFF;
}
}
}
\ No newline at end of file
import React, { useEffect, useState } from 'react';
import { Row, Col, Tabs, Button } from 'antd';
import level1 from '@/assets/icons/the_first.png';
import level2 from '@/assets/icons/the_second.png';
import level3 from '@/assets/icons/the_third.png';
import styles from './index.less';
import TriangleTag from '../triangleTag';
import RankRow from '../rankRow';
const { TabPane } = Tabs;
const RankItem = () => {
return (
<div className={styles.rank}>
<div className={styles.rankHeader}>
<h5>竞价排名</h5>
<div className={styles.rankHeaderBox}>
<img src={level1} alt={`排名1`} />
<h4><div style={{display: 'inline-block',position: 'relative',left: '-3%',top: '-5%'}}><TriangleTag text='最低价' wrapStyle={{backgroundColor : '#EA8000'}} bgcolor='#EA8000' direction='right' /></div>广州白马皮具交易中心</h4>
<div className={styles.rankHeaderBoxInfo}>
<div className={styles.rankHeaderBoxInfoChild}>当前最低价:<span>¥ 900.00</span></div>
<div className={styles.rankHeaderBoxInfoChild}>报价次数:<span>5</span></div>
</div>
</div>
</div>
<Tabs defaultActiveKey="1">
<TabPane tab="报价排名" key="1">
<RankRow />
<Button type="link" block>显示更多</Button>
</TabPane>
<TabPane tab="报名会员" key="2">
<RankRow rowType={2} />
<Button type="link" block>显示更多</Button>
</TabPane>
</Tabs>
</div>
)
}
export default RankItem;
.rankRow {
height: 56px;
border-radius: 28px;
padding: 0 16px;
display: flex;
align-items: center;
justify-content: center;
flex-direction: row;
margin-bottom: 4px;
.rankRowLeft {
flex: 1;
color: #303133;
.rankRowLeftTop {
display: flex;
flex-direction: row;
align-items: center;
img {
width: 24px;
margin-right: 8px;
}
.rankRowLeftTopRank {
width: 24px;
height: 24px;
line-height: 24px;
text-align: center;
margin-right: 8px;
background-color: #EBECF0;
font-size: 12px;
color: #909399;
}
}
.rankRowLeftBottom {
padding-left: 32px;
display: flex;
flex-direction: row;
font-size: 14px;
color: #303133;
.rankRowLeftBottomTag {
color: #606266;
font-size: 12px;
padding: 2px;
border-radius: 2px;
margin-left: 8px;
background-color: #F4F5F7;
}
}
.rankRowLeftBottomPhone{
color: #909399;
}
}
.rankRowRight {
display: flex;
flex-direction: row;
align-items: center;
color: #909399;
font-size: 12px;
}
}
.rankRow_level_1 {
background: -webkit-linear-gradient(left, rgba(253, 197, 47, .2), #FFFFFF);
}
.rankRow_level_2 {
background: -webkit-linear-gradient(left, rgba(153, 176, 192, .2), #FFFFFF);
}
.rankRow_level_3 {
background: -webkit-linear-gradient(left, rgba(210, 164, 104, .2), #FFFFFF);
}
import React, { useEffect, useState } from 'react';
import level1 from '@/assets/icons/the_first.png';
import level2 from '@/assets/icons/the_second.png';
import level3 from '@/assets/icons/the_third.png';
import TriangleTag from '../triangleTag';
import IMBtn from '../../../../../components/detail/components/iMBtn';
import styles from './index.less';
interface RankRowProps {
detail?: any,
rowType?: number
}
const RankRow: React.FC<RankRowProps> = (props: any) => {
const { detail, rowType } = props;
const _returnRow = () => {
if (rowType === 1) {
return (
<div className={`${styles.rankRow} ${styles.rankRow_level_1}`}>
<div className={styles.rankRowLeft}>
<div className={styles.rankRowLeftTop}>
<img src={level1} alt="" />
广州白马皮具交易中心
<TriangleTag text='最低价' wrapStyle={{ backgroundColor: '#EA8000', marginLeft: '8px' }} bgcolor='#EA8000' direction='left' />
</div>
<div className={styles.rankRowLeftBottom}>
¥900.00
<div className={styles.rankRowLeftBottomTag}>第2次</div>
</div>
</div>
<div className={styles.rankRowRight}>
蒯美政
<IMBtn func={() => console.log(1)} />
</div>
</div>
)
} else {
return (
<div className={`${styles.rankRow}`}>
<div className={styles.rankRowLeft}>
<div className={styles.rankRowLeftTop}>广州白马皮具交易中心</div>
<div className={styles.rankRowLeftBottomPhone}>185 2929 6758</div>
</div>
<div className={styles.rankRowRight}>
蒯美政
<IMBtn func={() => console.log(1)} />
</div>
</div>
)
}
}
return (
_returnRow()
)
}
RankRow.defaultProps = {
rowType: 1
}
export default RankRow;
.statusBox{
font-size: 12px;
.statusBoxStatus{
background-color: #EA8000;
text-align: center;
line-height: 48px;
height: 48px;
color: #FFFFFF;
font-size: 12px;
span{
font-size: 16px;
}
}
.statusBoxTips{
color: #909399;
margin: 16px 0;
text-align: center;
}
.statusBoxTime{
display: flex;
align-items: baseline;
justify-content: center;
.statusBoxTimeChild{
.statusBoxTimeChild_top{
width: 64px;
height: 64px;
line-height: 64px;
text-align: center;
background-color: #FFF8E6;
font-size: 32px;
color: #EA8000;
margin-bottom: 8px;
}
.statusBoxTimeChild_bottom{
color: #909399;
text-align: center;
}
}
span{
font-size: 32px;
color: #909399;
margin: 0 12px;
}
}
h4{
font-size: 14px;
color: #303133;
margin-bottom: 16px;
}
.statusBoxText{
display: flex;
align-items: center;
margin-bottom: 8px;
color: #303133;
div{
color: #909399;
width: 88px;
}
&:nth-last-child(1){
margin-bottom: 0;
}
}
}
\ No newline at end of file
import React from 'react';
import { Row, Col, Tooltip, Divider } from 'antd';
import styles from './index.less'
const StatuBox = () => {
return (
<div className='ant-card ant-card-bordered'>
<div className='ant-card-body'>
<div className={styles.statusBox}>
<div className={styles.statusBoxStatus}>当前状态:<span>竞价中</span></div>
<p className={styles.statusBoxTips}>距离竞价结束还剩</p>
<div className={styles.statusBoxTime}>
<div className={styles.statusBoxTimeChild}>
<div className={styles.statusBoxTimeChild_top}>02</div>
<p className={styles.statusBoxTimeChild_bottom}>小时</p>
</div>
<span>:</span>
<div className={styles.statusBoxTimeChild}>
<div className={styles.statusBoxTimeChild_top}>32</div>
<p className={styles.statusBoxTimeChild_bottom}>分钟</p>
</div>
<span>:</span>
<div className={styles.statusBoxTimeChild}>
<div className={styles.statusBoxTimeChild_top}>48</div>
<p className={styles.statusBoxTimeChild_bottom}></p>
</div>
</div>
<Divider dashed style={{color: '#EBECF0',margin: '6px 0' }} />
<h4></h4>
<div className={styles.statusBoxText}><div>报价规则:</div>项目总价(含税)</div>
<div className={styles.statusBoxText}><div>起拍价:</div>¥ 1,500.00</div>
<div className={styles.statusBoxText}><div>目标价:</div>¥ 900.00</div>
<div className={styles.statusBoxText}><div>最小价差:</div>¥ 100.00</div>
<div className={styles.statusBoxText}><div>允许报价次数:</div>3</div>
<div className={styles.statusBoxText}><div>报价排名:</div>按项目总价排名</div>
<div className={styles.statusBoxText}><div>公开最低报价:</div></div>
<div className={styles.statusBoxText}><div>公开报价排名:</div></div>
</div>
</div>
</div>
)
}
export default StatuBox
\ No newline at end of file
.triangleTag{
display: inline-block;
position: relative;
color: #FFFFFF;
font-size: 12px;
border-radius: 2px;
.directionTriangle{
width: 0;
height: 0;
border-width: 4px;
border-style: solid;
position: absolute;
}
}
\ No newline at end of file
import React, { useEffect, useState } from 'react';
import styles from './index.less';
interface TriangleTagProps {
text: string,
bgcolor?: string,
direction?: string,
wrapStyle: React.CSSProperties
}
const TriangleTag: React.FC<TriangleTagProps> = (props: any) => {
const { text, bgcolor, direction, wrapStyle } = props;
const _returndirectionStyle = () => {
if(direction === 'left'){
return {
borderColor: `transparent ${bgcolor} transparent transparent`,
left: '-8px',
top : '26%'
}
}else if(direction === 'right'){
return {
borderColor: `transparent ${bgcolor} transparent transparent`,
transform: 'rotate(180deg)',
right: '-8px',
top : '26%'
}
}
}
return (
<div className={styles.triangleTag} style={wrapStyle}>
<div className={styles.directionTriangle} style={_returndirectionStyle()}></div>
{text}
</div>
)
}
TriangleTag.defaultProps = {
bgcolor: '#EA8000',
direction: 'left'
}
export default TriangleTag;
.warp {
.header {
display: flex;
height: 48px;
line-height: 48px;
font-size: 16px;
background-color: #FFFFFF;
color: #303133;
padding: 0 16px;
align-items: center;
&::before {
content: " ";
width: 2px;
height: 16px;
background: @primary-color;
margin-right: 6px;
}
}
.layout {
margin: 24px;
}
:global {
.ant-card-head-wrapper{
padding: 12px 0;
.ant-card-head-wrapper{
padding: 0;
}
}
}
}
import React, { useEffect, useState } from 'react';
import { Row, Col, Tooltip, Button } from 'antd';
import RankItem from './components/rank';
import StatusBox from './components/statusBox';
import QuotationDeskLayout from '../../../components/detail/components/quotationDeskLayout';
import BidDetailLayout from '../../../components/detail/components/bidDetailLayout';
import styles from './index.less';
const Management = () => {
return (
<div className={styles.warp}>
<div className={styles.header}>进口头层黄牛皮荔枝纹竞价</div>
<div className={styles.layout}>
<Row gutter={[8,8]}>
<Col span={6}>
<RankItem />
</Col>
<Col span={18}>
<Row gutter={[8,8]} style={{marginBottom: '8px'}}>
<Col span={16}>
<QuotationDeskLayout />
</Col>
<Col span={8}>
<StatusBox />
</Col>
</Row>
<Row>
<BidDetailLayout />
</Row>
</Col>
</Row>
</div>
</div>
)
}
export default Management;
......@@ -20,6 +20,9 @@ import MaterialLayout from '../../components/detail/components/materialLayout';
import DemandLayout from '../../components/detail/components/demandLayout';
import BidCommonLayout from '../../components/detail/components/bidCommonLayout';
import ModalOperate from '../../components/modalOperate';
import ConfirmBidResultModal from '../components/confirmBidResultModal';
import UploadBidResultModal from '../components/uploadBidResultModal';
import QuotationDetailsDrawer from '../components/quotationDetailsDrawer';
const ICON_STYLE: any = {
color: '#C0C4CC',
......@@ -52,6 +55,12 @@ const SearchDetail = () => {
const [path] = useState(pathname.split('/')[pathname.split('/').length - 1]);
const [pathPci] = useState(pathname.split('/')[pathname.split('/').length - 2]);
const [visible, setVisible] = useState<boolean>(false);
// 确认竞价结果
const [confirmBidResultVisible , setConfirmBidResultVisible] = useState<boolean>(false);
// 提交竞价结果
const [uploadBidResultVisible , setUploadBidResultVisible] = useState<boolean>(false);
// 报价明细
const [quotationDetailsVisible , setQuotationDetailsVisible] = useState<boolean>(false);
const [dataSource, setDataSource] = useState<any>({});
const [basicEffect, setBasicEffect] = useState<any>([]);
const [conditionEffect, setConditionEffect] = useState<any>([]);
......@@ -180,6 +189,20 @@ const SearchDetail = () => {
单据审核
</Button>
)}
<Button
onClick={() => setConfirmBidResultVisible(true)}
type='primary'
>
<CheckCircleOutlined />
确认竞价结果
</Button>
{/* <Button
onClick={() => setUploadBidResultVisible(true)}
type='primary'
>
<CheckCircleOutlined />
提交竞价结果
</Button> */}
</>
}
components={
......@@ -306,7 +329,12 @@ const SearchDetail = () => {
]
} />
<DemandLayout storeList={storeList} />
<BidCommonLayout layoutId="resultLayout" title="授标结果" layoutType='result' effect={
<BidCommonLayout
layoutId="resultLayout"
title="授标结果"
layoutType='result'
checkDetailFunc={() => {setQuotationDetailsVisible(true)}}
effect={
[
{},
{},
......@@ -314,9 +342,7 @@ const SearchDetail = () => {
{},
]
}
extra={<Button type='link'>
查看竞价过程
</Button>} />
extra={<Button type='link'>查看竞价过程</Button>} />
<RecordLyout />
</Fragment>
}
......@@ -330,6 +356,21 @@ const SearchDetail = () => {
onCancel={() => setVisible(false)}
onOk={() => history.goBack()}
/>
<ConfirmBidResultModal
title="确认竞价结果"
visible={confirmBidResultVisible}
onCancel={() => setConfirmBidResultVisible(false)}
/>
<UploadBidResultModal
title="提交竞价结果"
visible={uploadBidResultVisible}
onCancel={() => setUploadBidResultVisible(false)}
/>
<QuotationDetailsDrawer
title="报价明细"
visible={quotationDetailsVisible}
onClose={() => setQuotationDetailsVisible(false)}
/>
</Context.Provider>
)
}
......
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