CalculatorView.js 6.81 KB
import React, {Component} from 'react';
import {Text, View,} from 'react-native';
import {Calculate, convertCurrency, isJSONString} from "../utils/utils";
// 默认高度
const defaultHeight = (62);
// 默认标题高度
const titleViewHeight = (24);
// 默认横向内边距
const HPading = (16);
// 默认纵向内边距
const VPading = (6);

/*
计算公式组件(type:'CALCULATOR')
 */
export default class CalculatorView extends Component {
    // 构造方法
    constructor(props) {
        super(props);
        this.state = {
            result: '',// 计算结果
        };
        // 传入参数
        this.attrData = this.props.attrData;
        // 键盘格式
        this.inputType = this.props.inputType || 'default';
        // json解析后的传入参数
        this.extendData = (this.attrData.data && this.attrData.data.length > 0) ? JSON.parse(this.attrData.data) : {};
        // 计算公式
        this.expression = this.extendData.expression;
        // 计算公式分子数组
        this.moleculeDataList = [];
    }

    // 生命周期-组件将要展示
    componentWillMount() {
        // 设置默认值
        if (this.attrData.value && this.attrData.value.length > 0) {
            if (isJSONString(this.attrData.value)) {
                let data = JSON.parse(this.attrData.value);
                this.setState({
                    result: data.result
                })
            }
        }
    }

    // 计算
    calculateValue(count, key) {
        // 如果计算公式为空、或输入的数值不是表达式中的分子,不计算
        if (!!!this.expression || this.expression.length === 0 || this.expression.indexOf(key) === -1) {
            return;
        }
        // 计算表达式
        let moleculeData = {count: count, key: key};
        this.updateMoleculeDataList(moleculeData);
        let expression = this.replaceExpression();

        var calculate = new Calculate(expression);
        let _result = calculate.calculateResult();
        if (_result && _result.length > 0) {
            // 结果是整数,不做精度计算
            _result = Number.isInteger(_result) ? _result : parseFloat(_result).toFixed(2);
        }
        this.setState({
            result: _result
        });
        // 计算结果
        let resultValue = {expression: this.expression, result: _result};
        this.attrData.value = JSON.stringify(resultValue)
    }

    /**
     * 更新公式分子
     * @param data
     */
    updateMoleculeDataList(data) {
        if (this.moleculeDataList && this.moleculeDataList.length > 0) {
            let length = this.moleculeDataList.length;
            for (let i = 0; i < length; i++) {
                let _molecule = this.moleculeDataList[i];
                if (_molecule.key === data.key) {
                    // 刷新分子数值
                    if (data.count && data.count.length > 0) {
                        _molecule.count = data.count;
                    } else {
                        this.moleculeDataList.splice(i, 1);
                    }
                    return;
                }
            }
        }
        // 添加新分子
        this.moleculeDataList.push(data);
    }

    /**
     * 替换表达式
     */
    replaceExpression() {
        if (this.moleculeDataList && this.moleculeDataList.length > 0) {
            let wreckedExpression = this.expression;
            this.moleculeDataList.map(molecule => {
                wreckedExpression = wreckedExpression.replace(molecule.key, molecule.count);
            });
            return wreckedExpression;
        }
        return '';
    }

    // 绘制UI
    render() {
        /*
        name:标题
        code:代码编号
        type:控件类型(CALCULATOR)
        description:描述
        isRequired:是否必须
        isPreview:是否预览
        */
        let {name, code, type, description, isRequired, isPreview} = this.attrData;
        /*
        placeholder:输入提示文字
        showChinese:是否显示大写金额
        */
        let {placeholder, showChinese} = this.extendData;

        let calcHeight = defaultHeight;
        if (showChinese) {
            calcHeight += 40
        }

        return (
            // 最外层样式区域
            <View style={{
                // 宽度
                width: '100%',
                // 背景色
                backgroundColor: 'white',
                // 上内边距
                paddingTop: VPading,
                // 左内边距
                paddingLeft: 10,
                // 右内边距
                paddingRight: 15,
                // 高度
                height: calcHeight
            }}>
                {/*标题显示区域*/}
                <View style={{
                    flexDirection: 'row',
                    height: titleViewHeight,
                    justifyContent: 'flex-start',
                    alignItems: 'center'
                }}>
                    {/*是否必须UI设定*/}
                    {isRequired && <Text style={{color: "#FF3030"}}>* </Text>}
                    {!isRequired && <Text style={{color: "#fff"}}>* </Text>}
                    {/*标题设定*/}
                    <Text style={{fontSize: 16, color: 'rgba(0, 0, 0, 1)'}}>{name || ""}</Text>
                </View>
                {/*计算结果显示区域*/}
                <View style={{
                    width: "100%",
                    height: 30,
                    marginLeft: 10,
                    marginTop: 4,
                    marginBottom: 4,
                    justifyContent: 'center',
                    backgroundColor: 'white'
                }}>
                    <Text
                        style={{
                            fontSize: 14,
                            color: (!!this.state.result && this.state.result.length > 0) ? 'black' : '#999',
                            textAlign: 'left',
                        }}>{this.state.result || placeholder || '自动计算数值'}
                    </Text>
                </View>
                {/*大写金额显示区域*/}
                {showChinese && <View style={{
                    height: 40,
                    paddingBottom: VPading,
                    flexDirection: 'row',
                    alignItems: 'center',
                    backgroundColor: '#fff',
                    marginLeft: 10,
                    marginRight: 15
                }}>
                    <Text style={{fontSize: 16, color: 'rgba(0, 0, 0, 1)'}}>大写</Text>
                    <Text style={{
                        fontSize: 14,
                        color: 'rgba(0, 0, 0, 1)',
                        marginLeft: 4,
                        marginRight: 4
                    }}>{!!this.state.result ? convertCurrency(this.state.result) : ''}</Text>
                </View>
                }
            </View>
        )
    }
}