import React, { useCallback } from 'react'; import Icon from '@ant-design/icons'; import { decorator } from "grey-react-box"; import { Form } from "kts-components-antd-x3"; import { AutoComplete, Button, Checkbox, Col, Input, InputProps, Row, Tooltip } from 'kts-xui' import { CheckboxChangeEvent } from 'kts-components-antd-x4/lib/checkbox'; import { FormComponentProps } from "kts-components-antd-x3/lib/form"; import { WrappedFormUtils } from 'kts-components-antd-x3/lib/form/Form'; import { ReactComponent as ArrowUpSvg } from './svg/arrowUp.svg'; import { ReactComponent as ArrowDownSvg } from './svg/arrowDown.svg'; import { ReactComponent as PlusSvg } from './svg/plus.svg' import InvoiceController from "../../../InvoiceController"; import Invoice from "../../../../Invoice"; import './index.less'; import classNames from 'classnames'; import CardSelect from '../../components/CardSelect'; import NationalSelect from '../../components/NationalSelect'; const RULES = { companyName: (label: string) => [ { required: true, message: `${label}必填` }, { max: 100, message: `${label}内容超长` } ], taxId: (label: string) => [ { max: 20, message: `${label}内容超长` }, { pattern: /^([a-zA-Z0-9])*$/g, message: `${label}仅能数字、英文` } ], buyerTelPhone: (label: string) => [ { max: 100, message: `${label}内容超长` }, { pattern: /^[0-9\s\-\+]+$/g, message: `${label}仅能数字、空格、-、+` } ], sellerTelPhone: (label: string) => [ { required: true, message: `${label}必填` }, { max: 100, message: `${label}内容超长` }, { pattern: /^[0-9\s\-\+]+$/g, message: `${label}仅能数字、空格、-、+` } ], bankName: (label: string) => [ { max: 100, message: `${label}内容超长` } ], bankAccount: (label: string) => [ { max: 100, message: `${label}内容超长` }, { pattern: /^([0-9a-zA-Z-\s])*$/g, message: `${label}仅能数字、字母、-、空格` } ] } const formatCompanyName = (e: any) => { const value = e?.target?.value; if (value) { return value.replace('(', '(').replace(')', ')').replace(' ', ''); } } export interface IStakeholder { /** 是否显示导入按钮 */ isShowImportButton?: boolean; /** 点击了 */ onClickImportButton?: (e: InvoiceController) => void; /** 查看当前可用授信额度 */ lineCredit?: React.ReactNode; /** 票种类型 */ isVatNormal?: boolean; /** 是否可以选择自然人 */ isNaturalPerson?: boolean; /** 是否展开 */ isExpand?: boolean; /** 购方,销方银行信息 勾选按钮是否显示 **/ leqi?: boolean; /** 是否允许编辑勾选按钮 */ allowEditFlag?: boolean; /** 购方,销方地址电话 勾选按钮是否显示 **/ riskData?: boolean; invoiceMarkCallback?: (value: any) => void; changeNaturalPersonFlag?: (value: any) => void; } /** 干系人 */ export default decorator(Form.create())(props => { const { form, isShowImportButton, allowEditFlag, onClickImportButton, isVatNormal = false, changeNaturalPersonFlag } = props; const [isExpand, setExpand] = React.useState(typeof props.isExpand === 'boolean' ? props.isExpand : true); const [validateStatus, setStatus] = React.useState(''); const [errorInfo, setInfo] = React.useState(''); const [nation, setNationStatue] = React.useState(''); const [nationInfo, setNation] = React.useState(''); const { getFieldDecorator } = form; const controller = Invoice.useInvoiceController(); const model = controller.useMemo(s => s.model, []); const disableds = controller.useMemo(s => s.stakeholder.disableds || [], []); const rulesMap = controller.useMemo(s => s.stakeholder.rulesMap || {}, []); const naturalPersonFlag = controller.useMemo(s => s.stakeholder.naturalPersonFlag || 'COMPANY', []); /** 乐企 */ const leqispanW = React.useMemo(() => { if (props.leqi) { return 0; } else { return 2; } }, [props.leqi, props.riskData]); /** 直连 */ const riskspanW = React.useMemo(() => { if (props.riskData) { return 0; } else { return 2; } }, [props.leqi, props.riskData]); const readOnly = React.useMemo(() => { if (model === 'readOnly') return true; if (model === 'prefab') return true; return false; }, [model]); const onExpand = React.useCallback(() => { setExpand(e => !e) }, []); const isReadOnly = React.useCallback(field => readOnly || disableds.indexOf(field) >= 0, [disableds, readOnly]); const isReadOnly2 = React.useCallback(field => model === 'readOnly' || (model === 'prefab' && !allowEditFlag), [allowEditFlag, model]); const getRules = React.useCallback((field, defaultRules) => { if (isReadOnly(field)) return []; return rulesMap[field] || defaultRules; }, [rulesMap, isReadOnly, isReadOnly]); controller.useForm('stakeholder', form); // props.isExpand 变化的时候更新 React.useEffect(() => { setExpand(typeof props.isExpand === 'boolean' ? props.isExpand : true); }, [props.isExpand]) const onChangeType = React.useCallback( (value: string) => { const buyerTaxId = form?.getFieldValue("buyerTaxId"); const certificateNumber = form?.getFieldValue("certificateNumber"); const nationality = form?.getFieldValue("nationality"); if (value === "201") { // 当“自然人证件类型”选择“201:居民身份证”时,校验是否为“156:中国’ form?.setFieldsValue({ nationality: "156" }); setNationStatue(''); setNation(''); if (buyerTaxId !== certificateNumber) { setStatus('error'); setInfo('证件号码应与购方税号保持一致') } } else if (value === "210") { if (value.startsWith("M")) { //如果“证件号码”以M开头,"国籍(或地区头,)”必须为“446:中国澳门”;校验证件号码必须以H或M开头 if (nationality !== '446') { setNationStatue('error'); setNation('请选择正确的国籍'); } else { setNationStatue(''); setNation(''); } } else if (value.startsWith("H")) { //如果“证件号码”以H开国籍(或地区)”必须为“344:中国香港”; if (nationality !== '344') { setNationStatue('error'); setNation('请选择正确的国籍'); } else { setNationStatue(''); setNation(''); } } else { setStatus('error'); setInfo('请输入正确的证件号码') } } else if (value === "237") { if (value.startsWith("810000")) { if (nationality !== '344') { setNationStatue('error'); setNation('请选择正确的国籍'); } else { setNationStatue(''); setNation(''); } } else if (value.startsWith("820000")) { if (nationality !== '446') { setNationStatue('error'); setNation('请选择正确的国籍'); } else { setNationStatue(''); setNation(''); } } else { setStatus('error'); setInfo('请输入正确的证件号码') return Promise.reject("请输入正确的证件号码"); } } else if (value === "227") { // 当“自然人证件类型”选择“227:中华人民共和国护照”时,校验是否为“156:中国 form?.setFieldsValue({ nationality: "156" }); } else if (value === "213" || value === "238") { // 当“自然人证件类型”选择“213:台湾居民来往大陆通行证”时,校验是否为”158:中国台湾” // 当“自然人证件类型”选择“238:中华人民共和国台湾居民居住证”时,校验是否为“ 158:中国台湾” form?.setFieldsValue({ nationality: "158" }); } }, [form] ); /** 校验证件号码*/ const validateIDCode = useCallback( (_: any, value: string) => { if (!value) { setStatus('error'); setInfo('请输入正确的证件号码') return Promise.resolve(); } const idtype = form?.getFieldValue("certificateType"); const nationality = form?.getFieldValue("nationality"); if (idtype === "210") { // 当“自然人证件类型”选择“210:港澳居民来往内地通行证”时, if (value.startsWith("M")) { //如果“证件号码”以M开头,"国籍(或地区头,)”必须为“446:中国澳门”;校验证件号码必须以H或M开头 if (nationality !== '446') { setNationStatue('error'); setNation('请选择正确的国籍'); } else { setNationStatue(''); setNation(''); } } else if (value.startsWith("H")) { //如果“证件号码”以H开国籍(或地区)”必须为“344:中国香港”; if (nationality !== '344') { setNationStatue('error'); setNation('请选择正确的国籍'); } else { setNationStatue(''); setNation(''); } } else { setStatus('error'); setInfo('请输入正确的证件号码') return Promise.reject("请输入正确的证件号码"); } } else if (idtype === "237") { //当“自然人证件类型”选择“237:中华人民共和国港澳居民居住证”时,校验证件号码必须以810000或820000开头,如果“证件号码”以810000开头,必须为“344:中国香国籍(或地区))港”;如果“证件号码”以820000开头,国籍(或地区)必须为“446:中国澳门” if (value.startsWith("810000")) { if (nationality !== '344') { setNationStatue('error'); setNation('请选择正确的国籍'); } else { setNationStatue(''); setNation(''); } } else if (value.startsWith("820000")) { if (nationality !== '446') { setNationStatue('error'); setNation('请选择正确的国籍'); } else { setNationStatue(''); setNation(''); } } else { setStatus('error'); setInfo('请输入正确的证件号码') return Promise.reject("请输入正确的证件号码"); } } // 当“销售方自然人证件类型”填写“201:居民身份证”,“销售方纳税人识别号”必须与“销售方自然人证件号码”完全一致 if (idtype === "201") { const buyerTaxId = form?.getFieldValue("buyerTaxId"); if (value !== buyerTaxId) { setStatus('error'); setInfo('证件号码应与购方税号保持一致') return Promise.reject("证件号码应与购方税号保持一致"); } else if (value === buyerTaxId) { setStatus(''); setInfo('') } } setStatus(''); setInfo('') return Promise.resolve(); }, [form] ); const validateIDCode2 = useCallback( (e: any) => { const value = e.target.value; // if (!value) { // setStatus(''); // setInfo('') // } const idtype = form?.getFieldValue("certificateType"); // // 当“自然人证件类型”填写“201:居民身份证”,“购买方纳税人识别号”必须与“自然人证件号码”完全一致 if (idtype === "201") { const certificateNumber = form?.getFieldValue("certificateNumber"); console.log(value, certificateNumber) if (value !== certificateNumber) { setStatus('error'); setInfo('证件号码应与购方税号保持一致') } else { setStatus(''); setInfo('') } } }, [form] ); const validateNationality = useCallback( (_: any, value: string) => { if (!value) { setNationStatue('error'); setNation('请选择正确的国籍'); return Promise.resolve(); } const idtype = form?.getFieldValue("certificateType"); const idcode = form?.getFieldValue("certificateNumber"); console.log(value, idtype, idcode) if (idtype === "201" || idtype === "227") { // 当“自然人证件类型”选择“201:居民身份证”时,校验是否为“156:中国’ // 当“自然人证件类型”选择“227:中华人民共和国护照”时,校验是否为“156:中国 if (value !== "156") { setNationStatue('error'); setNation('请选择正确的国籍'); return Promise.reject("请选择正确的国籍"); } } else if (idtype === "213" || idtype === "238") { // 当“自然人证件类型”选择“213:台湾居民来往大陆通行证”时,校验是否为”158:中国台湾” // 当“自然人证件类型”选择“238:中华人民共和国台湾居民居住证”时,校验是否为“ 158:中国台湾” if (value !== "158") { setNationStatue('error'); setNation('请选择正确的国籍'); return Promise.reject("请选择正确的国籍"); } } else if (idtype === "210") { //当“自然人证件类型”选择“210:港澳居民来往内地通行证”时,如果“证件号码”以H开国籍(或地区)”必须为“344:中国香港”;如果“证件号码”以M开头,"国籍(或地区头,)”必须为“446:中国澳门”; let r = false; if (idcode) { if (idcode.startsWith("M") && value === "446") { r = true; } else if (idcode.startsWith("H") && value === "344") { r = true; } } else if (value === "344" || value === "446") { r = true; } if (!r) { setNationStatue('error'); setNation('请选择正确的国籍'); return Promise.reject("请选择正确的国籍"); } } else if (idtype === "237") { //当“自然人证件类型”选择“237:中华人民共和国港澳居民居住证”时,校验证件号码必须以810000或820000开头,如果“证件号码”以810000开头,必须为“344:中国香国籍(或地区))港”;如果“证件号码”以820000开头,国籍(或地区)必须为“446:中国澳门” let r = false; if (idcode) { if (idcode.startsWith("820000") && value === "446") { r = true; } else if (idcode.startsWith("810000") && value === "344") { r = true; } } else if (value === "344" || value === "446") { r = true; } if (!r) { setNationStatue('error'); setNation('请选择正确的国籍'); return Promise.reject("请选择正确的国籍"); } } setNationStatue(''); setNation(''); return Promise.resolve(); }, [form] ); return ( <>
{'购买方信息'.split('').map(e => {e})} { // !readOnly && }
{ props.isNaturalPerson === true && {getFieldDecorator('naturalPersonFlag', { })( )} }
{getFieldDecorator('buyerName', { rules: getRules('buyerName', RULES.companyName('购买方名称')), })( } onClick={() => { onClickImportButton && onClickImportButton(controller) }} /> } /> )} {getFieldDecorator('buyerTaxId', { rules: getRules('buyerTaxId', [{ required: !isVatNormal, message: '购买方纳税人识别号必填' }, ...RULES.taxId('购买方纳税人识别号')]) })( )} {getFieldDecorator('buyerAddress', { rules: getRules('buyerAddress', [{ max: 100, message: '购买方地址内容超长' }]) })()} {getFieldDecorator('buyerPhone', { rules: getRules('buyerPhone', RULES.buyerTelPhone('购买方电话')) })()} {(props.leqi) && {getFieldDecorator('buyerAddressPhoneFlag', { valuePropName: 'checked', })(是否展示)} } {getFieldDecorator('buyerBank', { rules: getRules('buyerBank', RULES.bankName('购买方开户银行')) })()} {getFieldDecorator('buyerAccount', { rules: getRules('buyerAccount', RULES.bankAccount('购买方银行账号')) })()} {(props.leqi) && {getFieldDecorator('buyerBankAccountFlag', { valuePropName: 'checked', })(是否展示)} }
{'销售方信息'.split('').map(e => {e})} { // !readOnly && }
{ !readOnly && props.lineCredit &&
}
{getFieldDecorator('supplierName', { rules: getRules('supplierName', RULES.companyName('销售方名称')), getValueFromEvent: formatCompanyName })()} {getFieldDecorator('supplierTaxId', { rules: getRules('supplierTaxId', [{ required: true, message: '销售方纳税人识别号必填' }, ...RULES.taxId('销售方纳税人识别号')]) })()} {getFieldDecorator('sellerAddress', { rules: getRules('sellerAddress', [{ max: 300, message: '销售方地址内容超长' }]) })()} {getFieldDecorator('sellerPhone', { rules: getRules('sellerPhone', RULES.sellerTelPhone('销售方电话')) })()} {(props.leqi) && {getFieldDecorator('sellerAddressPhoneFlag', { valuePropName: 'checked', })(是否展示)} } {getFieldDecorator('sellerBank', { rules: getRules('sellerBank', RULES.bankName('销售方开户银行')) })()} {getFieldDecorator('sellerAccount', { rules: getRules('sellerAccount', RULES.bankAccount('销售方银行账号')) })()} {(props.leqi) && {getFieldDecorator('sellerBankAccountFlag', { valuePropName: 'checked', })(是否展示)} }
{ naturalPersonFlag === 'NATURAL' &&
{/* */} {getFieldDecorator('certificateType', { rules: [{ required: true, message: '证件类型必填' }] })()} {getFieldDecorator('certificateNumber', { rules: [{ required: true, message: '证件号码必填' }, { max: 30, message: `内容超长` }, { validator: validateIDCode },] })()} {getFieldDecorator('nationality', { rules: [{ required: true, message: '国籍必填' }, { validator: validateNationality }] })( { if (option) { return option.label?.indexOf(input) >= 0; } return false; }} readOnly={isReadOnly('nationality')} placeholder="国籍必填" autoComplete="off" />)}
} ) }) function NaturalPersonFlag(props: { // NATURAL("自然人"), COMPANY("非自然人"); value?: 'COMPANY' | 'NATURAL', onChange?: (e: 'COMPANY' | 'NATURAL') => void readOnly?: boolean; }) { const controller = Invoice.useInvoiceController(); const [value, setValue] = React.useState(props.value || 'COMPANY'); const onChange = React.useCallback((e: CheckboxChangeEvent) => { if (props.readOnly) return; const naturalPersonFlag = e.target.checked ? 'NATURAL' : 'COMPANY' setValue(naturalPersonFlag); controller.pipeline(async (s) => { s.stakeholder.naturalPersonFlag = naturalPersonFlag })(); props.onChange && props.onChange(naturalPersonFlag); }, [props.onChange, props.readOnly]) React.useEffect(() => { setValue(props.value || 'COMPANY') }, [props.value]) return ( 是否开票给自然人 ) } function BuyerNameInput(props: InputProps & { fieldName: string; myform: WrappedFormUtils }) { const { fieldName, myform: form } = props; const controller = Invoice.useInvoiceController(); const rootElement = controller.useMemo(s => s.rootElement, []); const autoComplete = controller.useMemo(s => s.autoComplete, []) const [options, setOptions] = React.useState([]) const onChangeAutoComplete = React.useCallback(value => { const record = options.filter(e => e[fieldName] === value)[0] as any; if (!record || !form) return; form.setFieldsValue(record); setOptions([]) }, [options, fieldName, form]) const onSearch = React.useCallback(async (searchText: string) => { await Discontinue.start(); try { if (fieldName === 'buyerName') { if (autoComplete.onBuyerNameSearch) { setOptions(await autoComplete.onBuyerNameSearch(searchText)); } } else if (fieldName === 'buyerTaxId') { if (autoComplete.onBuyerTaxIdSearch) { setOptions(await autoComplete.onBuyerTaxIdSearch(searchText)); } } } catch (error) { setOptions([]); throw error; } }, [autoComplete.onBuyerNameSearch, fieldName]) if (props.readOnly) return {props.value}; return ( ({ value: e[fieldName] }))} onChange={onChangeAutoComplete} value={props.value} getPopupContainer={() => rootElement || document.body} style={{ width: '100%' }} > ) } class MyInput extends React.Component { render() { const props = this.props; if (props.readOnly) { return {props.value} } else { return } } } class Discontinue { private static timer: any; static start = (interval = 200) => new Promise(resolve => { clearTimeout(Discontinue.timer); Discontinue.timer = setTimeout(resolve, interval); }) }