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

feat: 竞价单详情页,对应组件搬迁

parent f7c81310
......@@ -10,15 +10,15 @@ const router = {
hidePageHeader: true,
component: '@/pages/purchaseAbility/purchaseBid/search',
},
// {
// // 采购竞价单详情
// path: '/purchaseBid/demand/search/preview',
// name: '采购竞价单详情',
// component: '@/pages/purchaseAbility/purchaseBid/detail',
// hidePageHeader: true,
// hideInMenu: true,
// noMargin: true,
// },
{
// 采购竞价单详情
path: '/purchaseBid/demand/search/detail',
name: '采购竞价单详情',
component: '@/pages/purchaseAbility/purchaseBid/detail',
hidePageHeader: true,
hideInMenu: true,
noMargin: true,
},
{
// 待审核采购竞价单
path: '/purchaseBid/demand/examineSearch',
......@@ -26,15 +26,15 @@ const router = {
hidePageHeader: true,
component: '@/pages/purchaseAbility/purchaseBid/examineSearch',
},
// {
// // 采购竞价单详情 审核
// path: '/purchaseBid/demand/examineSearch/detail',
// name: '待审核采购竞价单详情',
// component: '@/pages/purchaseAbility/purchaseBid/detail',
// hidePageHeader: true,
// hideInMenu: true,
// noMargin: true,
// },
{
// 采购竞价单详情 审核
path: '/purchaseBid/demand/examineSearch/detail',
name: '待审核采购竞价单详情',
component: '@/pages/purchaseAbility/purchaseBid/detail',
hidePageHeader: true,
hideInMenu: true,
noMargin: true,
},
// {
// // 采购竞价单详情
// path: '/purchaseBid/demand/examineSearch/preview',
......
import React, { useState, useMemo } from 'react';
import { CaretDownOutlined, CaretUpOutlined } from '@ant-design/icons';
const areaItem = (props: any) => {
const { data } = props;
const [showMore, setShowMore] = useState<any>(false);
const showDataSource = showMore ? data : [...data].splice(0, 3)
// const showDataSource = useMemo(() => {
// return showMore ? data : [...data].splice(0, 3)
// }, [showMore, data])
const toogleMore = () => {
setShowMore(!showMore);
}
return (
<>
{showDataSource.map((_item, _i) => <p key={`address${_i}`}>{_item.province + '/' + (_item.city || '')}</p>)}
{
data.length > 3 &&
<p onClick={toogleMore} style={{ cursor: 'pointer' }} className="commonPickColor">
{showMore ? '收起' : '展开'}{showMore ? <CaretUpOutlined /> : <CaretDownOutlined />}
</p>
}
</>
)
}
export default areaItem
\ No newline at end of file
import React from 'react';
import { Typography } from 'antd';
import { LinkOutlined } from '@ant-design/icons';
const FilesItem = (props: any) => {
const { files } = props;
if (files && files.length > 0) {
return (
files.map((item, index) => {
return (
<div key={index}>
<Typography.Link href={item.url} target="_blank">
<LinkOutlined />
{item.name}
</Typography.Link>
</div>
)
})
)
}else{
return '无'
}
}
export default FilesItem
\ No newline at end of file
.pieItem{
background-color: #FAFBFC;
padding: 6px;
display: flex;
.box{
flex: 1;
display: flex;
flex-direction: column;
justify-content: center;
margin-left: 20px;
.title{
font-size: 12px;
color: #909399;
}
.price{
font-size: 18px;
color: #303133;
}
}
}
.baseItem{
display: flex;
font-size: 12px;
margin-bottom: 16px;
.label{
width: 104px;
color: #909399;
margin: 0;
}
.content{
flex: 1;
margin: 0;
}
}
\ No newline at end of file
import React, { useContext, useEffect, useState } from 'react';
import { Tabs, Table, Row, Col, Space, Typography, Divider, Tooltip } from 'antd';
import { QuestionCircleOutlined, CaretRightOutlined } from '@ant-design/icons';
import { PublicApi } from '@/services/api';
import Card from '../../../card';
import { Context } from '../context';
import selfStyles from './index.less';
import AreaItem from './areaItem';
import FilesItem from './filesItem';
import MsgItem from './msgItem';
import ResultItem from './resultItem';
import PieItem from './pieItem';
const ICON_STYLE: any = {
color: '#C0C4CC',
fontSize: '14px',
marginLeft: '5px'
}
export interface BidCommonLayoutProps {
effect?: any,
layoutId: string,
title: string,
layoutType?: string,
extra?: React.ReactNode,
checkDetailFunc?: Function
}
const BidCommonLayout: React.FC<BidCommonLayoutProps> = (props: any) => {
const { layoutId, title, effect, layoutType, extra, checkDetailFunc } = props;
const _returnItem = (data) => {
switch (data.type) {
case 'text':
return data.extra || '-'
case 'area':
return data.extra ? (<AreaItem data={data.extra} />) : '-'
case 'files':
return data.extra ? (<FilesItem files={data.extra} />) : '-'
}
}
const _returnChild = (child, key) => {
if (child.type === 'text' || child.type === 'area' || child.type === 'files') {
return (
<div className={selfStyles.baseItem} key={key}>
<h5 className={selfStyles.label}>
{child.tips ? <Tooltip placement="top" title={child.tips}>
{child.label}: <QuestionCircleOutlined style={ICON_STYLE} />
</Tooltip> : `${child.label}: `}
</h5>
<h5 className={selfStyles.content}>{_returnItem(child)}</h5>
</div>
)
} else if (child.type === 'pie') {
return (
<div className={selfStyles.pieItem} key={key}>
<PieItem />
<div className={selfStyles.box}>
<div className={selfStyles.title}>中标金额(含税):</div>
<div className={selfStyles.price}>¥114,000.00</div>
</div>
</div>
)
}
}
const _returnWarp = () => {
if (!layoutType) {
return (<Row gutter={[8, 8]}>
{effect.map((item, index) => (
<Col span={8} key={`effect_text_${index}`}>
{item.col.map((child, key) => _returnChild(child, key))}
</Col>
))}
</Row>)
} else if (layoutType === 'msg') {
return (<Row gutter={[8, 8]}>
{effect.map((item, index) => (
<Col span={5} key={`effect_msg_${index}`}>
<MsgItem data={item} rank={index} />
</Col>
))}
</Row>)
} else if (layoutType === 'result') {
return (
<Row gutter={[8, 8]}>
{effect?.list?.map((item, index) => (
<Col span={5} key={`effect_result_${index}`}>
<ResultItem detail={item} itemIndex={index} checkDetailFunc={checkDetailFunc} />
</Col>
))}
<Col span={24}>
<Divider dashed style={{ color: '#EBECF0' }} />
<div className={selfStyles.baseItem}>
<h5 className={selfStyles.label}>授标意见: </h5>
<h5 className={selfStyles.content}>{effect.signUpIdea}</h5>
</div>
<div className={selfStyles.baseItem}>
<h5 className={selfStyles.label}>附件: </h5>
<h5 className={selfStyles.content}><FilesItem /></h5>
</div>
</Col>
</Row>
)
}
}
return (
<Card
id={layoutId}
title={title}
extra={extra}
>
{_returnWarp()}
</Card>
)
}
export default BidCommonLayout
\ No newline at end of file
.msgItem {
background: #FAFBFC;
padding: 12px 14px;
.msgItemRow {
display: flex;
margin-bottom: 6px;
font-size: 12px;
color: #909399;
.badge {
width: 16px;
height: 16px;
background: #EBECF0;
border-radius: 8px;
text-align: center;
line-height: 16px;
color: #909399;
font-size: 12px;
margin-right: 4px;
}
.title {
font-size: 12px;
color: #303133;
flex: 1;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
word-break: break-all;
}
.label{
width: 40%;
}
.files{
flex: 1;
}
}
}
import React from 'react';
import { Tabs, Table, Row, Col, Space, Typography, Button, Tooltip } from 'antd';
import { LinkOutlined } from '@ant-design/icons';
import styles from './index.less';
export interface MsgItemPrpos {
rank?: number,
data?: any,
}
const MsgItem: React.FC<MsgItemPrpos> = (props: any) => {
const { data, rank } = props;
const rankNumber = Number(rank) + 1;
return (
<div className={styles.msgItem}>
<div className={styles.msgItemRow}>
<div className={styles.badge}>{rankNumber}</div>
<div className={styles.title}>{data.memberName}</div>
</div>
<div className={styles.msgItemRow}><div className={styles.label}>联系人姓名:</div><div className={styles.title}>{data.contacts}</div></div>
<div className={styles.msgItemRow}><div className={styles.label}>联系人手机:</div><div className={styles.title}>{data.tel}</div></div>
<div className={styles.msgItemRow}><div className={styles.label}>电子邮箱:</div><div className={styles.title}>{data.mail}</div></div>
<div className={styles.msgItemRow}><div className={styles.label}>联系地址:</div>{<Tooltip placement="top" title={data.address}>
<div className={styles.title}>{data.address}</div>
</Tooltip>}</div>
<div className={styles.msgItemRow}>
<div className={styles.label}>报名文件:</div>
<div className={styles.files}>
{data.enclosureUrls ? data.enclosureUrls.map((item, index) => {
return (
<Typography.Link
style={{ display: 'block', paddingBottom: '8px' }}
target="_blank"
href={item.url}
key={`Typography_${item.name}_${index}`}
>
<LinkOutlined />{item.name}
</Typography.Link>
)
}) : '-'}
</div>
</div>
</div>
)
}
export default MsgItem
import React from "react";
import {
Chart,
// Interval,
Axis,
Tooltip,
Coordinate,
Legend,
View,
} from "bizcharts";
import Interval from 'bizcharts/lib/geometry/Interval';
import { Text } from 'bizcharts/lib/components/Annotation';
import DataSet from "@antv/data-set";
const PieItem = () => {
const { DataView } = DataSet;
const userData = [
{ type: '睡觉', value: 70 },
{ type: '晨练', value: 30 },
];
const userDv = new DataView();
userDv.source(userData).transform({
type: 'percent',
field: 'value',
dimension: 'type',
as: 'percent',
});
return (
<Chart placeholder={false} height={60} width={60} padding={0} autoFit>
<Legend visible={false} />
{/* 绘制图形 */}
<View data={userDv.rows} scale={{
percent: {
formatter: (val) => {
return (val * 100).toFixed(2) + '%';
},
}
}}>
<Tooltip shared showTitle={false} />
<Coordinate type="theta" innerRadius={0.75} />
<Interval
position="percent"
adjust="stack"
color={['type',['#FFC400','#6C9CEB']]}
// color="type"
// label={['type', {offset: 40}]}
/>
<Text
position={['50%', '50%']}
content="75%"
style={{
lineHeight: 64,
fontSize: 10,
fill: '#262626',
textAlign: 'center',
}}
/>
</View>
</Chart>
);
}
export default PieItem
\ No newline at end of file
.resultItem {
height: 131px;
background: #FAFBFC;
padding: 12px 14px;
.resultItemWinBid{
position: absolute;
width: 40px;
right: 8px;
top: -8px;
}
.resultItemRow {
display: flex;
margin-bottom: 6px;
font-size: 12px;
color: #909399;
.money {
color: #303133;
font-size: 16px;
flex: 1;
span {
color: #909399;
font-size: 12px;
}
}
.badge {
width: 24px;
height: 24px;
background: #EBECF0;
border-radius: 12px;
text-align: center;
line-height: 24px;
color: #909399;
font-size: 12px;
margin-left: 4px;
display: inline-block;
}
.title {
font-size: 12px;
color: #303133;
flex: 1;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
word-break: break-all;
img {
margin-left: 4px;
width: 24px;
}
}
.label {
width: 40%;
}
}
}
import React from 'react';
import { Divider, Table, Row, Col, Space, Typography, Button, Tooltip } from 'antd';
import level1 from '@/asserts/icons/the_first.png';
import level2 from '@/asserts/icons/the_second.png';
import level3 from '@/asserts/icons/the_third.png';
import winBig from '@/asserts/imgs/win-bid.png';
import styles from './index.less';
export interface ResultItemPrpos {
itemIndex: number,
detail?: any,
checkDetailFunc?: Function
}
const ResultItem: React.FC<ResultItemPrpos> = (props: any) => {
const { itemIndex, detail, checkDetailFunc } = props;
const _returnBadge = (number) => {
const _number = Number(number)+1;
switch (_number) {
case 1:
return <img src={level1} alt='第一名' />;
case 2:
return <img src={level2} alt='第二名' />;
case 3:
return <img src={level3} alt='第三名' />;
default:
return <div className={styles.badge}>{_number}</div>
}
}
return (
<div key={`msgItem_key_${itemIndex}`} className={styles.resultItem}>
{detail.isAward && <img src={winBig} alt="授标" className={styles.resultItemWinBid}/>}
<div className={styles.resultItemRow}>
<div className={styles.title}>{detail.memberName}{_returnBadge(detail.purchaseRanking)}</div>
</div>
<div className={styles.resultItemRow}>
<div className={styles.money}>¥{detail.price}<span>(含税)</span></div>
<Button type='link' onClick={() => {checkDetailFunc(detail.id)}}>查看报价明细</Button>
</div>
<Divider dashed style={{ color: '#EBECF0', margin: '6px 0' }} />
<div className={styles.resultItemRow}><div className={styles.label}>联系人姓名:</div><div className={styles.title}>{detail.contacts}</div></div>
<div className={styles.resultItemRow}><div className={styles.label}>联系人手机:</div><div className={styles.title}>{detail.tel}</div></div>
</div>
)
}
export default ResultItem
.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;
}
}
}
}
.btnItem2 {
border: 1px solid #F4F5F7;
font-size: 12px;
cursor: pointer;
background-color: #FFFFFF;
color: #909399;
.info {
background-color: #F7F8FA;
padding: 6px 12px;
display: flex;
flex-direction: row;
span {
flex: 1;
text-align: right;
}
}
.box {
padding: 12px;
.price {
display: flex;
flex-direction: row;
margin-bottom: 4px;
div {
flex: 1;
color: #303133;
font-size: 12px;
span {
color: #909399;
font-size: 12px;
margin-left: 4px;
}
}
}
.time {
display: flex;
flex-direction: row;
span {
flex: 1;
color: #303133;
}
}
}
}
.btnItem3 {
border: 1px solid #F4F5F7;
font-size: 12px;
cursor: pointer;
.title {
padding: 18.5px 12px;
display: flex;
flex-direction: row;
div {
flex: 1;
font-size: 16px;
color: #303133;
span {
color: #909399;
font-size: 12px;
margin-left: 4px;
}
}
}
}
\ No newline at end of file
import React, { useContext, useEffect, useState } from 'react';
import { Row, Col, Table, Button } from 'antd';
import { CaretDownOutlined } from '@ant-design/icons'
import { formatTimeString } from '@/utils'
import TrendTag from '../trendTag';
import styles from './index.less';
interface BtnItemProps {
btnType?: number,
active?: boolean,
detail?: any,
onOk?: Function,
onCancle?: Function
}
const BtnItem: React.FC<BtnItemProps> = (props: any) => {
const { btnType, active, detail, onOk, onCancle } = props;
const _returnBtn = () => {
if (btnType === 1) {
return (
<div className={styles.btnItem} style={{ borderColor: active ? '#00B37A' : '#F4F5F7' }}>
<div className={styles.btnItemTitle}>
<div>{detail?.memberName}</div>
{detail?.peportPriceSum}</div>
<div className={styles.btnItemPrice}>
<div>
¥{detail?.sumPice}
<span>(含税)</span>
</div>
{formatTimeString(detail?.peportTime)}
</div>
</div>
)
} else if (btnType === 2) {
return (
<div className={styles.btnItem2} style={{ borderColor: active ? '#00B37A' : '#F4F5F7' }}>
<div className={styles.info}>
{detail?.ranking}
<span>当前最低价:¥{detail?.minPrice}</span>
</div>
<div className={styles.box}>
<div className={styles.price}>
<div>¥{detail?.sumPice}<span>(含税)</span></div>
{detail?.peportPriceSum}
</div>
<div className={styles.time}>
<span>{formatTimeString(detail?.peportTime)}</span>
<TrendTag />
</div>
</div>
</div>
)
} else if (btnType === 3) {
return (
<div className={styles.btnItem3} style={{ borderColor: active ? '#00B37A' : '#F4F5F7' }}>
<div className={styles.title}>
<div>
¥{detail?.sumPice}
<span>(含税)</span>
</div>
{detail?.peportPriceSum}
</div>
<Row>
<Col span={12}>
<Button block style={{ backgroundColor: '#F4F5F7', border: 0 }} onClick={onCancle}>取消</Button>
</Col>
<Col span={12}>
<Button type="primary" block onClick={onOk} disabled={!active}>提交报价</Button>
</Col>
</Row>
</div>
)
}
}
return (
_returnBtn()
)
}
BtnItem.defaultProps = {
btnType: 1
}
export default BtnItem;
\ No newline at end of file
import React, { useEffect, useState } from 'react';
import { ColumnType } from 'antd/lib/table/interface';
import { Row, Col, Space, Button, Typography, Popconfirm, Badge, Tag, Table, Drawer } from 'antd';
import BtnItem from '../bidDetailBtnItem';
interface BidProgressDrawerProps {
visible?: boolean,
onClose?: Function,
awardProcess?: any
}
const { Text } = Typography;
const BidProgressDrawer: React.FC<BidProgressDrawerProps> = (props: any) => {
const { visible, onClose, awardProcess = [] } = props;
const [activeItem, setActiveItem] = useState<any>(awardProcess ? awardProcess[0] : {});
useEffect(() => {
awardProcess && setActiveItem(awardProcess[0])
}, [awardProcess])
const columns: ColumnType<any>[] = [{
title: '序号',
align: 'center',
dataIndex: 'id',
key: 'id',
render: (t, r, i) => ++i
}, {
title: '物料编号/摘要',
key: 'number',
dataIndex: 'number',
render: (text: any, record: any) => (
<Space direction='vertical'>
<Text type='secondary'>{text}</Text>
<Text type='secondary'>{record.details}</Text>
</Space>
)
}, {
title: '规格型号',
key: 'model',
dataIndex: 'model',
render: (text: any, record: any) => text,
}, {
title: '品类',
key: 'category',
dataIndex: 'category',
render: (text: any, record: any) => text,
}, {
title: '品牌',
key: 'brand',
dataIndex: 'brand',
render: (text: any, record: any) => text,
}, {
title: '采购数量/单位',
key: 'purchaseCount',
dataIndex: 'purchaseCount',
render: (text: any, record: any) => (
<Space direction='vertical'>
<Text type='secondary'>{text}</Text>
<Text type='secondary'>{record.unit}</Text>
</Space>
),
}, {
title: '含税/税率',
key: 'isTax',
dataIndex: 'isTax',
render: (text: any, record: any) => (
<Space direction='vertical'>
<Text type='secondary'>{text === 1 ? '是' : '否'}</Text>
<Text type='secondary'>{record.taxRate}%</Text>
</Space>
),
}, {
title: '单价(含税)',
key: 'unitPrice',
dataIndex: 'unitPrice',
render: (text: any, record: any) => ${text}`,
}, {
title: '金额(含税)',
key: 'price',
dataIndex: 'price',
render: (text: any, record: any) => ${text}`,
}];
const chooseItem = (item: any) => {
if (item.id !== activeItem.id) {
setActiveItem(item);
}
}
return (
<Drawer
title="竞价过程"
width={1200}
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>
}
>
<Row gutter={[8, 8]} style={{ marginBottom: '10px' }}>
{awardProcess?.length > 0 && awardProcess?.map((item, index) => {
return (
<Col span={7} key={item.id} onClick={() => { chooseItem(item) }}>
<BtnItem detail={item} active={item?.id === activeItem?.id} />
</Col>
)
})}
</Row>
<Table
columns={columns}
dataSource={activeItem?.detailss ?? []}
rowKey={(record) => record.id}
pagination={{
hideOnSinglePage: true
}}
/>
</Drawer>
)
}
export default BidProgressDrawer
/** 详情通用 - 流转进度 */
import React, { useEffect, useState } from 'react';
import { Radio, Steps } from 'antd';
import Card from '../../../card';
export interface ProgressProps {
effect?: any[]
}
const ProgressLayout: React.FC<ProgressProps> = (props: any) => {
const { effect } = props;
const [logStatesItem, setLogStatesItem] = useState<any>(effect[0]);
useEffect(() => {
effect && setLogStatesItem(effect[0]);
}, [effect])
return (
<Card
id='progressLayout'
title='流转进度'
extra={
<Radio.Group
onChange={(e) => setLogStatesItem(e.target.value)}
value={logStatesItem}
>
{effect.map((item: any, index: number) => {
return (<Radio.Button value={item} key={index}>{item.title}</Radio.Button>)
})}
</Radio.Group>
}
>
<Steps
progressDot
>
{logStatesItem && logStatesItem.logs?.map(item => (
<Steps.Step
key={item.state}
title={item.roleName}
description={item.operationalProcess}
status={item.isExecute ? 'finish' : 'wait'}
/>
))}
</Steps>
</Card>
)
}
export default ProgressLayout
.list {
display: flex;
h5 {
margin-bottom: 2em;
}
.listLable {
flex: 0 0 25%;
color: #909399;
}
}
\ No newline at end of file
import React, { useContext, useRef } from 'react';
import { Row, Col, Image, Tag, Tooltip, Switch, Typography } from 'antd';
import { StandardTable } from 'god';
import Card from '../../../card';
import { Context } from '../context';
import style from './index.less';
import { QuestionCircleOutlined } from '@ant-design/icons';
const TYPE = {
1: '发布至平台',
2: '系统匹配',
3: '邀请会员',
}
const ColStyle = {
display: 'flex',
alignItems: 'center',
border: '1px solid #1fbf87',
paddingTop: ' 6px',
paddingBottom: '6px',
margin: '5px',
borderRadius: '4px',
}
const TextStyle = {
color: '#1fbf87',
marginLeft: '10px',
}
export interface DemandLayoutIProps {
storeList?: any,
title?: string,
bidId: number,
number: string,
fetch?: () => Promise<unknown>
}
const DemandLayout: React.FC<DemandLayoutIProps> = (props: any) => {
const { storeList, title, bidId, number, fetch } = props;
const tableRef = useRef<any>({});
const context = useContext(Context);
const columns = [
{
title: '序号',
key: 'number',
dataIndex: 'number',
render: (text: any, record: any, index: number) => <>{index + 1}</>
},
{
title: '会员名称',
key: 'memberName',
dataIndex: 'memberName',
},
{
title: '会员类型',
key: 'memberTypeName',
dataIndex: 'memberTypeName',
},
{
title: '会员角色',
key: 'roleName',
dataIndex: 'roleName',
},
{
title: '会员等级',
key: 'levelTag',
dataIndex: 'levelTag',
},
{
title: '是否归属会员',
key: 'membershipOrNot',
dataIndex: 'membershipOrNot',
render: (text: any) => (<Tag color={text ? 'success' : 'error'}>{text ? '是' : '否'}</Tag>)
},
{
title: (
<>
<span>需求发送</span>
<Tooltip placement="top" title='打开开关,审核通过后,将发送需求至选择的归属会员'>
<QuestionCircleOutlined
style={{
marginLeft: '5px',
fontSize: '14px',
color: '#909399'
}}
/>
</Tooltip>
</>
),
key: 'state',
dataIndex: 'state',
render: (text: any) => (
<Switch checked={text} disabled={true} />
)
},
{
title: '操作',
key: 'operate',
dataIndex: 'operate',
render: (_text: any, _record: any) => (
<Typography.Link href={`/shop?shopId=${btoa(JSON.stringify({ roleId: _record.roleId, memberId: _record.memberId }))}`} target="_blank">
进入店铺
</Typography.Link>
)
},
]
/** 列表数据 */
const fetchData = (params?: any) => {
return new Promise((resolve, reject) => {
fetch({ id: bidId, number: number, ...params }).then(res => {
resolve(res.data)
})
})
}
return (
<Card
id='demandLayout'
title='需求对接'
>
<div className={style.list}>
<h5 className={style.listLable} style={{ flex: '0 0 100px' }}>{title}</h5>
<h5 className={style.listContent}>{TYPE[context.type]}</h5>
</div>
{context.type === 1
&& (
<Row gutter={[16, 16]}>
{storeList.map(item => (
<Col
span={6}
key={item.id}
style={ColStyle}
>
<Image width={32} height={32} src={item.logoUrl} />
<span style={TextStyle}>{item.name}</span>
</Col>
))}
</Row>
)}
{context.type !== 1
&& (
<StandardTable
currentRef={tableRef}
columns={columns}
tableProps={{ rowKew: 'id' }}
fetchTableData={(params: any) => fetchData(params)}
/>
)}
</Card>
)
}
DemandLayout.defaultProps = {
title: '发布方式'
}
export default DemandLayout;
import React, { useRef, useImperativeHandle } from 'react';
import { StandardTable } from 'god';
import { ColumnType } from 'antd/lib/table/interface';
import { createFormActions, FormEffectHooks } from '@formily/antd';
import { Row, Col, Space, Button, Typography, Popconfirm, Badge, Tag, Menu, Drawer } from 'antd';
import { FORM_FILTER_PATH } from '@/formSchema/const';
import NiceForm from '@/components/NiceForm';
import { useStateFilterSearchLinkageEffect } from '@/formSchema/effects/useFilterSearch';
import { PublicApi } from '@/services/api';
const { Text } = Typography;
const formActions = createFormActions();
const QuotationDetailsDrawer = (props: any) => {
const { visible, onClose, schemaType, effects, reload, fetch, quotationDetailsId, number } = props;
const tableRef = useRef<any>({});
const columns: ColumnType<any>[] = [{
title: '序号',
align: 'center',
dataIndex: 'id',
key: 'id',
render: (t, r, i) => ++i
}, {
title: '物料编号/摘要',
key: 'number',
dataIndex: 'number',
render: (text: any, record: any) => (
<Space direction='vertical'>
<Text type='secondary'>{text}</Text>
<Text type='secondary'>{record.details}</Text>
</Space>
)
}, {
title: '规格型号',
key: 'model',
dataIndex: 'model',
render: (text: any, record: any) => text,
}, {
title: '品类',
key: 'category',
dataIndex: 'category',
render: (text: any, record: any) => text,
}, {
title: '品牌',
key: 'brand',
dataIndex: 'brand',
render: (text: any, record: any) => text,
}, {
title: '采购数量/单位',
key: 'purchaseCount',
dataIndex: 'purchaseCount',
render: (text: any, record: any) => (
<Space direction='vertical'>
<Text type='secondary'>{text}</Text>
<Text type='secondary'>{record.unit}</Text>
</Space>
),
}, {
title: '含税/税率',
key: 'isTax',
dataIndex: 'isTax',
render: (text: any, record: any) => (
<Space direction='vertical'>
<Text type='secondary'>{text === 1 ? '是' : '否'}</Text>
<Text type='secondary'>{record.taxRate}%</Text>
</Space>
),
}, {
title: '单价(含税)',
key: 'unitPrice',
dataIndex: 'unitPrice',
render: (text: any, record: any) => ${text}`,
}, {
title: '金额(含税)',
key: 'price',
dataIndex: 'price',
render: (text: any, record: any) => ${text}`,
}];
/** 列表数据 */
const fetchData = (params?: any) => {
return new Promise((resolve, reject) => {
visible && fetch({ id: quotationDetailsId, number: number, ...params }).then(res => {
resolve(res.data)
})
})
}
// 搜索
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);
}}
// schema={
// schemaType && SchemaRender()
// }
>
</NiceForm>
}
/>
</Drawer>
)
}
export default QuotationDetailsDrawer
.trendTag {
color: #E63F3B;
background-color: #FFEBE6;
padding: 0 2px;
}
import React from 'react'
import { CaretDownOutlined } from '@ant-design/icons'
import styles from './index.less';
interface TrendTagProps {
ratio?: any
}
const TrendTag: React.FC<TrendTagProps> = (props: any) => {
const { ratio } = props;
return (
<div className={styles.trendTag}>
<CaretDownOutlined style={{ color: '#E63F3B', fontSize: '10px', marginRight: '2px' }} />
{ratio}%
</div>
)
}
export default TrendTag
\ No newline at end of file
/** 价单外部状态颜色 */
export const BID_EXTERNALSTATE_COLOR = {
'-1': 'error',
99: 'success',
1: 'default',
2: 'warning',
3: 'warning',
4: 'warning',
5: 'default',
6: 'processing',
7: 'error',
8: 'error',
}
/** 报价内部状态颜色 */
export const BID_INTERNALSTATE_COLOR = {
'-1': 'error',
99: 'success',
1: 'default',
2: 'warning',
3: 'warning',
4: 'processing',
8: 'error',
9: 'error',
10: 'default',
11: 'error',
}
\ No newline at end of file
......@@ -13,11 +13,10 @@ import Table from '../../components/table';
import ModalOperate from '../../components/modalOperate';
import {
OFFTER_EXTERNALSTATE,
OFFTER_EXTERNALSTATE_COLOR,
} from '../../constants';
BID_EXTERNALSTATE_COLOR,
BID_INTERNALSTATE_COLOR
} from '../../constants/purchaseBid';
const { Text } = Typography;
......@@ -33,7 +32,7 @@ const ExamineSearch = () => {
render: (text: any, record: any) => (
<Space direction='vertical'>
<EyePreview
url={`/purchase/demand/demandInquiry/preview?id=${record.id}&number=${record.biddingNo}`}>{text}</EyePreview>
url={`/purchaseBid/demand/examineSearch/detail?id=${record.id}&number=${record.biddingNo}`}>{text}</EyePreview>
<Text type="secondary">{record.details}</Text>
</Space>
)
......@@ -60,7 +59,7 @@ const ExamineSearch = () => {
title: '外部状态',
key: 'externalState',
dataIndex: 'externalState',
render: (text: any, record: any) => <Tag color={OFFTER_EXTERNALSTATE_COLOR[text]}>{record.externalStateName}</Tag>
render: (text: any, record: any) => <Tag color={BID_EXTERNALSTATE_COLOR[text]}>{record.externalStateName}</Tag>
}, {
title: '操作',
key: 'operate',
......
......@@ -10,11 +10,10 @@ import { PublicApi } from '@/services/api';
import Table from '../../components/table';
import {
OFFTER_EXTERNALSTATE,
OFFTER_EXTERNALSTATE_COLOR,
} from '../../constants';
BID_EXTERNALSTATE_COLOR,
BID_INTERNALSTATE_COLOR
} from '../../constants/purchaseBid';
const { Text } = Typography;
......@@ -27,7 +26,7 @@ const Search = () => {
render: (text: any, record: any) => (
<Space direction='vertical'>
<EyePreview
url={`/purchase/demand/demandInquiry/preview?id=${record.id}&number=${record.biddingNo}`}>{text}</EyePreview>
url={`/purchaseBid/demand/search/detail?id=${record.id}&number=${record.biddingNo}`}>{text}</EyePreview>
<Text type="secondary">{record.details}</Text>
</Space>
)
......@@ -54,7 +53,7 @@ const Search = () => {
title: '外部状态',
key: 'externalState',
dataIndex: 'externalState',
render: (text: any, record: any) => <Tag color={OFFTER_EXTERNALSTATE_COLOR[text]}>{record.externalStateName}</Tag>
render: (text: any, record: any) => <Tag color={BID_EXTERNALSTATE_COLOR[text]}>{record.externalStateName}</Tag>
}];
return (
......
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