Commit cde62b0c authored by XieZhiXiong's avatar XieZhiXiong

feat: 新增入库分类信息pro组件

parent c890010c
/**
* @Description 序号 Filed
*/
import React, { HTMLAttributes } from 'react';
import { FormPath } from '@formily/antd';
const IndexField: React.FC<any> & { isFieldComponent: boolean } = (props) => {
const { name } = props;
const xComponentProps: HTMLAttributes<HTMLDivElement> = props.props['x-component-props'] || {};
const index = FormPath.transform(name, /\d/, $1 => {
return `${$1 + 1}`
});
return (
<div {...xComponentProps}>{index}</div>
)
}
IndexField.isFieldComponent = true
export default IndexField;
\ No newline at end of file
@import '~antd/es/style/themes/default.less';
@import '../../../../../../global/styles/utils.less';
.pay-type {
width: 100%;
flex: 1 1 0%;
&-content {
padding: 0 @padding-xs;
display: flex;
position: relative;
height: 32px;
// border: 1px solid @background-color-base;
border: 1px solid @select-border-color;
background-color: @background-color-base;
border-radius: 4px;
&-text {
flex: 1;
padding-right: 15px;
.textOverflow();
}
&-arrow {
position: absolute;
top: 50%;
right: @padding-xs;
height: 12px;
margin-top: -6px;
color: @input-placeholder-color;
}
&-active,
&:hover {
border-color: @primary-color;
}
}
&-overlay {
position: absolute;
top: 0;
left: 0;
right: 0;
background-color: #FFFFFF;
padding: @padding-xs;
border-radius: 4px;
}
&-options {
margin-bottom: @margin-md;
border-bottom: 1px solid @background-color-base;
&-item {
display: inline-block;
margin-right: @margin-xs;
margin-bottom: @margin-xs;
&-btn {
border: none;
&-active {
color: @primary-color;
}
}
}
}
&-actions {
display: flex;
align-items: center;
padding-top: @padding-xss;
&-item {
flex: 1;
padding: 0 @padding-xss;
}
}
}
\ No newline at end of file
/**
* 结算方式Filed组件
*/
import React, { useEffect, useState } from 'react';
import { useIntl } from 'umi';
import { Select, Dropdown, Button, Form, Input, } from 'antd';
import { DownOutlined } from '@ant-design/icons';
import { FieldData } from 'rc-field-form/lib/interface';
import classNames from 'classnames';
import { ISchema } from '@formily/antd';
import themeConfig from '@/../config/lingxi.theme.config';
import { PAY_TYPE_CASH, PAY_TYPE_MONTHLY_STATEMENT, PAY_TYPE_PAYMENT_DAYS_DAY, PAY_TYPE_PAYMENT_DAYS_MONTH } from '@/constants/settlement';
import { PATTERN_MAPS } from '@/constants/regExp';
import styles from './index.less';
type PayTypeEnum = {
label: string;
value: number;
}
export type PayTypeFiledValueType = {
/**
* 结算方式
*/
payType: number,
/**
* 账期,几月
*/
month?: string,
/**
* 结算日,每月几号
*/
monthDay?: string,
/**
* 结算天数
*/
days?: string,
}
interface PayTypeFiledProps {
/**
* 值
*/
value: PayTypeFiledValueType,
/**
* 自定义内容区块样式
*/
contentStyle?: React.CSSProperties,
}
const PayTypeFiled = (props) => {
const {
mutators,
editable,
} = props;
const xComponentProps: PayTypeFiledProps = props.props['x-component-props'] || {};
const { contentStyle } = xComponentProps;
const [visible, setVisible] = useState(false);
const [internalPayType, setInternalPaytype] = useState(undefined);
const [formValues, setFormValues] = useState<PayTypeFiledValueType | undefined>(undefined);
const [form] = Form.useForm();
const intl = useIntl();
const value = typeof props.value === 'object' ? props.value : {};
const options: PayTypeEnum[] = props.props.enum || [];
useEffect(() => {
if (typeof props.value === 'object') {
if ((value as PayTypeFiledValueType).payType !== internalPayType) {
setInternalPaytype((value as PayTypeFiledValueType).payType);
}
form.setFieldsValue(value);
}
}, [value]);
const triggerChange = (next: PayTypeFiledValueType) => {
mutators.change(next);
};
const handleVisibleChange = (flag: boolean) => {
setVisible(flag);
};
// TODO: 有时间再把支付类型抽成Fields组件
const handlePayTypeChange = (next: PayTypeEnum) => {
setInternalPaytype(next.value);
form.resetFields();
};
const handleFormValuesChange = (_: Omit<PayTypeFiledValueType, 'payType'>, allValues: Omit<PayTypeFiledValueType, 'payType'>) => {
// triggerChange({ ...value, payType: internalPayType, ...allValues });
setFormValues({ payType: internalPayType, ...allValues });
};
const renderSettlementDate = () => {
switch (internalPayType) {
case PAY_TYPE_CASH: {
break;
}
case PAY_TYPE_PAYMENT_DAYS_DAY: {
return (
<>
<Form.Item
label="账期 (几个月)"
name="month"
style={{ marginBottom: themeConfig['@margin-xs'] }}
rules={[
{
pattern: PATTERN_MAPS.quantity,
message: intl.formatMessage({ id: 'member.management.memberPrComingClassify.drawer.form.classify.month.legal' }, { default: '请输入正整数' }),
},
]}
>
<Input addonAfter={intl.formatMessage({ id: 'member.management.memberPrComingClassify.drawer.form.classify.month.addonAfter' }, { default: '个月' })} />
</Form.Item>
<Form.Item
label="结算日 (每月几号)"
name="monthDay"
style={{ marginBottom: themeConfig['@margin-xs'] }}
rules={[
{
pattern: PATTERN_MAPS.quantity,
message: intl.formatMessage({ id: 'member.management.memberPrComingClassify.drawer.form.classify.monthDay.legal' }, { default: '请输入正整数' }),
},
{
validator(value) {
const intVal = +value;
return intVal > 31 || intVal < 0 ? Promise.reject(new Error(intl.formatMessage({ id: 'member.management.memberPrComingClassify.drawer.form.classify.monthDay.limit' }, { default: '请输入大于0 小于等于 31的数值' }))) : Promise.resolve();
}
},
]}
>
<Input addonAfter={intl.formatMessage({ id: 'member.management.memberPrComingClassify.drawer.form.classify.monthDay.addonAfter' }, { default: '号' })} />
</Form.Item>
</>
);
}
case PAY_TYPE_PAYMENT_DAYS_MONTH: {
return (
<Form.Item
label="账期 (间隔多少天)"
name="days"
rules={[
{
pattern: PATTERN_MAPS.quantity,
message: intl.formatMessage({ id: 'member.management.memberPrComingClassify.drawer.form.classify.days.legal' }, { default: '请输入正整数' }),
},
]}
>
<Input addonAfter={intl.formatMessage({ id: 'member.management.memberPrComingClassify.drawer.form.classify.days.addonAfter' }, { default: '天' })} />
</Form.Item>
);
}
case PAY_TYPE_MONTHLY_STATEMENT: {
return (
<Form.Item
label="结算日 (每月几号)"
name="monthDay"
style={{ marginBottom: themeConfig['@margin-xs'] }}
rules={[
{
pattern: PATTERN_MAPS.quantity,
message: intl.formatMessage({ id: 'member.management.memberPrComingClassify.drawer.form.classify.monthDay.legal' }, { default: '请输入正整数' }),
},
{
validator(value) {
const intVal = +value;
return intVal > 31 || intVal < 0 ? Promise.reject(new Error(intl.formatMessage({ id: 'member.management.memberPrComingClassify.drawer.form.classify.monthDay.limit' }, { default: '请输入大于0 小于等于 31的数值' }))) : Promise.resolve();
}
},
]}
>
<Input addonAfter={intl.formatMessage({ id: 'member.management.memberPrComingClassify.drawer.form.classify.monthDay.addonAfter' }, { default: '号' })} />
</Form.Item>
);
}
default:
break;
}
};
const handleSubmit = () => {
triggerChange({
payType: internalPayType,
...form.getFieldsValue(),
});
setVisible(false);
};
const currentPayType = options?.find((item) => item.value === internalPayType);
const content = (
<div>
{`
${currentPayType ? currentPayType.label : ''}
${formValues?.month ? ':' + formValues.month + '个月' : ''}
${formValues?.monthDay ? ',结算日:' + formValues.monthDay + '号' : ''}
${formValues?.days ? ':' + formValues.days + '天' : ''}
`}
</div>
);
if (!editable) return content;
return (
<div className={styles['pay-type']}>
<Dropdown
visible={visible}
onVisibleChange={handleVisibleChange}
overlay={(
<div className={styles['pay-type-overlay']}>
<div className={styles['pay-type-options']}>
{options.map((item) => (
<div
key={item.value}
className={styles['pay-type-options-item']}
>
<Button
className={classNames(
styles['pay-type-options-item-btn'],
{
[styles['pay-type-options-item-btn-active']]: item.value === internalPayType,
}
)}
onClick={() => handlePayTypeChange(item)}
>
{item.label}
</Button>
</div>
))}
</div>
<Form
form={form}
layout="vertical"
onValuesChange={handleFormValuesChange}
>
{renderSettlementDate()}
</Form>
<div className={styles['pay-type-actions']}>
<div className={styles['pay-type-actions-item']}>
<Button onClick={() => setVisible(false)} block>取消</Button>
</div>
<div className={styles['pay-type-actions-item']}>
<Button
type="primary"
onClick={handleSubmit}
block
>
确定
</Button>
</div>
</div>
</div>
)}
trigger={['click']}
>
<div
className={classNames(styles['pay-type-content'], { [styles['pay-type-content-active']]: visible })}
style={contentStyle}
>
<div className={styles['pay-type-content-text']}>
{content}
</div>
<DownOutlined className={styles['pay-type-content-arrow']} />
</div>
{/* <Select
value={'账期(按月):3个月,结算日:1号'}
dropdownStyle={{ display: 'none' }}
onClick={(e) => { e.stopPropagation(); }}
disabled
/> */}
</Dropdown>
</div>
);
};
PayTypeFiled.isFieldComponent = true;
export default PayTypeFiled;
/**
* @Description TreeSelect Filed
*/
import React from 'react';
import { TreeSelect } from 'antd';
const TreeSelectField: React.FC<any> & { isFieldComponent: boolean } = (props) => {
const { mutators, value, editable } = props;
const xComponentProps: React.ComponentProps<typeof TreeSelect> = props.props['x-component-props'] || {};
const { disabled, ...restComponentProps } = xComponentProps;
const onChange = (value) => {
mutators.change(value);
}
return (
<TreeSelect
style={{ width: '100%' }}
dropdownStyle={{ maxHeight: 400, overflow: 'auto' }}
value={value}
onChange={onChange}
treeDefaultExpandAll
showSearch
allowClear
treeCheckable
disabled={!editable}
// showCheckedStrategy={TreeSelect.SHOW_PARENT}
{...restComponentProps}
/>
)
}
TreeSelectField.isFieldComponent = true
export default TreeSelectField;
\ No newline at end of file
/*
* @Description: 会员分类信息pro
*/
import React, { useEffect, useRef, useState, useImperativeHandle } from 'react';
import { useIntl } from 'umi';
import {
Button,
Spin,
} from 'antd';
import { PlusOutlined } from '@ant-design/icons';
import NiceForm from '@/components/NiceForm';
import {
createAsyncFormActions,
FormEffectHooks,
FormPath,
} from '@formily/antd';
import { ArrayCards, ArrayTable } from '@formily/antd-components';
import {
getMemberAbilityMaintenanceDetailRecordClassify,
getMemberAbilityMaintenanceDetailRecordClassifyCategoryItems,
getMemberAbilityMaintenanceDetailRecordClassifyCity,
getMemberAbilityMaintenanceDetailRecordClassifyProvince,
getMemberDepositClassifyCategoryItems,
getMemberDepositClassifyCity,
getMemberDepositClassifyProvince,
} from '@/services/MemberV2Api';
import { getProductCustomerGetCustomerCategoryTree } from '@/services/ProductV2Api';
import {
PAY_TYPE_CASH,
PAY_TYPE_MONTHLY_STATEMENT,
PAY_TYPE_PAYMENT_DAYS_DAY,
PAY_TYPE_PAYMENT_DAYS_MONTH,
} from '@/constants/settlement';
import themeConfig from '@/../config/lingxi.theme.config';
import MellowCard, { MellowCardProps } from '@/components/MellowCard';
import { schema } from './schema';
import { breakUpCategory, CategoryItemType, CategoryType, getCategoryAllKeys, getCategoryPath, nestedCategory } from './utils';
import CascaderFormItem from '../CascaderFormItem';
import PayTypeFiled, { PayTypeFiledValueType } from './components/PayTypeFiled';
import TreeSelectField from './components/TreeSelectField';
import IndexField from './components/IndexField';
import styles from './index.less';
const formActions = createAsyncFormActions();
const {
onFormInit$,
onFieldValueChange$,
onFieldInputChange$,
} = FormEffectHooks;
// 省级接口map
const PROVINCE_API_MAP = {
0: getMemberAbilityMaintenanceDetailRecordClassifyProvince,
1: getMemberDepositClassifyProvince,
};
// 会员品类接口map
const CATEGORY_TREE_API_MAP = {
0: getProductCustomerGetCustomerCategoryTree,
1: getProductCustomerGetCustomerCategoryTree,
};
// 结算类型、发票类型接口map
const ITEMS_API_MAP = {
0: getMemberAbilityMaintenanceDetailRecordClassifyCategoryItems,
1: getMemberDepositClassifyCategoryItems,
};
// 城市接口map
const CITY_API_MAP = {
0: getMemberAbilityMaintenanceDetailRecordClassifyCity,
1: getMemberDepositClassifyCity,
};
type CategoriesBasicValueItem = {
/**
* 发票类型
*/
invoiceType: number,
/**
* 税点,只要百分比的分子部分,不要转换为小数
*/
taxPoint: number,
/**
* 预付款
*/
advanceCharge: number,
/**
* 结算单据
*/
settlementDocuments: number,
/**
* 付款方式
*/
paymentType: number,
/**
* 品类明细
*/
details: string[],
}
type CategoriesValueItemType = CategoriesBasicValueItem & {
/**
* 结算方式
*/
payType: PayTypeFiledValueType,
}
export type FormSubmitBasicValueType = {
/**
* 会员编码
*/
code: string,
/**
* 合作关系类型枚举
*/
partnerType: number,
/**
* 币别
*/
currencyType: number,
/**
* 备注
*/
remark: string,
}
export type AreaCodesItemType = {
/**
* 省编码
*/
provinceCode: string,
/**
* 市编码
*/
cityCode: string,
}
export type FormSubmitValueType = FormSubmitBasicValueType & {
/**
* 单次合作金额
*/
maxAmount: string,
/**
* 适用区域编码列表
*/
areaCodes: AreaCodesItemType[],
/**
* 主营品类列表
*/
categories: CategoriesValueItemType[],
/**
* 适用区域
*/
classifyAreas?: string,
}
type SubmitCategoriesValueType = Omit<CategoriesBasicValueItem, 'details'> & {
payType: number,
month: number,
monthDay: number,
days: number,
details: CategoryType[],
}
export type SubmitValueType = FormSubmitBasicValueType & {
maxAmount: number,
/**
* 适用区域编码列表
*/
areaCodes: AreaCodesItemType[],
categories: SubmitCategoriesValueType[],
}
export interface ValueType extends SubmitValueType {
/**
* 合作类型名称
*/
partnerTypeName: string,
/**
* 适用区域
*/
classifyAreas: string[],
}
export type PartnerTypesItem = {
/**
* label
*/
label: string,
/**
* value
*/
value: number,
}
export interface MemberDocCategoryProProps extends Omit<MellowCardProps, 'onSubmit'> {
/**
* 值
*/
value?: ValueType,
/**
* 是否可审核的,默认 0
*/
isVerify?: 0 | 1,
/**
* 审核id
*/
validateId?: string,
/**
* submit触发事件
*/
onSubmit?: (values: SubmitValueType) => void | Promise<void>,
/**
* 点击完成触发事件
*/
onFinish?: () => void,
/**
* 是否可编辑的
*/
editable?: boolean,
/**
* 外部传入合作关系
*/
partnerTypes?: PartnerTypesItem[],
}
export type MemberDocCategoryProRef = {
/**
* 触发表单 submit 事件
*/
submit: () => void,
}
const MemberDocCategoryPro: React.ForwardRefRenderFunction<MemberDocCategoryProRef, MemberDocCategoryProProps> = (props, ref) => {
const {
value,
isVerify = 0,
validateId,
onSubmit,
onFinish,
editable,
partnerTypes,
...rest
} = props;
const [classifyInfo, setClassifyInfo] = useState<FormSubmitValueType>();
const [infoLoading, setInfoLoading] = useState(false);
const [isModify, setIsModify] = useState(false);
const [finishing, setFinishing] = useState(false);
const categoryTreeRef = useRef<{}>({});
const intl = useIntl();
const isEditable = editable || isModify;
useEffect(() => {
if ('value' in props && value) {
const { categories, maxAmount, classifyAreas, ...rest } = value;
setClassifyInfo({
maxAmount: `${maxAmount}`,
...rest,
categories: categories?.map(({ payType, month, monthDay, days, details, ...rest }) => ({
...rest,
details: getCategoryAllKeys(details),
payType: {
payType,
month: month ? `${month}` : '',
monthDay: monthDay ? `${monthDay}` : '',
days: days ? `${days}` : '',
},
})),
classifyAreas: classifyAreas?.join(';'),
});
}
}, [value]);
useEffect(() => {
if ('partnerTypes' in props && partnerTypes && partnerTypes.length) {
formActions.setFieldState('partnerType', state => {
FormPath.setIn(state, 'props.enum', partnerTypes);
});
}
}, [partnerTypes]);
const getClassifyRecord = () => {
if (!validateId) {
return;
}
setInfoLoading(true);
getMemberAbilityMaintenanceDetailRecordClassify({
validateId,
}).then(res => {
if (res.code === 1000) {
setClassifyInfo({
code: res.data?.code,
partnerType: res.data?.partnerType,
maxAmount: `${parseFloat(res.data?.maxAmount)}`,
areaCodes: res.data?.areaCodes,
categories: res.data?.categories.map(({ details, payType, month, monthDay, days, taxPoint, ...rest }) => ({
details: getCategoryAllKeys(details as unknown as CategoryType[]),
payType: {
payType,
month: month ? `${month}` : '',
monthDay: monthDay ? `${monthDay}` : '',
days: days ? `${days}` : '',
},
taxPoint: +taxPoint * 100,
...rest
})),
currencyType: res.data?.currencyType,
remark: res.data?.remark,
});
const partnerTypes = res.data?.partnerTypes.map((item) => ({
value: item.id,
label: item.text,
}))
formActions.setFieldState('partnerType', state => {
FormPath.setIn(state, 'props.enum', partnerTypes);
});
}
}).catch((err) => {
console.warn(err);
}).finally(() => {
setInfoLoading(false);
});
};
const handleSubmit = (values: FormSubmitValueType) => {
if (onSubmit) {
const { maxAmount, categories, ...rest } = values;
const formated = categories.map((item) => {
const categoryArr = item.details.map((category) => getCategoryPath(category, categoryTreeRef.current));
const genealogies = categoryArr.map((item) => nestedCategory(item));
return {
details: genealogies,
payType: item.payType?.payType,
month: item.payType?.month ? +item.payType?.month : undefined,
monthDay: item.payType?.monthDay ? +item.payType?.monthDay : undefined,
days: item.payType?.days ? +item.payType?.days : undefined,
invoiceType: item.invoiceType,
taxPoint: +item.taxPoint,
advanceCharge: item.advanceCharge,
settlementDocuments: item.settlementDocuments,
paymentType: item.paymentType,
};
});
const res = onSubmit({
maxAmount: +maxAmount,
categories: formated,
...rest,
});
if (res instanceof Promise) {
setFinishing(true);
res.then(() => {
setIsModify(false);
}).finally(() => {
setFinishing(false);
});
}
}
};
const MemberCodeDescription = isEditable ? (
<div className={styles.description}>
<span>{intl.formatMessage({ id: 'member.management.memberPrComingClassify.drawer.form.classify.code.description-1' })}</span>
<span>{intl.formatMessage({ id: 'member.management.memberPrComingClassify.drawer.form.classify.code.description-2' })}</span>
</div>
) : null;
const MemberCypher = isEditable ? (
<div className={styles.description}>
<div>{intl.formatMessage({ id: 'member.management.memberPrComingClassify.drawer.form.classify.maxAmount.description-1' })}</div>
</div>
) : null;
const useBusinessEffects = () => {
// 省级改变时,,请求出对应的市级数据
onFieldInputChange$('areaCodes.*.provinceCode').subscribe(fieldState => {
formActions.setFieldState(
FormPath.transform(fieldState.name, /\d/, $1 => `areaCodes.${$1}.cityCode`),
state => {
FormPath.setIn(state, 'value', undefined);
}
);
});
// 省级改变时,,请求出对应的市级数据
onFieldValueChange$('areaCodes.*.provinceCode').subscribe((fieldState) => {
if (fieldState.value === undefined) {
return;
}
formActions.setFieldState(
FormPath.transform(fieldState.name, /\d/, $1 => `areaCodes.${$1}.cityCode`),
state => {
FormPath.setIn(state, 'props.x-props.hasFeedback', true);
FormPath.setIn(state, 'loading', true);
}
);
CITY_API_MAP[isVerify]({
provinceCode: fieldState.value,
}).then(res => {
if (res.code === 1000) {
const { data = [] } = res;
const options = data.map(item => ({ label: item.name, value: item.code }));
formActions.setFieldState(
FormPath.transform(fieldState.name, /\d/, $1 => `areaCodes.${$1}.cityCode`),
state => {
FormPath.setIn(state, 'props.enum', options);
}
);
}
}).catch((err) => {
console.warn(err);
}).finally(() => {
formActions.setFieldState(
FormPath.transform(fieldState.name, /\d/, $1 => `areaCodes.${$1}.cityCode`),
state => {
FormPath.setIn(state, 'loading', false);
}
);
});
});
// 结算方式改变,联动显示对应的 FormItem
onFieldValueChange$('categories.*.payType').subscribe((fieldState) => {
formActions.setFieldState(
FormPath.transform(fieldState.name, /\d/, $1 => `categories.${$1}.*(PAYMENT_DAYS_MONTH_WRAP,PAYMENT_DAYS_DAY_WRAP,MONTHLY_TATEMENT_WRAP)`),
state => {
FormPath.setIn(state, 'visible', false);
}
);
switch (fieldState.value) {
case PAY_TYPE_CASH: {
break;
}
case PAY_TYPE_PAYMENT_DAYS_DAY: {
formActions.setFieldState(
FormPath.transform(fieldState.name, /\d/, $1 => `categories.${$1}.PAYMENT_DAYS_MONTH_WRAP`),
state => {
FormPath.setIn(state, 'visible', true);
}
);
break;
}
case PAY_TYPE_PAYMENT_DAYS_MONTH: {
formActions.setFieldState(
FormPath.transform(fieldState.name, /\d/, $1 => `categories.${$1}.PAYMENT_DAYS_DAY_WRAP`),
state => {
FormPath.setIn(state, 'visible', true);
}
);
break;
}
case PAY_TYPE_MONTHLY_STATEMENT: {
formActions.setFieldState(
FormPath.transform(fieldState.name, /\d/, $1 => `categories.${$1}.MONTHLY_TATEMENT_WRAP`),
state => {
FormPath.setIn(state, 'visible', true);
}
);
break;
}
default:
break;
}
});
};
const renderAddition = () => {
return (
<Button
icon={<PlusOutlined />}
type="dashed"
// style={{
// marginTop: themeConfig['@margin-md'],
// }}
block
>
添加
</Button>
);
};
const handleRemove = async (index: number) => {
const mutators = await formActions.createMutators('categories');
mutators.remove(index);
};
const renderRemove = (index: number) => {
return (
<Button
type="link"
onClick={() => handleRemove(index)}
style={{
width: 66,
}}
>
<a>删除</a>
</Button>
);
};
const handleModify = () => {
setIsModify(true);
getClassifyRecord();
};
const handleFinish = () => {
onFinish?.();
};
useImperativeHandle(ref, () => ({
submit: () => formActions.submit(),
}));
return (
<MellowCard
title={intl.formatMessage({ id: 'member.components.MemberDocCategory.title' })}
extra={(
<>
{validateId && (
<>
{!isModify ? (
<Button
type="link"
loading={infoLoading}
onClick={handleModify}
>
{intl.formatMessage({ id: 'member.components.MemberDocCategory.edit' })}
</Button>
) : (
<Button
type="link"
loading={finishing}
onClick={handleFinish}
>
提交
</Button>
)}
</>
)}
</>
)}
{...rest}
>
<Spin spinning={infoLoading}>
<NiceForm
previewPlaceholder=" "
value={classifyInfo}
components={{
ArrayCards,
ArrayTable,
CascaderFormItem,
PayTypeFiled,
TreeSelectField,
IndexField,
}}
expressionScope={{
MemberCodeDescription,
MemberCypher,
renderAddition,
renderRemove,
}}
effects={($, { setFieldState }) => {
useBusinessEffects();
onFormInit$().subscribe(() => {
// 请求省级数据
PROVINCE_API_MAP[isVerify]().then(res => {
if (res.code === 1000) {
const { data = [] } = res;
const options = data.map(item => ({ label: item.name, value: item.code }));
formActions.setFieldState('areaCodes.*.provinceCode', state => {
FormPath.setIn(state, 'props.enum', options);
});
}
}).catch((err) => {
console.warn(err);
});
// 请求会员品类数据
CATEGORY_TREE_API_MAP[isVerify]().then(res => {
if (res.code === 1000) {
const { data = [] } = res;
// categoryTreeRef.current = data as unknown as CategoryItemType[];
categoryTreeRef.current = breakUpCategory(data as unknown as CategoryItemType[]);
formActions.setFieldState('categories.*.details', state => {
FormPath.setIn(state, 'props.x-component-props.treeData', data);
});
}
}).catch((err) => {
console.warn(err);
});
// 请求结算方式与发票类型数据
ITEMS_API_MAP[isVerify]().then(res => {
if (res.code === 1000 && res.data) {
const {
payTypes = [],
invoiceTypes = [],
advanceCharges = [],
paymentTypes = [],
settlementDocuments = [],
currencyTypes = [],
} = res.data;
formActions.setFieldState('categories.*.payType', state => {
FormPath.setIn(state, 'props.enum', payTypes.map((item) => ({
label: item.payTypeName,
value: item.payType,
})));
});
formActions.setFieldState('categories.*.invoiceType', state => {
FormPath.setIn(state, 'props.enum', invoiceTypes.map((item) => ({
label: item.invoiceTypeName,
value: item.invoiceType,
})));
});
formActions.setFieldState('categories.*.advanceCharge', state => {
FormPath.setIn(state, 'props.enum', advanceCharges.map((item) => ({
label: item.advanceChargeTypeName,
value: item.advanceChargeType,
})));
});
formActions.setFieldState('categories.*.paymentType', state => {
FormPath.setIn(state, 'props.enum', paymentTypes.map((item) => ({
label: item.paymentTypeName,
value: item.paymentType,
})));
});
formActions.setFieldState('categories.*.settlementDocuments', state => {
FormPath.setIn(state, 'props.enum', settlementDocuments.map((item) => ({
label: item.settlementDocumentsTypeName,
value: item.settlementDocumentsType,
})));
});
formActions.setFieldState('currencyType', state => {
FormPath.setIn(state, 'props.enum', currencyTypes.map((item) => ({
label: item.currencyTypeName,
value: item.currencyType,
})));
});
}
}).catch((err) => {
console.warn(err);
});
});
}}
actions={formActions}
schema={schema(isEditable)}
onSubmit={handleSubmit}
editable={isEditable}
/>
</Spin>
</MellowCard>
);
};
const MemberDocCategoryProForWard = React.forwardRef<MemberDocCategoryProRef, MemberDocCategoryProProps>(MemberDocCategoryPro);
export default MemberDocCategoryProForWard;
/*
* @Author: XieZhiXiong
* @Date: 2021-07-07 15:23:11
* @LastEditors: XieZhiXiong
* @LastEditTime: 2021-07-13 15:35:58
* @Description:
*/
import { ISchema } from '@formily/antd';
import { getIntl } from 'umi';
import { PATTERN_MAPS } from '@/constants/regExp';
import { MEMBER_TAX_POINT, MEMBER_TAX_POINT_1, MEMBER_TAX_POINT_2, MEMBER_TAX_POINT_3, MEMBER_TAX_POINT_4, MEMBER_TAX_POINT_5 } from '@/constants/member';
const intl = getIntl();
const TAX_POINT_OPTIONS = [
{
label: MEMBER_TAX_POINT[MEMBER_TAX_POINT_1],
value: MEMBER_TAX_POINT_1,
},
{
label: MEMBER_TAX_POINT[MEMBER_TAX_POINT_2],
value: MEMBER_TAX_POINT_2,
},
{
label: MEMBER_TAX_POINT[MEMBER_TAX_POINT_3],
value: MEMBER_TAX_POINT_3,
},
{
label: MEMBER_TAX_POINT[MEMBER_TAX_POINT_4],
value: MEMBER_TAX_POINT_4,
},
{
label: MEMBER_TAX_POINT[MEMBER_TAX_POINT_5],
value: MEMBER_TAX_POINT_5,
},
];
/**
* 获取 schema
* @param editable 是否可编辑的
* @returns
*/
export const schema = (editable: boolean): ISchema => {
return ({
type: 'object',
properties: {
MEGA_LAYOUT: {
type: 'object',
'x-component': 'Mega-Layout',
'x-component-props': {
grid: true,
full: true,
autoRow: true,
columns: 2,
labelWidth: 144,
labelAlign: 'left',
},
properties: {
code: {
type: 'string',
title: intl.formatMessage({ id: 'member.management.memberPrComingClassify.drawer.form.classify.code' }),
required: true,
description: '{{MemberCodeDescription}}',
'x-rules': [
{
pattern: /^[a-zA-Z0-9_-]{1,10}$/,
message: intl.formatMessage({ id: 'member.management.memberPrComingClassify.drawer.form.classify.code.rules-legal' }),
},
],
},
maxAmount: {
type: 'string',
title: intl.formatMessage({ id: 'member.management.memberPrComingClassify.drawer.form.classify.maxAmount' }),
required: true,
'x-component-props': {
addonBefore: intl.formatMessage({ id: 'common.money' }),
},
description: '{{MemberCypher}}',
'x-rules': [
{
pattern: PATTERN_MAPS.money,
message: intl.formatMessage({ id: 'member.management.memberPrComingClassify.drawer.form.classify.maxAmount.rules-legal' }),
},
{
max: 8,
message: intl.formatMessage({ id: 'member.management.memberPrComingClassify.drawer.form.classify.maxAmount.rules-max' }),
},
],
},
currencyType: {
type: 'string',
title: '币别',
enum: [],
'x-component-props': {
placeholder: '请选择',
},
required: true,
},
...(editable ? (
{
partnerType: {
type: 'string',
enum: [],
title: intl.formatMessage({ id: 'member.management.memberPrComingClassify.drawer.form.classify.partnerType' }),
'x-component-props': {
placeholder: intl.formatMessage({ id: 'member.management.memberPrComingClassify.drawer.form.select.placeholder' }),
},
required: true,
}
}
) : (
{
partnerTypeName: {
type: 'string',
title: intl.formatMessage({ id: 'member.management.memberPrComingClassify.drawer.form.classify.partnerType' }),
editable: false,
}
}
)),
...(editable ? (
{
areaCodes: {
type: 'array',
title: intl.formatMessage({ id: 'member.management.memberPrComingClassify.drawer.form.classify.areaCodes' }),
required: true,
'x-component': 'CustomAddArray',
default: [],
items: {
type: 'object',
properties: {
MEGA_LAYOUT_AREA: {
type: 'object',
'x-component': 'Mega-Layout',
'x-props': {
width: '100%',
},
'x-component-props': {
grid: true,
full: true,
autoRow: true,
columns: 2,
},
properties: {
provinceCode: {
type: 'string',
enum: [],
'x-component-props': {
allowClear: true,
},
},
cityCode: {
type: 'string',
enum: [],
'x-component-props': {
allowClear: true,
},
},
},
}
}
}
},
}
) : (
{
classifyAreas: {
type: 'string',
title: intl.formatMessage({ id: 'member.management.memberPrComingClassify.drawer.form.classify.areaCodes' }),
editable: false,
}
}
)),
remark: {
type: 'string',
title: '备注',
'x-component': 'Textarea',
'x-component-props': {
placeholder: '最长200个字符,100个汉字',
rows: 1,
},
'x-rules': [
{
limitByte: true, // 自定义校验规则
maxByte: 200,
}
],
},
categories: {
type: 'array',
title: intl.formatMessage({ id: 'member.management.memberPrComingClassify.drawer.form.classify.categories' }),
required: true,
'x-mega-props': {
span: 2,
labelAlign: 'top',
},
'x-component': 'ArrayTable',
'x-component-props': {
renderMoveDown: () => null,
renderMoveUp: () => null,
renderAddition: '{{renderAddition}}',
renderRemove: '{{renderRemove}}',
operationsWidth: '128px',
scroll: {
x: 1200,
},
},
items: {
type: 'object',
properties: {
index: {
type: 'string',
title: '序号',
editable: false,
'x-component': 'IndexField',
'x-component-props': {
style: {
width: 64,
},
},
},
advanceCharge: {
type: 'string',
'x-component': 'string',
enum: [],
title: '预付款',
'x-rules': [
{
required: true,
message: '请选择预付款',
},
],
'x-component-props': {
style: {
width: 114,
},
},
},
settlementDocuments: {
type: 'string',
title: '结算单据',
enum: [],
'x-rules': [
{
required: true,
message: '请选择结算单据',
},
],
'x-component-props': {
style: {
width: 144,
},
},
},
payType: {
type: 'string',
enum: [],
'x-component': 'PayTypeFiled',
title: intl.formatMessage({ id: 'member.management.memberPrComingClassify.drawer.form.classify.payType' }, { default: '结算方式' }),
'x-rules': [
{
required: true,
message: intl.formatMessage({ id: 'member.management.memberPrComingClassify.drawer.form.classify.payType.required' }, { default: '请选择结算方式' }),
},
],
'x-component-props': {
contentStyle: {
width: 272,
},
},
},
paymentType: {
type: 'string',
title: '付款方式',
enum: [],
'x-rules': [
{
required: true,
message: '请选择付款方式',
},
],
'x-component-props': {
style: {
width: 176,
},
},
},
invoiceType: {
type: 'string',
enum: [],
title: intl.formatMessage({ id: 'member.management.memberPrComingClassify.drawer.form.classify.invoiceTypeName' }),
required: true,
'x-component-props': {
style: {
width: 176,
},
},
},
taxPoint: {
type: 'string',
title: intl.formatMessage({ id: 'member.management.memberPrComingClassify.drawer.form.classify.taxPoint' }),
required: true,
enum: editable ? TAX_POINT_OPTIONS : undefined,
'x-component-props': {
style: {
width: 112,
},
addonAfter: editable ? '' : '%',
},
},
details: {
type: 'string',
title: intl.formatMessage({ id: 'member.management.memberPrComingClassify.drawer.form.classify.category' }),
'x-component': 'TreeSelectField',
'x-component-props': {
fieldNames: { label: 'title', value: 'id' },
style: {
width: 290,
},
},
required: true,
},
},
},
},
// categories: {
// type: 'array',
// title: intl.formatMessage({ id: 'member.management.memberPrComingClassify.drawer.form.classify.categories' }),
// required: true,
// 'x-mega-props': {
// span: 2,
// labelAlign: 'top',
// },
// 'x-component': 'ArrayCards',
// 'x-component-props': {
// title: ' ',
// renderMoveDown: () => null,
// renderMoveUp: () => null,
// },
// items: {
// type: 'object',
// 'x-mega-props': {
// labelCol: 5,
// wrapperCol: 19,
// },
// properties: {
// details: {
// type: 'string',
// title: intl.formatMessage({ id: 'member.management.memberPrComingClassify.drawer.form.classify.category' }),
// 'x-component': 'CascaderFormItem',
// 'x-component-props': {
// fieldNames: { label: 'title', value: 'id', children: '123' }, // 这里的 '123' 是故意给的,目的是为了只展示一级层级
// changeOnSelect: true,
// expandTrigger: 'hover',
// },
// required: true,
// },
// // CATEGORY_LAYOUT: {
// // type: 'object',
// // 'x-component': 'Mega-Layout',
// // 'x-component-props': {
// // grid: true,
// // full: true,
// // autoRow: true,
// // columns: 3,
// // label: '品类',
// // },
// // properties: {
// // aaa: {
// // type: 'string',
// // 'x-component': 'CascaderFormItem',
// // 'x-component-props': {
// // },
// // },
// // provinceId: {
// // type: 'string',
// // enum: [],
// // 'x-component-props': {
// // placeholder: '请选择',
// // },
// // required: true,
// // },
// // cityId: {
// // type: 'string',
// // enum: [],
// // 'x-component-props': {
// // placeholder: '请选择',
// // },
// // required: true,
// // },
// // areaId: {
// // type: 'string',
// // enum: [],
// // 'x-component-props': {
// // placeholder: '请选择',
// // },
// // required: true,
// // },
// // },
// // },
// advanceCharge: {
// type: 'string',
// 'x-component': 'Radio',
// enum: [],
// title: '预付款',
// 'x-rules': [
// {
// required: true,
// message: '请选择预付款',
// },
// ],
// },
// settlementDocuments: {
// type: 'string',
// title: '结算单据',
// enum: [],
// 'x-rules': [
// {
// required: true,
// message: '请选择结算单据',
// },
// ],
// },
// payType: {
// type: 'string',
// enum: [],
// 'x-component': 'Radio',
// title: intl.formatMessage({ id: 'member.management.memberPrComingClassify.drawer.form.classify.payType' }, { default: '结算方式' }),
// 'x-rules': [
// {
// required: true,
// message: intl.formatMessage({ id: 'member.management.memberPrComingClassify.drawer.form.classify.payType.required' }, { default: '请选择结算方式' }),
// },
// ],
// },
// PAYMENT_DAYS_MONTH_WRAP: {
// type: 'object',
// 'x-component': 'Mega-Layout',
// 'x-component-props': {
// grid: true,
// full: true,
// autoRow: true,
// columns: 2,
// label: ' ',
// labelCol: 8,
// },
// properties: {
// month: {
// type: 'string',
// title: '',
// 'x-component-props': {
// addonAfter: intl.formatMessage({ id: 'member.management.memberPrComingClassify.drawer.form.classify.month.addonAfter' }, { default: '个月' }),
// },
// 'x-rules': [
// {
// pattern: PATTERN_MAPS.quantity,
// message: intl.formatMessage({ id: 'member.management.memberPrComingClassify.drawer.form.classify.month.legal' }, { default: '请输入正整数' }),
// },
// ],
// },
// monthDay: {
// type: 'string',
// title: intl.formatMessage({ id: 'member.management.memberPrComingClassify.drawer.form.classify.monthDay' }, { default: '结算日' }),
// 'x-component-props': {
// addonAfter: intl.formatMessage({ id: 'member.management.memberPrComingClassify.drawer.form.classify.monthDay.addonAfter' }, { default: '号' }),
// },
// 'x-rules': [
// {
// pattern: PATTERN_MAPS.quantity,
// message: intl.formatMessage({ id: 'member.management.memberPrComingClassify.drawer.form.classify.monthDay.legal' }, { default: '请输入正整数' }),
// },
// {
// validator(value) {
// const intVal = +value;
// return intVal > 31 || intVal < 0 ? intl.formatMessage({ id: 'member.management.memberPrComingClassify.drawer.form.classify.monthDay.limit' }, { default: '请输入大于0 小于等于 31的数值' }) : '';
// }
// },
// ],
// },
// },
// visible: false,
// },
// PAYMENT_DAYS_DAY_WRAP: {
// type: 'object',
// 'x-component': 'Mega-Layout',
// 'x-component-props': {
// grid: true,
// full: true,
// autoRow: true,
// columns: 2,
// label: ' ',
// labelCol: 8,
// },
// properties: {
// days: {
// type: 'string',
// title: '',
// 'x-component-props': {
// addonAfter: intl.formatMessage({ id: 'member.management.memberPrComingClassify.drawer.form.classify.days.addonAfter' }, { default: '天' }),
// },
// 'x-rules': [
// {
// pattern: PATTERN_MAPS.quantity,
// message: intl.formatMessage({ id: 'member.management.memberPrComingClassify.drawer.form.classify.days.legal' }, { default: '请输入正整数' }),
// },
// ],
// },
// },
// visible: false,
// },
// MONTHLY_TATEMENT_WRAP: {
// type: 'object',
// 'x-component': 'Mega-Layout',
// 'x-component-props': {
// grid: true,
// full: true,
// autoRow: true,
// columns: 2,
// label: ' ',
// labelCol: 8,
// },
// properties: {
// monthDay: {
// type: 'string',
// title: intl.formatMessage({ id: 'member.management.memberPrComingClassify.drawer.form.classify.monthDay' }, { default: '结算日' }),
// 'x-component-props': {
// addonAfter: intl.formatMessage({ id: 'member.management.memberPrComingClassify.drawer.form.classify.monthDay.addonAfter' }, { default: '号' }),
// },
// 'x-rules': [
// {
// pattern: PATTERN_MAPS.quantity,
// message: intl.formatMessage({ id: 'member.management.memberPrComingClassify.drawer.form.classify.monthDay.legal' }, { default: '请输入正整数' }),
// },
// {
// validator(value) {
// const intVal = +value;
// return intVal > 31 || intVal < 0 ? intl.formatMessage({ id: 'member.management.memberPrComingClassify.drawer.form.classify.monthDay.limit' }, { default: '请输入大于0 小于等于 31的数值' }) : '';
// }
// },
// ],
// },
// },
// visible: false,
// },
// paymentType: {
// type: 'string',
// title: '付款方式',
// enum: [],
// 'x-rules': [
// {
// required: true,
// message: '请选择付款方式',
// },
// ],
// },
// invoiceType: {
// type: 'string',
// enum: [],
// title: intl.formatMessage({ id: 'member.management.memberPrComingClassify.drawer.form.classify.invoiceTypeName' }),
// required: true,
// },
// taxPoint: {
// type: 'string',
// title: intl.formatMessage({ id: 'member.management.memberPrComingClassify.drawer.form.classify.taxPoint' }),
// enum: [
// {
// label: MEMBER_TAX_POINT[MEMBER_TAX_POINT_1],
// value: MEMBER_TAX_POINT_1,
// },
// {
// label: MEMBER_TAX_POINT[MEMBER_TAX_POINT_2],
// value: MEMBER_TAX_POINT_2,
// },
// {
// label: MEMBER_TAX_POINT[MEMBER_TAX_POINT_3],
// value: MEMBER_TAX_POINT_3,
// },
// {
// label: MEMBER_TAX_POINT[MEMBER_TAX_POINT_4],
// value: MEMBER_TAX_POINT_4,
// },
// {
// label: MEMBER_TAX_POINT[MEMBER_TAX_POINT_5],
// value: MEMBER_TAX_POINT_5,
// },
// ],
// required: true,
// },
// },
// },
// },
},
},
},
});
};
\ No newline at end of file
export type CategoryItemType = {
/**
* 数据id
*/
id: string,
/**
* 父级id
*/
parentId: string,
/**
* 标题
*/
title: string,
/**
* 是否选中
*/
checked: boolean,
/**
* 图片url路径
*/
imageUrl: string,
/**
* 子元素
*/
children?: CategoryItemType[],
}
export function breakUpCategory(dataSource: CategoryItemType[]): {} {
const valueMap = {};
function loops(list, parent?) {
return (list || []).map(({ children, id, title }) => {
const node: any = (valueMap[id] = {
parent,
parentId: parent?.categoryId || 0,
categoryId: +id,
level: (parent?.level || 0) + 1,
name: title,
});
node.children = loops(children, node);
return node;
});
}
loops(dataSource);
return valueMap;
}
export type CategoryType = {
/**
* 层级
*/
level: number,
/**
* 品类id
*/
categoryId: number,
/**
* 品类名称
*/
name: string,
/**
* 子节点
*/
children?: CategoryType[],
/**
* 父级id
*/
parentId: number,
/**
* 父级
*/
parent?: CategoryType,
}
export function getCategoryPath(value: string, valueMap: {}): CategoryType[] {
const path: CategoryType[] = [];
let current = valueMap[value];
while (current) {
path.unshift({
level: current.level,
categoryId: current.categoryId,
name: current.name,
parentId: current.parentId,
});
current = current.parent;
}
return path;
}
export function getCategoryAllKeys(dataSource: CategoryType[]): string[] {
const ret: string[] = [];
function loops(list: CategoryType[]) {
list.forEach((item) => {
if (item.children && item.children.length) {
loops(item.children);
} else {
ret.push(`${item.categoryId}`);
}
});
}
loops(dataSource);
return ret;
};
export function nestedCategory(dataSource: CategoryType[]): CategoryType {
return dataSource.reduceRight((pre, now) => {
const { parent, ...rest } = now;
return [{
...rest,
children: pre,
}];
}, [])[0];
}
\ No newline at end of file
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