react插件(参考)

一、form表单

Attach.js

/**
 * 表单附件上传组件
 *
 * @date    2017-07-10
 * @author  shuwenjie<4483378@qq.com>
 */

import React, { PropTypes } from 'react';
import { ImagePicker  } from 'antd-mobile';

import FormConfigs from './configs';
import common from '../../../configs/common';

class Attach extends React.Component {

  static get propTypes() {
    return {
      title: PropTypes.string,
      defaultValue:PropTypes.array,
      onValueChange: PropTypes.func,
      isrequired: PropTypes.number,
    };
  }
  static get defaultProps() {
    return {
      defaultValue:[],
      isrequired:0,
      onValueChange: () => {},
    };
  }
  constructor(props) {
    super(props);
    const {defaultValue}=this.props;
    this.state = {
      files: defaultValue
    };
  }

  onChange = (files, type, index) => {
    console.log(files);
    this.setState({
      files,
    });
  };

  onAddImageClick = (e) => {
    //e.preventDefault();
    // this.setState({
    //   files: this.state.files.concat({
    //     url: 'https://zos.alipayobjects.com/rmsportal/hqQWgTXdrlmVVYi.jpeg',
    //     id: '3',
    //   }),
    // });
  };
  onTabChange = (key) => {
    console.log(key);
  };



  render() {
    const {style,placeholder,title,isrequired,defaultValue}=this.props;
    const { files } = this.state;
    return (
      <div
        style={{
          height:this.MultilineHeight,
          ...common.theme.borderBottomStyle,
          ...style,
        }}
      >
        {
          title?
          <div>
            <div
              style={{
                ...common.theme.commonTextStyle,
                padding:'.3rem .2rem',
                fontSize:'.3rem'
              }}
              >
                {isrequired?'*':null}{title}
              </div>
              <div
                style={{
                  ...common.theme.borderBottomStyle,
                  height:1,
                  margin:'0rem .2rem'
                }}
              />

          </div>:null
        }
        
        <div
          style={{
            ...common.theme.commonFlexStyle,
            height:'100%',
            padding:'.2rem',
          }}
        >
          <ImagePicker
            files={files}
            onChange={this.onChange}
            onImageClick={(index, fs) => console.log(index, fs)}
            onAddImageClick={this.onAddImageClick}
          />
        </div>
        
      </div>
    );
  }
}
export default Attach;

AttachUpload.js

/**
 * 表单文本输入框组件
 *
 * @date    2017-06-21
 * @author  shuwenjie<4483378@qq.com>
 */

import React, { PropTypes } from 'react';
import { Icon} from 'antd-mobile';
import common from '../../../configs/common';

class AttachUpload extends React.Component {

  static get propTypes() {
    return {
      title: PropTypes.string,
      onValueChange: PropTypes.func,
      placeholder: PropTypes.string,
      defaultValue: PropTypes.string,
      isrequired: PropTypes.number,
      style:PropTypes.object,
      maxlength: PropTypes.number,
    };
  }
  static get defaultProps() {
    return {
      onValueChange() {},
      placeholder: '请输入',
      defaultValue: '',
      isrequired: 0,
      style:{},
      maxlength:200
    };
  }
  constructor(props) {
    super(props);
    const {style}=this.props;

    this.state = { };
  }

  componentDidMount() {
    const { defaultValue,onValueChange } = this.props;
    if (defaultValue && defaultValue !== '') {
      if(onValueChange)
        onValueChange(defaultValue);
    }
  }

  //渲染单行文本
  returnSingleInput(){
    const {style,placeholder,title,maxlength,isrequired,defaultValue,onValueChange}=this.props;
    return(
      <div
        style={{
          ...style,
        }}
      >
        <div
          style={{
            ...common.theme.commonFlexStyle,
            //...common.theme.borderBottomStyle,
            flexDirection:'row',
            alignItems:'center',
            padding:'.2rem 0rem'
          }}
        >
          <div
          style={{
            ...common.theme.commonTextStyle,
            padding:'.3rem .2rem',
            fontSize:'.3rem',
            width:'1.5rem'
          }}
          >
            {isrequired?'*':null}{title}
          </div>
          <div
            style={{
              ...common.theme.commonFlexStyle,
              flex:1,
              flexDirection:'row',
              justifyContent:'flex-end',
              alignItems:'center',
              position:'relative'
            }}
          >
            <input 
              style={{
                position:'absolute',
                width:'100%',
                height:'100%',
                opacity:'0',
              }}
              onChange={()=>{
                console.log('dd');
              }}
              type='file'
              accept="image/png,image/gif,image/jpg"
            />
            <img
              style={{
                width: '1.4rem',
                height: '1.4rem',
                borderRadius:'1.4rem',
              }}
              src={defaultValue}
            />
            {/*<InputItem
              style={{
                backgroundColor:'transparent',
                height:'auto',
                minHeight:'auto',
                color:'#fff',
                boder:'none'
              }}
              placeholder={placeholder?placeholder:'请输入'}
              defaultValue={defaultValue}
              onChange={(text)=>{
                if(onValueChange)
                  onValueChange(text);
                //this.setState({keyWord:text})
              }}
            />*/}
            <Icon
              style={{
                width:'.6rem',
                height:'.6rem',
                color:'#fff',
                justifyContent:'center'
              }}
              type='right'
            />
          </div>
          
        </div>
        <div
          style={{
            ...common.theme.borderBottomStyle,
            height:1,
          }}
        />
      </div>

    );
  }

  
  

  render() {
    const {style}=this.props;
    
    return(
      this.returnSingleInput()
    );
  }
}
export default AttachUpload;

Calculate.js

 

/**
 * 表单公式计算组件
 *
 * @date    2017-07-12
 * @author  shuwenjie<4483378@qq.com>
 */

import React, { PropTypes } from 'react';
import {
  Text,
  View,
} from 'react-native';

import FormConfigs from './configs';
import common from '../../../configs/common';

class TaskFormCalculate extends React.Component {

  static get propTypes() {
    return {
      title: PropTypes.string,
      currentValue: PropTypes.object,
      onValueChange: PropTypes.func,
      formulaString: PropTypes.string,
    };
  }
  static get defaultProps() {
    return {
      title: '标题',
      onValueChange() {},
    };
  }
  constructor(props) {
    super(props);
    this.state = {
      value: 0,
      formula: {},
    };
  }
  componentDidMount() {
    const { formulaString, currentValue } = this.props;
    const json = formulaString.replace(/\'/g, '"');
    const formula = JSON.parse(json);
    this.setState({ formula });
    this._computed(formula, currentValue);
  }
  componentWillReceiveProps(nextProps) {
    const { currentValue } = this.props;
    if (currentValue._count !== nextProps.currentValue._count) {
      // 值改变以后根据计算公式重新计算值
      this._computed(this.state.formula, nextProps.currentValue);
    }
  }
  // 开始计算
  _computed(formula, formValue) {
    let value = 0;
    const { type, params } = formula;
    if (type && Array.isArray(params)) {
      value = this._calc(type, params, formValue);
    }
    this.setState({ value });
  }
  // 展开公式
  _calc(type, params, formValue) {
    let result = 0;
    if (Array.isArray(params)) {
      for (let i = 0; i < params.length; i++) {
        const temp = this._calc(params[i].type, params[i].params, formValue);
        if (i === 0) {
          // 第一个数为初始化值
          result = temp;
        } else {
          switch (type) {
            case 'ADD': result += temp; break;
            case 'SUB': result -= temp; break;
            case 'MUL': result *= (temp === 0 ? 1 : temp); break;
            case 'DIV': result /= (temp === 0 ? 1 : temp); break;
            default: result = 0; break;
          }
        }
      }
    } else {
      switch (type) {
        case 'FIELD': result = this._getFieldValueFromFormValue(params, formValue); break;
        case 'VALUE': result = isNaN(params) ? 0 : parseFloat(params); break;
        default: result = 0; break;
      }
    }
    return result;
  }
  // 从表单中取出字段值
  _getFieldValueFromFormValue (ctrlName, formValue) {
    let result = 0;
    try {
      if (ctrlName.indexOf(';') > 0) {
        // 子表列求和
        const ctrlArr = ctrlName.split(';');
        const tableValue = formValue[ctrlArr[0]];
        if (tableValue) {
          for (let i = 0; i < tableValue.length; i ++) {
            const subTableValue = tableValue[i][ctrlArr[1]];
            if (subTableValue && !isNaN(subTableValue)) {
              result += parseFloat(subTableValue);
            }
          }
        }
      } else {
        // 直接去主表值
        result = parseFloat(formValue[ctrlName]);
      }
    } catch (e) {
      result = 0;
    }
    return isNaN(result) ? 0 : result;
  }

  // 渲染标题
  renderTitle() {
    const { title } = this.props;
    return (
      <View
        style={{
          width: FormConfigs.titleWidth,
          justifyContent: 'center',
        }}
      >
        <Text
          style={{
            fontSize: 14,
            color: common.theme.txtColor,
          }}
        >{title}</Text>
      </View>
    );
  }

  render() {
    return (
      <View
        style={{
          width: common.size.width,
          height: FormConfigs.lineHeight,
          backgroundColor: '#ffffff',
          flexDirection: 'row',
          paddingLeft: FormConfigs.paddingLeftAndRight,
          paddingRight: FormConfigs.paddingLeftAndRight,
          alignItems: 'center',
          borderBottomColor: common.theme.borderColor,
          borderBottomWidth: 1,
        }}
      >
        { this.renderTitle() }
        <View style={{ flex: 1 }} />
        <Text style={{
          fontSize: 14,
          color: common.theme.txtColor,
        }}>{this.state.value}</Text>
      </View>
    );
  }
}
export default TaskFormCalculate;

configs.js

/**
 * 表单设置
 *
 * @route   TaskForm
 * @date    2017-06-21
 * @author  shuwenjie<4483378@qq.com>
 */


const FormConfigs = {
  titleWidth: 80,
  paddingLeftAndRight: 15,
  lineHeight: 45,
  buttonHeight: 50,
  placeholderTextColor: 'rgba(255, 255, 255,0.5)',
  // 配置转换
  KEYBOARD_TYPE: {
    DEFAULT: 'default',
    NUMERIC: 'numeric',
  },
  SELECT_TYPE: {
    SELECT_SINGLE_PAGE: 'SELECT_SINGLE_PAGE',
    SELECT_YES_OR_NO: 'SELECT_YES_OR_NO',
  },
  TEXT_TYPE: {
    TEXT_SINGLE_DEFAULT: 'TEXT_SINGLE_DEFAULT', // 单行普通文本
    TEXT_SINGLE_NUMBER: 'TEXT_SINGLE_NUMBER',   // 单行数字文本
    TEXT_SINGLE_MONEY: 'TEXT_SINGLE_MONEY',     // 单行金额文本
    TEXT_MULTIPLE: 'TEXT_MULTIPLE',             // 多行普通文本
  },
  OPERATE_TYPE: {
    START: 'start',
    AUDIT: 'audit',
    REJECT: 'reject',
  }
};

export default FormConfigs;

DatePicker.js

/**
 * 表单日期选择组件
 *
 * @date    2017-06-22
 * @author  shuwenjie<4483378@qq.com>
 */

import React, { PropTypes } from 'react';
import { DatePicker,List } from 'antd-mobile';

import FormConfigs from './configs';
import common from '../../../configs/common';
import moment from 'moment';

class TaskFormDatePicker extends React.Component {

  static get propTypes() {
    return {
      style:PropTypes.object,
      mode:PropTypes.string,
      title: PropTypes.string,
      placeholder: PropTypes.string,
      defaultValue: PropTypes.any,
      onValueChange: PropTypes.func,
      isrequired: PropTypes.number,
      minDate:PropTypes.any,
      maxDate:PropTypes.any
    };
  }
  static get defaultProps() {
    return {
      style:{},
      mode:'datetime',
      title: '标题',
      placeholder: '请选择日期',
      defaultValue:moment(),
      isrequired:0,
      onValueChange() {},
      minDate:null,
      maxDate:null
    };
  }
  constructor(props) {
    super(props);
    this.state = { };
  }
  componentDidMount() {
    const { defaultValue,mode,onValueChange } = this.props;
    if (defaultValue && defaultValue !== '') {
      switch(mode){
        case 'date':
          if(onValueChange)
            onValueChange(defaultValue);
          break;
        default:
          break;
      }
    }
  }

 
  

