Commit 60b32185 authored by Bill's avatar Bill

添加结算策略配置,修改modalTable 首次弹出时请求两次接口

parent b7e76fd8
......@@ -69,7 +69,20 @@ const router = {
component: '@/pages/ruleSettingManage/memberAuthManage/detail',
hideInMenu: true,
hidePageHeader: true
}
},
// 平台结算策略配置, 列表页
{
path: '/ruleSettingManager/platformSettlementStrategy',
name: 'platformSettlementStrategy',
component: '@/pages/ruleSettingManage/platformSettlementStrategy/list'
},
// 平台结算策略配置, 新增平台策略配置
{
path: '/ruleSettingManager/platformSettlementStrategy/add',
name: 'addplatformSettlementStrategy',
component: '@/pages/ruleSettingManage/platformSettlementStrategy/info',
hidePageHeader: true
}
]
}
export default router
\ No newline at end of file
import React, { ReactText, useRef, useEffect } from 'react'
import React, { ReactText, useRef, useEffect, useState } from 'react'
import {StandardTable} from 'god'
import { IStandardTableProps } from 'god/dist/src/standard-table'
import { Row, Col, Modal } from 'antd'
......@@ -22,11 +22,17 @@ export interface ModalTableProps extends IStandardTableProps<any> {
const ModalTable:React.FC<ModalTableProps> = (props) => {
const { width = 704,modalTitle, confirm, cancel, visible, currentRef, resetModal, modalType = 'none', ...resetTable } = props
const selfRef = currentRef || useRef<any>({})
const selfRef = currentRef || useRef<any>({});
// 这里modaltable 第一次渲染的话会加载两次,这里是因为visible reload加载一次,standard table 加载一次
const [firstRender, setFirstRender] = useState<boolean>(true)
useEffect(() => {
if (visible) {
// 重新开启时需reload接口
selfRef.current.reload && selfRef.current.reload()
// modaltable 第一次加载的时候不做任何操作,等下一次加载的时候才做
if(!firstRender) {
selfRef.current.reload && selfRef.current.reload()
}
setFirstRender(false);
} else {
selfRef.current.resetField && selfRef.current.resetField({
validate: false
......
......@@ -34,6 +34,7 @@ export interface PayInitializeConfig {
export interface PayPlatformPayConfig {
id: number;
way: string;
wayId?: any;
payType: number;
isPitchOn: number;
}
......@@ -49,7 +50,7 @@ export interface ShopInfo {
type: number;
environment: number;
logoUrl: string;
describe: string;
describe?: any;
state: number;
url: string;
}
......
......@@ -107,6 +107,8 @@ export default {
'menu.ruleSettingManager.ruleDetails': '交易规则详情',
'menu.ruleSettingManager.memberAuthManage': '会员角色权限设置',
'menu.ruleSettingManager.memberAuthManageDetail': '会员角色权限设置',
'menu.ruleSettingManager.platformSettlementStrategy': '平台结算策略配置',
'menu.ruleSettingManager.addplatformSettlementStrategy': '新增平台结算策略',
// 品类和属性
'menu.classAndProperty': '平台品类及属性',
......
......@@ -119,7 +119,7 @@ const logisticsDetail: React.FC = () => {
<Descriptions.Item label="结算单数:">{infoDetail?.totalCount }</Descriptions.Item>
<Descriptions.Item label="结算金额:">{infoDetail?.amount}</Descriptions.Item>
<Descriptions.Item label="结算方式:">{infoDetail?.settlementWayName}</Descriptions.Item>
<Descriptions.Item label="外部状态:">
<Descriptions.Item label="结算状态:">
<StatusTag text={infoDetail?.statusName} />
</Descriptions.Item>
</Descriptions>
......
.flexRow() {
display: flex;
flex-direction: row;
}
.radiosContainer {
display: flex;
flex-direction: row;
.dayRadio {
margin-right: 20px
}
}
.values {
.days {
.flexRow();
// margin-left: 25px;
margin-top: 25px;
}
}
// .period {
// .flexRow();
// margin-bottom: 20px;
// .days {
// .flexRow();
// margin-left: 25px;
// }
// }
\ No newline at end of file
/*
* @Author: bILL
* @Date: 2020-10-20 17:39:16
* @Description: 新增会员结算结算方式
*/
import React, { useEffect, useState } from 'react';
import { Radio, Input, Tooltip } from 'antd';
import { QuestionCircleOutlined } from '@ant-design/icons';
import styles from './index.less';
import { registerValidationRules } from '@formily/antd' // 或者 @formily/next
const DAY = 1;
const MONTH = 2;
registerValidationRules({
settleMethodRule: value => {
const { active, otherValues } = value;
const isNumber = /^\d+$/; // 数字
const pattern = /[0-9]+\.[0-9]*/;
if(active == MONTH) {
return (otherValues[1] < 0 || otherValues[1] > 31) || pattern.test(otherValues[1]) ? '只允许填写1-31号': ''
} else {
return !isNumber.test(otherValues[0]) || pattern.test(otherValues[0]) ? '只允许填写正整数' : ""
}
}
})
const SettleMethod = (props) => {
const { active = DAY, otherValues = [30, 1] } = props.value || {};
const { daysVisible, monthVisible } = props;
const handleChange = (e, type) => {
if(active == type) {
return ;
}
const previewValue = otherValues
// setActive(type)
props.onChange({
active: type,
otherValues: previewValue
})
}
const handleInputChange = (value, type) => {
const target = type - 1;
console.log(target);
const temp = [...otherValues];
temp[target] = value;
console.log(temp[target]);
props.onChange({
active: type,
otherValues: temp
})
}
return (
<div>
<div className={styles.radiosContainer}>
<div className={styles.dayRadio}>
<Radio name="method" checked={active == DAY} onChange={(e) => handleChange(e, DAY)}>账期(默认)</Radio>
<Tooltip title="选择账期并设置账期天数后,即结算时间为T+账期天数,系统每天自动将支付时间达到账期天数的支付金额进行结算,如设置账期天数为30天,则系统每天结算支付时间达到30天的支付金额">
<QuestionCircleOutlined />
</Tooltip>
</div>
<div >
<Radio name="method" checked={active == MONTH} onChange={(e) => handleChange(e, MONTH)}>月结</Radio>
<Tooltip title="选择月结并设置每月结算日期后,系统将在每月结算日当天自动将上月发生的支付金额进行结算,如每月结算日期设置为每月1号,则每月1号系统自动结算上月所有已发生的支付金额">
<QuestionCircleOutlined />
</Tooltip>
</div>
</div>
<div className={styles.values}>
{
active === DAY
? <div className={styles.days}>
<div style={{margin: '0 20px 0 0px'}}>账期天数</div>
<div>
<Input
addonAfter={"天"}
value={otherValues[DAY - 1]}
onChange={(e) => handleInputChange(e.target.value, DAY)}
disabled={active !== DAY}
style={{width: '160px'}}
/></div>
</div>
: <div className={styles.days}>
<div style={{marginRight: '20px'}}>每月结算日期:每月</div>
<div>
<Input
addonAfter={"号"}
style={{width: '160px'}}
value={otherValues[MONTH - 1]}
onChange={(e) => handleInputChange(e.target.value, MONTH)}
disabled={active !== MONTH}
/>
</div>
</div>
}
</div>
<div>
{
!monthVisible && !daysVisible
? <div>请在pass平台配置结算方式,否则无法创建会员策略</div>
: null
}
</div>
</div>
)
}
const Index = (props) => {
const value = props.value || {active: 0, otherValues: [30, 1]};
const componentProps = props.props['x-component-props'] || {};
const options = componentProps.options || {};
// 默认选择
useEffect(() => {
// const componentProps = props.props['x-component-props'] || {};
const defaultValue = componentProps.default || {};
if(!options.days && !options.month) {
return
}
if(typeof props.initialValue == 'undefined') {
props.mutators.change(defaultValue)
} else {
props.mutators.change(props.initialValue)
}
}, [props.initialValue, options])
const onChange = (value) => {
console.log(value);
props.mutators.change(value);
}
return (
<SettleMethod
value={value}
daysVisible={options.days}
monthVisible={options.month}
onChange={onChange}
/>
)
}
Index.isFieldComponent = true;
export default Index;
\ No newline at end of file
/*
* @Author: Bill
* @Date: 2020-10-19 16:54:15
* @Description: 新建会员策略支付策略
*/
import React, { useEffect, useState } from 'react';
import { PageHeaderWrapper } from '@ant-design/pro-layout'
import NiceForm from '@/components/NiceForm';
import { Card, Button, message } from 'antd';
import { createFormActions } from '@formily/antd';
import { PlusOutlined } from '@ant-design/icons'
import ModalTable from '@/components/ModalTable';
import SearchSelect from '@/components/NiceForm/components/SearchSelect'
import Search from '@/components/NiceForm/components/Search'
import Submit from '@/components/NiceForm/components/Submit'
import { useStateFilterSearchLinkageEffect } from '@/formSchema/effects/useFilterSearch';
import { addSchema, memberSchema } from './schema';
import { FORM_FILTER_PATH } from '@/formSchema/const';
import { useAsyncSelect } from '@/formSchema/effects/useAsyncSelect';
import SettleMethod from '../../components/SettleMethod';
import { useRowSelectionTable } from '@/hooks/useRowSelectionTable';
import { PublicApi } from '@/services/api';
import { usePageStatus } from '@/hooks/usePageStatus';
import { history, Prompt } from 'umi'
export const fetchOptions = (service) => {
return async function() {
const res = await service();
if(res.code === 1000) {
return res.data.map((item) => {return { label: item.text, value: item.id }})
}
return [];
}
}
const formActions = createFormActions();
const { getSettleAccountsPlatformConfigGetMemberSettlementStrategyDetail } = PublicApi
const common_columns: any = [
{ title: 'ID', dataIndex: 'memberId' },
{
title: '会员名称',
dataIndex: 'name',
render: (text: string, record: any) => {
return record.name || record.memberName
}
},
{ title: '会员类型', dataIndex: 'memberTypeName' },
{ title: '会员角色', dataIndex: 'roleName' },
{
title: '会员等级',
dataIndex: 'levelTag',
render: (text: string, record: any) => {
return record.levelTag || record.levelName
}
},
]
const MemberSettleAdd: React.FC = () => {
const [visible, setVisible] = useState(false)
const [memberRowSelection, memberRowCtl] = useRowSelectionTable({ customKey: 'memberId' });
const [initialValue, setInitialValue] = useState({});
const { id, preview } = usePageStatus();
const [submitLoading, setSubmitLoading ] = useState(false);
const [unsaved, setUnsaved] = useState(true);
const isAdd = !id && !preview;
const tableAddButton = () => {
return (
<div>
<Button
onClick={() => setVisible(true)}
style={{marginBottom: 16}}
block
icon={<PlusOutlined/>}
type='dashed'
>
选择适用会员
</Button>
</div>
)
}
const columns = common_columns.concat(
[
{
title: '操作',
render: (text, record) => {
return (
<a onClick={() => handleRemove(record.memberId)}>删除</a>
)
}
}
]
);
const handleCancelAddMember = () => {
setVisible(false);
}
// 从PAAS平台--规则配置--平台规则配置取已勾选的结算方式决定是否显示结算方式
const fetchBalancedMethods = async () => {
const { data } = await PublicApi.getManageRuleConfigurationList({platformType: '5'});
const length = data.length
return {
days: length > 0 && data[0].check,
month: length > 1 && data[1].check
};
}
// 获取适用会员
const fetchMemberData = async (params: any) => {
const { data } = await PublicApi.getMemberManageLowerPageBynamerole(params);
return data
}
// 获取适用会员下拉搜索框
const fetchMemberSearchFilter = async () => {
// /member/manage/role/sub/list
const { data, code } = await PublicApi.postMemberManageRoleSubList({}, {method: 'GET',ctlType: "none"});
// console.log(data);
if(code === 1000) {
return data
}
return [];
}
// 使用会员弹框确认
const handleOkAddMember = () => {
formActions.setFieldValue('Tabs.memberTab.someLists', memberRowCtl.selectRow);
setVisible(false);
}
// 提交
const handleSubmit = (value) => {
console.log(value);
return ;
const memberList = value.someLists.map((item) => ({ memberId: item.memberId, roleId: item.roleId }));
const tempData = {
name: value.name,
settlementOrderType: value.settlementOrderType,
memberList: memberList,
settlementWay: value.settlementWay.active,
settlementDays: value.settlementWay.otherValues[0],
settlementDate: value.settlementWay.otherValues[1],
}
const serviceActions = isAdd
? PublicApi.postSettleAccountsPlatformConfigAddMemberSettlementStrategy
: PublicApi.postSettleAccountsPlatformConfigUpdateMemberSettlementStrategy
const postData = {...tempData, id: id || 0 }
setSubmitLoading(true);
setUnsaved(false);
serviceActions(postData).then((data) => {
setSubmitLoading(false);
if(data.code === 1000) {
history.push('/memberCenter/balance/settleRules/memberSettleList')
}
})
}
// 提交
const handleClick = () => {
formActions.submit()
}
//
const handleRemove = (id: number) => {
const string = 'Tabs.memberTab.someLists';
const chooseList = formActions.getFieldValue(string);
const res = chooseList.filter((item) => item.memberId !== id);
formActions.setFieldValue(string, res);
// 必须设置key
memberRowCtl.setSelectRow(res);
memberRowCtl.setSelectedRowKeys(res.map((item) => item.memberId))
}
// 从PAAS平台--规则配置--平台规则配置取已勾选的结算方式决定是否显示结算方式
useEffect(() => {
fetchBalancedMethods().then(data => {
formActions.setFieldState('Tabs.basicTab.layout.settlementWay', (state) => {
//@ts-ignore
state.props['x-component-props']['options'] = data;
})
})
}, [])
/**
* 进入详情页之后,初始化数据
*/
useEffect(() => {
if(id) {
async function getInfo() {
const res = await getSettleAccountsPlatformConfigGetMemberSettlementStrategyDetail({id})
if(res.code === 1000) {
setInitialValue({
name: res.data.name,
settlementOrderType: res.data.settlementOrderType,
memberList: res.data.memberList,
settlementWay: {
active: res.data.settlementWay,
otherValues: [res.data.settlementDays, res.data.settlementDate],
}
})
formActions.setFieldValue('Tabs.memberTab.someLists', res.data.memberList);
// 必须设置key
memberRowCtl.setSelectRow(res.data.memberList);
memberRowCtl.setSelectedRowKeys(res.data.memberList.map((item) => item.memberId))
} else {
message.error({content: res.message})
}
}
getInfo();
}
}, [id])
return (
<PageHeaderWrapper
extra={[
<Button loading={submitLoading} key="1" type="primary" onClick={handleClick} >
保存
</Button>,
]}
>
<Card>
<NiceForm
actions={formActions}
initialValues={initialValue}
expressionScope={{
tableAddButton: tableAddButton(),
tableColumns: columns
}}
components={{SettleMethod}}
onSubmit={values => handleSubmit(values)}
schema={addSchema}
effects={() => {
useAsyncSelect(
"settlementOrderType",
fetchOptions(PublicApi.getSettleAccountsCommonGetStrategySettlementOrderType)
)
}}
/>
<ModalTable
modalTitle='选择适用会员'
confirm={handleOkAddMember}
cancel={handleCancelAddMember}
visible={visible}
columns={common_columns}
rowSelection={memberRowSelection}
fetchTableData={params => fetchMemberData(params)}
tableProps={{
rowKey: 'memberId',
}}
formilyProps={
{
ctx: {
schema: memberSchema,
actions: formActions,
components: { ModalSearch: Search, SearchSelect, Submit } ,
effects: ($, actions) => {
useStateFilterSearchLinkageEffect(
$,
actions,
'name',
FORM_FILTER_PATH,
)
// useAsyncSelect(
// 'roleId',
// fetchMemberSearchFilter,
// ['roleName', 'roleId']
// )
}
}
}
}
/>
</Card>
<Prompt when={unsaved} message="内容还没保存,确定离开吗?"/>
</PageHeaderWrapper>
)
}
export default MemberSettleAdd
\ No newline at end of file
import { ISchema } from '@formily/antd'
import { FORM_FILTER_PATH } from '@/formSchema/const';
/**
* 新增会员结算策略schema
*
*/
export const addSchema: ISchema = {
type: 'object',
properties: {
'Tabs': {
type: 'object',
'x-component': 'tab',
'x-component-props': {
type: 'card'
},
properties: {
basicTab: {
type: 'object',
'x-component': 'tabpane',
'x-component-props': {
tab: '基本信息'
},
properties: {
layout: {
type: 'object',
'x-component': 'mega-layout',
'x-component-props': {
labelCol: 4,
wrapperCol: 9,
labelAlign: 'left'
},
properties: {
name: {
title: '策略名称',
type: 'string',
'x-rules': [
{required: true, message: '请填写策略名称'},
]
},
settlementWay: {
title: '结算方式',
'x-component': 'SettleMethod',
'x-rules': [
{
required: true,
message: '请选择结算方式并填写信息'
},
{
settleMethodRule: true
}
],
'x-component-props': {
// options: {
// days: true,
// month: false
// },
default: {
active: 1,
otherValues: [30, 1]
}
}
},
// settlementOrderType: {
// type: 'string',
// enum: [],
// title: '结算单据',
// 'x-rules': [
// {required: true, message: '请填写策略名称'},
// ]
// }
},
}
}
},
memberTab: {
type: 'object',
'x-component': 'tabpane',
'x-component-props': {
tab: '适用会员'
},
properties: {
layout: {
type: 'object',
'x-component': 'mega-layout',
'x-component-props': {
labelCol: 4,
wrapperCol: 9,
labelAlign: 'left'
},
properties: {
isAllMember: {
type: 'radio',
enum: [
{label: '所有会员(默认)', value: 1},
{label: '指定会员', value: 2},
],
default: 1,
title: '适用会员',
'x-linkages': [
{
type: 'value:visible',
target: '*(someLists)',
condition: '{{$value === 2}}'
}
]
}
}
},
someLists: {
type: 'array:number',
'x-mega-props': {
wrapperCol: 24,
},
'x-component': 'MultTable',
'x-component-props': {
rowKey: 'memberId',
prefix: "{{tableAddButton}}",
columns: "{{tableColumns}}"
// columns: "{{tableColumns}}",
}
}
}
}
}
}
}
}
export const memberSchema: ISchema = {
type: 'object',
properties: {
name: {
type: 'string',
'x-component': 'ModalSearch',
'x-component-props': {
placeholder: '商品名称',
align: 'flex-left',
},
},
[FORM_FILTER_PATH]: {
type: 'object',
'x-component': 'flex-layout',
'x-component-props': {
rowStyle: {
flexWrap: 'nowrap',
style: {
marginRight: 0
}
},
colStyle: {
marginTop: 20,
},
},
properties: {
roleId: {
type: 'string',
enum: [],
"x-component-props": {
placeholder: '选择会员角色',
style: {width: '200px'}
}
},
submit: {
"x-component": 'Submit',
"x-mega-props": {
span: 1
},
"x-component-props": {
children: '查询'
}
}
}
}
}
}
\ No newline at end of file
/**
* @author Bill
* @description 平台结算策略
*/
import React, { useRef } from 'react';
import { Card, Button } from 'antd';
import NiceForm from '@/components/NiceForm';
import { StandardTable } from 'god';
import { PublicApi } from '@/services/api';
import EyePreview from '@/components/EyePreview';
import StatusSwitch from '@/components/StatusSwitch';
import { createFormActions } from '@formily/antd';
import { PlusOutlined } from '@ant-design/icons';
import { ColumnsType } from 'antd/es/table';
import { history } from 'umi';
import schema from './schema'
const formActions = createFormActions();
const MemberSettle: React.FC<{}> = () => {
const ref = useRef<any>({});
const fetchData = async (params: any) => {
console.log(params);
const { current, pageSize, name } = params
const postData = {current, pageSize, name: name || ''}
const { data } = await PublicApi.getSettleAccountsPlatformConfigPageMemberSettlementStrategy(postData);
return data;
};
const handleModify = async (record) => {
const { code } = await PublicApi.postSettleAccountsPlatformConfigSetMemberSettlementStrategyStatus({id: record.id, status: record.status ? 0 : 1})
if(code == 1000) {
formActions.submit();
}
}
const columns: ColumnsType<any> = [
{title: 'ID',dataIndex: 'id',},
{
title: '策略名称',
dataIndex: 'name',
render: (text, record) => {
return (
<div>
<EyePreview
url={`/memberCenter/balance/settleRules/memberSettleList/detail?id=${record.id}&preview=1`}
>
{text}
</EyePreview>
</div>
)
}
},
{ title: '结算方式', dataIndex: 'settlementOrderTypeName'},
{ title: '结算单据',dataIndex: 'settlementWayName'},
{
title: '状态',
dataIndex: 'status',
render: (text, record) => {
return (
<StatusSwitch
handleConfirm={() => handleModify(record)}
record={record}
fieldNames="status"
/>
)
}
},
]
const goToCreate = () => {
history.push('/memberCenter/balance/settleRules/memberSettleList/add');
}
return (
<Card>
<StandardTable
tableProps={{
rowKey: 'id',
}}
columns={columns}
currentRef={ref}
fetchTableData={(params: any) => fetchData(params)}
controlRender={
<NiceForm
actions={formActions}
expressionScope={{
createBtn: (
<div style={{width: '112px'}}>
<Button type="primary" onClick={goToCreate}><PlusOutlined /> 新建</Button>
</div>
)
}}
onSubmit={values => ref.current.reload(values)}
schema={schema}
/>
}
/>
</Card>
)
}
export default MemberSettle
\ No newline at end of file
import { ISchema } from '@formily/antd'
const schema: ISchema = {
type: 'object',
properties: {
layout: {
type: 'object',
'x-component': 'mega-layout',
'x-component-props': {
grid: true,
columns: 6
},
properties: {
createBtn: {
type: 'object',
'x-component': 'Children',
'x-component-props': {
children: '{{createBtn}}'
},
"x-mega-props": {
"span": 4
},
},
name: {
type: 'string',
'x-component': 'Search',
"x-mega-props": {
"span": 2
},
'x-component-props': {
placeholder: '搜索',
advanced: false,
},
},
}
}
}
}
export default schema
\ 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