Commit 9b3ec29f authored by 前端-黄佳鑫's avatar 前端-黄佳鑫

🦄 refactor: 商品询价/报价/物流重构

parent 01bc3f48
import React from 'react';
export interface CardType {
id?: string,
title?: string,
extra?: React.ReactNode,
backgroundColor?: string,
}
const Card: React.FC<CardType> = (props: any) => {
const { id, title, extra, children, backgroundColor } = props;
return (
<div id={id} className='ant-card ant-card-bordered' style={{ overflow: 'hidden' }}>
<div className='ant-card-head' style={{ padding: 0, backgroundColor: backgroundColor ? backgroundColor : 'transparent' }}>
<div className='ant-card-head-wrapper' style={{ padding: '12px 16px' }}>
<div className='ant-card-head-wrapper' style={{ color: backgroundColor ? '#FFF' : '#303133', fontWeight: 'bold' }}>
{title}
</div>
{extra &&
<div className='ant-card-extra'>
{extra}
</div>
}
</div>
</div>
<div className='ant-card-body'>
{children}
</div>
</div>
)
}
export default Card;
.cell {
display: flex;
h5 { margin-bottom: 2em; }
.label {
flex: 0 0 25%;
color: #909399;
}
.content {
flex: 0 0 70%;
}
}
/** 详情通用 - 基本信息 */
import React from 'react';
import { Row, Col } from 'antd';
import Card from '../../../card';
import style from './index.less';
export interface BasicInfoProps {
effect?: any,
}
const count = 0;
const BasicLayout: React.FC<BasicInfoProps> = (props: any) => {
const { effect } = props;
return (
<Card
id='basicLayout'
title='基本信息'
>
<Row gutter={[8, 8]}>
{effect.length > count && effect.map((item, index) => (
<Col key={`effect_${index + 1}`} span={8}>
{ item.col.map((it, idx) => (
<div className={style.cell} key={`effect_col_${idx + 1}`}>
<h5 className={style.label}>{it.label}: </h5>
<h5 className={style.content}>{it.extra}</h5>
</div>
))}
</Col>
))}
</Row>
</Card>
)
}
export default BasicLayout
import { createContext } from 'react';
/** 详情 */
export const Context = createContext<any>({})
/**招标详情 Context */
export const BidDetailContext = createContext<any>({})
/**采购竞价单详情 Context */
export const PurchaseBidContext = createContext<any>({})
.cell {
display: flex;
h5 { margin-bottom: 2em; }
.label {
flex: 0 0 25%;
color: #909399;
}
}
/** 详情通用 - 基本信息 */
import React, { ReactNode } from 'react';
import { Row, Col } from 'antd';
import Card from '../../../card';
import style from './index.less';
export interface GeneraInfoProps {
/** 数据 */
effect?: any,
/** 锚点 */
anchor?: string,
/** 标题 */
title: string,
/** extra */
extra?: ReactNode,
}
const count = 0;
const GeneralLayout: React.FC<GeneraInfoProps> = (props: any) => {
const { effect, anchor, title, extra } = props;
return (
<Card
id={anchor}
title={title}
extra={extra}
>
<Row gutter={[8, 8]}>
{effect.length > count && effect.map((item, index) => (
<Col key={`effect_${index + 1}`} span={8}>
{ item.col.map((it, idx) => (
<div className={style.cell} key={`effect_col_${idx + 1}`}>
<h5 className={style.label}>{it.label}: </h5>
<h5 className={style.content}>{it.extra}</h5>
</div>
))}
</Col>
))}
</Row>
</Card>
)
}
export default GeneralLayout
import React, { useRef } from 'react';
import { Table } from 'antd';
import { StandardTable } from 'god';
import { ColumnType } from 'antd/lib/table/interface';
import Card from '../../../card';
export interface ListLayoutIProps {
/** 锚点 */
anchor?: string,
/** id */
id?: string | number,
/** 标题 */
title: string,
/** columns */
columns: ColumnType<any>[],
/** 接口 */
fetch?: () => Promise<unknown>,
/** 是否请求 */
done?: boolean,
/** 展示的数据 */
data?: [],
}
const ListLayout: React.FC<ListLayoutIProps> = (props: any) => {
const { anchor, id, title, columns, fetch, done, data } = props;
const currentRef = useRef({});
const fetchTableData = (params: any) => {
return new Promise(resolve => {
fetch({ id, ...params }).then((res: any) => {
resolve(res.data)
})
})
}
return (
<Card
id={anchor}
title={title}
>
{!done && (
<StandardTable
currentRef={currentRef}
columns={columns}
tableProps={{ rowKey: 'id' }}
fetchTableData={(params: any) => fetchTableData(params)}
/>
)}
{done && (
<Table
rowKey="id"
columns={columns}
dataSource={data}
pagination={false}
/>
)}
</Card>
)
}
export default ListLayout
/** 详情通用 - 流转进度 */
import React, { useContext, useState } from 'react';
import { Radio, Steps } from 'antd';
import { Context } from '../context';
import Card from '../../../card';
import style from './index.less';
const LOGSTATESTYPE = {
/** 外部流转 */
EXTERNALSTATES: 1,
/** 内部流转 */
INTERIORSTATES: 2,
/** 竞价结果内部流转 */
EXMAINEINERIORSTATES: 3
}
export interface ProgressProps {
/** 选中哪个radio */
logstate?: number,
}
const ProgressLayout: React.FC<ProgressProps> = (props: any) => {
const { logstate } = props;
const context = useContext(Context);
const [logStatesStatus, setLogStatesStatus] = useState<number>( logstate || LOGSTATESTYPE.EXTERNALSTATES);
return (
<Card
id='progressLayout'
title='流转进度'
extra={
<Radio.Group
onChange={(e) => setLogStatesStatus(e.target.value)}
defaultValue={logStatesStatus}
>
{context.externalLogStates && <Radio.Button value={LOGSTATESTYPE.EXTERNALSTATES}>外部流转</Radio.Button>}
{context.interiorLogStates && <Radio.Button value={LOGSTATESTYPE.INTERIORSTATES}>内部流转</Radio.Button>}
{context.examineInteriorLogStates && <Radio.Button value={LOGSTATESTYPE.EXMAINEINERIORSTATES}>竞价结果内部流转</Radio.Button>}
</Radio.Group>
}
>
<Steps
progressDot
>
{logStatesStatus === LOGSTATESTYPE.EXTERNALSTATES ?
context.externalLogStates && context.externalLogStates.map(item => (
<Steps.Step
key={item.state}
title={item.operationalProcess}
description={item.roleName}
status={item.isExecute ? 'finish' : 'wait'}
/>
)) : (logStatesStatus === LOGSTATESTYPE.INTERIORSTATES ?
context.interiorLogStates && context.interiorLogStates.map(item => (
<Steps.Step
key={item.state}
title={item.operationalProcess}
description={item.roleName}
status={item.isExecute ? 'finish' : 'wait'}
/>
)) :
context.examineInteriorLogStates && context.examineInteriorLogStates.map(item => (
<Steps.Step
key={item.state}
title={item.operationalProcess}
description={item.roleName}
status={item.isExecute ? 'finish' : 'wait'}
/>
))
)
}
</Steps>
</Card>
)
}
export default ProgressLayout
import React from 'react';
import { ColumnType } from 'antd/lib/table/interface';
import { Typography, Tag } from 'antd';
import moment from 'moment';
export const EXTERNALSTATE_COLOR = (text) => {
switch (Number(text)) {
case -1:
case 7:
case 8:
return 'danger';
case 2:
case 3:
case 4:
return 'warning';
case 6:
return 'primary';
case 99:
return 'success';
default:
return 'default'
}
}
export const INTERNALSTATE_COLOR = (text) => {
switch (Number(text)) {
case -1:
case 8:
case 9:
case 11:
return 'error';
case 2:
case 3:
case 13:
case 14:
case 15:
return 'warning';
case 4:
case 12:
return 'processing';
case 99:
return 'success';
default:
return 'default';
}
}
const format = (text) => {
return <>{moment(text).format("YYYY-MM-DD HH:mm")}</>
}
const { Text } = Typography;
/** 外部流转记录 */
export const EXTERNALLOGS: ColumnType<any>[] = [
{
title: '流转顺序号',
key: 'index',
dataIndex: 'index',
render: (_text: any, _record: any, index: number) => <Text>{index + 1}</Text>
},
{
title: '操作角色',
key: 'roleName',
dataIndex: 'roleName',
},
{
title: '状态',
key: 'state',
dataIndex: 'state',
render: (_text: any, _record: any) => <Tag color={EXTERNALSTATE_COLOR(_text) || 'default'}>{_record.stateName}</Tag>
},
{
title: '操作',
key: 'operation',
dataIndex: 'operation',
},
{
title: '操作时间',
key: 'createTime',
dataIndex: 'createTime',
render: (_text: any, _record: any) => <Text>{format(_text)}</Text>
},
{
title: '审核意见',
key: 'auditOpinion',
dataIndex: 'auditOpinion',
},
]
/** 内部流转记录 */
export const INTERNALLOGS: ColumnType<any>[] = [
{
title: '流转顺序号',
key: 'index',
dataIndex: 'index',
render: (_text: any, _record: any, index: number) => <Text>{index + 1}</Text>
},
{
title: '操作人',
key: 'roleName',
dataIndex: 'roleName',
},
{
title: '部门',
key: 'department',
dataIndex: 'department',
},
{
title: '职位',
key: 'position',
dataIndex: 'position',
},
{
title: '状态',
key: 'state',
dataIndex: 'state',
render: (_text: any, _record: any) => <Tag color={INTERNALSTATE_COLOR(_text) || 'default'}>{_record.stateName}</Tag>
},
{
title: '操作',
key: 'operation',
dataIndex: 'operation',
},
{
title: '操作时间',
key: 'createTime',
dataIndex: 'createTime',
render: (_text: any, _record: any) => <Text>{format(_text)}</Text>
},
{
title: '审核意见',
key: 'auditOpinion',
dataIndex: 'auditOpinion',
},
]
/** 详情通用 - 流转进度 */
import React, { useContext, useState } from 'react';
import { Radio, Table } from 'antd';
import { Context } from '../context';
import Card from '../../../card';
import {
EXTERNALLOGS,
INTERNALLOGS,
} from './columns';
const LOGSTATESTYPE = {
/** 外部流转 */
EXTERNALSTATES: 1,
/** 内部流转 */
INTERIORSTATES: 2
}
export interface ProgressProps {
/** 选中哪个radio */
logstate?: number,
}
const RecordLayout: React.FC<ProgressProps> = (props: any) => {
const { logstate } = props;
const context = useContext(Context);
const [logStatus, setLogStatus] = useState<number>(context.externalLogs ? LOGSTATESTYPE.EXTERNALSTATES : LOGSTATESTYPE.INTERIORSTATES );
return (
<Card
id='recordLyout'
title='流转记录'
extra={
<Radio.Group
onChange={(e) => setLogStatus(e.target.value)}
defaultValue={context.externalLogs ? LOGSTATESTYPE.EXTERNALSTATES : LOGSTATESTYPE.INTERIORSTATES}
>
{/* {context.externalLogs && <Radio.Button value={LOGSTATESTYPE.EXTERNALSTATES}>外部流转</Radio.Button>}
{context.interiorLogs && <Radio.Button value={LOGSTATESTYPE.INTERIORSTATES}>内部流转</Radio.Button>} */}
<Radio.Button value={LOGSTATESTYPE.EXTERNALSTATES}>外部流转</Radio.Button>
<Radio.Button value={LOGSTATESTYPE.INTERIORSTATES}>内部流转</Radio.Button>
</Radio.Group>
}
>
<Table
columns={logStatus === LOGSTATESTYPE.EXTERNALSTATES ? EXTERNALLOGS : INTERNALLOGS}
dataSource={
logStatus === LOGSTATESTYPE.EXTERNALSTATES ?
context.externalLogs :
context.interiorLogs
}
rowKey={(record) => record.id}
pagination={{
hideOnSinglePage: true
}}
/>
</Card>
)
}
export default RecordLayout
.wrap {
.title {
display: flex;
align-items: center;
justify-content: space-between;
padding: 8px 16px;
.titleBox {
display: flex;
align-items: center;
.goBack {
font-size: 14px;
color: #909399;
}
.titleContext {
color: #303133;
font-size: 16px;
font-weight: 500;
margin-left: 8px;
}
}
}
.anchor {
display: flex;
padding: 0 16px;
}
.layout {
margin: 24px;
:global {
.ant-card {
margin-bottom: 24px;
.ant-card-head {
> .ant-card-head-wrapper {
padding: 12px 0;
}
}
.ant-card-extra {
padding: 0 0;
.ant-radio-button-wrapper {
height: 24px;
line-height: 23px;
}
.ant-radio-button-wrapper:hover {
color: #606266;
}
.ant-radio-button-wrapper-checked:not(.ant-radio-button-wrapper-disabled) {
color: #fff;
background: #6B778C;
border-color: #6B778C;
}
}
}
.god-table-control {
margin-bottom: 0;
}
}
}
:global {
.ant-anchor {
display: flex;
.ant-anchor-ink {
display: none;
}
.ant-anchor-link {
padding: 14px 0 !important;
margin: 0 16px;
.ant-anchor-link-title {
font-size: 14px;
color: #909399;
}
}
.ant-anchor-link-active {
position: relative;
border-bottom: 2px solid #00B37A;
box-sizing: border-box;
.ant-anchor-link-title {
font-weight: 500;
color: #303133;
}
}
}
}
}
import React, { useEffect, useState, useContext } from 'react';
import { Anchor } from 'antd';
import { Context } from './components/context';
import style from './index.less';
import { ArrowLeftOutlined } from '@ant-design/icons';
import { history } from 'umi';
const activeAnchorClassName = 'ant-anchor-link-active'
export type tabLink = {
id: string,
title: string
}
export interface IProps {
/** 单号 */
no?: string | React.ReactNode,
/** 详情描述 */
detail?: string,
/** 锚点Link */
tabLink?: Array<tabLink>,
/** 审核操作按钮放这 */
effect?: React.ReactNode,
/** 页面的组件 */
components?: React.ReactNode,
/** 隐藏头部分割线 */
hideBreak?: boolean,
}
const PeripheralLayout: React.FC<IProps> = (props: any) => {
const {
no,
detail,
tabLink,
effect,
components,
hideBreak
} = props;
const dataSource = useContext(Context)
/** the argument */
const [targetOffset, setTargetOffset] = useState<number | undefined>(undefined);
const [currLink, setCurrLink] = useState(activeAnchorClassName)
/** the event */
const onChange = (link) => {
if (link && currLink) {
setCurrLink('')
} else if (!link && !currLink) {
setCurrLink(activeAnchorClassName)
}
}
const onClick = (e) => {
e.preventDefault();
}
useEffect(() => {
setTargetOffset(window.innerHeight / 6);
}, [])
return (
<div className={style.wrap}>
<Anchor
targetOffset={targetOffset}
onChange={onChange}
onClick={onClick}
>
{/* 头部信息 */}
<div style={{ flex: 1 }}>
<div className={style.title}>
<div className={style.titleBox}>
<ArrowLeftOutlined className={style.goBack} onClick={() => history.goBack()} />
<span className={style.titleContext}>
{detail ? detail : dataSource.details}
&nbsp;{!hideBreak && '|'}&nbsp;
{no}
</span>
</div>
{effect}
</div>
<div className={style.anchor}>
{tabLink.map((item, index) => (
<Anchor.Link
className={!index && currLink}
key={`link${index + 1}`}
href={`#${item.id}`}
title={item.title}
/>
))}
</div>
</div>
</Anchor>
<div className={style.layout}>
{components}
</div>
</div>
)
}
export default PeripheralLayout
.upload_item {
padding: 5px 8px;
margin-bottom: 16px;
display: flex;
align-items: center;
justify-content: space-between;
background-color: #FAFBFC;
.upload_left {
display: flex;
align-items: center;
color: #303133;
:global {
.anticon-file-word {
color: #4279df;
font-size: 20px;
margin-right: 8px;
}
}
}
.upload_right {
color: #00B37A;
cursor: pointer;
:global {
.anticon-delete {
margin-left: 19px;
color: #C0C4CC;
}
}
}
}
import React, { useEffect, useState, useContext } from 'react';
import {
Modal,
Form,
Input,
Button,
Upload,
message
} from 'antd';
import { UploadOutlined, LinkOutlined, DeleteOutlined } from '@ant-design/icons';
import { UPLOAD_TYPE } from '@/constants'
import style from './index.less'
import { PublicApi } from '@/services/api';
import { BidDetailContext } from '../components/context';
import { isEmpty, sumBy } from 'lodash';
const { TextArea } = Input;
export interface IProps {
id: number,
turn: number,
visible: boolean,
handleConfirm: () => void,
onCancel: () => void,
}
const BidModal: React.FC<IProps> = (props: any) => {
const [form] = Form.useForm();
const { id, turn, visible, handleConfirm, onCancel } = props;
const [files, setFiles] = useState([]);
const [loading, setloading] = useState(false);
const [priceParityInfos, setPriceParityInfos] = useState<any>([]);
const dataSource = useContext(BidDetailContext);
/**判断文件类型和大小 */
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])
}
// 删除附件
const removeFiles = (index: any) => {
const arr = [...files];
arr.splice(index, 1);
setFiles(arr);
}
useEffect(() => {
if (dataSource.length > 0) {
const arr: any = dataSource[0].company || [];
const params: any = [];
arr.forEach((it: any, idx: number) => {
let item = {
awardCount: it.awardCount,
id: it.id,
memberId: it.memberId,
memberName: it.memberName,
memberRoleId: it.memberRoleId,
minimum: it.minimum,
ranking: it.ranking,
subtotal: it.subtotal,
sumPrice: it.sumPrice,
awardInfoResponses: [],
}
let awardInfoResponses = [];
dataSource.forEach((item: any, index: number) => {
let cItem = {
brand: item.brand,
category: item.category,
goodsId: item.goodsId,
unit: item.unit,
model: item.model,
name: item.name,
number: item.number,
purchaseCount: item.purchaseCount,
awardTaxProbability: item.company[idx].awardTaxProbability,
taxPrice: item.company[idx].taxPrice,
taxProbability: item.company[idx].taxProbability,
taxUnitPrice: item.company[idx].taxUnitPrice,
isPrize: item.company[idx].isPrize,
isTax: item.company[idx].isTax,
id: item.company[idx].itemId,
}
awardInfoResponses.push(cItem)
})
item.awardInfoResponses = awardInfoResponses
params.push(item)
})
setPriceParityInfos(params)
}
}, [visible])
const handleSubmit = async () => {
try {
const values = await form.validateFields();
const params = {
id,
turn,
awardComments: values.awardComments,
urls: files,
priceParityInfos,
}
for(let i = 0; i < dataSource.length; i++) {
const count = sumBy(dataSource[i].company, 'awardTaxProbability');
if (count > 100 || count < 100) {
message.warning(`${dataSource[i].number}授标百分比分配不准确,请核对!`);
return
}
}
PublicApi.postPurchaseConfirmQuotedPriceSubmitContrastPrice(params).then(res => {
if (res.code === 1000) {
handleConfirm();
}
})
} catch (errInfo) {
console.log('Save failed:', errInfo);
}
}
return (
<Modal
title='提交审核'
visible={visible}
width={600}
onCancel={onCancel}
onOk={handleSubmit}
>
<Form form={form} layout="vertical">
<Form.Item
name='awardComments'
label='授标意见'
>
<TextArea />
</Form.Item>
<Form.Item label='附件' name='upload'>
<div className={style.upload_data}>
{files.length > 0 && files.map((v, index) => (
<div key={index} className={style.upload_item}>
<div className={style.upload_left}>
<LinkOutlined />
<span>{v.name}</span>
</div>
<div className={style.upload_right} onClick={() => removeFiles(index)}>
<DeleteOutlined />
</div>
</div>
))}
</div>
<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 BidModal;
import React, { useRef, useState, useImperativeHandle } from 'react';
import { PageHeaderWrapper } from '@ant-design/pro-layout';
import { Card } from 'antd';
import { StandardTable } from 'god';
import { FORM_FILTER_PATH } from '@/formSchema/const';
import { ColumnType } from 'antd/lib/table/interface';
import NiceForm from '@/components/NiceForm';
import { createFormActions, FormEffectHooks } from '@formily/antd';
import { useStateFilterSearchLinkageEffect } from '@/formSchema/effects/useFilterSearch';
import { useLinkageUtils } from '@/utils/formEffectUtils';
import { searchSelectGetSelectCategoryOptionEffect } from '@/pages/systemManage/effect';
const { onFormMount$ } = FormEffectHooks
interface Iprops {
/** 列表接口 */
fetch?: () => Promise<unknown>,
/** 多选返回 */
fetchRowkeys?(e: any),
/** 操作按钮 */
controllerBtns?: React.ReactNode,
/** 搜索的schema */
schema?: any,
/** 列表表头 */
columns: ColumnType<any>[],
/** schema搜索第一个的name */
effects?: string,
/** 是否多选 */
selectedRow?: boolean,
/** 刷新 */
reload?: any,
/** 外部状态数据 */
externalStatusFetch?: () => Promise<unknown>,
/** 内部状态数据 */
interiorStatusFetch?: () => Promise<unknown>,
}
const formActions = createFormActions();
const Table: React.FC<Iprops> = (props: any) => {
const {
schema,
columns,
effects,
fetch,
controllerBtns,
selectedRow,
reload,
fetchRowkeys,
externalStatusFetch,
interiorStatusFetch
} = props;
const tableRef = useRef<any>({});
/** 列表数据 */
const fetchData = (params?: any) => {
return new Promise((resolve, reject) => {
fetch({ ...params }).then(res => {
resolve(res.data)
})
})
}
/**多选 */
const [selectedRowKeys, setSelectedRowKeys] = useState<Array<number>>([]);
const rowSelection = {
selectedRowKeys: selectedRowKeys,
onChange: (rowKeys: any) => {
console.log(rowKeys, 98)
fetchRowkeys(rowKeys)
setSelectedRowKeys(rowKeys);
},
}
useImperativeHandle(reload, () => ({
reload: () => {
tableRef.current.reload();
}
}));
// 搜索
const search = (values: any) => {
tableRef.current.reload(values)
}
const useBusinessEffects = () => {
const linkage = useLinkageUtils();
onFormMount$().subscribe(() => {
externalStatusFetch && externalStatusFetch().then(res => {
const _enum = res.data.map((item) => { return { label: item.name, value: item.state } })
linkage.enum('externalState', _enum)
linkage.enum('externalStatusList', _enum)
})
interiorStatusFetch && interiorStatusFetch().then(res => {
const _enum = res.data.map((item) => { return { label: item.name, value: item.state } })
linkage.enum('interiorState', _enum)
linkage.enum('innerStatusList', _enum)
})
})
}
return (
<PageHeaderWrapper>
<Card>
<StandardTable
currentRef={tableRef}
columns={columns}
tableProps={{ rowKew: 'id' }}
rowSelection={selectedRow && rowSelection}
fetchTableData={(params: any) => fetchData(params)}
controlRender={
<NiceForm
actions={formActions}
components={{
controllerBtns: () => controllerBtns,
}}
onSubmit={values => search(values)}
effects={($, actions) => {
useStateFilterSearchLinkageEffect($, actions, effects, FORM_FILTER_PATH)
FormEffectHooks.onFieldChange$('category').subscribe(state => {
searchSelectGetSelectCategoryOptionEffect(actions, 'category')
})
useBusinessEffects();
}}
schema={schema}
>
</NiceForm>
}
/>
</Card>
</PageHeaderWrapper>
)
}
export default Table;
/** 外部状态 */
export const EXTERNALSTATE_COLOR: any = (text) => {
switch (Number(text)) {
case -1:
case 7:
case 8:
return 'danger';
case 2:
case 3:
case 4:
return 'warning';
case 6:
return 'primary';
case 99:
return 'success';
default:
return 'default'
}
}
/** 内部状态 */
export const INTERNALSTATE_COLOR: any = (text) => {
switch (Number(text)) {
case -1:
case 8:
case 9:
case 11:
return 'error';
case 2:
case 3:
case 13:
case 14:
case 15:
return 'warning';
case 4:
case 12:
return 'processing';
case 99:
return 'success';
default:
return 'default';
}
}
This diff is collapsed.
/* @Author: H_Jiax */
import React, { ReactNode, useRef } from 'react';
import React, { useRef } from 'react';
import { Card } from 'antd';
import { StandardTable } from 'god';
import { logisticsSearchSchema } from './schema'
import { ColumnType } from 'antd/lib/table/interface';
import { history } from 'umi';
import { PublicApi } from '@/services/api';
import statuStyle from './colorTag';
import moment from 'moment';
import NiceForm from '@/components/NiceForm';
import { useStateFilterSearchLinkageEffect } from '@/formSchema/effects/useFilterSearch';
import { FORM_FILTER_PATH } from '@/formSchema/const';
import { createFormActions } from '@formily/antd';
import { createFormActions, FormEffectHooks } from '@formily/antd';
import { EyeOutlined } from '@ant-design/icons';
import StatusTag from '@/components/StatusTag';
import { useLinkageUtils } from '@/utils/formEffectUtils';
const formActions = createFormActions();
const { onFormMount$ } = FormEffectHooks
const EXTERNALSTATE_COLOR: any = (text) => {
switch (Number(text)) {
case 1:
return 'warning';
case 2:
return 'primary';
case 3:
return 'danger';
case 4:
return 'success';
default:
return 'default'
}
}
const OrderSearchList: React.FC<{}> = (props) => {
const ref = useRef<any>({})
......@@ -81,27 +98,31 @@ const OrderSearchList: React.FC<{}> = (props) => {
title: '外部状态',
dataIndex: 'status',
key: 'status',
render: (_: any, reconds) => {
let component: ReactNode = null
if (reconds.status == 4) {
component = <span style={statuStyle.success}>接受物流单</span>
} else if (reconds.status == 3) {
component = <span style={statuStyle.error}>不接受物流单</span>
} else if (reconds.status == 2) {
component = <span style={statuStyle.confirm}>待确认</span>
} else if (reconds.status == 1) {
component = <span style={statuStyle.default}>待提交</span>
}
return component
}
render: (text: any, record) => <StatusTag type={EXTERNALSTATE_COLOR(text)} title={record.statusName} />
}
]
const search = (values: any) => {
ref.current.reload(values)
}
const useBusinessEffects = () => {
const linkage = useLinkageUtils();
onFormMount$().subscribe(() => {
PublicApi.getLogisticsOrderSubmitStatusList().then(res => {
if (res.code !== 1000) {
return
}
linkage.enum("status", res.data.map(item => {
return {
label: item.message,
value: item.code
}
}))
})
})
}
return (
<Card>
<StandardTable
......@@ -115,6 +136,7 @@ const OrderSearchList: React.FC<{}> = (props) => {
onSubmit={values => search(values)}
effects={($, actions) => {
useStateFilterSearchLinkageEffect($, actions, 'logisticsOrderNo', FORM_FILTER_PATH)
useBusinessEffects();
}}
schema={logisticsSearchSchema}
>
......
......@@ -86,20 +86,7 @@ export const logisticsSearchSchema: ISchema = {
"x-component-props":{
placeholder:'外部状态'
},
enum: [
{
label: '待提交', value: 1
},
{
label: '待确认', value: 2
},
{
label: '不接受物流单', value: 3
},
{
label: '接受物流单', value: 4
}
]
enum: []
},
}
},
......
import React, { useRef, ReactNode } from 'react';
import { PageHeaderWrapper } from '@ant-design/pro-layout';
import { Card, Tag } from 'antd';
import { StandardTable } from 'god';
import { ColumnType } from 'antd/lib/table/interface';
import NiceForm from '@/components/NiceForm';
import { createFormActions, FormEffectHooks } from '@formily/antd';
import { useStateFilterSearchLinkageEffect } from '@/formSchema/effects/useFilterSearch';
import {searchSelectGetSelectCategoryOptionEffect} from '../../systemManage/effect'
import { FORM_FILTER_PATH } from '@/formSchema/const';
import { rfqSearchSchema } from '../schema';
import moment from 'moment';
import React, { useEffect, useState } from 'react';
import Table from '@/components/TableLayout';
import { ColumnType } from 'antd/lib/table';
import EyePreview from '@/components/EyePreview';
import { timeRange } from '@/utils/index';
import moment from 'moment';
import StatusTag from '@/components/StatusTag';
import { EXTERNALSTATE_COLOR } from '@/components/TableLayout/stateColor';
import { INQUIRYORDERSEARCHSCHEMA } from '../schema';
import { PublicApi } from '@/services/api';
const formActions = createFormActions();
const List:React.FC<{}> = () => {
const ref = useRef<any>({});
const InquiryOrderSearch = () => {
const format = (text) => {
return <>{moment(text).format("YYYY-MM-DD HH:mm:ss")}</>
}
const ExternalState = (text:any) => {
let component: ReactNode = null;
text === 1 ? component = <Tag color="default">提交询价单</Tag>:
text === 2 ? component = <Tag color="processing">提交报价单</Tag>:
text === 3 ? component = <Tag color="warning">确认报价单</Tag>:
text === 4 ? component = <Tag color="success">报价通过</Tag>:
component = <Tag color="error">报价不通过</Tag>
return component;
}
// 表头
const columns: ColumnType<any>[] = [{
title: '询价单号',
key: 'inquiryListNo',
dataIndex: 'inquiryListNo',
render: (text: any, record: any) => <EyePreview
url={`/rfq/details?id=${record.id}`}>{text}</EyePreview>
},{
title: '询价单摘要',
key: 'details',
dataIndex: 'details',
},{
title: '询价会员',
key: 'inquiryListMemberName',
dataIndex: 'inquiryListMemberName',
},{
title: '被询价会员',
key: 'memberName',
dataIndex: 'memberName',
},{
title: '交付日期',
key: 'deliveryTime',
dataIndex: 'deliveryTime',
render: (text: any, record: any) => format(text)
},{
title: '报价截止时间',
key: 'quotationAsTime',
dataIndex: 'quotationAsTime',
render: (text: any, record: any) => format(text)
},{
title: '单据时间',
key: 'voucherTime',
dataIndex: 'voucherTime',
render: (text: any, record: any) => format(text)
},{
title: '外部状态',
key: 'externalState',
dataIndex: 'externalState',
render: (text: any, record: any) => ExternalState(text)
}]
const fecheData = (params:any) => {
return new Promise((resolve, reject) => {
PublicApi.getOrderPlatformInquiryList({...params}).then(res => {
resolve(res.data)
})
})
}
// 搜索
const search = (values: any) => {
if (values.voucherTime) {
values.startDocumentsTime = timeRange(values.voucherTime).st
values.endDocumentsTime = timeRange(values.voucherTime).et
delete values.voucherTime
const columns: ColumnType<any>[] = [
{
title: '询价单号',
key: 'inquiryListNo',
dataIndex: 'inquiryListNo',
render: (text: any, record: any) => <EyePreview
url={`/rfq/details?id=${record.id}`}>{text}</EyePreview>
},
{
title: '询价单摘要',
key: 'details',
dataIndex: 'details',
},
{
title: '询价会员',
key: 'inquiryListMemberName',
dataIndex: 'inquiryListMemberName',
},
{
title: '被询价会员',
key: 'memberName',
dataIndex: 'memberName',
},
{
title: '交付日期',
key: 'deliveryTime',
dataIndex: 'deliveryTime',
render: (text: any, record: any) => format(text)
},
{
title: '报价截止时间',
key: 'quotationAsTime',
dataIndex: 'quotationAsTime',
render: (text: any, record: any) => format(text)
},
{
title: '单据时间',
key: 'voucherTime',
dataIndex: 'voucherTime',
render: (text: any, record: any) => format(text)
},
{
title: '外部状态',
key: 'externalState',
dataIndex: 'externalState',
render: (text: any, record: any) => <StatusTag type={EXTERNALSTATE_COLOR(text)} title={record.externalStateName} />
}
ref.current.reload(values)
}
return(
<PageHeaderWrapper>
<Card>
<StandardTable
currentRef={ref}
columns={columns}
tableProps={{ rowKew: 'id' }}
fetchTableData={(params:any) => fecheData(params)}
controlRender={
<NiceForm
actions={formActions}
onSubmit={values => search(values)}
effects={($, actions) => {
useStateFilterSearchLinkageEffect($,actions,'inquiryListNo',FORM_FILTER_PATH)
FormEffectHooks.onFieldChange$('category').subscribe(state => {
searchSelectGetSelectCategoryOptionEffect(actions,'category')
})
}}
schema={rfqSearchSchema}
>
</NiceForm>
}
>
]
</StandardTable>
</Card>
</PageHeaderWrapper>
return (
<Table
effects="inquiryListNo"
columns={columns}
schema={INQUIRYORDERSEARCHSCHEMA}
fetch={PublicApi.getTransactionPlatformInquiryList}
externalStatusFetch={PublicApi.getTransactionProductInquiryExternalStateEnum}
/>
)
}
export default List
export default InquiryOrderSearch;
import { ISchema} from '@formily/antd';
import { FORM_FILTER_PATH } from '@/formSchema/const';
import { ISchema } from "@formily/antd";
import { FORM_FILTER_PATH } from "@/formSchema/const";
/**
* @description: 询价单
* @param {type}
* @return {type}
* @param {type}
* @return {type}
*/
export const rfqSearchSchema: ISchema = {
type:'object',
properties:{
megalayout:{
type:'object',
"x-component":'mega-layout',
properties:{
inquiryListNo:{
type:'string',
"x-component":"Search",
"x-mega-props":{
export const INQUIRYORDERSEARCHSCHEMA: ISchema = {
type: "object",
properties: {
megalayout: {
type: "object",
"x-component": "mega-layout",
properties: {
inquiryListNo: {
type: "string",
"x-component": "Search",
"x-mega-props": {
},
"x-component-props":{
placeholder:'询价单号',
align: 'flex-left',
"x-component-props": {
placeholder: "询价单号",
align: "flex-left",
}
}
}
},
[FORM_FILTER_PATH]:{
type:'object',
"x-component":"flex-layout",
"x-component-props":{
rowStyle:{
justifyContent: 'flex-start',
flexWrap:'nowrap'
[FORM_FILTER_PATH]: {
type: "object",
"x-component": "flex-layout",
"x-component-props": {
rowStyle: {
justifyContent: "flex-start",
flexWrap: "nowrap"
},
colStyle:{//改变间隔
colStyle: {//改变间隔
marginRight: 20
}
},
properties:{
PRO_LAYOUT:{
type:'object',
"x-component":'mega-layout',
"x-mega-props":{
properties: {
PRO_LAYOUT: {
type: "object",
"x-component": "mega-layout",
"x-mega-props": {
span: 5
},
"x-component-props":{
"x-component-props": {
inline: true
},
properties:{
details:{
type:'string',
"x-component-props":{
placeholder:'询价单摘要'
properties: {
details: {
type: "string",
"x-component-props": {
placeholder: "询价单摘要"
}
},
inquiryListMemberName:{
type:'string',
"x-component-props":{
placeholder:'询价会员'
inquiryListMemberName: {
type: "string",
"x-component-props": {
placeholder: "询价会员"
}
},
memberName:{
type:'string',
"x-component-props":{
placeholder:'被询价会员'
},
memberName: {
type: "string",
"x-component-props": {
placeholder: "被询价会员"
}
},
voucherTime:{
type:'string',
"x-component-props":{
placeholder: '单据时间(全部)'
},
enum: [
{
label: '单据时间(全部)', value: 0
},
{
label: '今天', value: 1
},
{
label: '一周内', value: 2
},
{
label: '一个月内', value: 3
},
{
label: '三个月内', value: 4
},
{
label: '六个月内', value: 5
},
{
label: '一年内', value: 6
},
{
label: '一年前', value: 7
}
]
"[startDocumentsTime,endDocumentsTime]": {
type: 'string',
"x-component": "DateRangePickerUnix",
"x-component-props": {
placeholder: ['开始时间','结束时间'],
}
},
externalState:{
type:'string',
"x-component-props":{
placeholder:'外部状态'
},
enum: [
{
label: '提交询价单', value: 1
},
{
label: '提交报价单', value: 2
},
{
label: '确认报价单', value: 3
},
{
label: '报价通过', value: 4
},
{
label: '报价不通过', value: 5
externalState: {
type: "string",
"x-component-props": {
placeholder: "外部状态",
style: {
width: '160px'
}
]
},
enum: []
},
}
},
sumbit:{
"x-component":'Submit',
"x-mega-props":{
sumbit: {
"x-component": "Submit",
"x-mega-props": {
span: 1
},
"x-component-props":{
children:'查询'
"x-component-props": {
children: "查询"
}
}
}
}
}
}
\ No newline at end of file
}
import React, { useRef, ReactNode } from 'react';
import { PageHeaderWrapper } from '@ant-design/pro-layout';
import { Card, Tag } from 'antd';
import { StandardTable } from 'god';
import { ColumnType } from 'antd/lib/table/interface';
import NiceForm from '@/components/NiceForm';
import { createFormActions, FormEffectHooks } from '@formily/antd';
import { useStateFilterSearchLinkageEffect } from '@/formSchema/effects/useFilterSearch';
import {searchSelectGetSelectCategoryOptionEffect} from '../effect'
import { FORM_FILTER_PATH } from '@/formSchema/const';
import { rfqSearchSchema } from '../schema';
import moment from 'moment';
import React, { useEffect, useState } from 'react';
import Table from '@/components/TableLayout';
import { ColumnType } from 'antd/lib/table';
import EyePreview from '@/components/EyePreview';
import { timeRange } from '@/utils/index';
import moment from 'moment';
import StatusTag from '@/components/StatusTag';
import { EXTERNALSTATE_COLOR } from '@/components/TableLayout/stateColor';
import { OFFERORDERSEARCHSCHEMA } from '../schema';
import { PublicApi } from '@/services/api';
const formActions = createFormActions();
const List:React.FC<{}> = () => {
const OfferOrderSearch = () => {
const format = (text) => {
return <>{moment(text).format("YYYY-MM-DD HH:mm:ss")}</>
}
const ExternalState = (text:any) => {
let component: ReactNode = null;
text === 1 ? component = <Tag color="default">提交询价单</Tag>:
text === 2 ? component = <Tag color="processing">提交报价单</Tag>:
text === 3 ? component = <Tag color="warning">确认报价单</Tag>:
text === 4 ? component = <Tag color="success">报价通过</Tag>:
component = <Tag color="error">报价不通过</Tag>
return component;
}
const ref = useRef<any>({});
// 表头
const columns: ColumnType<any>[] = [{
title: '报价单号',
key: 'quotationNo',
dataIndex: 'quotationNo',
render: (text: any, record: any) => <EyePreview
url={`/rfqOffer/rfq/details?id=${record.id}`}>{text}</EyePreview>
},{
title: '询价单号',
key: 'inquiryListNo',
dataIndex: 'inquiryListNo',
render: (text: any, record: any) => <EyePreview
url={`/rfqOffer/inquiry/details?id=${record.inquiryListId}`}>{text}</EyePreview>
},{
title: '报价单摘要',
key: 'details',
dataIndex: 'details',
},{
title: '询价会员',
key: 'memberName',
dataIndex: 'memberName',
},{
title: '报价会员',
key: 'offerMemberName',
dataIndex: 'offerMemberName',
},{
title: '报价截止时间',
key: 'quotationAsTime',
dataIndex: 'quotationAsTime',
render: (text: any, record: any) => format(text)
},{
title: '单据时间',
key: 'voucherTime',
dataIndex: 'voucherTime',
render: (text: any, record: any) => format(text)
},{
title: '外部状态',
key: 'externalState',
dataIndex: 'externalState',
render: (text: any, record: any) => ExternalState(text)
}]
const fecheData = (params:any) => {
return new Promise((resolve, reject) => {
PublicApi.getOrderPlatformProductQuotationList({...params}).then(res => {
resolve(res.data)
})
})
}
// 搜索
const search = (values: any) => {
if (values.voucherTime) {
values.startDocumentsTime = timeRange(values.voucherTime).st
values.endDocumentsTime = timeRange(values.voucherTime).et
delete values.voucherTime
const columns: ColumnType<any>[] = [
{
title: '报价单号',
key: 'quotationNo',
dataIndex: 'quotationNo',
render: (text: any, record: any) => <EyePreview
url={`/rfqOffer/rfq/details?id=${record.id}`}>{text}</EyePreview>
},
{
title: '询价单号',
key: 'inquiryListNo',
dataIndex: 'inquiryListNo',
render: (text: any, record: any) => <EyePreview
url={`/rfqOffer/inquiry/details?id=${record.inquiryListId}`}>{text}</EyePreview>
},
{
title: '报价单摘要',
key: 'details',
dataIndex: 'details',
},
{
title: '询价会员',
key: 'memberName',
dataIndex: 'memberName',
},
{
title: '报价会员',
key: 'offerMemberName',
dataIndex: 'offerMemberName',
},
{
title: '报价截止时间',
key: 'quotationAsTime',
dataIndex: 'quotationAsTime',
render: (text: any, record: any) => format(text)
},
{
title: '单据时间',
key: 'voucherTime',
dataIndex: 'voucherTime',
render: (text: any, record: any) => format(text)
},
{
title: '外部状态',
key: 'externalState',
dataIndex: 'externalState',
render: (text: any, record: any) => <StatusTag type={EXTERNALSTATE_COLOR(text)} title={record.externalStateName} />
}
ref.current.reload(values)
}
return(
<PageHeaderWrapper>
<Card>
<StandardTable
currentRef={ref}
columns={columns}
tableProps={{ rowKew: 'id' }}
fetchTableData={(params:any) => fecheData(params)}
controlRender={
<NiceForm
actions={formActions}
onSubmit={values => search(values)}
effects={($, actions) => {
useStateFilterSearchLinkageEffect($,actions,'quotationNo',FORM_FILTER_PATH)
FormEffectHooks.onFieldChange$('category').subscribe(state => {
searchSelectGetSelectCategoryOptionEffect(actions,'category')
})
}}
schema={rfqSearchSchema}
>
</NiceForm>
}
>
]
</StandardTable>
</Card>
</PageHeaderWrapper>
return (
<Table
effects="quotationNo"
columns={columns}
schema={OFFERORDERSEARCHSCHEMA}
fetch={PublicApi.getTransactionPlatformProductQuotationList}
externalStatusFetch={PublicApi.getTransactionProductInquiryExternalStateEnum}
/>
)
}
export default List
\ No newline at end of file
export default OfferOrderSearch;
import { ISchema} from '@formily/antd';
import { FORM_FILTER_PATH } from '@/formSchema/const';
import { ISchema } from "@formily/antd";
import { FORM_FILTER_PATH } from "@/formSchema/const";
/**
* @description: 询价报价单
* @param {type}
* @return {type}
* @param {type}
* @return {type}
*/
export const rfqSearchSchema: ISchema = {
type:'object',
properties:{
megalayout:{
type:'object',
"x-component":'mega-layout',
properties:{
quotationNo:{
type:'string',
"x-component":"Search",
"x-mega-props":{
export const OFFERORDERSEARCHSCHEMA: ISchema = {
type: "object",
properties: {
megalayout: {
type: "object",
"x-component": "mega-layout",
properties: {
quotationNo: {
type: "string",
"x-component": "Search",
"x-mega-props": {
},
"x-component-props":{
placeholder:'报价单号',
align: 'flex-left',
"x-component-props": {
placeholder: "报价单号",
align: "flex-left",
}
}
}
},
[FORM_FILTER_PATH]:{
type:'object',
"x-component":"flex-layout",
"x-component-props":{
rowStyle:{
justifyContent: 'flex-start',
flexWrap:'nowrap'
[FORM_FILTER_PATH]: {
type: "object",
"x-component": "flex-layout",
"x-component-props": {
rowStyle: {
justifyContent: "flex-start",
flexWrap: "nowrap"
},
colStyle:{//改变间隔
colStyle: {//改变间隔
marginRight: 20
}
},
properties:{
PRO_LAYOUT:{
type:'object',
"x-component":'mega-layout',
"x-mega-props":{
properties: {
PRO_LAYOUT: {
type: "object",
"x-component": "mega-layout",
"x-mega-props": {
span: 5
},
"x-component-props":{
"x-component-props": {
inline: true
},
properties:{
inquiryListNo:{
type:'string',
"x-component-props":{
placeholder:'询价单号'
properties: {
inquiryListNo: {
type: "string",
"x-component-props": {
placeholder: "询价单号"
}
},
details:{
type:'string',
"x-component-props":{
placeholder:'报价单摘要'
details: {
type: "string",
"x-component-props": {
placeholder: "报价单摘要"
}
},
memberName:{
type:'string',
"x-component-props":{
placeholder:'询价会员'
memberName: {
type: "string",
"x-component-props": {
placeholder: "询价会员"
}
},
offerMemberName:{
type:'string',
"x-component-props":{
placeholder:'报价会员'
},
offerMemberName: {
type: "string",
"x-component-props": {
placeholder: "报价会员"
}
},
voucherTime:{
type:'string',
"x-component-props":{
placeholder: '单据时间(全部)'
},
enum: [
{
label: '单据时间(全部)', value: 0
},
{
label: '今天', value: 1
},
{
label: '一周内', value: 2
},
{
label: '一个月内', value: 3
},
{
label: '三个月内', value: 4
},
{
label: '六个月内', value: 5
},
{
label: '一年内', value: 6
},
{
label: '一年前', value: 7
}
]
"[startDocumentsTime,endDocumentsTime]": {
type: "string",
"x-component": "DateRangePickerUnix",
"x-component-props": {
placeholder: ["开始时间", "结束时间"],
}
},
externalState:{
type:'string',
"x-component-props":{
placeholder:'外部状态'
},
enum: [
{
label: '提交询价单', value: 1
},
{
label: '提交报价单', value: 2
},
{
label: '确认报价单', value: 3
},
{
label: '报价通过', value: 4
},
{
label: '报价不通过', value: 5
externalState: {
type: "string",
"x-component-props": {
placeholder: "外部状态",
style: {
width: "160px"
}
]
},
enum: []
},
}
},
sumbit:{
"x-component":'Submit',
"x-mega-props":{
sumbit: {
"x-component": "Submit",
"x-mega-props": {
span: 1
},
"x-component-props":{
children:'查询'
"x-component-props": {
children: "查询"
}
}
}
}
}
}
\ No newline at end of file
}
......@@ -19,6 +19,8 @@ import * as ReportApiV2 from './ReportV2Api';
import * as SettleV2Api from './SettleV2Api';
import * as MessageV2 from './MessageV2Api';
import * as MemberV2Api from './MemberV2Api';
import * as LogisticsV2Api from './LogisticsV2Api';
import * as TransactionV2Api from './TransactionV2Api';
/**
......@@ -51,4 +53,6 @@ export const PublicApi = {
...SettleV2Api,
...MessageV2,
...MemberV2Api,
...LogisticsV2Api,
...TransactionV2Api,
}
......@@ -20,6 +20,8 @@ const tokenList = [
{ name: 'ReportV2', token: 'dab50c384c27f1c981a03f2c44ad76d1e7e1f60b4520bd279cea67f5cf146cee', categoryIds: [0] }, // 报表服务v2
{ name: 'SettleV2', token: 'fed8d45aa92e7f0e382a3dcc5e0ef63f13f0badeabab76d6a6e2db49aa403346', categoryIds: [0] }, //结算服务v2
{ name: 'MessageV2', token: '69a667ec9861e8bdc25b89238d0b908a2123d9fce26e72fec3cdf6cd0b1f2681', categoryIds: [0] }, // 消息服务v2
{ name: 'LogisticsV2', token: '732fb8e33970ff5dee830423a630e8e85c3ef3293abba7581b16749dfce8608b', categoryIds: [0] }, // 物流服务V2
{ name: 'TransactionV2', token: '98fe6ad41a8e1834b017b4795e8cddff5c3def48282ba3d239da5558ca9fc234', categoryIds: [0] }, // 交易服务v2
]
const getConfigMap = (tokens) => tokens.map(v => ({
......
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