  render() {
    const {style,isrequired,title,placeholder,onValueChange,mode,minDate,maxDate,defaultValue}=this.props;
    return(
      <div
        style={{
          ...style,
        }}
      >
        <DatePicker
          mode={mode}
          title='选择日期'
          extra={placeholder}
          minDate={minDate}
          maxDate={maxDate}
          value={this.state.selectedDate?this.state.selectedDate:defaultValue}
          onChange={(date)=>{
            switch(mode){
              case 'date':
                this.setState({ selectedDate:date});
                if(onValueChange)
                  onValueChange(date);
                break;
              default:
                break;
            }
            
            
          }}
        >
          <List.Item 
            style={{
              paddingLeft:'.2rem'
            }}
            arrow="horizontal"
          >
            {isrequired?'*':null}{title}
          </List.Item>
        </DatePicker>
        <div
          style={{
            ...common.theme.borderBottomStyle,
            height:1,
          }}
        />
      </div>
    );
  }
}
export default TaskFormDatePicker;

Input.js

/**
 * 表单文本输入框组件
 *
 * @date    2017-06-21
 * @author  shuwenjie<4483378@qq.com>
 */

import React, { PropTypes } from 'react';
import { TextareaItem,InputItem} from 'antd-mobile';
import common from '../../../configs/common';

class FormInput extends React.Component {

  static get propTypes() {
    return {
      type: PropTypes.string,
      multiline: PropTypes.bool,
      title: PropTypes.string,
      onValueChange: PropTypes.func,
      placeholder: PropTypes.string,
      defaultValue: PropTypes.string,
      isrequired: PropTypes.number,
      style:PropTypes.object,
      maxlength: PropTypes.number,
    };
  }
  static get defaultProps() {
    return {
      type:'text',
      multiline: false,
      onValueChange() {},
      placeholder: '请输入',
      defaultValue: '',
      isrequired: 0,
      style:{},
      maxlength:200
    };
  }
  constructor(props) {
    super(props);
    const {style}=this.props;

    this.state = { };
    this.MultilineHeight='3rem';
    if(style.flex==1){
      this.MultilineHeight='100%';
    }
  }

  componentDidMount() {
    const { defaultValue,onValueChange } = this.props;
    if (defaultValue && defaultValue !== '') {
      if(onValueChange)
        onValueChange(defaultValue);
    }
  }

  //渲染单行文本
  returnSingleInput(){
    const {style,type,placeholder,title,maxlength,isrequired,defaultValue,onValueChange}=this.props;
    return(
      <div
        style={{
          ...style,
        }}
      >
        <div
          style={{
            height:'1rem',
            ...common.theme.commonFlexStyle,
            //...common.theme.borderBottomStyle,
            flexDirection:'row',
            alignItems:'center'
          }}
        >
          <div
          style={{
            ...common.theme.commonTextStyle,
            padding:'.3rem .2rem',
            fontSize:'.3rem',
            width:'1.5rem'
          }}
          >
            {isrequired?'*':null}{title}
          </div>
          <div
            style={{
              ...common.theme.commonFlexStyle,
              flex:1,
            }}
          >
            <InputItem
              style={{
                backgroundColor:'transparent',
                height:'auto',
                minHeight:'auto',
                color:'#fff',
                boder:'none'
              }}
              maxLength={maxlength}
              type={type}
              placeholder={placeholder?placeholder:'请输入'}
              defaultValue={defaultValue}
              onChange={(text)=>{
                if(onValueChange)
                  onValueChange(text);
                //this.setState({keyWord:text})
              }}
            />
          </div>
        </div>
        <div
          style={{
            ...common.theme.borderBottomStyle,
            height:1,
          }}
        />
      </div>

    );
  }

  //渲染多行文本
  returnMultilineInput(){
    const {style,placeholder,title,maxlength,isrequired,defaultValue,onValueChange}=this.props;
    return(
      <div
        style={{
          
          height:this.MultilineHeight,
          ...common.theme.borderBottomStyle,
          ...style,
        }}
      >
        {
          title?
          <div
            style={{
              ...common.theme.commonTextStyle,
              padding:'.3rem .2rem',
              fontSize:'.3rem'
            }}
          >
            {isrequired?'*':null}{title}
          </div>
          :null
        }
        {
          title?
          <div
            style={{
            ...common.theme.borderBottomStyle,
            height:1,
            margin:'0rem .2rem'
          }}
        />:null
        }

        <div
          style={{
            ...common.theme.commonFlexStyle,
            flex:1,
            height:'100%',
            padding:'.2rem',
            boxSizing: 'border-box'
          }}
        >
          <TextareaItem 
            placeholder={placeholder}
            maxLength={maxlength?maxlength:200}
            count={maxlength?maxlength:100}
            style={{
              width:'100%',
              height:'100%',
              minHeight:'1.5rem',
              backgroundColor: 'transparent',
              ...common.theme.commonTextStyle,
              border:'none'
            }}
            onChange={(text)=>{
              if(onValueChange)
                onValueChange(text);
            }}
            defaultValue={defaultValue}
          />
        </div>
        
      </div>

    );
  }
  

  render() {
    const {multiline,style}=this.props;
    let returnObj=null;
    if(multiline)
    {
      returnObj=this.returnMultilineInput();
    }else{
      returnObj=this.returnSingleInput()
    }
    
    return(
      returnObj
    );
  }
}
export default FormInput;

ListItem.js

 

/**
 * 下拉选择组件
 *
 * @date    2017-08-12
 * @author  wuxiaoyan<408991702@qq.com>
 */

import React, { PropTypes } from 'react';
import { Menu,Icon  } from 'antd-mobile';
import FormConfigs from './configs';
import common from '../../../configs/common';

import './ListItem.less';

class ListItem extends React.Component {

  static get propTypes() {
    return {
      title: PropTypes.string,
      onValueChange: PropTypes.func,
      placeholder: PropTypes.string,
      defaultValue:PropTypes.string || PropTypes.object,
      isrequired: PropTypes.number,
      dataSource:PropTypes.array,
      relationfield:PropTypes.array,
    };
  }
  static get defaultProps() {
    return {
      title: '标题',
      onValueChange() {},
      placeholder: '请选择',
      isrequired:0,
      relationfield:['value','label']
    };
  }

  constructor(props) {
    super(props);
    const {
      placeholder,defaultValue,onValueChange
    } = this.props;
    let state={
      isShowPanel:false
    };
    
    if(defaultValue)
    {
      state = {...state, value:defaultValue};
      if (onValueChange && defaultValue) onValueChange(defaultValue);
    }else{
      state = {...state, value:placeholder};
    }
    this.state=state;
    
  }


 

  // 渲染选中值
  renderValue() {
    const {
      placeholder,
    } = this.props;
    let styles={};
    if(this.state.value==placeholder)
    {
      styles = {
        padding: 0,
        fontSize: '.3rem',
        color:FormConfigs.placeholderTextColor,
        textAlign:'right',
      };

    }else{
      styles = {
        padding: 0,
        fontSize: '.3rem',
        color:common.theme.txtColor,
        textAlign:'right',
      };

    }
    return (
      <span
        style={styles}
      >{this.state.value}</span>
    );
  }
  // 渲染向右的箭头
  renderIcon() {
    return (
      <Icon
        style={{
          color:'#fff'
        }}
        type='right' 
      />
    );
  }
  

  render() {
    const {style,title,isrequired,defaultValue,onValueChange,dataSource,relationfield}=this.props;

    let dataForMenu=[];
    dataSource.map((item,index)=>{
      dataForMenu.push({
        value:item[relationfield[0]],
        label:item[relationfield[1]],
      });
    });

    return (
      <div
        style={{
          ...style,
        }}
      >
        <div
          style={{
            height:'1rem',
            ...common.theme.commonFlexStyle,
            flexDirection:'row',
            alignItems:'center'
          }}
        >
          <div
            style={{
              ...common.theme.commonTextStyle,
              padding:'.3rem .2rem',
              fontSize:'.3rem',
              width:'1.5rem'
            }}
          >
            {isrequired?'*':null}{title}
          </div>
          
          <div 
            style={{
              ...common.theme.commonFlexStyle,
              flex:1,
              flexDirection:'row'
            }}
            onClick={()=>{
              this.setState({isShowPanel:true})
            }}
          >
            <div
              style={{
                ...common.theme.commonFlexStyle,
                flex:1,
                justifyContent:'center',
              }}
            >
              { 
                this.renderValue() 
              }
            </div>
            { this.renderIcon() }
            
          </div>




        </div>
        <div
          style={{
            ...common.theme.borderBottomStyle,
            height:1,
          }}
        />
        {
          dataForMenu.length>0 && this.state.isShowPanel?
          <Menu
          style={{
            position:'fixed',
            width:'100%',
            height:'100%',
            bottom:0,
            zIndex:'9999',
            backgroundImage:'-webkit-linear-gradient(120deg,#19194B,#30C8D3)',
            padding:'.3rem',
            boxSizing:'border-box'
          }}
          className='Menu'
          data={dataForMenu}
          level={1}
          onChange={(value)=>{
            this.setState({isShowPanel:false});
            dataSource.map((item)=>{
              if(item[relationfield[0]]==value){
                this.setState({value:item[relationfield[1]]});
                if(onValueChange)
                  onValueChange(item);
              }
            });

          }}
          height={document.documentElement.clientHeight}
        />:null

        }

        
      </div>
    );
    
  }
}
export default ListItem;

ListItem.less

.Menu{
  background: red;
  .am-flexbox{
    background: red;
  }
}

RichText.js

/**
 * 表单文本输入框组件
 *
 * @date    2017-06-21
 * @author  shuwenjie<4483378@qq.com>
 */

import React, { PropTypes } from 'react';
import common from '../../../configs/common';

class RichText extends React.Component {

  static get propTypes() {
    return {
      id: PropTypes.string,
      height:PropTypes.number
    };
  }
  static get defaultProps() {
    return {
      height:200,
    };
  }
  constructor(props) {
    super(props);
    const {style}=this.props;

    this.state = { };
  }

  componentDidMount() {
    this.initEditor();
  }

  componentWillUnmount() {
    // 组件卸载后,清除放入库的id
    UE.delEditor(this.props.id);
  }


  initEditor() {
    const id = this.props.id;
    const ueEditor = UE.getEditor(this.props.id, {
                  toolbars:[[
                  "fullscreen", "source", "|", 'undo', 'redo', '|',"bold", "italic", "underline","|",
              'fontborder', 'strikethrough', 'superscript', 'subscript', 'removeformat', 'formatmatch', 'autotypeset', 'blockquote', 'pasteplain', '|', 'forecolor', 'backcolor', 'insertorderedlist', 'insertunorderedlist', 'selectall', 'cleardoc', '|',
              'rowspacingtop', 'rowspacingbottom', 'lineheight', '|',
              'customstyle', 'paragraph', 'fontfamily', 'fontsize', '|',
              'directionalityltr', 'directionalityrtl', 'indent', '|',
               "justifyleft", "justifycenter", "justifyright", "justifyjustify", "simpleupload",'insertvideo']],wordCount:false,elementPathEnabled:false,autoHeight: false
           }
    );
    const self = this;
    ueEditor.ready((ueditor) => {
      if (!ueditor) {
        UE.delEditor(id);
        self.initEditor();
      }
    })
  }


  

  render() {
    
    return(
      <div id={this.props.id} name="content" type="text/plain"></div>
    );
  }
}
export default RichText;

SingleSelect.js

/**
 * 表单单选组件
 *
 * @date    2017-06-21
 * @author  shuwenjie<4483378@qq.com>
 */

import React, { PropTypes } from 'react';
import {
  Text,
  View,
  Switch,
  TouchableOpacity,
  Platform,
  DeviceEventEmitter,
} from 'react-native';

import FormConfigs from './configs';
import common from '../../../configs/common';
import Ionicons from 'react-native-vector-icons/Ionicons';
import { toastShort } from '../../../utils/Toast';
import LabelGroup from '../LabelGroup';

class TaskFormSingleSelect extends React.Component {

