import * as React from 'react'; import { StyleSheet, Text, TextStyle, TouchableOpacity, TouchableWithoutFeedback, View, ViewStyle, } from 'react-native'; import { cashier } from '../../_styles/themes/default.components'; import { innerScaleSize } from '../../_styles/themes/responsive'; import MDIcon from '../icon'; export interface IMDCashierChannel { icon?: React.ReactNode; text: string; value: string; } interface IMDCashierProps { styles?: IMDCashierStyle; channelData?: T[]; channelLimit?: number; // 支付渠道超出限制数目时展示更多支付渠道按钮, default is 2 defaultIndex?: number; // 默认选中支付渠道索引, default is 0 paymentTitle?: string; // 支付金额标题, default is `支付金额(元)` paymentAmount?: number; // 支付金额, default is 0 paymentDescribe?: string; // 支付金额说明 moreButtonText?: string; // 更多支付方式 renderChannel?: (channel: T, index: number) => React.ReactNode; onSelect?: (index: number) => void; } interface IMDCashierState { checkedIndex?: number; expand: boolean; } interface IMDCashierStyle { wrapper?: ViewStyle; text?: TextStyle; headerWrapper?: ViewStyle; headerTitle?: TextStyle; headerAmount?: TextStyle; headerDesc?: TextStyle; itemWrapper?: ViewStyle; channelWrapper?: ViewStyle; bottomButton?: ViewStyle; channelMoreWrapper?: ViewStyle; channelMoreText?: TextStyle; triangle?: ViewStyle; } export const MDCashierStyles: IMDCashierStyle = { wrapper: { backgroundColor: 'white', }, headerWrapper: { backgroundColor: 'white', paddingTop: innerScaleSize(65), paddingBottom: innerScaleSize(25), }, headerTitle: { fontSize: cashier.chooseTitleFontSize, color: cashier.chooseTitleColor, textAlign: 'center', }, headerAmount: { fontFamily: cashier.chooseAmountFontFamily, fontSize: cashier.chooseAmountFontSize, color: cashier.chooseAmountColor, lineHeight: cashier.chooseAmountLineHeight, marginTop: innerScaleSize(20), letterSpacing: innerScaleSize(-2), textAlign: 'center', }, headerDesc: { fontSize: cashier.chooseDescribeFontSize, color: cashier.chooseDescribeColor, textAlign: 'center', }, itemWrapper: { flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', paddingVertical: innerScaleSize(10), }, channelWrapper: { backgroundColor: 'white', flexDirection: 'column', paddingVertical: innerScaleSize(40), paddingHorizontal: innerScaleSize(60), }, channelMoreWrapper: { flexDirection: 'row', alignItems: 'center', justifyContent: 'center', marginTop: innerScaleSize(10), }, channelMoreText: { color: cashier.chooseMoreColor, fontSize: cashier.chooseMoreFontSize, }, triangle: { borderTopWidth: innerScaleSize(16), borderTopColor: cashier.chooseMoreColor, borderLeftColor: 'transparent', borderLeftWidth: innerScaleSize(8), borderRightColor: 'transparent', borderRightWidth: innerScaleSize(8), marginLeft: innerScaleSize(10), marginTop: innerScaleSize(8), }, }; const styles = StyleSheet.create(MDCashierStyles); export default class MDCashierChannel extends React.Component< IMDCashierProps, IMDCashierState > { public static defaultProps = { styles, paymentTitle: '支付金额(元)', paymentAmount: 0, paymentDescribe: '关于支付金额的特殊说明', moreButtonText: '更多支付方式', channelLimit: 2, defaultIndex: 0, }; constructor (props: IMDCashierProps) { super(props); this.state = { checkedIndex: props.defaultIndex, expand: false, }; } public render () { const { styles: _styles, channelData, channelLimit } = this.props; const { expand } = this.state; // 需要收起 const needFolder = channelData && channelData.length > channelLimit!; const needRenderMore = !expand && needFolder; return ( {this.renderHeader()} {channelData && channelData.length > 0 ? ( {this.renderChannelList( needRenderMore ? channelData.slice(0, 1) : channelData )} {needRenderMore && this.renderChannelMore()} ) : null} {this.props.children} ); } private renderHeader () { const { styles: _styles, paymentTitle, paymentAmount, paymentDescribe, } = this.props; return ( {paymentTitle} {paymentAmount!.toFixed(2)} {paymentDescribe} ); } private renderChannel (channel: IMDCashierChannel, index: number): React.ReactNode { const { checkedIndex } = this.state; const { onSelect } = this.props; const checked = checkedIndex === index; return ( { this.setState({ checkedIndex: index }); onSelect && onSelect(index); }} key={index} > {typeof channel.icon === 'string' ? ( channel.icon ) : ( channel.icon )} {channel.text} ); } private renderChannelList (channelData: T[]) { const renderChannel = this.props.renderChannel || this.renderChannel.bind(this); if (channelData && channelData.length > 0) { const channelList = channelData.map((channel, index) => { if ( !( // @ts-ignore channel.hasOwnProperty('value') && // @ts-ignore channel.hasOwnProperty('icon') && // @ts-ignore channel.hasOwnProperty('text') ) && !this.props.renderChannel ) { console.error('You need to impletment renderChannel'); } return renderChannel(channel as any, index); }); return channelList; } return null; } private renderChannelMore () { const { styles: _styles, moreButtonText } = this.props; return ( { this.setState({ expand: true }); }} > {moreButtonText} ); } }