Commit 071580ba authored by 前端-黄佳鑫's avatar 前端-黄佳鑫

feat: 采购能力 -> 在线竞价国际化

parent 3378e9da
......@@ -141,6 +141,7 @@ const PurchaseLocales = {
'detail.purchase.signUpMsgLayout': '报名信息',
'detail.purchase.signUpFileLayout': '报名文件',
'detail.purchase.basicLayout': '基本信息',
'detail.purchase.winBidResultLayout': '中标结果',
'detail.purchase.basicLayout1': '基本流程',
'detail.purchase.offerLayout': '报价信息',
'detail.purchase.offerExplain': '报价说明',
......@@ -193,12 +194,13 @@ const PurchaseLocales = {
'detail.purchase.contactsMessage': '请输入联系人姓名',
'detail.purchase.telPhone': '联系人手机',
'detail.purchase.telPrefix': '请选择区号',
'detail.purchase.tel': '请输入你的手机号码',
'detail.purchase.tel': '请输入手机号码',
'detail.purchase.quotedDetails1': '报价摘要',
'detail.purchase.quotedPriceNo': '报价单号',
'detail.purchase.quotedMenber': '报价会员',
'detail.purchase.purchaseMaterial': '对应采购物料',
'detail.purchase.file': '附件',
'detail.purchase.quotationRecordLayout': '最低报价记录',
'detail.purchase.option': '操作',
'detail.purchase.demandCycle': '需求计划周期',
'detail.purchase.correspondence': '对应',
......@@ -260,6 +262,7 @@ const PurchaseLocales = {
'detail.purchase.seeBidStep': '查看竞价过程',
'detail.purchase.cancelOffer': '取消报价',
'detail.purchase.statusBoxStatus': '当前状态',
'detail.purchase.startStill': '开始竞价',
'detail.purchase.stillRunStart': '竞价中',
'detail.purchase.stillRunend': '竞价结束',
'detail.purchase.distanceStillRunend': '距离竞价结束还剩',
......@@ -273,6 +276,8 @@ const PurchaseLocales = {
'detail.purchase.offerRule4': '按项目总价排名',
'detail.purchase.offerRule5': '按项目总价排名',
'detail.purchase.null': '无',
'detail.purchase.thanks': '感谢函',
'detail.purchase.respect': '尊敬的',
'detail.purchase.modalTitle': '公开招标',
'detail.purchase.modalTitle1': '选择货品',
......@@ -346,6 +351,11 @@ const PurchaseLocales = {
'detail.purchase.message54': '请选择交付日期',
'detail.purchase.message55': '请选择交付地址',
'detail.purchase.message56': '请输入金额',
'detail.purchase.message57': '请上传附件',
'detail.purchase.message58': '请输入正确格式的手机号',
'detail.purchase.message59': '请输入电子邮箱',
'detail.purchase.message60': '请输入正确格式的邮箱',
'detail.purchase.message61': '请填写详细地址',
'detail.purchase.placeholder': '选择开始日期',
'detail.purchase.placeholder1': '确定要执行这个操作?',
......@@ -360,6 +370,9 @@ const PurchaseLocales = {
'detail.purchase.placeholder10': '请输入目标价',
'detail.purchase.placeholder11': '请输入最小价差',
'detail.purchase.placeholder12': '请输入报价次数',
'detail.purchase.placeholder13': '选择区域',
'detail.purchase.placeholder14': '请完善适用地市',
'detail.purchase.placeholder15': '请填写详细地址,路名、门牌号等,最长100个字符,50个汉字',
'detail.purchase.priceMethod': '比价方式',
'detail.purchase.purchaseType1': '有固定采购金额',
......@@ -387,6 +400,24 @@ const PurchaseLocales = {
'detail.purchase.tips15': '当前报价金额不满足最小价差要求,请修改后再报价!',
'detail.purchase.tips16': '当前报价次数已超过允许报价次数!',
'detail.purchase.label': '中标金额(含税!',
'detail.purchase.label1': '中标理由',
'detail.purchase.label2': '价格最低',
'detail.purchase.label3': '至',
'detail.purchase.label4': '第',
'detail.purchase.label5': '名',
'detail.purchase.label6': '次',
'detail.purchase.label7': '不公开',
'detail.purchase.label8': '第一名',
'detail.purchase.label9': '第二名',
'detail.purchase.label10': '第三名',
'detail.purchase.label11': '报价历史',
'detail.purchase.label12': '本次报价金额',
'detail.purchase.label13': '最近报价',
'detail.purchase.label14': '报名',
'detail.purchase.label15': '重新报名',
'detail.purchase.label16': '报名要求说明',
'detail.purchase.label17': '地址',
}
export default PurchaseLocales
......@@ -4,8 +4,11 @@ import moment from 'moment';
import { getAuth } from '@/utils/auth';
import style from './index.less'
import { getIntl } from 'umi';
const intl = getIntl();
interface ThankItemProps {
visible: boolean,
detail: any,
......@@ -17,7 +20,7 @@ const ThankItem: React.FC<ThankItemProps> = (props: any) => {
const userInfo = useMemo(() => getAuth(), [detail]);
return (
<Modal
title="感谢函"
title={intl.formatMessage({ id: 'detail.purchase.thanks' })}
visible={visible}
onOk={onOk}
onCancel={onOk}
......@@ -25,9 +28,9 @@ const ThankItem: React.FC<ThankItemProps> = (props: any) => {
className={style.thankModal}
>
<div className={style.thankLetter}>
<h2>感谢函</h2>
<h2>{intl.formatMessage({ id: 'detail.purchase.thanks' })}</h2>
<h4>THANKS LETTER</h4>
<p className={style.name}>尊敬的{userInfo.name}</p>
<p className={style.name}>{intl.formatMessage({ id: 'detail.purchase.respect' })}{userInfo.name}</p>
<p>{detail.content}</p>
<p className={style.company}>{detail.createMemberName}</p>
<p className={style.time}>{moment().format('YYYY-MM-DD')}</p>
......
......@@ -11,6 +11,9 @@ import TrendTag from '../../../../components/detail/components/trendTag';
import styles from './index.less';
import OfferItem from '../offer';
import { getIntl } from 'umi';
const intl = getIntl();
interface HistoryItemProps {
detail: any
......@@ -27,11 +30,11 @@ const HistoryItem: React.FC<HistoryItemProps> = (props: any) => {
const _number = Number(detail?.ranking ?? 0);
switch (_number) {
case 1:
return <img src={level1} alt="第一名" className={styles.icon} />;
return <img src={level1} alt={intl.formatMessage({ id: 'detail.purchase.label8' })} className={styles.icon} />;
case 2:
return <img src={level2} alt="第二名" className={styles.icon} />;
return <img src={level2} alt={intl.formatMessage({ id: 'detail.purchase.label9' })} className={styles.icon} />;
case 3:
return <img src={level3} alt="第三名" className={styles.icon} />;
return <img src={level3} alt={intl.formatMessage({ id: 'detail.purchase.label10' })}className={styles.icon} />;
default:
return <div className={styles.badge}>{_number}</div>
}
......@@ -41,22 +44,22 @@ const HistoryItem: React.FC<HistoryItemProps> = (props: any) => {
return (
<div className={styles.history}>
<div className={styles.historyHeader}>
<h5>报价历史</h5>
<h5>{intl.formatMessage({ id: 'detail.purchase.label11' })}</h5>
<div className={styles.box}>
{_returnBadge()}
<div className={styles.rightPosition}>
{firstData?.offerRatio ? <TrendTag ratio={firstData?.offerRatio} /> : ''}
</div>
<p>本次报价金额</p>
<p>{intl.formatMessage({ id: 'detail.purchase.label12' })}</p>
<p className={styles.currentPrice}><span>¥</span>{firstData?.offerPrice ? priceFormat(firstData?.offerPrice) : '-'}</p>
<div className={styles.row}>
<div className={styles.col} style={{ borderRight: '1px solid #EBECF0' }}>当前最低价:<span>{detail.isOpenPurchase ? (detail?.minLowPrice ? `¥${priceFormat(detail?.minLowPrice)}` : '-') : '不公开'}</span></div>
<div className={styles.col}>报价次数<span>{firstData?.offerCount ? firstData?.offerCount : '-'}</span></div>
<div className={styles.col} style={{ borderRight: '1px solid #EBECF0' }}>{intl.formatMessage({ id: 'detail.purchase.nowMinPrice1' })}<span>{detail.isOpenPurchase ? (detail?.minLowPrice ? `¥${priceFormat(detail?.minLowPrice)}` : '-') : '不公开'}</span></div>
<div className={styles.col}>{intl.formatMessage({ id: 'detail.purchase.allowPurchaseCount1' })}<span>{firstData?.offerCount ? firstData?.offerCount : '-'}</span></div>
</div>
</div>
</div>
<div className={styles.historyFootter}>
<h5>最近报价</h5>
<h5>{intl.formatMessage({ id: 'detail.purchase.label13' })}</h5>
{mapData && mapData.map((item) => {
return (<OfferItem key={item.offerTime} detail={{ ...item, isOpenRanking: detail.isOpenRanking, isOpenPurchase: detail.isOpenPurchase }} />)
})}
......
import React, { useEffect, useState } from 'react';
import { history } from 'umi';
import { getIntl, history } from 'umi';
import { Row, Col } from 'antd';
import { ArrowLeftOutlined } from '@ant-design/icons';
import { isEmpty } from 'lodash'
......@@ -18,6 +18,8 @@ import IMBtn from '../../../components/detail/components/iMBtn';
import HistoryItem from './history';
const intl = getIntl();
import styles from './index.less';
......@@ -69,8 +71,8 @@ const Detail = () => {
data.minLowPrice = socketObj.minLowPrice;
}
data.onlineId = Number(onlineId);
let _data : any = {...data};
_data?.offerLogs.forEach((item,index,arr) => {
let _data: any = { ...data };
_data?.offerLogs.forEach((item, index, arr) => {
const _arrLength = arr.length;
if (index != _arrLength - 1 && _arrLength > 2) {
_data.offerLogs[index].offerRatio = Number(((item.offerPrice - arr[index + 1].offerPrice) / arr[index + 1].offerPrice * 100).toFixed(2))
......@@ -87,12 +89,12 @@ const Detail = () => {
_quotationDesks.forEach((item) => {
_offerList.push({ type: 'offer', time: formatTimeString(item.offerTime || item.peportTime, 'HH:mm:ss'), value: priceFormat(item.price || item.sumPice, 0) });
})
_list.push({ title: '报价金额', type: 'offer', list: _offerList });
_list.push({ title: intl.formatMessage({ id: 'detail.purchase.label4' }), type: 'offer', list: _offerList });
if (data.isOpenPurchase) {
_quotationDesks.forEach((item) => {
_minList.push({ type: 'min', time: formatTimeString(item.offerTime || item.peportTime, 'HH:mm:ss'), value: priceFormat(item.minPrice, 0) });
})
_list.push({ title: '最低价', type: 'min', list: _minList });
_list.push({ title: intl.formatMessage({ id: 'detail.purchase.minPrice1' }), type: 'min', list: _minList });
}
setChartsList(_list)
})
......
......@@ -6,9 +6,9 @@ import { priceFormat } from '@/utils/numberFomat';
import TrendTag from '../../../../components/detail/components/trendTag';
import styles from './index.less';
import { getIntl } from 'umi';
const intl = getIntl();
interface OfferItemProps {
detail: any
}
......@@ -17,14 +17,14 @@ const OfferItem: React.FC<OfferItemProps> = (props: any) => {
const { detail } = props;
return (
<div className={styles.offerItem}>
<div className={styles.left}>{detail.isOpenRanking ? `第${detail.ranking}名` : '不公开'}</div>
<div className={styles.left}>{detail.isOpenRanking ? `${intl.formatMessage({ id: 'detail.purchase.label4' })}${detail.ranking}${intl.formatMessage({ id: 'detail.purchase.label5' })}` : intl.formatMessage({ id: 'detail.purchase.label7' })}</div>
<div className={styles.right}>
<div className={styles.row}>
<div className={styles.rowPrice}>
<span>¥ {priceFormat(detail.offerPrice)}</span>
当前最低价{detail.isOpenPurchase ? `¥${priceFormat(detail.minPrice)}` : '不公开'}
{intl.formatMessage({ id: 'detail.purchase.nowMinPrice1' })}{detail.isOpenPurchase ? `¥${priceFormat(detail.minPrice)}` : '不公开'}
</div>
{detail.offerCount}
${intl.formatMessage({ id: 'detail.purchase.label4' })}{detail.offerCount}${intl.formatMessage({ id: 'detail.purchase.label6' })}
</div>
<div className={styles.row}>
<div className={styles.rowTime}>
......
import React, { useRef } from 'react';
import { history } from 'umi';
import { getIntl, history } from 'umi';
import { Button, Badge, Typography, Space } from 'antd';
import { ColumnType } from 'antd/lib/table/interface';
import { PlayCircleOutlined, PoweroffOutlined } from '@ant-design/icons';
......@@ -10,6 +10,8 @@ import StatusTag from '@/components/StatusTag';
import Table from '../../components/table'
const intl = getIntl();
import {
BID_EXTERNALSTATE_COLOR,
BID_INTERNALSTATE_COLOR
......@@ -21,13 +23,13 @@ const { Text } = Typography;
const ReadyBid = () => {
const ref = useRef<any>({});
const columns: ColumnType<any>[] = [{
title: '序号',
title: intl.formatMessage({ id: 'table.purchase.id' }),
align: 'center',
dataIndex: 'id',
key: 'id',
render: (t, r, i) => ++i
}, {
title: '竞价单号/摘要',
title: intl.formatMessage({ id: 'table.purchase.biddingNo' }),
key: 'biddingNo',
dataIndex: 'biddingNo',
render: (text: any, record: any) => (
......@@ -38,7 +40,7 @@ const ReadyBid = () => {
</Space>
)
}, {
title: '采购会员',
title: intl.formatMessage({ id: 'table.purchase.createMemberName' }),
key: 'createMemberName',
dataIndex: 'createMemberName',
render: (text: any, record: any) => (
......@@ -46,7 +48,7 @@ const ReadyBid = () => {
url={`${ENTERPRISE_CENTER_URL}/shop/${record.createMemberId}_${record.createMemberRoleId}`}>{text}</EyePreview>
)
}, {
title: '竞价开始/结束时间',
title: intl.formatMessage({ id: 'table.purchase.biddingStartTime' }),
key: 'biddingStartTime',
dataIndex: 'biddingStartTime',
render: (text: any, record: any) => <>
......@@ -55,7 +57,7 @@ const ReadyBid = () => {
</>,
width: 180
}, {
title: '竞价开始/结束时间',
title: intl.formatMessage({ id: 'table.purchase.biddingStartTime' }),
key: 'startSignUp',
dataIndex: 'startSignUp',
render: (text: any, record: any) => <>
......@@ -64,7 +66,7 @@ const ReadyBid = () => {
</>,
width: 180
}, {
title: '外部状态',
title: intl.formatMessage({ id: 'table.purchase.externalStatus' }),
key: 'externalState',
dataIndex: 'externalState',
render: (text: any, record: any) => <StatusTag type={BID_EXTERNALSTATE_COLOR(text)} title={record.externalStateName} />
......@@ -83,7 +85,7 @@ const ReadyBid = () => {
onClick={() => { history.push(`/memberCenter/procurementAbility/onlineBid/readyBid/bid?id=${record.id}&number=${record.biddingNo}&onlineId=${record.onlineId}`) }}
type='link'
>
开始竞价
{intl.formatMessage({ id: 'detail.purchase.startStill' })}
</Button>
}];
......
import React, { useRef } from 'react';
import { history } from 'umi';
import { getIntl, history } from 'umi';
import { Button, Badge, Typography, Space } from 'antd';
import { ColumnType } from 'antd/lib/table/interface';
import { PlayCircleOutlined, PoweroffOutlined } from '@ant-design/icons'
......@@ -9,6 +9,8 @@ import EyePreview from '@/components/EyePreview';
import StatusTag from '@/components/StatusTag';
import { getPurchaseOnlineBiddingStayExamineBiddingSignup } from '@/services/PurchaseV2Api';
const intl = getIntl();
import Table from '../../components/table'
import {
......@@ -21,31 +23,31 @@ const { Text } = Typography;
const ReadySignUp = () => {
const ref = useRef<any>({});
const columns: ColumnType<any>[] = [{
title: '序号',
title: intl.formatMessage({ id: 'table.purchase.id' }),
align: 'center',
dataIndex: 'id',
key: 'id',
render: (t, r, i) => ++i
}, {
title: '竞价单号/摘要',
title: intl.formatMessage({ id: 'table.purchase.biddingNo' }),
key: 'biddingNo',
dataIndex: 'biddingNo',
render: (text: any, record: any) => (
<Space direction='vertical' style={{width: 300}}>
<Space direction='vertical' style={{ width: 300 }}>
<EyePreview
url={`/memberCenter/procurementAbility/onlineBid/readySignUp/detail?id=${record.id}&number=${record.biddingNo}`}>{text}</EyePreview>
<Text type="secondary">{record.details}</Text>
</Space>
)
}, {
title: '采购会员',
title: intl.formatMessage({ id: 'table.purchase.createMemberName' }),
key: 'createMemberName',
dataIndex: 'createMemberName',
render: (text: any, record: any) => (
<EyePreview url={`${ENTERPRISE_CENTER_URL}/shop/${record.createMemberId}_${record.createMemberRoleId}`}>{text}</EyePreview>
)
}, {
title: '竞价开始/结束时间',
title: intl.formatMessage({ id: 'table.purchase.biddingStartTime' }),
key: 'biddingStartTime',
dataIndex: 'biddingStartTime',
render: (text: any, record: any) => <>
......@@ -54,7 +56,7 @@ const ReadySignUp = () => {
</>,
width: 180
}, {
title: '报名开始/结束时间',
title: intl.formatMessage({ id: 'table.purchase.startSignUp' }),
key: 'startSignUp',
dataIndex: 'startSignUp',
render: (text: any, record: any) => <>
......@@ -63,7 +65,7 @@ const ReadySignUp = () => {
</>,
width: 180
}, {
title: '外部状态',
title: intl.formatMessage({ id: 'table.purchase.externalStatus' }),
key: 'externalState',
dataIndex: 'externalState',
render: (text: any, record: any) => <StatusTag type={BID_EXTERNALSTATE_COLOR(text)} title={record.externalStateName} />
......@@ -82,7 +84,7 @@ const ReadySignUp = () => {
onClick={() => { history.push(`/memberCenter/procurementAbility/onlineBid/readySignUp/signUp?id=${record.id}&number=${record.biddingNo}`) }}
type='link'
>
{record.button === 3 ? '报名' : '重新报名'}
{record.button === 3 ? intl.formatMessage({ id: 'detail.purchase.label14' }) : intl.formatMessage({ id: 'detail.purchase.label15' })}
</Button>
}];
......
import React, { useState, useEffect } from 'react';
import { history } from 'umi';
import { getIntl, history } from 'umi';
import { PageHeaderWrapper } from '@ant-design/pro-layout';
import { Card, Button, message } from 'antd';
import { createFormActions } from '@formily/antd'
......@@ -15,6 +15,7 @@ import ReutrnEle from '@/components/ReturnEle';
import { formatTimeString } from '@/utils'
import { getAuth } from '@/utils/auth'
const intl = getIntl();
import { formSchema } from './schema'
......@@ -79,7 +80,7 @@ const SignUpForm = () => {
const beforeUpload = file => {
if (file.size / 1024 / 1024 > 20) {
message.warning('附件大小超过20M');
message.warning(intl.formatMessage({ id: 'detail.purchase.message21' }));
return Promise.reject();
}
setRefundDisabled(true);
......@@ -124,9 +125,9 @@ const SignUpForm = () => {
return (
<PageHeaderWrapper
onBack={() => history.goBack()}
backIcon={<ReutrnEle description="返回" />}
backIcon={<ReutrnEle description={intl.formatMessage({ id: 'detail.purchase.back' })} />}
extra={
<Button disabled={refundDisabled} type="primary" onClick={() => addSchemaAction.submit()} loading={btnLoading} icon={<SaveOutlined />}> 保存</Button>
<Button disabled={refundDisabled} type="primary" onClick={() => addSchemaAction.submit()} loading={btnLoading} icon={<SaveOutlined />}> {intl.formatMessage({ id: 'detail.purchase.save' })}</Button>
}
>
<Card>
......
......@@ -10,23 +10,26 @@ import { getPurchaseOnlineBiddingList, getPurchaseOnlineBiddingExternalStatus, g
import Table from '../../components/table'
const intl = getIntl();
import {
BID_EXTERNALSTATE_COLOR,
BID_INTERNALSTATE_COLOR
} from '../../constants/purchaseBid';
import { getIntl } from 'umi';
const { Text } = Typography;
const Search = () => {
const ref = useRef<any>({});
const columns: ColumnType<any>[] = [{
title: '序号',
title: intl.formatMessage({ id: 'table.purchase.id' }),
align: 'center',
dataIndex: 'id',
key: 'id',
render: (t, r, i) => ++i
}, {
title: '竞价单号/摘要',
title: intl.formatMessage({ id: 'table.purchase.biddingNo' }),
key: 'biddingNo',
dataIndex: 'biddingNo',
render: (text: any, record: any) => (
......@@ -37,12 +40,12 @@ const Search = () => {
</Space>
)
}, {
title: '采购会员',
title: intl.formatMessage({ id: 'table.purchase.createMemberName' }),
key: 'createMemberName',
dataIndex: 'createMemberName',
render: (text: any, record: any) => text
}, {
title: '竞价开始/结束时间',
title: intl.formatMessage({ id: 'table.purchase.biddingStartTime' }),
key: 'biddingStartTime',
dataIndex: 'biddingStartTime',
render: (text: any, record: any) => <>
......@@ -51,7 +54,7 @@ const Search = () => {
</>,
width: 180
}, {
title: '报名开始/结束时间',
title: intl.formatMessage({ id: 'table.purchase.startSignUp' }),
key: 'startSignUp',
dataIndex: 'startSignUp',
render: (text: any, record: any) => <>
......@@ -60,14 +63,14 @@ const Search = () => {
</>,
width: 180
}, {
title: '是否中标',
title: intl.formatMessage({ id: 'table.purchase.isWin' }),
key: 'isPrize',
dataIndex: 'isPrize',
render: (text: any, record: any) => <>
{(text !== 1 && text !== 0) ? null : <StatusTag type={text ? 'success' : 'danger'} title={text ? '是' : '否'} />}
{(text !== 1 && text !== 0) ? null : <StatusTag type={text ? 'success' : 'danger'} title={text ? intl.formatMessage({ id: 'table.purchase.okText' }) : intl.formatMessage({ id: 'table.purchase.cancelText' })} />}
</>
}, {
title: '外部状态',
title: intl.formatMessage({ id: 'table.purchase.externalStatus' }),
key: 'externalState',
dataIndex: 'externalState',
render: (text: any, record: any) => <StatusTag type={BID_EXTERNALSTATE_COLOR(text)} title={record.externalStateName} />
......
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