  static get propTypes() {
    return {
      title: PropTypes.string,
      type: PropTypes.oneOf(Object.keys(FormConfigs.SELECT_TYPE)),
      value: PropTypes.string,
      placeholder: PropTypes.string,
      defalutValue: PropTypes.string,
      options: PropTypes.array,
      onValueChange: PropTypes.func,
      disabled: PropTypes.bool,
      dataSourceId: PropTypes.string,
      dataSourceType: PropTypes.string,
      reference: PropTypes.array,
      displayFieldName: PropTypes.string,
      displayReferName: PropTypes.string,
      ctrlId: PropTypes.string,
      rowIndex: PropTypes.number,
      isrequired: PropTypes.any,
      defaultDisplay: PropTypes.string,
      onSelectValueChange: PropTypes.func,
    };
  }
  static get defaultProps() {
    return {
      title: '标题',
      type: '',
      value: '',
      placeholder: '请选择',
      defalutValue: '',
      options: [],
      onValueChange() {},
      onSelectValueChange() {},
      disabled: false,
      reference: [],
      displayFieldName: '',
      defaultDisplay: '',
    };
  }
  constructor(props) {
    super(props);
    this.state = {
      val: false,
      display: '',
      current: '',
      reference: {},
    };
  }
  componentDidMount() {
    const { type, defalutValue, options } = this.props;
    if (type === FormConfigs.SELECT_TYPE.SELECT_YES_OR_NO && defalutValue === '1') {
      this.setState({ val: true });
      return;
    }
    if (defalutValue !== '') {
      let display = '';
      for (let i = 0; i < options.length; i++) {
        if (options[i].value === defalutValue) {
          display = options[i].title;
        }
      }
      this.setState({ display });
    }
  }
  _selecting() {
    const { title, type, disabled, navigation, dataSourceId, dataSourceType, displayFieldName, ctrlId, rowIndex,  } = this.props;
    if (disabled) {
      toastShort(`${title}不能改变`);
      return;
    }
    if (type === FormConfigs.SELECT_TYPE.SELECT_YES_OR_NO) {
      return;
    }
    // 注册一次性事件
    const event = `event_${(new Date()).valueOf()}`;
    navigation.navigate('TaskSubmitFormSingleSelectOption', { data: { title, event, dataSourceId, dataSourceType, value: this.state.current } });
    DeviceEventEmitter.addListener(event, (option, complex) => {
      if (option && option !== null) {
        const { onSelectValueChange, reference, displayReferName } = this.props;
        if (complex) {
          this.setState({
            display: option.data[displayFieldName],
            reference: option.data,
            current: option.value
          });
          const complexValue = [
            { ctrlId, value: option.value, rowIndex },
            { ctrlId: displayReferName, value: option.data[displayFieldName], rowIndex },
          ];
          for (let i = 0; i < reference.length; i++) {
            const refer = reference[i];
            const key = refer.dataSourceId.substring(refer.dataSourceId.indexOf(';') + 1);
            complexValue.push({
              ctrlId: refer.name,
              value: option.data[key],
              rowIndex,
            });
          }
          onSelectValueChange(complexValue);
        } else {
          this.setState({ 
            display: option.title,
            current: option.value,
          });
          const complexValue = [
            { ctrlId, value: option.value, rowIndex },
            { ctrlId: `_display_${ctrlId}`, value: option.title, rowIndex },
          ];
          onSelectValueChange(complexValue);
        }
      }
      DeviceEventEmitter.removeCurrentListener();
    });
  }
  // 渲染标题
  renderTitle() {
    const { title, isrequired } = this.props;
    const showTitle = isrequired === 1 ? `* ${title}` : title;
    return (
      <View
        style={{
          width: FormConfigs.titleWidth,
          justifyContent: 'center',
        }}
      >
        <Text
          style={{
            fontSize: 14,
            color: common.theme.txtColor,
          }}
        >{showTitle}</Text>
      </View>
    );
  }
  // 渲染值显示
  renderValueDisplay() {
    const { type, placeholder, defaultDisplay } = this.props;
    if (type === FormConfigs.SELECT_TYPE.SELECT_YES_OR_NO) {
      return <View style={{ flex: 1 }} />;
    }
    let display = '';
    if (defaultDisplay !== '') {
      display = defaultDisplay;
    }
    if (this.state.display !== '') {
      display = this.state.display;
    }
    return (
      <View
        style={{
          flex: 1,
          alignItems: 'flex-end',
        }}
      >
        <Text
          style={{
            color: display && display !== '' ? common.theme.txtColor : FormConfigs.placeholderTextColor,
            fontSize: 14,
          }}
        >{display && display !== '' ? display : placeholder}</Text>
      </View>
    );
  }
  // 渲染操作指示
  renderOperation() {
    const { type, onValueChange, ctrlId, rowIndex } = this.props;
    if (type === FormConfigs.SELECT_TYPE.SELECT_YES_OR_NO) {
      return (
        <View
          style={{
            paddingLeft: 10,
          }}
        >
          <Switch
            thumbTintColor={this.state.val ? common.theme.mainColor : '#999999'}
            onTintColor="rgba(70, 149, 247, 0.5)"
            tintColor="#dddddd"
            value={this.state.val}
            onValueChange={(val) => {
              onValueChange(ctrlId, val ? '1' : '2', rowIndex);
              this.setState({ val });
            }}
          />
        </View>
      );
    }
    return (
      <View
        style={Platform.OS === 'ios' ? {
          paddingLeft: 10,
          paddingTop: 3,
        } : {
          paddingLeft: 10,
        }}
      >
        <Ionicons
          color={common.theme.txtColor}
          size={20}
          name="ios-arrow-forward"
        />
      </View>
    );
  }

  render() {
    const { type, reference } = this.props;
    const group = [];
    for (let i = 0; i < reference.length; i++) {
      const refer = reference[i];
      const key = refer.dataSourceId.substring(refer.dataSourceId.indexOf(';') + 1);
      // const display = this.state.reference[key];
      let display = '';
      if (refer.defaultDisplay && refer.defaultDisplay !== '') {
        display = refer.defaultDisplay;
      }
      if (this.state.reference[key] && this.state.reference[key] !== '') {
        display = this.state.reference[key];
      }
      group.push({
        title: refer.title,
        info: <Text>{display}</Text>,
      });
    }
    return (
      <View>
        <TouchableOpacity
          style={{
            width: common.size.width,
            height: FormConfigs.lineHeight,
            backgroundColor: '#ffffff',
            flexDirection: 'row',
            paddingLeft: FormConfigs.paddingLeftAndRight,
            paddingRight: FormConfigs.paddingLeftAndRight,
            alignItems: 'center',
            borderBottomColor: common.theme.borderColor,
            borderBottomWidth: 1,
          }}
          activeOpacity={type !== FormConfigs.SELECT_TYPE.SELECT_YES_OR_NO ? 0.8 : 1}
          onPress={this._selecting.bind(this)}
        >
          { this.renderTitle() }
          { this.renderValueDisplay() }
          { this.renderOperation() }
        </TouchableOpacity>
        {group.length > 0 ?
          <LabelGroup
            group={group}
            titleSize={14}
            rowHeight={40}
            noborder={true}
            txtColor={common.theme.txtColor}
          />
        : null}
        {group.length > 0 ?
          <View style={{
            borderBottomColor: common.theme.borderColor,
            borderBottomWidth: 1,
          }}/>
        : null}
      </View>
    );
  }
}
export default TaskFormSingleSelect;

SubmitButton.js

/**
 * 提交表单按钮
 *
 * @date    2017-07-11
 * @author  wuxiaoyan<408991702@qq.com>
 */

import React, { PropTypes } from 'react';
import { Button } from 'antd-mobile';
import common from '../../../configs/common';

class SubmitButton extends React.Component {
  // 接口属性
  static get propTypes() {
    return {
      onPress: PropTypes.func,
      text:PropTypes.string
    };
  }


  constructor(props) {
    super(props);
    
    // Initialize the view state
    this.state = {
      showIndex:0,
    };
  }

  render() {
    const {onPress} = this.props;
    const {text} = this.props;
    return (
      <div 
        style={{
          alignItems:'center',
          margin:'.2rem .5rem'
        }}
      >
        <Button 
          className="btn" 
          type="primary"
          onClick={(e) => {
            if (onPress) onPress();
          }}
          style={{
            ...common.theme.submitButtonStyle
          }}
        >
          {text?text:'提交'}
        </Button>
      </div>
    );
  }
}

export default SubmitButton;

二、其他

BannerScroll.js

 

/**
 * 广告图轮播组件
 *
 * @date    2017-07-08
 * @author  wuxiaoyan<408991702@qq.com>
 */

/**
 * 引用格式
 * <BannerScroll  height={200} navigation={navigation} dataList={}/>
 */

/**
 * 配置格式
 * dataList:[
        {
          url:'SystemLogin',  //跳转链接 选填  默认30
          path:require('../../images/index/u84.jpg')
        }
      ]
 */

import React,{PropTypes} from 'react';
import {
  Image,
  TouchableOpacity
} from 'react-native';

import ViewPager from 'react-native-viewpager';


import common from '../../configs/common';



class BannerScroll extends React.Component {

  // injection reduer object and other params
  static get propTypes() {
    return {
      dataList: PropTypes.array,
      height: PropTypes.number,
    };
  }

  constructor(props) {
    super(props);
    
    this.renderPage = this.renderPage.bind(this);
    this.bannerImgClick = this.bannerImgClick.bind(this);
    let dataSource=new ViewPager.DataSource({
      pageHasChanged:(p1,p2)=> p1!==p2,
    });
    // Initialize the view state
    this.state = {
      dataSource:dataSource.cloneWithPages(this.props.dataList)
    };
  }


  //渲染单张轮播图
  renderPage(data,pageID){
    let url=data?data.url:'';
    if(data.url){
      return(
        <TouchableOpacity
          style={{
            flex: 1,
            width:common.size.width,
            height:this.props.height,
          }}
          onPress={this.bannerImgClick.bind(this, url)}
        >
          <Image 
            source={data.path} 
            style={{
              width:common.size.width,
              flex:1,
              height:this.props.height,
              resizeMode:'stretch'
            }}
          />
        </TouchableOpacity>
      );
    }else{
      return(
        <Image 
          source={data.path} 
          style={{
            width:common.size.width,
            flex:1,
            height:this.props.height,
            resizeMode:'stretch'
          }}
        />
      );

    }
    

  }

  //图片点击事件
  bannerImgClick(url){
    const {navigation} = this.props;
    navigation.navigate(url);
  }

  render() {
    return (
      <ViewPager
        style={{height:this.props.height}}
        dataSource={this.state.dataSource}
        renderPage={this.renderPage}
        isLoop={true}
        autoPlay={true}/>
    );
  }

}
// export redux component
export default BannerScroll;

Calendar.js

/**
 * 日历组件
 *
 * @date    2017-08-10
 * @author  wuxiaoyan<408991702@qq.com>
 */
import React from 'react'
import {render} from 'react-dom'

import CalendarHeader from './CalendarHeader'
import CalendarMain from './CalendarMain'
const displayDaysPerMonth = (year)=> {

  //定义每个月的天数,如果是闰年第二月改为29天
  let daysInMonth = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
  if ((year % 4 === 0 && year % 100 !== 0) || year % 400 === 0) {
    daysInMonth[1] = 29
  }

  //以下为了获取一年中每一个月在日历选择器上显示的数据,
  //从上个月开始,接着是当月,最后是下个月开头的几天

  //定义一个数组,保存上一个月的天数

  let daysInPreviousMonth = [].concat(daysInMonth)
  daysInPreviousMonth.unshift(daysInPreviousMonth.pop())

  //获取每一个月显示数据中需要补足上个月的天数
  let addDaysFromPreMonth = new Array(12)
    .fill(null)
    .map((item, index)=> {
      let day = new Date(year, index, 1).getDay()
      if (day === 0) {
        return 6
      } else {
        return day
      }
    })

  //已数组形式返回一年中每个月的显示数据,每个数据为6行*7天
  return new Array(12)
    .fill([])
    .map((month, monthIndex)=> {
      let addDays = addDaysFromPreMonth[monthIndex],
        daysCount = daysInMonth[monthIndex],
        daysCountPrevious = daysInPreviousMonth[monthIndex],
        monthData = []
      //补足上一个月
      for (; addDays > 0; addDays--) {
        monthData.unshift(daysCountPrevious--)
      }
      //添入当前月
      for (let i = 0; i < daysCount;) {
        monthData.push(++i)
      }
      //补足下一个月
      for (let i = 42 - monthData.length, j = 0; j < i;) {
        monthData.push(++j)
      }
      return monthData
    })
}

class Calendar extends React.Component {
  constructor() {
    //继承React.Component
    super()
    let now = new Date()
    this.state = {
      year: now.getFullYear(),
      month: now.getMonth(),
      day: now.getDate(),
      //picked: false
    }
  }

  componentDidMount() {
    this.datePick(new Date().getDate());
  }

  //切换到下一个月
  nextMonth() {
    if (this.state.month === 11) {
      this.setState({
        year: ++this.state.year,
        month: 0
      })
    } else {
      this.setState({
        month: ++this.state.month
      })
    }
  }
  //切换到上一个月
  prevMonth() {
    if (this.state.month === 0) {
      this.setState({
        year: --this.state.year,
        month: 11
      })
    } else {
      this.setState({
        month: --this.state.month
      })
    }
  }
  //选择日期
  datePick(day) {
    const {onValueChange}=this.props;
    this.setState({day},()=>{
      if(onValueChange)
        onValueChange(this.state.year,this.state.month,this.state.day);
    });
    

  }
  //标记日期已经选择
  picked() {
    this.state.picked = true
  }

  render() {
    let props = {
      viewData: displayDaysPerMonth(this.state.year),
      datePicked: `${this.state.year} 年
                   ${this.state.month + 1} 月
                   ${this.state.day} 日`
    }
    const {style}=this.props;
    return (
      <div
        style={{
          ...style,
          color:'#fff'
        }}
        ref="main"
      >
        <CalendarHeader prevMonth={::this.prevMonth}
                        nextMonth={::this.nextMonth}
                        year={this.state.year}
                        month={this.state.month}
                        day={this.state.day}/>
        <CalendarMain {...props}
                      prevMonth={::this.prevMonth}
                      nextMonth={::this.nextMonth}
                      datePick={::this.datePick}
                      year={this.state.year}
                      month={this.state.month}
                      day={this.state.day}/>
      </div>
    )
  }
}

//将calender实例添加到window上以便获取日期选择数据
export default Calendar;

CalendarHeader.js

 

import React from 'react'

export default class CalendarHeader extends React.Component {
  render() {
    return (
      <div
        style={{
          display:'flex',
          flexDirection:'row',
          alignItems:'center',
          height:'.8rem'
        }}
      >
        <div 
          style={{
            display:'flex',
            width:'1rem',
            justifyContent:'center',
            fontSize:'.4rem'
          }}
          onClick={this.props.prevMonth}
        >
          &lt;
        </div>
        <div
          style={{
            display:'flex',
            flex:1,
            justifyContent:'center',
            fontSize:'.3rem'
          }}
        >
          {this.props.year}年{this.props.month + 1}月
        </div>
        <div
          style={{
            display:'flex',
            width:'1rem',
            justifyContent:'center',
            fontSize:'.4rem'
          }}
          onClick={this.props.nextMonth}
        >
          &gt;
        </div>
      </div>
    )
  }
}

CalendarMain.js

import React from 'react'

export default class CalendarMain extends React.Component {

  //处理日期选择事件,如果是当月,触发日期选择;如果不是当月,切换月份
  handleDatePick(index, styleName) {
    switch (styleName) {
      case 'thisMonth':
        let month = this.props.viewData[this.props.month]
        this.props.datePick(month[index])
        break
      case 'prevMonth':
        this.props.prevMonth()
        break
      case 'nextMonth':
        this.props.nextMonth()
        break
    }
  }

  //处理选择时选中的样式效果
  //利用闭包保存上一次选择的元素,
  //在月份切换和重新选择日期时重置上一次选择的元素的样式
  changeColor() {
    let previousEl = null
    return function (event) {
      let name = event.target.nodeName.toLocaleLowerCase()
      if (previousEl && (name === 'i' || name === 'td')) {
        previousEl.style = ''
      }
      if (event.target.className === 'thisMonth') {
        event.target.style = 'background:#F8F8F8;color:#000'
        previousEl = event.target
      }
    }
  }

  //绑定颜色改变事件
  componentDidMount() {
    // let changeColor = this.changeColor()
    // document.getElementById('calendarContainer')
    //   .addEventListener('click', changeColor, false);

  }

  render() {
    //确定当前月数据中每一天所属的月份,以此赋予不同className
    let month = this.props.viewData[this.props.month],
      rowsInMonth = [],
      i = 0,
      styleOfDays = (()=> {
        let i = month.indexOf(1),
          j = month.indexOf(1, i + 1),
          arr = new Array(42)
        arr.fill('prevMonth', 0, i)
        arr.fill('thisMonth', i, j)
        arr.fill('nextMonth', j)
        return arr
      })()

    //把每一个月的显示数据以7天为一组等分
    month.forEach((day, index)=> {
      if (index % 7 === 0) {
        rowsInMonth.push(month.slice(index, index + 7))
      }
    })

    return (
      <table
        style={{
          width:'100%'
        }}
      >
        <thead>
        <tr
          style={{
            lineHeight:'.6rem'
          }}
        >
          <th
            style={{
              fontSize:'.25rem'
            }}
          ></th>
          <th
            style={{
              fontSize:'.25rem'
            }}
          >一</th>
          <th
            style={{
              fontSize:'.25rem'
            }}
          >二</th>
          <th
            style={{
              fontSize:'.25rem'
            }}
          >三</th>
          <th
            style={{
              fontSize:'.25rem'
            }}
          >四</th>
          <th
            style={{
              fontSize:'.25rem'
            }}
          >五</th>
          <th
            style={{
              fontSize:'.25rem'
            }}
          >六</th>
        </tr>
        </thead>
        <tbody>
        {
          rowsInMonth.map((row, rowIndex)=> {
            return (
              <tr key={rowIndex}>
                {
                  row.map((day)=> {
                    let tdStyle={};
                    if(this.props.day==day && styleOfDays[i]=='thisMonth'){
                      tdStyle={
                        backgroundColor:'#11ACE9'
                      };
                    }
                    if(styleOfDays[i]!='thisMonth'){
                      tdStyle={
                        backgroundColor:'rgba(40,40,40,0.1)',
                        color:'rgba(180,180,180,1)'
                      };
                    }
                    return (
                      <td
                        style={{
                          backgroundColor:'rgba(255,255,255,0.1)',
                          textAlign:'center',
                          lineHeight:'.8rem',
                          fontSize:'.25rem',
                          ...tdStyle
                        }}
                          onClick={
                            this.handleDatePick.bind
                            (this, i, styleOfDays[i])}
                          key={i++}>
                        {day}
                      </td>
                    )
                  })
                }
              </tr>
            )
          })
        }
        </tbody>
      </table>
    )
  }
}

detailsLay.js

import React, {PropTypes} from 'react'
import {connect} from 'react-redux'
import {link, hushHistory} from 'react-router'
import ReactDOM from 'react-dom'
import { Table, Input, Icon, Button, Popconfirm, Row, Col, Select, DatePicker } from 'antd'

export default function creatRow12(option) {
    const Option = option
    return (<Row style={{marginBottom: '40px'}}>
            <Col span={12} style={{display: 'flex'}}>
                <div style={{lineHeight:'.55rem', fontWeight:'bold',width:'15%',textAlign:'right'}}>
                    {Option.leftTitle}
                </div>
                {creatLeft(Option)}
            </Col>
            <Col span={12} style={{display: 'flex'}}>
                <div style={{lineHeight:'.55rem', fontWeight:'bold',width:'15%',textAlign:'right'}}>
                    {Option.rightTitle}
                </div>
                {creatRight(Option)}
            </Col>
        </Row>)
}

var a = {
    leftType: 'select',
    leftMust: false,
    rightType: 'input',
    rightMust: false,
    selectMap:  [],
    leftTitle: 'aaa',
    rightTitle: 'bbb'
}
//左侧栅格渲染
function creatLeft(option) {
    function handleChange(value) {
        console.log(`selected ${value}`);
    }
    function onChange(date, dateString) {
        console.log(date, dateString);
    }
    if (option.leftType && option.leftType == 'select') {
        if (option.selectMap && option.selectMap.length > 0) {
            return creatSelect(option.selectMap)
        }
    } else if (option.leftType && option.leftType == 'input') {
        return creatInput(option)
    } else if (option.leftType && option.leftType == 'date') {
        return creatDate()
    }
}
//右侧栅格渲染
function creatRight(option) {
    function handleChange(value) {
        console.log(`selected ${value}`);
    }
    function onChange(date, dateString) {
        console.log(date, dateString);
    }
    if (option.rightType && option.rightType == 'select') {
        if (option.selectMap && option.selectMap.length > 0) {
            return creatSelect(option.selectMap)
        }
    } else if (option.rightType && option.rightType == 'input') {
        return creatInput(option)
    } else if (option.rightType && option.rightType == 'date') {
        return creatDate()
    }
}
//渲染下拉选择框
function creatSelect(map) {
    function handleChange(value) {
        console.log(`selected ${value}`);
    }  
    if (map && map.length > 0) {
        let arr = []
        for(let i of map) {
            arr.push(<Select.Option key={i} value={i} style={{}}>{i}</Select.Option>)
        }
        return (
            <Select defaultValue={map[0]} style={{ width: '60%', marginLeft: '20px'}} onChange={handleChange}>
                {arr.map((item)=>{return(item);})}
            </Select>
        )
    }
}
//渲染输入框
function creatInput(option) {
    return (<Input placeholder="" style={{width: '60%',marginLeft: '20px'}} disabled={true} placeholder={option.leftTitle}/>)
}
//渲染双输入框
function dobulInput() {
    return (
        <div>
            <Input placeholder="" style={{width: '60%',height:40,marginLeft: '20px'}}/>到
            <Input placeholder="" style={{width: '60%',height:40,marginLeft: '20px'}}/>
        </div>
    )
}
//渲染日期选择框
function creatDate() {
    function onChange(date, dateString) {
        console.log(date, dateString);
    }
    return (
        <div style={{marginLeft: '20px'}}>
            <DatePicker onChange={onChange} /> 到 <DatePicker onChange={onChange} />
        </div>
    )
}

FunNavigation.js

 

/**
 * 功能列表组件
 *
 * @date    2017-07-08
 * @author  wuxiaoyan<408991702@qq.com>
 */
/**
 * 引用格式
 * <FunNavigation  navigation={} funNavigateCon={}/>
 */

/**
 * 配置格式
 * funNavigateCon:{
        rowNum:4,//一行展示几个  选填  默认4
        imgSize:40,//图片大小 选填  默认30
        textStyle:{//文字样式  选填
          fontSize:12,
          color:common.theme.txtColor
        },
        list:[//必填
          {
            name:'水费',
            icon:require('../../images/index/u162.png'),
            url:'SystemAgreement',
            backgroundColor:'#7AC00D'
          }
        ]
      }
 */


import React,{PropTypes} from 'react';
import {
  Image,
  View,
  Text,
  TouchableOpacity
} from 'react-native';


import common from '../../configs/common';



class FunNavigation extends React.Component {

  // injection reduer object and other params
  static get propTypes() {
    return {
      funNavigateCon: PropTypes.object,
    };
  }

  constructor(props) {
    super(props);
    
    // Initialize the view state
    this.state = {
    };
  }

  //渲染单个图标
  renderFunNavigateItem(item,index){
    let rowNum=this.props.funNavigateCon.rowNum?this.props.funNavigateCon.rowNum:4;
    const {navigation} = this.props;
    return(
      <TouchableOpacity
        key={'item'+index}
        onPress={()=>navigation.navigate(...item.url)}
      >
        <View 
          style={{
            alignItems:'center',
            justifyContent:'center',
            //width:(common.size.width-(common.size.width-(this.props.funNavigateCon.imgSize?this.props.funNavigateCon.imgSize:30+10)*rowNum)/(rowNum+1))/rowNum,
            width:common.size.width/(rowNum),
            marginBottom:10,
          }}
        >
          <View style={{
            backgroundColor:item.backgroundColor,
            borderRadius:8,
            padding:5,
            alignItems:'center',
            justifyContent:'center',
            marginBottom:5
          }}>
            <Image 
              source={item.icon}
              style={{
                width:this.props.funNavigateCon.imgSize?this.props.funNavigateCon.imgSize:30,
                height:this.props.funNavigateCon.imgSize?this.props.funNavigateCon.imgSize:30
              }}
            />

          </View>
          <Text style={{
            alignItems:'center',
            justifyContent:'center',
            fontSize:12,
            color:'#333333',
            ...this.props.funNavigateCon.textStyle
          }}>
            {item.name}
          </Text>
        </View>
      </TouchableOpacity>
      
    );

  }


  render() {
    return(
      <View 
        style={{
          flexDirection:'row',
          flexWrap:'wrap',
          alignItems:'center',
          backgroundColor:'#fff',
          justifyContent:'center',
          width:common.size.width,
          paddingTop:10,
          paddingBottom:10
        }}
      >
        {
          this.props.funNavigateCon.list.map((item,index) => this.renderFunNavigateItem(item,index) )
        }
      </View>
    );
  }

}
// export redux component
export default FunNavigation;

LabelGroup.js

 

/**
 * 文本标签组
 *
 * @date    2017-05-24
 * @author  shuwenjie<4483378@qq.com>
 */

import React, { PropTypes } from 'react';
import { Link } from 'react-router';
import { Icon } from 'antd-mobile';
import common from '../../configs/common';

class Label extends React.Component {
  // 接口属性
  static get propTypes() {
    return {
      style: PropTypes.object,
      group: PropTypes.array,
      rowHeight: PropTypes.number,
      titleSize: PropTypes.number,
      arrowForwardIconSize: PropTypes.number,
    };
  }
  static get defaultProps() {
    return {
      rowHeight: 50,
      titleSize: 14,
      arrowForwardIconSize: common.size.arrowForwardIconSize,
    };
  }

  render() {
    const {
      group,
      style,
      rowHeight,
      titleSize,
    } = this.props;
    return (
      <div
        style={{
          backgroundColor: common.theme.mainColor,
          ...style
        }}
      >
        {group.map((item, index) => {
          const {
            icon,
            imageSource,
            title,
            onPress,
            info,
            navigation
          } = item;
          return (
            <div
              key={index}
              style={{
                height: '1rem',
              }}
              onClick={() => {
                  if (onPress) onPress(() => {
                  });
                }}
            >
              <div
                style={{
                  display:'flex',
                  height: '1rem',
                  flexDirection: 'row',
                  alignItems: 'center',
                  justifyContent: 'flex-start',
                }}
              >
                {imageSource ?
                  <div
                    style={{
                      display:'flex',
                      width: '.5rem',
                      height: '.5rem',
                      marginLeft:'.2rem',
                    }}
                  >
                    <img
                      style={{
                        width: '.5rem',
                        height: '.5rem'
                      }}
                      src={imageSource}
                    />
                  </div>
                : null}

                {
                  info?
                  <div
                  style={{
                    display:'flex',
                    width: '2rem',
                    marginLeft:'.2rem',
                    alignItems: 'center',
                    justifyContent: 'flex-start',
                    textAlign:'left',
                    ...common.theme.commonTextStyle,
                    fontSize:'.3rem'
                  }}
                >
                  {title}
                </div>:
                <div
                  style={{
                    display:'flex',
                    flex: 1,
                    marginLeft:'.2rem',
                    alignItems: 'center',
                    justifyContent: 'flex-start',
                    textAlign:'left',
                    ...common.theme.commonTextStyle,
                    fontSize:'.3rem'
                  }}
                >
                  {title}
                </div>
                  

                }

                {
                  info?
                  <div
                    style={{
                      ...common.theme.commonFlexStyle,
                      ...common.theme.commonTextStyle,
                      flex: 1,
                      paddingRight: '.2rem',
                      alignItems: 'flex-end',
                      justifyContent: 'flex-end',
                      fontSize:'.3rem',
                      color: 'rgba(255, 255, 255,.7)'
                    }}
                  >
                  {info}
                  </div>
                  :
                  <div
                    style={{
                      ...common.theme.commonFlexStyle,
                      ...common.theme.commonTextStyle,
                      paddingRight: '.2rem',
                      alignItems: 'flex-end',
                      justifyContent: 'flex-end',
                      fontSize:'.3rem'
                    }}
                  >
                    <Icon 
                      style={{
                        fontSize:'.3rem'
                      }}
                      type="right" 
                      color="#fff" 
                    />
                  </div>

                }
                
              </div>
              {group.length > index + 1 ?
                <div
                  style={{
                    float:'flex',
                    height: 1,
                    marginLeft: 20,
                    marginRight:20,
                    backgroundColor: common.theme.borderColor,
                  }}
                />
              : null}
            </div>
          );
        })}
      </div>
    );
  }
}

export default Label;

Loading.js

/**
 * 数据交互提示框
 *
 * @date    2017-06-01
 * @author  shuwenjie<4483378@qq.com>
 */

import React from 'react';
import { Icon } from 'antd';
import common from '../../configs/common';
const SIZES = ['small', 'large'];

class Loading extends React.Component {
  // 接口属性
  static get propTypes() {
    return {
      visible: React.PropTypes.bool,
      color: React.PropTypes.string,
      size: React.PropTypes.oneOf(SIZES),
      overlayColor: React.PropTypes.string,
      onRequestClose: React.PropTypes.func,
      loadTip: React.PropTypes.string,
    };
  }
  static get defaultProps() {
    return {
      visible: false,
      color: 'white',
      size: 'large',
      overlayColor: 'transparent',
      onRequestClose() {},
      loadTip: '数据加载中...'
    };
  }

  render() {
    const {visible,loadTip}=this.props;
    let obj=null;
    if(visible)
    {
      obj=<div
      style={{
        ...common.theme.commonFlexStyle,
        flex: 1,
        backgroundColor: 'transparent',
        position: 'absolute',
        top: 0,
        bottom: 0,
        left: 0,
        right: 0,
        alignItems: 'center',
        justifyContent: 'center',
        zIndex:'99999'
      }}
    >
      <div 
        style={{
          ...common.theme.commonFlexStyle,
          alignItems: 'center',
          justifyContent: 'center',
          width: '3rem',
          height: '3rem',
          borderRadius: '.1rem',
          backgroundColor: 'rgba(0, 0, 0, 1)'
        }}
      >
          <Icon type="loading" />
          <p 
            style={{
              marginTop: '.2rem',
              textAlign: 'center',
              ...common.theme.commonTextStyle
            }}
          >
            {loadTip}
          </p>
        </div>
    </div>;

    }

    return (
      obj
    );
  }
}
export default Loading;

NavBar.js

/**
 * 文本标签组
 *
 * @date    2017-05-24
 * @author  shuwenjie<4483378@qq.com>
 */

import React, { PropTypes } from 'react';
import { NavBar } from 'antd-mobile';
import { hashHistory } from 'react-router';

import common from '../../configs/common';

class NavBarControl extends React.Component {
  static get propTypes() {
    return {
      goBack: PropTypes.string,
      title: PropTypes.string,
    };
  }
 
  render() {
    const {goBack,title}=this.props;
    document.title=title;
    return (
        // <NavBar 
        //   mode='dark'
        //   style={{
        //     backgroundColor:'rgba(255, 255, 255,0.1)',
        //     ...common.theme.borderBottomStyle
        //   }}
        //   onLeftClick={() => {
        //     if(goBack)
        //     {
        //       hashHistory.push(goBack);
        //     }
        //     else{
        //       window.history.go(-1);
        //     }

        //   }} 
        // >
        //   {title}
        // </NavBar>
        null
    );
  }
}

export default NavBarControl;

NoticeScroll.js

/**
 * 通知公告上下滚动组件
 *
 * @date    2017-07-10
 * @author  wuxiaoyan<408991702@qq.com>
 */
/**
 * 引用格式
 * <NoticeScroll  navigation={} NoticeScrollList={}/>
 */

/**
 * 配置格式
 * NoticeScrollList:[
        {
          url:'SystemRegister',
          text:'各位业主,车辆请停到车位上,不能在小区门口随位上,不能在小区门口随'
        },
        {
          url:'SystemRegister',
          text:'1各位业主,车辆请停到车位上,不能在小区门口随位上,不能在小区门口随'
        }
      ]
 */


import React,{PropTypes} from 'react';
import {
  Text,
  TouchableOpacity
} from 'react-native';


import common from '../../configs/common';



class NoticeScroll extends React.Component {

  // injection reduer object and other params
  static get propTypes() {
    return {
      NoticeScrollList: PropTypes.array,
    };
  }

  constructor(props) {
    super(props);
    
    // Initialize the view state
    this.state = {
      showIndex:0,
    };
  }
  componentWillMount(){
    let showIndex=this.state.showIndex;
    this.timer = setInterval(() => 
    {
      if(showIndex>=this.props.NoticeScrollList.length-1)
      {
        showIndex=0;
      }else{
        showIndex=showIndex+1;
      }
      this.setState({showIndex:showIndex});
      
    },
      3000
    );

  }



  componentWillUnmount() {
    this.timer && clearTimeout(this.timer);  
  }
  
  
  render() {
    
    
    
    return(
      <TouchableOpacity
        onPress={()=>{
          const {navigation} = this.props;
          navigation.navigate(this.props.NoticeScrollList[this.state.showIndex].url);
        }}
      >
        <Text 
          style={{
            fontSize:12,
            color:common.theme.txtColor,
          }}
          numberOfLines={1}
        >
          {this.props.NoticeScrollList[this.state.showIndex].text}
        </Text>
      </TouchableOpacity>
    );
  }

}
// export redux component
export default NoticeScroll;

PagerListTree.js

/**
 * 数据列表组件
 *
 * @date    2017-06-12
 * @author  shuwenjie<4483378@qq.com>
 */

import React, { PropTypes } from 'react';
import { Table,Pagination, Row,Col } from 'antd'

import common from '../../configs/common';
import Loading from './Loading';



export default class PagerListView extends React.Component {

  static get propTypes() {
    return {
      pager: PropTypes.array,
      columns: PropTypes.array,
      childrenKey:PropTypes.string,
      rowSelection:PropTypes.object
    };
  }

  constructor(props) {
    super(props);
    this.state = {
    };
  }

  



  componentWillUnmount() {
    
  }



  changeChild(data){
    const { childrenKey } = this.props;
    data.map((item)=>{
      item.key=item.id;
      if(item[childrenKey] && item[childrenKey].length==0){
        delete item[childrenKey];
      }
      if(item[childrenKey] && !item.children){
        item.children=item[childrenKey];
        delete item[childrenKey];
        if (item.children.length>0  && item.children[0][childrenKey]) {
          this.changeChild(item.children);
        }
      }
    })

  }
  
  // 渲染项目列表
  renderListContent() {
    const { pager,columns,rowSelection } = this.props;
    // 加载中
    if (pager === null) {
      return (
        <Loading visible={true}/>
      );
    }

    let productType=pager;
    this.changeChild(productType);


    // 正常显示数据
    return (
      rowSelection?
      <Table bordered dataSource={productType} rowSelection={rowSelection} pagination={false} columns={columns} />:
      <Table bordered dataSource={productType} pagination={false} columns={columns} />
    );
  }

  render() {
    return this.renderListContent();
  }

}

PagerListView.css

.am-list-body{
    background: transparent;
    border-top:none;
}
.am-list-body:after{display: none}

PagerListView.js

/**
 * 数据列表组件
 *
 * @date    2017-06-12
 * @author  shuwenjie<4483378@qq.com>
 */

import React, { PropTypes } from 'react';
import { Table,Pagination, Row,Col } from 'antd'

import common from '../../configs/common';
import Loading from './Loading';
import style from './PagerListView.css';

let canLoadMore;
let loadMoreTime = 0;

export default class PagerListView extends React.Component {

  static get propTypes() {
    return {
      pager: PropTypes.object,
      onPage: PropTypes.func,
      columns: PropTypes.array,
    };
  }

  constructor(props) {
    super(props);
    this.state = {
    };
  }

  

  componentWillReceiveProps(nextProps) {
    const {pager}=this.props;

  }

  componentWillUnmount() {
  }
 

  // 渲染项目列表
  renderListContent() {
    const { pager,onPage,columns } = this.props;
    // 加载中
    if (pager.data === null || pager.initing) {
      return (
        <Loading visible={true}/>
      );
    }
    // 正常显示数据
    return (
      <div>
        <Table bordered dataSource={pager.data} pagination={false} columns={columns} />
        <Row key="4" style={{marginTop:15}}>
            <Col span={4}><span>{pager.total}</span>条
            </Col>
            <Col span={20} style={{textAlign:'right'}}>
                <Pagination 
                    showQuickJumper
                    showSizeChanger 
                    className="antd-page"     
                    current={pager.pageNum+1} 
                    total={pager.total} 
                    pageSize={pager.pageSize}                                                     
                    onChange={pageNo => {
                      
                      pager.setPageNum(pageNo-1);
                      if (onPage){
                        onPage()
                      }
                    }}  
                    onShowSizeChange={(n,pageSize) => {
                      pager.setpageSize(pageSize);
                      if (onPage){
                        onPage()
                      }
                    }}                                                                
                />
            </Col>
        </Row>
        
      </div>
    );
  }

  render() {
    return this.renderListContent();
  }

}

PageTitle.js

/**
 * 页面标题组件
 *
 * @date    2017-10-12
 * @author  shuwenjie<4483378@qq.com>
 */

import React, { PropTypes } from 'react';
import common from '../../configs/common';

export default class PageTitle extends React.Component {

  static get propTypes() {
    return {
      title: PropTypes.string
    };
  }

  constructor(props) {
    super(props);
    this.state = {
    };
  }
  render() {
    const { title } = this.props;
    return (
      <div 
        style={{
            height: '45px',
            lineHeight: '45px',
            fontSize: 16,
            borderBottom: '1px solid #ddd',
            marginBottom: '10px',
            color:'#333'
        }}
        >
            {title}
        </div>
    );
  }
}

SearchBar.css

.am-list-item.am-input-item:after{display: none;}
.am-list-item .am-input-control input{color: #fff}

SearchBar.js

/**
 * 文本标签组
 *
 * @date    2017-05-24
 * @author  shuwenjie<4483378@qq.com>
 */

import React, { PropTypes } from 'react';
import { Link } from 'react-router';
import { Input,Button  } from 'antd';
import common from '../../configs/common';

class SearchBar extends React.Component {
  // 接口属性
  static get propTypes() {
    return {
      group: PropTypes.array,
      buttons:PropTypes.any,
    };
  }
 

  render() {
    const {
      group,buttons
    } = this.props;
    return (
      <div
        style={{
          marginTop: 15
        }}
      >
        {
          group?
          group.map((item,index)=>{
            const {title,type,key}=item;
            switch(type){
              case 'input':
                return(
                  <div
                    key={index}
                    style={{
                      display:'inline-block',
                      marginBottom: 15,
                    }}
                  >
                    <label style={{padding:'0 10px 0 20px'}}>{title}</label><Input placeholder='请输入' style={{width:220}}/>
                  </div>
                )
              default:
                return null


            }
            
          })
          :null
          
        }
        {
          group?
          <Button 
          style={{
            marginLeft: 15,
            marginBottom: 15,
          }}
          type="primary" 
          size='large'
        >
          查询
        </Button>:null
        }
        
        {
          buttons?buttons:null
        }

      </div>
    );
  }
}

export default SearchBar;

SendVerificationCode.js

/**
 * 发送验证码组件
 *
 * @date    2017-07-08
 * @author  wuxiaoyan<408991702@qq.com>
 */

import React,{PropTypes} from 'react';
import {
  Text,
  TouchableOpacity
} from 'react-native';
import common from '../../configs/common';
import utils from '../../utils/Index';
import * as signinAction from '../../store/actions/signin';


class SendVerificationCode extends React.Component {

  // injection reduer object and other params
  static get propTypes() {
    return {
      telPhone: PropTypes.string,
    };
  }

  constructor(props) {
    super(props);
    // Initialize the view state
    this.state = { 
      text:'获得验证码',
      intervalTime:60,
      tempText:'获得验证码',
      disable:false,
      sendUrl:''
    };
  }

  componentWillUnmount() {  
    this.timer && clearTimeout(this.timer);  
  } 

  //点击按钮发送操作
  sendCode(){
    if(this.state.disable==false)
    {
      const { dispatch,telPhone } = this.props;
      if(!telPhone || typeof(telPhone)==undefined)
      {
        utils.toastShort('请输入手机号');
        return false;
      }
      if(!(/^1[34578]\d{9}$/.test(telPhone)))
      {
        utils.toastShort('手机号格式有误,请重新输入');
        return false;
      }

      this.setState({disable:true});
      dispatch(signinAction.requestSigninSendSMSCode(telPhone));



      let thisObj=this;
      let t=thisObj.state.intervalTime;
      this.timer = setInterval(
        () => 
        {
          if(t==0)
          {
            thisObj.setState({tempText:thisObj.state.text});
            this.setState({disable:false});
            clearInterval(this.timer);
          }else{
            thisObj.setState({tempText:t+'秒'});
            t--;
          }
          
        },
        1000
      );
    }
  }

  render() {
    return (
      <TouchableOpacity
        style={{
          justifyContent: 'center',
          alignItems: 'center'
        }}
        disable={this.state.disable}
        activeOpacity={0.8}
        onPress={() => this.sendCode()}
      >
        <Text style={{
          ...common.theme.commonTextStyle
        }}
        >
          {this.state.tempText}
        </Text>
      </TouchableOpacity>
    );
  }

}
// export redux component
export default SendVerificationCode;

StarList.js

/**
 * 星星评价组件
 *
 * @date    2017-07-08
 * @author  wuxiaoyan<408991702@qq.com>
 */
/**
 * 引用格式
 * <StarList 
    praiseStar={0} //必填  实心星星的个数
    size={20} //选填  星星的大小
    onPress={(text) => this.setState({star: text})} //选填  点击星星的回调
   />
 */



import React,{PropTypes} from 'react';
import { Icon } from 'antd-mobile';
import common from '../../configs/common';



class StarList extends React.Component {

  // injection reduer object and other params
  static get propTypes() {
    return {
      praiseStar: PropTypes.number,
      onPress:PropTypes.func,
      size:PropTypes.number,
    };
  }

  constructor(props) {
    super(props);
    
    // Initialize the view state
    this.state = {
      giveStar:0
    };
  }


  render() {
    let {praiseStar}=this.props;
    let {onPress}=this.props;
    let {size}=this.props;
    let res = [];
    for(var i = 0; i < 5; i++) {
      let tempI=i+1;
      res.push(
        <div
          key={'star'+(i+1)}
          style={{
            ...common.theme.commonFlexStyle,
            flex:1,
            justifyContent:'center',
            alignItems:'center',
          }}
          onClick={()=>{
            if(onPress){
              this.setState({giveStar: tempI});
              onPress(tempI); 
            }
            
          }}
        >
          {
            onPress?
            <Icon 
              type='star'
              size='sm'
              color={((!onPress &&i<praiseStar) || (onPress&& i< this.state.giveStar))?common.theme.starColor:common.theme.grayColor}
            />
            :
            <Icon 
              type='star'
              size='sm'
              color={i<praiseStar ?common.theme.starColor:common.theme.grayColor}
            />
            

          }
          
          
        </div>
      );
    }
    return (
    <div style={{
      ...common.theme.commonFlexStyle,
      flexDirection:'row'
    }}>
      {res}
    </div>
    );
  }
  

}
// export redux component
export default StarList;

三、config

 api.js

/**
 * 数据交互配置
 *
 * @date    2017-06-09
 * @author  shuwenjie<4483378@qq.com>
 */
import { Link,hashHistory } from 'react-router';
import {toastShort} from '../utils/Toast';

const api = {
  
  /**
   * 中南服务器
   */
  HOST: '/',
  SOCKETHOST: 'ws://192.168.10.120:8082/',
  RESOURCES: 'https://zn.ijianjian.cn/pmc/resources/',



  /**
   * URI 列表
   */
  //首页
  URI_SYSTEM_LOGIN: 'repair-master/login',//
  URI_SYSTEM_ENGINEER_LOGIN: 'repair-master/user/repair_engineer/bind_wx_openid',//
  URI_SYSTEM_MESSAGE: 'data/URI_SYSTEM_MESSAGE.json',
  URI_SYSTEM_MESSAGE_DETAIL: 'data/URI_SYSTEM_MESSAGE_DETAIL.json',
  URI_SYSTEM_MAINTAIN_HOMEDATA:'data/URI_SYSTEM_MAINTAIN_HOMEDATA.json',
  URI_SYSTEM_NissinSystemMain: 'data/URI_SYSTEM_NissinSystemMain.json',
  URI_SYSTEM_EXPLORATIONBUSINESS: 'data/URI_SYSTEM_EXPLORATIONBUSINESS.json',
  URI_SYSTEM_KNOWLEDGEBASE: 'data/URI_SYSTEM_KNOWLEDGEBASE.json',
  URI_SYSTEM_KNOWLEDGEBASEDETAIL: 'data/URI_SYSTEM_KNOWLEDGEBASEDETAIL.json',
  URI_SYSTEM_COLLECT:'data/URI_SYSTEM_COLLECT.json',
  URI_SYSTEM_EXPLORATION_PIC:'data/URI_SYSTEM_EXPLORATION_PIC.json',
  URI_SYSTEM_CUSTOMER_HOMEDATE:'data/URI_SYSTEM_CUSTOMER_HOMEDATE.json',
  URI_SYSTEM_SENG_ACCOUNT:'data/URI_SYSTEM_SENG_ACCOUNT.json',
  URI_SYSTEM_SEND_VERIFICATIONCODE:'data/URI_SYSTEM_SEND_VERIFICATIONCODE.json',
  URI_SYSTEM_CHECK_ACCOUNT:'data/URI_SYSTEM_CHECK_ACCOUNT.json',
  URI_SYSTEM_MODIFY_ACCOUNT_PASSWORD:'data/URI_SYSTEM_MODIFY_ACCOUNT_PASSWORD.json',

  //客户相关
  URI_CUSTOMER_CUSTOMER_LIST:'data/URI_CUSTOMER_CUSTOMER_LIST.json',
  URI_NEWS_NEWS_LIST: 'data/URI_NEWS_NEWS_LIST.json',



  //订单
  URI_ORDER_PRODUCT_TYPE: 'repair-master/product/system',//'data/URI_ORDER_PRODUCT_TYPE.json',//系统列表
  URI_ORDER_PRODUCT_LIST: 'repair-master/product/product/page_by_product_group',//data/URI_ORDER_PRODUCT_LIST.json',//关键字查产品
  URI_ORDER_PRODUCT_VERSION:'repair-master/product/product_type/list_by_product',//data/URI_ORDER_PRODUCT_VERSION.json',//查产品类型
  URI_ORDER_PRODUCT_PROJECT:'repair-master/product/product/page_by_product_group_and_project_name',//根据项目名进行查询
  URI_ORDER_PRODUCT_COMPANY:'repair-master/product/product/page_by_product_group_and_company_name',//根据公司名进行查询
  URI_ORDER_PRODUCTINFO_PAGE:'repair-master/product/product/product_and_info',//根基id查询产品详情信息
  URI_ORDER_PRODUCT_NUMBER:'repair-master/product/product/page_by_product_group_and_number',//根据物料编码进行查询
  URI_ORDER_CREATE_ORDER: 'data/URI_ORDER_CREATE_ORDER.json',
  //URI_ORDER_ORDER_LIST: 'data/URI_ORDER_ORDER_LIST.json',//客户端订单列表
  URI_ORDER_ORDER_LIST: 'data/URI_ORDER_ORDER_LIST1.json',//维修师端订单列表
  URI_ORDER_ORDER_DETAIL: 'data/URI_ORDER_ORDER_DETAIL.json',
  URI_ORDER_CHANGE_ORDER: 'data/URI_ORDER_CHANGE_ORDER.json',
  URI_ORDER_MODIFY_ORDER: 'data/URI_ORDER_MODIFY_ORDER.json',
  URI_ORDER_SELECT_ENGINEER: 'data/URI_ORDER_MODIFY_ORDER.json',
  URI_ORDER_CUSTOMER_EVALUATE: 'data/URI_ORDER_CHANGE_ORDER.json',
  URI_ORDER_ENGINEER_EVALUATE: 'data/URI_ORDER_MODIFY_ORDER.json',
  URI_ORDER_NEW_ORDER: 'data/URI_ORDER_NEW_ORDER.json',
  URI_ORDER_GET_EVALUATE: 'data/URI_ORDER_GET_EVALUATE.json',
  URI_ORDER_STATUS_LIST: 'data/URI_ORDER_STATUS_LIST.json',
  URI_ORDER_BACK_VISIT: 'data/URI_ORDER_CHANGE_ORDER.json',
  URI_ORDER_CREATE_KNOWLEDGE: 'data/URI_ORDER_CHANGE_ORDER.json',
  URI_ORDER_PRODUCT_INFO:'data/URI_ORDER_PRODUCT_INFO.json',
  URI_ORDER_PRODUCT_MANAGER: 'data/URI_ORDER_PRODUCT_MANAGER.json',

  //维修师
  URI_ENGINEER_ENGINEER_LIST: 'data/URI_ENGINEER_ENGINEER_LIST.json',

  //产品
  URI_PRODUCT_PRODUCT_LIST: 'data/URI_PRODUCT_PRODUCT_LIST.json',
  URI_PRODUCT_REPAIR_ORDER_LIST: 'data/URI_PRODUCT_REPAIR_ORDER_LIST.json',
  URI_PRODUCT_ORDER_MANAGER: 'data/URI_PRODUCT_ORDER_MANAGER.json',
  URI_PRODUCT_PRODUCT_MANAGER: 'repair-master/product/project',//'data/URI_PRODUCT_PRODUCT_MANAGER.json',//项目管理
  URI_PRODUCT_PRODUCT_MANAGER_FORM: 'repair-master/product/project',
  URI_PRODUCT_ADD_PRODUCT: 'repair-master/product/productCase',//产品录入

  //供应商
  URI_SUPPLIER_SUPPLIER_LIST: 'data/URI_SUPPLIER_SUPPLIER_LIST.json',

  //工作
  URI_WORK_SUPPLEMENT: 'data/URI_WORK_SUPPLEMENT.json',
  URI_WORKS_MSHEETRANKING: 'data/URI_WORKS_MSHEETRANKING.json',
  URI_WORKS_KONWRAKING: 'data/URI_WORKS_KONWRAKING.json',
  URI_WORKS_CSCORERANKING: 'data/URI_WORKS_CSCORERANKING.json',
 
  //我的
  URI_MINE_CUSTOMER_INFO_DETAIL: 'data/URI_MINE_CUSTOMER_INFO_DETAIL.json',
  URI_MINE_SAVE_CUSTOMER_INFO: 'data/URI_ORDER_CHANGE_ORDER.json',
  URI_MINE_ENGINEER_INFO_DETAIL: 'data/URI_MINE_ENGINEER_INFO_DETAIL.json',
  URI_MINE_SAVE_ENGINEER_INFO: 'data/URI_ORDER_CHANGE_ORDER.json',
  URI_MINE_COLLECT:'data/URI_MINE_COLLECT.json',
  URI_MINE_EVALUATE:'data/URI_MINE_EVALUATE.json',
  URI_MINE_EVALUATE_NUMBER:'data/URI_MINE_EVALUATE_NUMBER.json',
  URI_MINE_COMPLAINT:'data/URI_MINE_COMPLAINT.json',
  URI_MINE_MY_DEVICE:'data/URI_MINE_MY_DEVICE.json',

  //qq地图相关
  QQ_MAP_NAME:'myapp',
  QQ_MAP_KEY:'OB4BZ-D4W3U-B7VVO-4PJWW-6TKDJ-WPB77',

  
  /**
   * tip相关
   */
  networkTip: '网络错误,请重试!',
  getErrorTip,
  validResponse
};




/**
 * api调用错误提示
 * @param {object} error  - 异常信息
 */
function getErrorTip(error) {
  if (process.env.NODE_ENV === 'development') {
    //toastShort(`网络错误,${error}`);
  } else {
    //toastShort(api.networkTip);
  }
}

/**
 * 验证服务器响应对象
 * @param {object} res    - 服务器响应对象
 */
function validResponse(res) {
  if (res && res.resultCode == 0) return true;
  if (res && res.resultCode === 1002 ) {
    toastShort('登录失败,账号或密码错误');
  }else if(res && res.resultCode ===1004 || res && res.resultCode ===1005 || res && res.resultCode ===1006){
    toastShort('您的登录已失效,请重新登录');
    hashHistory.replace('/SystemLogin');
  }
  else {
    toastShort(res && res.resultMsg ? res.resultMsg : '网络错误,请重试');
  }
  

  return false;
}

export default api;

common.js

/**
 * 公用配置集合
 *
 * @date    2017-07-06
 * @author  shuwenjie<4483378@qq.com>
 */

import theme from './theme';
import size from './size';
import api from './api';

const common = {
  theme,
  size,
  api,
};

export default common;

func.js

/**
 * 公共方法
 *
 * @date    2017-08-02
 * @author  wuxiaoyan<408991702@qq.com>
 */
import { hashHistory } from 'react-router';

const func = {
  goBack
};

/**
 * api调用错误提示
 * @param {object} error  - 异常信息
 */
function goBack(url) {
  if(url)
  {
    hashHistory.push(url);  

  }else{
    window.history.go(-1);
  }
}



export default func;

history.js

import { useRouterHistory } from 'react-router'
import createHashHistory from 'history/lib/createHashHistory'

export default useRouterHistory(createHashHistory)()

routes.js

import React from 'react'
import { Route, IndexRoute } from 'react-router'



import SystemMenuScreen from '../components/system/Menu';
import SystemHomeScreen from '../components/system/Home';
import SystemNotFoundScreen from '../components/system/NotFound';
import SystemLoginScreen from '../components/system/Login';
//账号管理
import SystemAccountManagerScreen from '../components/system/AccountManager';
import SystemAccountModifyScreen from '../components/system/AccountModify';
import SystemRoleListScreen from '../components/system/roleList';
import SystemDistributionAuthorityScreen from '../components/system/DistributionAuthority';
import SystemDistributionRoleScreen from '../components/system/DistributionRole';
import SystemOrganizationListScreen from '../components/system/OrganizationList';

//资讯管理
import NewsNewListScreen from '../components/news/NewList'
import NewsNewGroupScreen from '../components/news/NewGroup';
import NewsNewEditScreen from '../components/news/NewEdit';
import NewsNewRecomScreen from '../components/news/NewRecom';
import NewsNewContentScreen from '../components/news/NewContent';

//客户资料管理
import CustomerCustomerListScreen from '../components/customer/CustomerList';
import CustomerCustomerContactsScreen from '../components/customer/CustomerContacts';
import CustomerCustomerOrderDetailsScreen from '../components/customer/CustomerOrderDetails';
import CustomerCustomerEstabilshScreen from '../components/customer/CustomerEstablish';
import CustomerOrderStatusScreen from '../components/customer/OrderStatus';
import CustomerRelatedContactsScreen from '../components/customer/relatedContacts';

//项目管理
import ProductProductManagerScreen from '../components/product/productManager';
//项目管理添加
import ProductProductManagerDetailsChangeScreen from '../components/product/productManagerDetailsChange';
//项目详情页面
import ProductProductManagerDetailsScreen from '../components/product/productManagerDetails';
//材料详情
import ProductMaterialDetailsScreen from '../components/product/materialDetails';

//供应商管理
import SupplierSupplierListScreen from '../components/supplier/SupplierList';
import SupplierSuppilerInfoInputScreen from '../components/supplier/SuppilerInfoInput';
import SupplierSuppilerDetailsScreen from '../components/supplier/SuppilerDetails';

//维修人员管理
import EngineerEngineerListScreen from '../components/engineer/EngineerList';
//维修人员录入
import EngineerEngineerEditScreen from '../components/engineer/EngineerEdit';


//产品列表
import ProductProductListScreen from '../components/product/productList';
//产品列表详情
import ProductProductListDetailsScreen from '../components/product/productListDetails';

//
import ProductRepairOrderListScreen from '../components/product/repairOrderList'
//
import ProductRepairOrderListDetailsScreen from '../components/product/repairOrderListDetails'
//
import SystemAuthorityManagerScreen from '../components/system/authorityManager'
//订单管理
import ProductOrderManagerScreen from '../components/product/orderManager'
//订单管理详情
import ProductOrderManagerDetailsScreen from '../components/product/orderManagerDetails'
//配件修改
import ProductProductPartsListEditScreen from '../components/product/ProductPartsListEdit'
//待派单列表
import ProductOrderingListScreen from '../components/product/orderingList'
//配件单管理
import ProductPartsListScreen from '../components/product/partsList'
//配件单详情
import ProductPartsListDetailsScreen from '../components/product/partsListDetails'
//维修师详情
import ProductEngineerDetailsScreen from '../components/engineer/engineerDetails'
//返厂订单
import ProductReturnListScreen from '../components/product/returnList'
//投诉订单
import ProductComplainListScreen from '../components/product/complainList'

//产品管理
import ProductProductGroupScreen from '../components/product/ProductGroup';
//产品录入
import ProductProductListEditScreen from '../components/product/productListEdit';
//配件退货
import ProductRejectedScreen from '../components/product/rejected';

//知识库管理
import KnowledgeKnowledgeListScreen from '../components/knowledge/KnowledgeList';
import KnowledgeKnowledgeGroupScreen from '../components/knowledge/KnowledgeGroup';
import KnowledgeKnowledgeEditScreen from '../components/knowledge/KnowledgeEdit';

//数据统计
import StatisticsIndexScreen from '../components/statistics/Index';

//KPI管理
import StatisticsKPIManagerScreen from '../components/statistics/KPIManager';

function checkLogin(nextState, replaceState) {
     if(!sessionStorage.getItem('USER_API_TOKEN') ){
     replaceState('/SystemLogin');
   }
}

const routes = (
  <Route>
    <Route path="/"   component={SystemMenuScreen} >
      <IndexRoute  onEnter={checkLogin}   component={SystemHomeScreen} />
      <Route path="/SystemAccountManager" component={SystemAccountManagerScreen} />
      <Route path="/SystemAccountModify" component={SystemAccountModifyScreen} />
      <Route path="/SystemDistributionAuthority" component={SystemDistributionAuthorityScreen} />
      <Route path="/SystemRoleList" component={SystemRoleListScreen} />
      <Route path="/SystemDistributionRole" component={SystemDistributionRoleScreen} />
      <Route path="/SystemOrganizationList" component={SystemOrganizationListScreen} />

      <Route path="/NewsNewList" component={NewsNewListScreen} />
      <Route path="/NewsNewGroup" component={NewsNewGroupScreen} />
      <Route path="/NewsNewEdit" component={NewsNewEditScreen} />
      <Route path="/NewsNewRecom" component={NewsNewRecomScreen} />
      <Route path="/NewsNewContent" component={NewsNewContentScreen} />

      <Route path="/CustomerCustomerList" component={CustomerCustomerListScreen} />
      <Route path="/CustomerCustomerContacts" component={CustomerCustomerContactsScreen} />
      <Route path="/CustomerCustomerOrderDetails" component={CustomerCustomerOrderDetailsScreen} />
      <Route path="/CustomerCustomerEstabilsh" component={CustomerCustomerEstabilshScreen} />
      <Route path="/CustomerOrderStatus" component={CustomerOrderStatusScreen} />
      <Route path="/CustomerRelatedContacts" component={CustomerRelatedContactsScreen} />

      <Route path="/SupplierSupplierList" component={SupplierSupplierListScreen} />
      <Route path="/SupplierSuppilerInfoInput" component={SupplierSuppilerInfoInputScreen} />
      <Route path="/SupplierSuppilerDetails" component={SupplierSuppilerDetailsScreen} />

      <Route path="/EngineerEngineerList" component={EngineerEngineerListScreen} />
      <Route path="/ProductEngineerDetails" component={ProductEngineerDetailsScreen} />

      <Route path="/ProductRepairOrderList" component={ProductRepairOrderListScreen} />
      <Route path="/ProductRepairOrderListDteails" component={ProductRepairOrderListDetailsScreen} /> 
      <Route path="/ProductPartsList" component={ProductPartsListScreen} /> 
      <Route path="/SystemAuthorityManager" component={SystemAuthorityManagerScreen} /> 
      <Route path="/ProductOrderManager" component={ProductOrderManagerScreen} /> 
      <Route path="/ProductPartsListEdit" component={ProductProductPartsListEditScreen} /> 
      <Route path="/ProductPartsListDetails" component={ProductPartsListDetailsScreen} /> 
      <Route path="/ProductOrderManagerDetails" component={ProductOrderManagerDetailsScreen} />
      <Route path="/ProductOrderingList" component={ProductOrderingListScreen} /> 
      <Route path="/ProductReturnList" component={ProductReturnListScreen} /> 
      <Route path="/ProductComplainList" component={ProductComplainListScreen} /> 
      <Route path="/ProductComplainList" component={ProductComplainListScreen} /> 
      <Route path="/EngineerEngineerEdit" component={EngineerEngineerEditScreen} /> 
      <Route path="/ProductProductListEdit" component={ProductProductListEditScreen} /> 
      <Route path="/ProductEngineerDetails" component={ProductEngineerDetailsScreen} /> 
      <Route path="/ProductRejected" component={ProductRejectedScreen} /> 

      

      <Route path="/ProductProductGroup" component={ProductProductGroupScreen} />
      <Route path="/ProductProductManager" component={ProductProductManagerScreen} /> 
      <Route path="/ProductProductManagerDetailsChange" component={ProductProductManagerDetailsChangeScreen} />
      <Route path="/ProductProductManagerDetails" component={ProductProductManagerDetailsScreen} />  
      <Route path="/ProductProductList" component={ProductProductListScreen} />  
      <Route path="/ProductProductListDetails" component={ProductProductListDetailsScreen} />
      <Route path="/ProductMaterialDetails" component={ProductMaterialDetailsScreen} /> 

      
      <Route path="/KnowledgeKnowledgeList" component={KnowledgeKnowledgeListScreen} />
      <Route path="/KnowledgeKnowledgeGroup" component={KnowledgeKnowledgeGroupScreen} />
      <Route path="/KnowledgeKnowledgeEdit" component={KnowledgeKnowledgeEditScreen} />

      <Route path="/StatisticsIndex" component={StatisticsIndexScreen} />
      <Route path="/StatisticsKPIManager" component={StatisticsKPIManagerScreen} />
    
    </Route>
    
    <Route path="/SystemLogin" component={SystemLoginScreen} />
    <Route path="*" component={SystemNotFoundScreen} />
  </Route>
);

export default routes;

 

 

 

 

size.js

/**
 * 应用尺寸配置
 *
 * @date    2017-07-06
 * @author  wuxiaoyan<408991702@qq.com>
 */

const size = {
  width: window.screen.width ,// 返回实际屏幕宽度
  height: window.screen.height ,// 返回实际屏幕高度
  iosStatusBarHeight: 6,
  inputComponentHeight: 40,// 输入框高度
  arrowForwardIconWidth: 30,
  arrowForwardIconSize: 20,
};

export default size;

theme.js

/**
 * 应用主题配置
 *
 * @date    2017-07-06
 * @author  shuwenjie<4483378@qq.com>
 */

const theme = {
  backgroundImage:'-webkit-linear-gradient(120deg,#19194B,#30C8D3);',
  nilColor: '#ffffff',      // 空白背景色
  mainColor: 'rgba(255, 255, 255,0.1)',     // 主色调
  statusBarColor:'#0290fe',//状态栏颜色
  oppColor: '#ffffff',      // 反色调
  grayColor: '#aaaaaa',     // 灰色
  txtColor: '#fff',         // 文字颜色
  linkTxtColor: 'blue',         // 链接文字颜色
  borderColor: 'rgba(220, 220, 220,0.2)',   // 边框色
  placeholderColor:'rgba(255, 255, 255,0.5)',  // 输入框提示颜色
  starColor:'#FFCC00',//星星颜色
  borderBottomStyle:{//边框样式
    borderBottomColor: 'rgba(225, 225, 225, 0.5)',
    borderBottomWidth:1,
    borderBottomStyle:'solid'
  },
  borderLeftStyle:{//边框样式
    borderLeftColor: 'rgba(225, 225, 225, 0.25)',
    borderLeftWidth:1,
    borderLeftStyle:'solid'
  },
  inputLableStyle:{//输入框对应文字样式
    color:'#222'
  },
  submitButtonStyle:{//提交按钮样式
    height: '.9rem',
    backgroundColor: '#11ACE9',
    borderRadius: '.1rem',
    borderColor:'rgba(121,121,121,0.1)',
    borderWidth:1,
    borderStyle:'solid'
  },
  submitButtonTextStyle:{//提交按钮文字样式
    color: '#ffffff',
    fontSize: 18
  },
  commonTextStyle:{//普通文字样式
    color: '#fff',
    fontSize: '.24rem'
  },
  commonFlexStyle:{//通用flex模型
    display:'flex',
    flexDirection:'column',
  },
  navBarStyle:{//导航栏的样式
    backgroundColor:'rgba(255, 255, 255,0.1)',
    marginBottom:1,
    position: 'fixed',
    left:0,
    right:0

  },
  buttonListStyle:{
    margin:'0px 10px',
    color:'rgb(0,153,0)',
    cursor: 'pointer'
  }
  
};

export default theme;

三 、utils

ajax.js

import fetch from 'isomorphic-fetch'
import { API_PREFIX, API_SUFFIX } from '../constants'

// todo : 连接store
// const code = global.$GLOBALCONFIG.STAFF.code

function buildParams(obj) {
  if (!obj) {
    return ''
  }
  const params = []
  for (const key of Object.keys(obj)) {
    const value = obj[key] === undefined ? '' : obj[key]
    params.push(`${key}=${encodeURIComponent(value)}`)
  }
  const arg = params.join('&')
  return arg
}

// 下面是注释用formdata的方式传输数据
/*export function fetchJSON(url, params) {
  params = {
    ...params,
    headers: {
      'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
      ...params.headers,
    },
  }
  url = `${API_PREFIX}${url}${API_SUFFIX}`
  return fetch(url, params)
}*/

export function fetchJSON(url, params, target) {
  let data = {
    'method': 'POST',
    'Content-Type': 'application/json',
    'body': JSON.stringify(params)
  }

  if(target){
    url = `${target}${url}${API_SUFFIX}`
  } else {
    url = `${API_PREFIX}${url}${API_SUFFIX}`
  }
  return fetch(url, data)
}


// eslint-disable-next-line arrow-parens
export const fetchJSONByPost = (url, target) => query => {
  // 下面是注释用formdata的方式传输数据
  /*const params = {
    method: 'POST',
    body: buildParams(query),
  }
  return fetchJSON(url, params)*/
  return fetchJSON(url, query, target)
}



export const fetchJSONStringByPost = url => query => {
  const params = {
    method: 'POST',
    body: query,
    headers: {
      'Content-Type': 'application/json;charset=UTF-8',
    },
  }
  return fetchJSON(url, params)
}

ApiClient.js

/**
 * 数据交换工具
 *
 * @date    2017-05-09
 * @author  shuwenjie<4483378@qq.com>
 */

import common from '../configs/common';
import Storage from './Storage';

//get方式
export const get = (url, params) => {
  if(url.indexOf('.json')>=0){
    url=url.split('.json')[0]+'.json';
  }
  if (params) {
    let paramsArray = [];
    Object.keys(params).forEach(key => paramsArray.push(key + '=' + encodeURIComponent(params[key])));
    url += '?' + paramsArray.join('&');
  }
  /*eslint-disable */
  console.log('ApiRequest',{ url, params });
  /*eslint-enable */
  return request(url, 'get', null, getheaders());
};

function getheaders() {
  return {
    'Authorization':sessionStorage.getItem('USER_API_TOKEN')
  };
}

//post请求
export const postForm = (url, params) => {
  /*eslint-disable */
  console.log('ApiRequest',{ url, params });
  /*eslint-enable */

  let body;
  if(url.indexOf('.json')>=0)
  {//本地调试
    body = params;
    return get(url, params);
  }else{
    body =  new FormData();
    for (let key in params){
      body.append(key, params[key]);
    }
    return request(url, 'post', body, getFormDataHeaders(url));
  }
};


function getFormDataHeaders(url) {
  if(url=='login')
  {
    return {};
  }else{
    let Authorization=sessionStorage.getItem('USER_API_TOKEN');
    return {
      //'Content-Type': 'multipart/form-data',
      'Authorization':Authorization
    };
  }
  
}

//x-www-form-urlencoded请求
export const formUrlencoded = (url, params) => {
  /*eslint-disable */
  console.log('ApiRequest',{ url, params });
  /*eslint-enable */

  let body;
  if(url.indexOf('.json')>=0)
  {//本地调试
    body = params;
    return get(url, params);
  }else{
    body =  '';
    for (let key in params){
      if(body==''){
        body=body+key+'='+params[key];
      }else{
        body=body+'&'+key+'='+params[key];
      }
      
    }
    return request(url, 'post', body, getformUrlencodedHeaders(url));
  }
};
function getformUrlencodedHeaders(url) {
  if(url=='login')
  {
    return {
      'Content-Type': 'application/x-www-form-urlencoded' 
    };
  }else{
    let Authorization=sessionStorage.getItem('USER_API_TOKEN');
    return {
      'Authorization':Authorization
    };
  }
  
}


function request(url, method, body, headers) {
  let isOk;
  return new Promise((resolve, reject) => {
    fetch(common.api.HOST + url, {
      method,
      headers: headers ? headers : {},
      body
    }).then((response) => {
      if (response.ok) {
        isOk = true;
      } else {
        isOk = false;
      }
      return response.json();
    }).then((responseData) => {
      if (process.env.NODE_ENV === 'development') {
        /*eslint-disable */
        console.log('ApiClient', {
          state: 'success',
          url,
          method,
          body,
          headers,
          res: responseData
        });
        /*eslint-enable */
      }
      if (isOk) {
        resolve(responseData);
      } else {
        reject(responseData);
      }
    }).catch((error) => {
      if (process.env.NODE_ENV === 'development') {
        /*eslint-disable */
        console.log('ApiClient', {
          state: 'error',
          url,
          method,
          body,
          headers,
          error
        });
        /*eslint-enable */
      }
      reject(error);
    });
    

  });
}

Formcheck.js

/**
 * 提示语工具
 *
 * @date    2017-05-09
 * @author  shuwenjie<4483378@qq.com>
 */

import { toastShort } from './Toast';

export const checkIsrequire = (checkObject) => {
  let result=true;
  for(var key in checkObject){
    if(checkObject[key].require && checkObject[key].value ==='' )
    {
      toastShort(checkObject[key].errorTip);
      result=false;
      return result;
    }
  }
  return result;
};

index.js

/**
 * 公用工具集合
 *
 * @date    2017-07-08
 * @author  wuxiaoyan<408991702@qq.com>
 */

import * as toast from './Toast';
import * as ApiClient from './ApiClient';
const utils = {
  ...toast,
  ...ApiClient,
};

export default utils;

Storage.js

/**
 * 本地存储操作工具
 *
 * @date    2017-05-09
 * @author  shuwenjie<4483378@qq.com>
 */
class DeviceStorage {
 
  static saveToken(token) {
    return null;
  }
  static getToken() {
    return sessionStorage.getItem('USER_API_TOKEN');
  }
  static getToken(key) {
    return sessionStorage.getItem(key);
  }


}

export default DeviceStorage;

Toast.js

/**
 * 提示语工具
 *
 * @date    2017-05-09
 * @author  shuwenjie<4483378@qq.com>
 */

import { message } from 'antd';
let toast;

export const toastShort = (content) => {
  message.info(content);
};

tools.js

import {Toast} from 'antd-mobile';
import { hashHistory } from 'react-router'

export function ajaxFn(returnData,callback,javaUrl){        
    $.ajax({
        type:"post",
        url:javaUrl,
        data:returnData,
        dataType: "json",
        //async:false,    //false 表示ajax执行完成之后在执行后面的代码
        success(data){   
            Toast.hide();
            switch(data.resultCode){
                case ('5'):
                    Toast.offline('登录超时,请重新登录!', 1.5,()=>{
                        // const url = window.location.href.split("#/")[0];                        
                        // window.location.href = url;
                        hashHistory.push('login');
                    });
                    break;                                            
            }    
            callback.call(this,data);                        
        },
        error(a,b,c){
            console.log(a,b,c);
            Toast.hide();
            Toast.offline('网络连接失败!', 1);            
        }
    });      
}


 /*获取传入时间的当月最后一天*/
export function getLastDay(time) {         
    let date = new Date(time);
    let new_year = date.getFullYear();    //取当前的年份          
    let new_month = date.getMonth() + 1;//取下一个月的第一天,方便计算(最后一天不固定)                        
    let new_date = new Date(new_year,new_month,1);                //取当年当月中的第一天          
    return (new Date(new_date.getTime()-1000*60*60*24)).getDate();//获取当月最后一天日期          
} 

/*获取对象长度*/
export function getObjectCount(object){  
    var n, count = 0;  
    for(n in object){  da
        if(object.hasOwnProperty(n)){  
            count++;
        }  
    }  
    return count;  
};

/*根据内容设置iframe高度*/
export function iframeAutoHeight(id){
    parent.document.getElementById(id).height=0;
    parent.document.getElementById(id).height=document.body.scrollHeight;         
} 


/*获取今天的日期*/
export function getNowFormatDate(time=new Date(),type,seperator="-") {
    let date = new Date(time);
    let year = date.getFullYear();
    let month = date.getMonth() + 1;
    let day = date.getDate();
    let hour = date.getHours();
    let minute = date.getMinutes();
    let second = date.getSeconds();
    if (month >= 1 && month <= 9)month = "0" + month;
    if (day >= 0 && day <= 9) day = "0" + day;
    if(hour >= 0 && hour <= 9) hour = "0"+hour;
    if(minute >= 0 && minute <= 9) minute = "0"+minute;
    if(type == "dateTime"){
        return `${year + seperator + month + seperator + day} ${hour}:${minute}:${second}`;
    }else if(type == "time"){
        return `${hour}:${minute}:${second}`;
    }else{
        return year + seperator + month + seperator + day;
    }
}


/*根据毫秒数转成正常时间格式*/
export function msConversionDate(millisecond,format){
    let date = new Date(millisecond);
    return getNowFormatDate(date,format);
}


/*滚动条加载数据*/
export function scrollLoad(callback){    
    let contrastValue = 0;
    /*滚到底部加载下一页*/
    window.onscroll = () => {
        const contentHeight = document.body.scrollHeight;       /*内容总高度*/
        const winHeight = window.innerHeight;                   /*当前窗口高度*/
        const scrollTop = document.body.scrollTop;              /*滚动条距离顶部的距离*/   
        
        /*两次距离一样就不操作*/                                
        if(scrollTop + winHeight >= contentHeight && scrollTop != contrastValue ){                        
            contrastValue = scrollTop;
            callback.call(this,contentHeight);                 
        }            
    };     
}

/*获取链接上的参数*/
export function geturl(name) {
    var reg = new RegExp("(^|\\?|&)" + name + "=([^&]*)(\\s|&|$)", "i");
    if (reg.test(location.href)) return decodeURI(RegExp.$2.replace(/\+/g, " ")); return "";
};


export function isWeiXin(){
    var ua = window.navigator.userAgent.toLowerCase();
    if(ua.match(/MicroMessenger/i) == 'micromessenger'){
        return true;
    }else{
        return false;
    }
}

 

转载于:https://www.cnblogs.com/webqiand/articles/11250528.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值