From f59a500d24291d7f54b71dcca939a2a23dedca7c Mon Sep 17 00:00:00 2001
From: king <18310653075@163.com>
Date: 星期四, 18 六月 2020 17:52:03 +0800
Subject: [PATCH] 2020-06-18

---
 src/mob/datasource/verifycard/voucherform/index.jsx   |  269 ++++
 src/mob/mobcard/index.scss                            |   24 
 src/mob/header/index.jsx                              |   25 
 src/mob/modelsource/index.jsx                         |   34 
 src/components/header/index.jsx                       |    6 
 src/mob/modelsource/index.scss                        |    9 
 src/mob/datasource/verifycard/customscript/index.jsx  |  257 ++++
 src/mob/dragsource/index.jsx                          |   13 
 src/mob/mobshell/index.jsx                            |  103 +
 src/mob/datasource/index.jsx                          |   96 +
 src/templates/comtableconfig/index.jsx                |   16 
 src/mob/datasource/verifycard/voucherform/index.scss  |    0 
 src/mob/datasource/verifycard/uniqueform/index.scss   |    0 
 src/mob/mobcard/mutilform/index.scss                  |    4 
 src/mob/dragsource/index.scss                         |    9 
 src/mob/datasource/verifycard/customform/index.jsx    |  232 +++
 src/mob/modelsource/option.jsx                        |   14 
 src/views/mobdesign/index.scss                        |    7 
 src/views/mobmanage/index.scss                        |    2 
 src/views/mobdesign/index.jsx                         |   98 +
 src/mob/datasource/verifycard/uniqueform/index.jsx    |  157 ++
 src/mob/mobshell/card.jsx                             |   57 
 src/mob/mobcard/index.jsx                             |  178 ++
 src/mob/mobshell/index.scss                           |    6 
 src/mob/datasource/verifycard/index.scss              |   66 +
 src/index.js                                          |    2 
 src/mob/datasource/verifycard/contrastform/index.jsx  |  166 ++
 src/mob/modelsource/dragsource/index.scss             |   25 
 src/locales/zh-CN/mob.js                              |    4 
 src/mob/datasource/index.scss                         |   79 +
 src/mob/datasource/verifycard/index.jsx               | 1084 +++++++++++++++++
 src/tabviews/rolemanage/index.jsx                     |   19 
 src/templates/zshare/formconfig.jsx                   |   31 
 src/router/index.js                                   |    2 
 src/mob/datasource/verifycard/customform/index.scss   |    0 
 src/tabviews/zshare/actionList/printbutton/index.jsx  |    4 
 src/tabviews/zshare/mutilform/index.jsx               |   15 
 src/mob/datasource/verifycard/customscript/index.scss |    5 
 src/mob/modelsource/dragsource/index.jsx              |   18 
 src/mob/mobcard/mutilform/index.jsx                   |   90 +
 src/views/mobmanage/index.jsx                         |    6 
 src/mob/datasource/verifycard/billcodeform/index.jsx  |  374 ++++++
 src/mob/header/index.scss                             |   37 
 src/mob/datasource/verifycard/contrastform/index.scss |    0 
 src/mob/datasource/verifycard/billcodeform/index.scss |    0 
 src/assets/mobimg/mob-login1.png                      |    0 
 src/locales/en-US/mob.js                              |    4 
 src/views/login/index.jsx                             |    2 
 48 files changed, 3,565 insertions(+), 84 deletions(-)

diff --git a/src/assets/mobimg/mob-login1.png b/src/assets/mobimg/mob-login1.png
new file mode 100644
index 0000000..9d4e94f
--- /dev/null
+++ b/src/assets/mobimg/mob-login1.png
Binary files differ
diff --git a/src/components/header/index.jsx b/src/components/header/index.jsx
index ef2b78d..7774abf 100644
--- a/src/components/header/index.jsx
+++ b/src/components/header/index.jsx
@@ -678,9 +678,9 @@
         {this.props.editLevel === 'HS' ? <Button className="level4-close" type="primary" onClick={this.exitManage}>閫�鍑�</Button> : null}
         {/* 杩涘叆缂栬緫鎸夐挳 */}
         {this.props.editState && !this.props.editLevel ? <Icon onClick={this.enterEdit} className="edit-check" type="edit" /> : null}
-        {/* {this.props.editState && !this.props.editLevel && options.systemType === 'local' && window.GLOB.systemType !== 'official' ?
-          <a href="#/mobmanage" target="_blank" className="mobile" type="edit"> 绉诲姩绔� <Icon type="arrow-right" /></a> : null
-        } */}
+        {this.props.editState && !this.props.editLevel && options.systemType === 'local' && window.GLOB.systemType !== 'official' ?
+          <a href="#/mobmanage" target="_blank" className="mobile" type="edit"> 搴旂敤绠$悊 <Icon type="arrow-right" /></a> : null
+        }
         {/* 缂栬緫鑿滃崟 */}
         {this.props.editLevel === 'level1' ? <EditMenu menulist={this.state.menulist} reload={this.reload} exitEdit={this.exitEdit}/> : null}
         {/* 澶村儚銆佺敤鎴峰悕 */}
diff --git a/src/index.js b/src/index.js
index e8e335e..52e544e 100644
--- a/src/index.js
+++ b/src/index.js
@@ -94,7 +94,7 @@
 }
 
 if (process.env.NODE_ENV === 'production') { // 鐢ㄤ簬鏍¢獙鏄惁瀛樺湪寮�鍙戞潈闄�
-  let _service = window.location.href.replace(/\/index.html(.*)/ig, '').replace(new RegExp(document.location.origin + '/?', 'ig'), '')
+  let _service = window.location.href.replace(/\/index.html(.*)|\/#(.*)/ig, '').replace(new RegExp(document.location.origin + '/?', 'ig'), '')
   window.GLOB.linkurl = window.location.href.split('#')[0]
   window.GLOB.service = _service ? _service + '/' : ''
 } else {
diff --git a/src/locales/en-US/mob.js b/src/locales/en-US/mob.js
index 15f67ba..4e8b687 100644
--- a/src/locales/en-US/mob.js
+++ b/src/locales/en-US/mob.js
@@ -1,6 +1,10 @@
 export default {
+  'mob.login': '鐧诲綍',
   'mob.confirm': '纭畾',
+  'mob.submit': '鎻愪氦',
   'mob.cancel': '鍙栨秷',
   'mob.header.logout': '閫�鍑�',
   'mob.header.logout.hint': '鎮ㄧ‘瀹氳閫�鍑哄悧?',
+  'mob.required.input': '璇疯緭鍏�',
+  'mob.required.select': '璇烽�夋嫨',
 }
\ No newline at end of file
diff --git a/src/locales/zh-CN/mob.js b/src/locales/zh-CN/mob.js
index 15f67ba..4e8b687 100644
--- a/src/locales/zh-CN/mob.js
+++ b/src/locales/zh-CN/mob.js
@@ -1,6 +1,10 @@
 export default {
+  'mob.login': '鐧诲綍',
   'mob.confirm': '纭畾',
+  'mob.submit': '鎻愪氦',
   'mob.cancel': '鍙栨秷',
   'mob.header.logout': '閫�鍑�',
   'mob.header.logout.hint': '鎮ㄧ‘瀹氳閫�鍑哄悧?',
+  'mob.required.input': '璇疯緭鍏�',
+  'mob.required.select': '璇烽�夋嫨',
 }
\ No newline at end of file
diff --git a/src/mob/datasource/index.jsx b/src/mob/datasource/index.jsx
new file mode 100644
index 0000000..3b1cfd1
--- /dev/null
+++ b/src/mob/datasource/index.jsx
@@ -0,0 +1,96 @@
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
+import { is, fromJS } from 'immutable'
+import { Icon, Modal } from 'antd'
+
+import Utils from '@/utils/utils.js'
+import zhCN from '@/locales/zh-CN/mob.js'
+import enUS from '@/locales/en-US/mob.js'
+import VerifyCard from './verifycard'
+import './index.scss'
+
+class DataSource extends Component {
+  static propTpyes = {
+    config: PropTypes.any,
+    updateConfig: PropTypes.func
+  }
+
+  state = {
+    dict: localStorage.getItem('lang') !== 'en-US' ? zhCN : enUS,
+    sourcelist: [],
+    visible: false,
+    source: null
+  }
+
+  UNSAFE_componentWillReceiveProps(nextProps) {
+
+  }
+
+  shouldComponentUpdate (nextProps, nextState) {
+    return !is(fromJS(this.props), fromJS(nextProps)) || !is(fromJS(this.state), fromJS(nextState))
+  }
+
+  editDataSource = (item) => {
+    if (!item) {
+      item = {
+        uuid: Utils.getuuid()
+      }
+    }
+
+    this.setState({
+      visible: true,
+      source: item
+    })
+  }
+
+  closeDataSource = () => {
+
+  }
+
+  render () {
+    const { sourcelist, visible, source, dict } = this.state
+
+    return (
+      <div className="mob-datasource">
+        {sourcelist.map(item => (
+          <span className="mob-input-group-wrapper" key={item.uuid}>
+            <span className="mob-input-wrapper">
+              <span className="mob-input-value">{item.label}</span>
+              <span className="mob-input-group-addon">
+                <Icon type="setting" onClick={() => this.editDataSource(item)} />
+                <Icon type="close" onClick={() => this.closeDataSource(item)} />
+              </span>
+            </span>
+          </span>
+        ))}
+        <span className="mob-input-group-wrapper">
+          <span className="mob-input-wrapper">
+            <span className="mob-input-insert" onClick={() => this.editDataSource()}>
+              <Icon type="plus" />
+            </span>
+          </span>
+        </span>
+        <Modal
+          wrapClassName="mob-datasource-verify-modal"
+          title={'鏁版嵁婧愰厤缃�'}
+          visible={visible}
+          width={'75vw'}
+          maskClosable={false}
+          style={{minWidth: '900px', maxWidth: '1200px'}}
+          okText={dict['mob.submit']}
+          onOk={this.verifySubmit}
+          onCancel={() => { this.setState({ visible: false }) }}
+          destroyOnClose
+        >
+          <VerifyCard
+            card={source}
+            dict={dict}
+            wrappedComponentRef={(inst) => this.verifyRef = inst}
+          />
+        </Modal>
+      </div>
+    )
+  }
+}
+
+export default DataSource
\ No newline at end of file
diff --git a/src/mob/datasource/index.scss b/src/mob/datasource/index.scss
new file mode 100644
index 0000000..00ba2d7
--- /dev/null
+++ b/src/mob/datasource/index.scss
@@ -0,0 +1,79 @@
+.mob-datasource {
+  width: 100%;
+  height: 100%;
+  overflow: hidden;
+
+  .mob-input-group-wrapper {
+    padding: 0 20px;
+    display: inline-block;
+    width: 100%;
+    text-align: start;
+    vertical-align: top;
+    margin-bottom: 15px;
+
+    .mob-input-wrapper {
+      position: relative;
+      display: table;
+      width: 100%;
+      border-collapse: separate;
+      border-spacing: 0;
+
+      .mob-input-value {
+        display: table-cell;
+        width: 100%;
+        border: 1px solid #d9d9d9;
+        border-radius: 4px 0px 0px 4px;
+        overflow: hidden;
+        text-overflow:ellipsis;
+        white-space: nowrap;
+        padding: 2px 10px;
+      }
+
+      .mob-input-group-addon {
+        display: table-cell;
+        width: 1px;
+        position: relative;
+        padding: 0 11px;
+        color: rgba(0, 0, 0, 0.65);
+        font-weight: normal;
+        font-size: 14px;
+        line-height: 1;
+        text-align: center;
+        background-color: #fafafa;
+        border: 1px solid #d9d9d9;
+        border-radius: 0px 4px 4px 0px;
+        white-space: nowrap;
+      }
+
+      .mob-input-insert {
+        display: table-cell;
+        width: 100%;
+        border: 1px dotted #d9d9d9;
+        border-radius: 4px;
+        text-align: center;
+        cursor: pointer;
+
+        .anticon-plus {
+          padding: 6px;
+          font-size: 16px;
+          color: rgb(38, 194, 129);
+        }
+      }
+    }
+    .anticon-setting {
+      margin-right: 5px;
+      padding: 6px;
+      cursor: pointer;
+    }
+    .anticon-setting:hover {
+      color: #1890ff;
+    }
+    .anticon-close {
+      padding: 6px;
+      cursor: pointer;
+    }
+    .anticon-close:hover {
+      color: #ff4d4f;
+    }
+  }
+}
\ No newline at end of file
diff --git a/src/mob/datasource/verifycard/billcodeform/index.jsx b/src/mob/datasource/verifycard/billcodeform/index.jsx
new file mode 100644
index 0000000..1c5591a
--- /dev/null
+++ b/src/mob/datasource/verifycard/billcodeform/index.jsx
@@ -0,0 +1,374 @@
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
+import { is, fromJS } from 'immutable'
+import { Form, Row, Col, Select, Button, InputNumber, Input, Tooltip, Icon } from 'antd'
+import { formRule } from '@/utils/option.js'
+import './index.scss'
+
+
+class UniqueForm extends Component {
+  static propTpyes = {
+    dict: PropTypes.object,         // 瀛楀吀椤�
+    btn: PropTypes.object,          // 鎸夐挳淇℃伅
+    fields: PropTypes.array,        // 琛ㄥ崟
+    billcodes: PropTypes.array,     // 琛ㄥ崟
+    columns: PropTypes.array,       // 琛ㄥ崟
+    modular: PropTypes.array,       // 琛ㄥ崟
+    modularDetail: PropTypes.array, // 琛ㄥ崟
+    orderChange: PropTypes.func     // 琛ㄥ崟
+  }
+
+  state = {
+    editItem: null,
+    modularDetail: [],
+    funFields: [],
+    billFields: [],
+    type: '1',
+    TypeCharOne: 'Lp'
+  }
+
+  UNSAFE_componentWillMount() {
+    let _modularDetail = []
+    let _billFields = []
+    if (this.props.modular.length > 0) {
+      _modularDetail = this.props.modularDetail.filter(item => item.BID === this.props.modular[0].ID)
+    }
+
+    let fieldMap = new Map()
+    this.props.fields.forEach(_field => {
+      if (_field.type === 'text' && !fieldMap.has(_field.field)) {
+        _billFields.push(_field)
+        fieldMap.set(_field.field, true)
+      }
+    })
+
+    if (this.props.btn.Ot !== 'notRequired') {
+      this.props.columns.forEach(_field => {
+        if (_field.type === 'text' && !fieldMap.has(_field.field)) {
+          _billFields.push(_field)
+          fieldMap.set(_field.field, true)
+        }
+      })
+    }
+
+    let _usedfields = this.props.billcodes.map(item => item.field)
+
+    this.setState({
+      modularDetail: _modularDetail,
+      funFields: this.props.fields.filter(field => field.type === 'funcvar' && !_usedfields.includes(field.field)),
+      billFields: _billFields
+    })
+  }
+
+  UNSAFE_componentWillReceiveProps (nextProps) {
+    if (!is(fromJS(this.props.modular), fromJS(nextProps.modular))) {
+      let _detail = nextProps.modularDetail.filter(item => item.BID === nextProps.modular[0].ID)
+
+      this.setState({
+        modularDetail: _detail
+      })
+    }
+  }
+
+  edit = (record) => {
+    let _usedfields = this.props.billcodes.map(item => item.field)
+    let _funFields = this.props.fields.filter(field => field.type === 'funcvar' && (!_usedfields.includes(field.field) || field.field === record.field))
+
+    if (record.TypeCharOne === 'Y' || record.TypeCharOne === 'n') {
+      let _detail = this.props.modularDetail.filter(item => item.BID === record.ModularCode)
+      let _modularDetailCode = ''
+
+      if (_detail.filter(item => item.ModularDetailCode === record.ModularDetailCode).length > 0) {
+        _modularDetailCode = record.ModularDetailCode
+      }
+
+      this.setState({
+        type: '2',
+        funFields: _funFields,
+        editItem: record,
+        modularDetail: _detail,
+        TypeCharOne: record.TypeCharOne
+      }, () => {
+        this.props.form.setFieldsValue({
+          field: record.field,
+          TypeCharOne: record.TypeCharOne,
+          ModularCode: record.ModularCode,
+          ModularDetailCode: _modularDetailCode,
+        })
+      })
+    } else {
+      this.setState({
+        type: '1',
+        funFields: _funFields,
+        editItem: record,
+        TypeCharOne: record.TypeCharOne
+      }, () => {
+        let _form = {
+          field: record.field,
+          TypeCharOne: record.TypeCharOne,
+          Type: record.Type,
+          linkField: record.linkField
+        }
+        if (record.TypeCharOne === 'Lp') {
+          _form.mark = record.mark || ''
+        }
+        this.props.form.setFieldsValue(_form)
+      })
+    }
+  }
+
+  voucherChange = (value) => {
+    let _detail = this.props.modularDetail.filter(item => item.BID === value)
+
+    this.setState({
+      modularDetail: _detail
+    })
+    this.props.form.setFieldsValue({
+      ModularDetailCode: _detail[0] ? _detail[0].ModularDetailCode : ''
+    })
+  }
+
+  TypeCharOneChange = (value) => {
+    if (value === 'Y' || value === 'n') {
+      this.setState({
+        type: '2',
+        TypeCharOne: value
+      })
+    } else {
+      this.setState({
+        type: '1',
+        TypeCharOne: value
+      })
+    }
+  }
+
+  handleConfirm = () => {
+    const { funFields, billFields } = this.state
+    // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭�
+    this.props.form.validateFieldsAndScroll((err, values) => {
+      if (!err) {
+        values.uuid = this.state.editItem ? this.state.editItem.uuid : ''
+
+        let _funField = funFields.filter(item => item.field === values.field)[0]
+        values.fieldName = _funField ? _funField.label : ''
+
+        // 涓�绾ц彍鍗曞�间负20190203125926873D6029A9C511041719420鏃禩ypeCharTwo=TableCode锛屽叾浠栫敤BillCode
+        if (values.ModularCode === '20190203125926873D6029A9C511041719420') {
+          values.TypeCharTwo = 'TableCode'
+        } else {
+          values.TypeCharTwo = 'BillCode'
+        }
+        // 璁剧疆绫诲瀷鍚嶇О锛岀敤浜庡垪琛ㄦ樉绀�
+        let billType = {
+          Y: '鍗曞彿',
+          n: '缂栫爜',
+          Lp: '琛屽彿',
+          BN: '鎵规',
+        }
+        values.billType = billType[values.TypeCharOne]
+
+        if (values.TypeCharOne === 'Y' || values.TypeCharOne === 'n') {
+          // 璁剧疆鍑瘉绫诲瀷涓枃鍚�
+          let ModularCode = this.props.modular.filter(item => item.ID === values.ModularCode)[0]
+          values.ModularCodeName = ModularCode.NameNO
+
+          // 璁剧疆娴佹按鍙蜂綅鏁�
+          let _detail = this.state.modularDetail.filter(item => item.ModularDetailCode === values.ModularDetailCode)[0]
+          values.Type = _detail.Type
+        } else {
+          let _billField = billFields.filter(item => item.field === values.linkField)[0]
+          values.linkFieldName = _billField ? _billField.label : ''
+        }
+
+        this.setState({
+          editItem: null
+        }, () => {
+          this.props.orderChange(values)
+          let _usedfields = this.props.billcodes.map(item => item.field)
+
+          this.setState({
+            funFields: this.props.fields.filter(field => field.type === 'funcvar' && !_usedfields.includes(field.field)),
+          })
+        })
+        let _form = {
+          field: ''
+        }
+        if (this.state.TypeCharOne === 'Lp') {
+          _form.mark = ''
+        }
+        this.props.form.setFieldsValue(_form)
+      }
+    })
+  }
+
+  render() {
+    const { getFieldDecorator } = this.props.form
+    const { type, TypeCharOne } = this.state
+    const formItemLayout = {
+      labelCol: {
+        xs: { span: 24 },
+        sm: { span: 10 }
+      },
+      wrapperCol: {
+        xs: { span: 24 },
+        sm: { span: 14 }
+      }
+    }
+
+    return (
+      <Form {...formItemLayout} className="verify-form">
+        <Row gutter={24}>
+          <Col span={7}>
+            <Form.Item label={this.props.dict['header.form.funcvar']}>
+              {getFieldDecorator('field', {
+                initialValue: '',
+                rules: [
+                  {
+                    required: true,
+                    message: this.props.dict['form.required.input'] + this.props.dict['header.form.funcvar'] + '!'
+                  }
+                ]
+              })(
+                <Select>
+                  {this.state.funFields.map(option =>
+                    <Select.Option title={option.label} id={option.uuid} key={option.uuid} value={option.field}>
+                      {option.label}
+                    </Select.Option>
+                  )}
+                </Select>
+              )}
+            </Form.Item>
+          </Col>
+          <Col span={7}>
+            <Form.Item label={'绫诲瀷'}>
+              {getFieldDecorator('TypeCharOne', {
+                initialValue: 'Lp',
+                rules: [
+                  {
+                    required: true,
+                    message: this.props.dict['form.required.select'] + '绫诲瀷!'
+                  }
+                ]
+              })(
+                <Select onChange={(value) => {this.TypeCharOneChange(value)}}>
+                  <Select.Option value="Y"> 鍗曞彿 </Select.Option>
+                  <Select.Option value="n"> 缂栫爜 </Select.Option>
+                  <Select.Option value="Lp"> 琛屽彿 </Select.Option>
+                  <Select.Option value="BN"> 鎵规 </Select.Option>
+                </Select>
+              )}
+            </Form.Item>
+          </Col>
+          {type === '1' ? <Col span={7}>
+            <Form.Item label={'鍏宠仈瀛楁'}>
+              {getFieldDecorator('linkField', {
+                initialValue: '',
+                rules: [
+                  {
+                    required: true,
+                    message: this.props.dict['form.required.input'] + '鍏宠仈瀛楁!'
+                  }
+                ]
+              })(
+                <Select>
+                  {this.state.billFields.map(option =>
+                    <Select.Option title={option.label} id={option.uuid} key={option.uuid} value={option.field}>
+                      {option.label}
+                    </Select.Option>
+                  )}
+                </Select>
+              )}
+            </Form.Item>
+          </Col> : null}
+          {type === '2' ? <Col span={7}>
+            <Form.Item label={'鍑瘉绫诲瀷'}>
+              {getFieldDecorator('ModularCode', {
+                initialValue: this.props.modular[0] ? this.props.modular[0].ID : '',
+                rules: [
+                  {
+                    required: true,
+                    message: this.props.dict['form.required.input'] + '鍑瘉绫诲瀷!'
+                  }
+                ]
+              })(
+                <Select
+                  showSearch
+                  filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0}
+                  onChange={(value) => {this.voucherChange(value)}}
+                >
+                  {this.props.modular.map(option =>
+                    <Select.Option title={option.NameNO} id={option.ID} key={option.ID} value={option.ID}>
+                      {option.NameNO}
+                    </Select.Option>
+                  )}
+                </Select>
+              )}
+            </Form.Item>
+          </Col> : null}
+          <Col span={3} className="add">
+            <Button onClick={this.handleConfirm} className="mk-green">
+              淇濆瓨
+            </Button>
+          </Col>
+          {type === '1' ? <Col span={7}>
+            <Form.Item label={'浣嶆暟'}>
+              {getFieldDecorator('Type', {
+                initialValue: 4,
+                rules: [
+                  {
+                    required: true,
+                    message: this.props.dict['form.required.input'] + '浣嶆暟!'
+                  }
+                ]
+              })(<InputNumber min={1} max={10} precision={0} />)}
+            </Form.Item>
+          </Col> : null}
+          {type === '2' ? <Col span={7}>
+            <Form.Item label={'鍑瘉鏍囪瘑'}>
+              {getFieldDecorator('ModularDetailCode', {
+                initialValue: this.state.modularDetail[0] ? this.state.modularDetail[0].ModularDetailCode : '',
+                rules: [
+                  {
+                    required: true,
+                    message: this.props.dict['form.required.input'] + '鍑瘉鏍囪瘑!'
+                  }
+                ]
+              })(
+                <Select
+                  showSearch
+                  filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0}
+                >
+                  {this.state.modularDetail.map(option =>
+                    <Select.Option style={{whiteSpace: 'unset'}} title={option.CodeName} id={option.ModularDetailCode} key={option.ModularDetailCode} value={option.ModularDetailCode}>
+                      {option.CodeName}
+                    </Select.Option>
+                  )}
+                </Select>
+              )}
+            </Form.Item>
+          </Col> : null}
+          {TypeCharOne === 'Lp' ? <Col span={7}>
+            <Form.Item label={
+              <Tooltip placement="topLeft" title="璇ユ爣璇嗙敤浜庣敓鎴愯鍙疯鍒欙紝涓虹┖鏃朵娇鐢ㄦ寜閽甀D">
+                <Icon type="question-circle" />
+                {'鏍囪瘑'}
+              </Tooltip>
+            }>
+              {getFieldDecorator('mark', {
+                initialValue: '',
+                rules: [
+                  {
+                    pattern: /^[a-zA-Z0-9]*$/ig,
+                    message: formRule.input.letternummsg
+                  }
+                ]
+              })(<Input placeholder="" autoComplete="off" />)}
+            </Form.Item>
+          </Col> : null}
+        </Row>
+      </Form>
+    )
+  }
+}
+
+export default Form.create()(UniqueForm)
\ No newline at end of file
diff --git a/src/mob/datasource/verifycard/billcodeform/index.scss b/src/mob/datasource/verifycard/billcodeform/index.scss
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/mob/datasource/verifycard/billcodeform/index.scss
diff --git a/src/mob/datasource/verifycard/contrastform/index.jsx b/src/mob/datasource/verifycard/contrastform/index.jsx
new file mode 100644
index 0000000..9393dc5
--- /dev/null
+++ b/src/mob/datasource/verifycard/contrastform/index.jsx
@@ -0,0 +1,166 @@
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
+import { Form, Row, Col, Select, Button, Input } from 'antd'
+import './index.scss'
+
+
+class UniqueForm extends Component {
+  static propTpyes = {
+    dict: PropTypes.object,       // 瀛楀吀椤�
+    contrastChange: PropTypes.func  // 淇敼鍑芥暟
+  }
+
+  state = {
+    editItem: null // 缂栬緫鍏冪礌
+  }
+
+  edit = (record) => {
+    this.setState({
+      editItem: record
+    })
+
+    this.props.form.setFieldsValue({
+      frontfield: record.frontfield,
+      operator: record.operator,
+      backfield: record.backfield,
+      errmsg: record.errmsg,
+      errorCode: record.errorCode
+    })
+  }
+
+
+  handleConfirm = () => {
+    // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭�
+    this.props.form.validateFieldsAndScroll((err, values) => {
+      if (!err) {
+        values.uuid = this.state.editItem ? this.state.editItem.uuid : ''
+
+        this.setState({
+          editItem: null
+        }, () => {
+          this.props.contrastChange(values)
+        })
+        this.props.form.setFieldsValue({
+          frontfield: '',
+          backfield: '',
+          errmsg: ''
+        })
+      }
+    })
+  }
+
+  render() {
+    const { getFieldDecorator } = this.props.form
+    const formItemLayout = {
+      labelCol: {
+        xs: { span: 24 },
+        sm: { span: 8 }
+      },
+      wrapperCol: {
+        xs: { span: 24 },
+        sm: { span: 16 }
+      }
+    }
+
+    return (
+      <Form {...formItemLayout} className="verify-form" id="verifycard1">
+        <Row gutter={24}>
+          <Col span={7}>
+            <Form.Item label={'鍐呭1'}>
+              {getFieldDecorator('frontfield', {
+                initialValue: '',
+                rules: [
+                  {
+                    required: true,
+                    message: this.props.dict['form.required.input'] + '鍐呭1!'
+                  }
+                ]
+              })(<Input placeholder="" autoComplete="off" />)}
+            </Form.Item>
+          </Col>
+          <Col span={7}>
+            <Form.Item label={'杩愮畻绗�'}>
+              {getFieldDecorator('operator', {
+                initialValue: '=',
+                rules: [
+                  {
+                    required: true,
+                    message: this.props.dict['form.required.select'] + '杩愮畻绗�!'
+                  }
+                ]
+              })(
+                <Select>
+                  <Select.Option value="="> = </Select.Option>
+                  <Select.Option value="!="> != </Select.Option>
+                  <Select.Option value=">"> &gt; </Select.Option>
+                  <Select.Option value="<"> &lt; </Select.Option>
+                  <Select.Option value=">="> &gt;= </Select.Option>
+                  <Select.Option value="<="> &lt;= </Select.Option>
+                  <Select.Option value="in"> in </Select.Option>
+                  <Select.Option value="like"> like </Select.Option>
+                </Select>
+              )}
+            </Form.Item>
+          </Col>
+          <Col span={7}>
+            <Form.Item label={'鍐呭2'}>
+              {getFieldDecorator('backfield', {
+                initialValue: '',
+                rules: [
+                  {
+                    required: true,
+                    message: this.props.dict['form.required.input'] + '鍐呭2!'
+                  }
+                ]
+              })(<Input placeholder="" autoComplete="off" />)}
+            </Form.Item>
+          </Col>
+          <Col span={3} className="add">
+            <Button onClick={this.handleConfirm} type="primary" className="mk-green">
+              淇濆瓨
+            </Button>
+          </Col>
+          <Col span={7}>
+            <Form.Item label={'鎻愮ず淇℃伅'}>
+              {getFieldDecorator('errmsg', {
+                initialValue: '',
+                rules: [
+                  {
+                    required: true,
+                    message: this.props.dict['form.required.input'] + '鎻愮ず淇℃伅!'
+                  },
+                  {
+                    pattern: /^[^']*$/ig,
+                    message: '鎻愮ず淇℃伅涓嶅厑璁稿寘鍚玕''
+                  }
+                ]
+              })(<Input placeholder="" autoComplete="off" />)}
+            </Form.Item>
+          </Col>
+          <Col span={7}>
+            <Form.Item label={'鎶ラ敊缂栫爜'}>
+              {getFieldDecorator('errorCode', {
+                initialValue: 'E',
+                rules: [
+                  {
+                    required: true,
+                    message: this.props.dict['form.required.select'] + '鎶ラ敊缂栫爜!'
+                  }
+                ]
+              })(
+                <Select>
+                  <Select.Option value="E"> E </Select.Option>
+                  <Select.Option value="N"> N </Select.Option>
+                  <Select.Option value="F"> F </Select.Option>
+                  <Select.Option value="NM"> NM </Select.Option>
+                </Select>
+              )}
+            </Form.Item>
+          </Col>
+        </Row>
+      </Form>
+    )
+  }
+}
+
+export default Form.create()(UniqueForm)
\ No newline at end of file
diff --git a/src/mob/datasource/verifycard/contrastform/index.scss b/src/mob/datasource/verifycard/contrastform/index.scss
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/mob/datasource/verifycard/contrastform/index.scss
diff --git a/src/mob/datasource/verifycard/customform/index.jsx b/src/mob/datasource/verifycard/customform/index.jsx
new file mode 100644
index 0000000..39b4d2e
--- /dev/null
+++ b/src/mob/datasource/verifycard/customform/index.jsx
@@ -0,0 +1,232 @@
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
+import { Form, Row, Col, Input, Select, Button, notification, Modal } from 'antd'
+import moment from 'moment'
+
+import Utils from '@/utils/utils.js'
+import Api from '@/api'
+import './index.scss'
+
+const { TextArea } = Input
+
+class CustomForm extends Component {
+  static propTpyes = {
+    dict: PropTypes.object,         // 瀛楀吀椤�
+    btn: PropTypes.object,          // 鎸夐挳
+    usefulfields: PropTypes.string, // 鍙敤瀛楁
+    initsql: PropTypes.string,      // 鍙敤瀛楁
+    customChange: PropTypes.func    // 琛ㄥ崟
+  }
+
+  state = {
+    editItem: null,
+    loading: false
+  }
+
+  edit = (record) => {
+    this.setState({
+      editItem: record
+    })
+
+    this.props.form.setFieldsValue({
+      sql: record.sql,
+      result: record.result,
+      errmsg: record.errmsg,
+      errorCode: record.errorCode
+    })
+  }
+
+
+  handleConfirm = () => {
+    // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭�
+    this.props.form.validateFieldsAndScroll((err, values) => {
+      if (!err) {
+        values.uuid = this.state.editItem ? this.state.editItem.uuid : ''
+        values.resultName = values.result === 'false' ? '涓嶅瓨鍦�' : '瀛樺湪'
+
+        let _quot = values.sql.match(/'{1}/g)
+        let _lparen = values.sql.match(/\({1}/g)
+        let _rparen = values.sql.match(/\){1}/g)
+
+        _quot = _quot ? _quot.length : 0
+        _lparen = _lparen ? _lparen.length : 0
+        _rparen = _rparen ? _rparen.length : 0
+
+        if (_quot % 2 !== 0) {
+          notification.warning({
+            top: 92,
+            message: 'sql涓璡'蹇呴』鎴愬鍑虹幇',
+            duration: 5
+          })
+          return
+        } else if (_lparen !== _rparen) {
+          notification.warning({
+            top: 92,
+            message: 'sql涓�()蹇呴』鎴愬鍑虹幇',
+            duration: 5
+          })
+          return
+        } else if (/--/ig.test(values.sql)) {
+          notification.warning({
+            top: 92,
+            message: '鑷畾涔塻ql璇彞涓紝涓嶅彲鍑虹幇瀛楃 -- 锛屾敞閲婅鐢� /*鍐呭*/',
+            duration: 5
+          })
+          return
+        }
+
+        let error = Utils.verifySql(values.sql)
+
+        if (error) {
+          notification.warning({
+            top: 92,
+            message: 'sql涓笉鍙娇鐢�' + error,
+            duration: 5
+          })
+          return
+        }
+
+        let param = {
+          func: 's_debug_sql',
+          LText: this.props.initsql + values.sql
+        }
+
+        // 鏁版嵁鏉冮檺
+        param.LText = param.LText.replace(/@\$|\$@/ig, '')
+
+        param.LText = Utils.formatOptions(param.LText)
+        param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') + '.000'
+        param.secretkey = Utils.encrypt(param.LText, param.timestamp)
+        
+        this.setState({loading: true})
+        Api.getLocalConfig(param).then(res => {
+          if (res.status) {
+            this.setState({
+              loading: false,
+              editItem: null
+            }, () => {
+              this.props.customChange(values)
+            })
+            this.props.form.setFieldsValue({
+              sql: '',
+              errmsg: ''
+            })
+          } else {
+            this.setState({loading: false})
+            
+            Modal.error({
+              title: res.message
+            })
+          }
+        })
+      }
+    })
+  }
+
+  render() {
+    const { usefulfields, btn } = this.props
+    const { getFieldDecorator } = this.props.form
+    const formItemLayout = {
+      labelCol: {
+        xs: { span: 24 },
+        sm: { span: 8 }
+      },
+      wrapperCol: {
+        xs: { span: 24 },
+        sm: { span: 16 }
+      }
+    }
+    return (
+      <Form {...formItemLayout} className="verify-form" id="verifycard2">
+        <Row gutter={24}>
+          {usefulfields ? <Col span={21} className="sqlfield">
+            <Form.Item label={'鍙敤瀛楁'}>
+              {usefulfields}
+            </Form.Item>
+          </Col> : null}
+          <Col span={21} className="sql">
+            <Form.Item label={'sql'}>
+              {getFieldDecorator('sql', {
+                initialValue: '',
+                rules: [
+                  {
+                    required: true,
+                    message: this.props.dict['form.required.input'] + 'sql!'
+                  }
+                ]
+              })(<TextArea rows={15} />)}
+            </Form.Item>
+          </Col>
+          <Col span={3} className="add">
+            <Button onClick={this.handleConfirm} loading={this.state.loading} className="mk-green">
+              淇濆瓨
+            </Button>
+            {btn.sql ? <div style={{marginTop: '31px'}}>
+              琛ㄥ悕:  <div style={{wordBreak: 'break-all'}}>{btn.sql}</div>
+            </div> : null}
+          </Col>
+          <Col span={7}>
+            <Form.Item label={'缁撴灉澶勭悊'}>
+              {getFieldDecorator('result', {
+                initialValue: 'true',
+                rules: [
+                  {
+                    required: true,
+                    message: this.props.dict['form.required.select'] + '缁撴灉澶勭悊!'
+                  }
+                ]
+              })(
+                <Select>
+                  <Select.Option value="true"> 瀛樺湪 </Select.Option>
+                  <Select.Option value="false"> 涓嶅瓨鍦� </Select.Option>
+                </Select>
+              )}
+            </Form.Item>
+          </Col>
+          <Col span={7}>
+            <Form.Item label={'鎻愮ず淇℃伅'}>
+              {getFieldDecorator('errmsg', {
+                initialValue: '',
+                rules: [
+                  {
+                    required: true,
+                    message: this.props.dict['form.required.input'] + '鎻愮ず淇℃伅!'
+                  },
+                  {
+                    pattern: /^[^']*$/ig,
+                    message: '鎻愮ず淇℃伅涓嶅厑璁稿寘鍚玕''
+                  }
+                ]
+              })(<Input placeholder="" autoComplete="off" />)}
+            </Form.Item>
+          </Col>
+          <Col span={7}>
+            <Form.Item label={'鎶ラ敊缂栫爜'}>
+              {getFieldDecorator('errorCode', {
+                initialValue: 'E',
+                rules: [
+                  {
+                    required: true,
+                    message: this.props.dict['form.required.select'] + '鎶ラ敊缂栫爜!'
+                  }
+                ]
+              })(
+                <Select
+                  getPopupContainer={() => document.getElementById('verifycard2')}
+                >
+                  <Select.Option value="E"> E </Select.Option>
+                  <Select.Option value="N"> N </Select.Option>
+                  <Select.Option value="F"> F </Select.Option>
+                  <Select.Option value="NM"> NM </Select.Option>
+                </Select>
+              )}
+            </Form.Item>
+          </Col>
+          
+        </Row>
+      </Form>
+    )
+  }
+}
+
+export default Form.create()(CustomForm)
\ No newline at end of file
diff --git a/src/mob/datasource/verifycard/customform/index.scss b/src/mob/datasource/verifycard/customform/index.scss
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/mob/datasource/verifycard/customform/index.scss
diff --git a/src/mob/datasource/verifycard/customscript/index.jsx b/src/mob/datasource/verifycard/customscript/index.jsx
new file mode 100644
index 0000000..7191459
--- /dev/null
+++ b/src/mob/datasource/verifycard/customscript/index.jsx
@@ -0,0 +1,257 @@
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
+import { Form, Row, Col, Input, Button, notification, Modal, Tooltip, Icon, Radio, Select } from 'antd'
+import moment from 'moment'
+
+import Utils from '@/utils/utils.js'
+import Api from '@/api'
+import './index.scss'
+
+const { TextArea } = Input
+
+class CustomForm extends Component {
+  static propTpyes = {
+    dict: PropTypes.object,         // 瀛楀吀椤�
+    btn: PropTypes.object,          // 鎸夐挳淇℃伅
+    usefulfields: PropTypes.string, // 鍙敤瀛楁
+    initsql: PropTypes.string,      // sql鍓嶇紑
+    systemScripts: PropTypes.array, // 绯荤粺鑴氭湰
+    customScripts: PropTypes.array, // 鑷畾涔夎剼鏈�
+    scriptsChange: PropTypes.func   // 琛ㄥ崟
+  }
+
+  state = {
+    editItem: null,
+    loading: false
+  }
+
+  edit = (record) => {
+    this.setState({
+      editItem: record
+    })
+
+    this.props.form.setFieldsValue({
+      sql: record.sql,
+      position: record.position || 'back'
+    })
+  }
+
+  handleConfirm = () => {
+    // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭�
+    this.props.form.validateFieldsAndScroll((err, values) => {
+      if (!err) {
+        values.uuid = this.state.editItem ? this.state.editItem.uuid : ''
+
+        let _quot = values.sql.match(/'{1}/g)
+        let _lparen = values.sql.match(/\({1}/g)
+        let _rparen = values.sql.match(/\){1}/g)
+
+        _quot = _quot ? _quot.length : 0
+        _lparen = _lparen ? _lparen.length : 0
+        _rparen = _rparen ? _rparen.length : 0
+
+        if (_quot % 2 !== 0) {
+          notification.warning({
+            top: 92,
+            message: 'sql涓璡'蹇呴』鎴愬鍑虹幇',
+            duration: 5
+          })
+          return
+        } else if (_lparen !== _rparen) {
+          notification.warning({
+            top: 92,
+            message: 'sql涓�()蹇呴』鎴愬鍑虹幇',
+            duration: 5
+          })
+          return
+        } else if (/--/ig.test(values.sql)) {
+          notification.warning({
+            top: 92,
+            message: '鑷畾涔塻ql璇彞涓紝涓嶅彲鍑虹幇瀛楃 -- 锛屾敞閲婅鐢� /*鍐呭*/',
+            duration: 5
+          })
+          return
+        }
+
+        let error = Utils.verifySql(values.sql, 'customscript')
+
+        if (error) {
+          notification.warning({
+            top: 92,
+            message: 'sql涓笉鍙娇鐢�' + error,
+            duration: 5
+          })
+          return
+        }
+
+        let tail = `
+          aaa:
+        `
+
+        let _initsql = ''
+        this.props.customScripts.forEach(script => {
+          if (this.state.editItem && this.state.editItem.uuid === script.uuid) return
+          if (script.status === 'false' || script.position !== 'init') return
+
+          _initsql += `
+            ${script.sql}
+            `
+        })
+
+        let param = {
+          func: 's_debug_sql',
+          LText: this.props.initsql + _initsql + values.sql + tail
+        }
+
+        // 鏁版嵁鏉冮檺
+        param.LText = param.LText.replace(/@\$|\$@/ig, '')
+
+        param.LText = Utils.formatOptions(param.LText)
+        param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') + '.000'
+        param.secretkey = Utils.encrypt(param.LText, param.timestamp)
+        
+        this.setState({loading: true})
+        Api.getLocalConfig(param).then(res => {
+          if (res.status) {
+            this.setState({
+              loading: false,
+              editItem: null
+            }, () => {
+              this.props.scriptsChange(values)
+            })
+            this.props.form.setFieldsValue({
+              sql: ''
+            })
+          } else {
+            this.setState({loading: false})
+
+            Modal.error({
+              title: res.message
+            })
+          }
+        })
+      }
+    })
+  }
+
+  handleCancel = () => {
+    this.setState({
+      editItem: null
+    })
+
+    this.props.form.setFieldsValue({
+      sql: ''
+    })
+  }
+
+  selectScript = (value, option) => {
+    let _sql = this.props.form.getFieldValue('sql')
+    if (_sql) {
+      _sql = _sql + ` 
+
+      `
+    }
+
+    _sql = _sql.replace(/\s{6}$/, '')
+    _sql = _sql + `/*${option.props.children}*/
+    `
+    _sql = _sql.replace(/\s{4}$/, '')
+    _sql = _sql + value
+
+    this.props.form.setFieldsValue({
+      sql: _sql
+    })
+  }
+
+  render() {
+    const { usefulfields, systemScripts, btn } = this.props
+    const { getFieldDecorator } = this.props.form
+    const formItemLayout = {
+      labelCol: {
+        xs: { span: 24 },
+        sm: { span: 8 }
+      },
+      wrapperCol: {
+        xs: { span: 24 },
+        sm: { span: 16 }
+      }
+    }
+
+    return (
+      <Form {...formItemLayout} className="verify-form" id="verify-custom-scripts">
+        <Row gutter={24}>
+          {btn.sql ? <Col span={8}>
+            <Form.Item label={'琛ㄥ悕'} style={{whiteSpace: 'nowrap', margin: 0}}>
+              {btn.sql}
+            </Form.Item>
+          </Col> : null}
+          <Col span={16}>
+            <Form.Item label={'鎶ラ敊瀛楁'} style={{margin: 0}}>
+              ErrorCode, retmsg
+            </Form.Item>
+          </Col>
+          {usefulfields ? <Col span={24} className="sqlfield">
+            <Form.Item label={'鍙敤瀛楁'}>
+              {usefulfields}
+            </Form.Item>
+          </Col> : null}
+          <Col span={8} style={{whiteSpace: 'nowrap'}}>
+            <Form.Item style={{marginBottom: 0}} label={
+              <Tooltip placement="bottomLeft" title={'鑷畾涔夎剼鏈笌榛樿sql浣嶇疆鍏崇郴銆�'}>
+                <Icon type="question-circle" style={{color: '#c49f47', marginRight: '5px'}} />
+                鎵ц浣嶇疆
+              </Tooltip>
+            }>
+              {getFieldDecorator('position', {
+                initialValue: 'front'
+              })(
+                <Radio.Group>
+                  <Radio value="init">鍒濆鍖�</Radio>
+                  <Radio value="front">sql鍓�</Radio>
+                  <Radio value="back">sql鍚�</Radio>
+                </Radio.Group>
+              )}
+            </Form.Item>
+          </Col>
+          <Col span={10}>
+            <Form.Item label={'蹇嵎娣诲姞'} style={{marginBottom: 0}}>
+              <Select
+                showSearch
+                filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0}
+                onChange={this.selectScript}
+                getPopupContainer={() => document.getElementById('verify-custom-scripts')}
+              >
+                {systemScripts.map((option, i) =>
+                  <Select.Option key={i} value={option.value}>{option.name}</Select.Option>
+                )}
+              </Select>
+            </Form.Item>
+          </Col>
+          <Col span={6} className="add">
+            <Button onClick={this.handleConfirm} loading={this.state.loading} className="mk-green" style={{marginBottom: 15, marginLeft: 40}}>
+              淇濆瓨
+            </Button>
+            <Button onClick={this.handleCancel} style={{marginBottom: 15, marginLeft: 10}}>
+              鍙栨秷
+            </Button>
+          </Col>
+          <Col span={24} className="sql">
+            <Form.Item label={'sql'}>
+              {getFieldDecorator('sql', {
+                initialValue: '',
+                rules: [
+                  {
+                    required: true,
+                    message: this.props.dict['form.required.input'] + 'sql!'
+                  }
+                ]
+              })(<TextArea rows={15} />)}
+            </Form.Item>
+          </Col>
+        </Row>
+      </Form>
+    )
+  }
+}
+
+export default Form.create()(CustomForm)
\ No newline at end of file
diff --git a/src/mob/datasource/verifycard/customscript/index.scss b/src/mob/datasource/verifycard/customscript/index.scss
new file mode 100644
index 0000000..89791c7
--- /dev/null
+++ b/src/mob/datasource/verifycard/customscript/index.scss
@@ -0,0 +1,5 @@
+#verify-custom-scripts {
+  .ant-select-dropdown-menu-item {
+    white-space: normal;
+  }
+}
\ No newline at end of file
diff --git a/src/mob/datasource/verifycard/index.jsx b/src/mob/datasource/verifycard/index.jsx
new file mode 100644
index 0000000..ddff706
--- /dev/null
+++ b/src/mob/datasource/verifycard/index.jsx
@@ -0,0 +1,1084 @@
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
+// import { fromJS } from 'immutable'
+import { Form, Tabs, Row, Col, Radio, Table, Popconfirm, Icon, notification, Modal, message, Tooltip, Typography } from 'antd'
+import moment from 'moment'
+
+import Api from '@/api'
+import Utils from '@/utils/utils.js'
+
+import UniqueForm from './uniqueform'
+import ContrastForm from './contrastform'
+import CustomForm from './customform'
+import CustomScript from './customscript'
+import BillcodeForm from './billcodeform'
+import VoucherForm from './voucherform'
+import './index.scss'
+
+const { TabPane } = Tabs
+const { confirm } = Modal
+const { Paragraph } = Typography
+
+class VerifyCard extends Component {
+  static propTpyes = {
+    floor: PropTypes.any,      // 鏄惁涓哄瓙琛�
+    btnTab: PropTypes.any,     // 琛ㄥ崟鏍囩椤碉紙鎸夐挳锛夊弬鏁�
+    config: PropTypes.any,     // 琛ㄥ崟鏍囩椤靛弬鏁�
+    dict: PropTypes.object,    // 瀛楀吀椤�
+    card: PropTypes.object,    // 鎸夐挳淇℃伅
+    columns: PropTypes.array
+  }
+
+  state = {
+    initsql: '',          // sql楠岃瘉鏃跺彉閲忓0鏄庡強璧嬪��
+    verify: {},
+    fields: [],
+    usefulfields: '',
+    defaultsql: '',         // 榛樿Sql
+    orderModular: [],
+    orderModularDetail: [],
+    voucher: [],
+    voucherDetail: [],
+    systemScripts: [],
+    columnsFields: [],
+    uniqueColumns: [
+      {
+        title: '瀛楁鍚�',
+        dataIndex: 'field',
+        width: '35%'
+      },
+      {
+        title: '鎶ラ敊缂栫爜',
+        dataIndex: 'errorCode',
+        width: '12%'
+      },
+      {
+        title: '楠岃瘉绫诲瀷',
+        dataIndex: 'verifyType',
+        width: '13%',
+        render: (text, record) => record.verifyType === 'logic' ? '閫昏緫楠岃瘉' : '鐗╃悊楠岃瘉'
+      },
+      {
+        title: '鐘舵��',
+        dataIndex: 'status',
+        width: '15%',
+        render: (text, record) => record.status === 'false' ?
+          (
+            <div>
+              {this.props.dict['header.form.status.forbidden']}
+              <Icon style={{marginLeft: '5px'}} type="stop" theme="twoTone" twoToneColor="#ff4d4f" />
+            </div>
+          ) :
+          (
+            <div>
+              {this.props.dict['header.form.status.open']}
+              <Icon style={{marginLeft: '5px'}} type="check-circle" theme="twoTone" twoToneColor="#52c41a" />
+            </div>
+          )
+      },
+      {
+        title: '鎿嶄綔',
+        align: 'center',
+        width: '25%',
+        dataIndex: 'operation',
+        render: (text, record) =>
+          (<div>
+            <span className="operation-btn" title={this.props.dict['model.edit']} onClick={() => this.handleEdit(record, 'unique')} style={{color: '#1890ff'}}><Icon type="edit" /></span>
+            <span className="operation-btn" title={this.props.dict['header.form.up']} onClick={() => this.handleUpDown(record, 'unique', 'up')} style={{color: '#1890ff'}}><Icon type="arrow-up" /></span>
+            <span className="operation-btn" title={this.props.dict['header.form.down']} onClick={() => this.handleUpDown(record, 'unique', 'down')} style={{color: '#ff4d4f'}}><Icon type="arrow-down" /></span>
+            <span className="operation-btn" title={this.props.dict['header.form.status.change']} onClick={() => this.handleStatus(record, 'unique')} style={{color: '#8E44AD'}}><Icon type="swap" /></span>
+            <Popconfirm
+              title={this.props.dict['header.form.query.delete']}
+              okText={this.props.dict['model.confirm']}
+              cancelText={this.props.dict['header.cancel']}
+              onConfirm={() => this.handleDelete(record, 'unique')
+            }>
+              <span className="operation-btn" style={{color: '#ff4d4f'}}><Icon type="delete" /></span>
+            </Popconfirm>
+          </div>)
+      }
+    ],
+    onceUniqueColumns: [
+      {
+        title: '瀛楁鍚�',
+        dataIndex: 'field',
+        width: '45%'
+      },
+      {
+        title: '鐘舵��',
+        dataIndex: 'status',
+        width: '30%',
+        render: (text, record) => record.status === 'false' ?
+          (
+            <div>
+              {this.props.dict['header.form.status.forbidden']}
+              <Icon style={{marginLeft: '5px'}} type="stop" theme="twoTone" twoToneColor="#ff4d4f" />
+            </div>
+          ) :
+          (
+            <div>
+              {this.props.dict['header.form.status.open']}
+              <Icon style={{marginLeft: '5px'}} type="check-circle" theme="twoTone" twoToneColor="#52c41a" />
+            </div>
+          )
+      },
+      {
+        title: '鎿嶄綔',
+        align: 'center',
+        width: '25%',
+        dataIndex: 'operation',
+        render: (text, record) =>
+          (<div>
+            <span className="operation-btn" title={this.props.dict['model.edit']} onClick={() => this.handleEdit(record, 'unique')} style={{color: '#1890ff'}}><Icon type="edit" /></span>
+            <span className="operation-btn" title={this.props.dict['header.form.up']} onClick={() => this.handleUpDown(record, 'unique', 'up')} style={{color: '#1890ff'}}><Icon type="arrow-up" /></span>
+            <span className="operation-btn" title={this.props.dict['header.form.down']} onClick={() => this.handleUpDown(record, 'unique', 'down')} style={{color: '#ff4d4f'}}><Icon type="arrow-down" /></span>
+            <span className="operation-btn" title={this.props.dict['header.form.status.change']} onClick={() => this.handleStatus(record, 'unique')} style={{color: '#8E44AD'}}><Icon type="swap" /></span>
+            <Popconfirm
+              title={this.props.dict['header.form.query.delete']}
+              okText={this.props.dict['model.confirm']}
+              cancelText={this.props.dict['header.cancel']}
+              onConfirm={() => this.handleDelete(record, 'unique')
+            }>
+              <span className="operation-btn" style={{color: '#ff4d4f'}}><Icon type="delete" /></span>
+            </Popconfirm>
+          </div>)
+      }
+    ],
+    contrastColumns: [
+      {
+        title: '鍐呭1',
+        dataIndex: 'frontfield',
+        width: '13%'
+      },
+      {
+        title: '杩愮畻绗�',
+        dataIndex: 'operator',
+        width: '13%'
+      },
+      {
+        title: '鍐呭2',
+        dataIndex: 'backfield',
+        width: '13%',
+      },
+      {
+        title: '鎻愮ず淇℃伅',
+        dataIndex: 'errmsg',
+        width: '13%'
+      },
+      {
+        title: '鎶ラ敊缂栫爜',
+        dataIndex: 'errorCode',
+        width: '13%'
+      },
+      {
+        title: '鐘舵��',
+        dataIndex: 'status',
+        width: '15%',
+        render: (text, record) => record.status === 'false' ?
+          (
+            <div>
+              {this.props.dict['header.form.status.forbidden']}
+              <Icon style={{marginLeft: '5px'}} type="stop" theme="twoTone" twoToneColor="#ff4d4f" />
+            </div>
+          ) :
+          (
+            <div>
+              {this.props.dict['header.form.status.open']}
+              <Icon style={{marginLeft: '5px'}} type="check-circle" theme="twoTone" twoToneColor="#52c41a" />
+            </div>
+          )
+      },
+      {
+        title: '鎿嶄綔',
+        align: 'center',
+        width: '20%',
+        dataIndex: 'operation',
+        render: (text, record) =>
+          (<div>
+            <span className="operation-btn" title={this.props.dict['model.edit']} onClick={() => this.handleEdit(record, 'contrast')} style={{color: '#1890ff'}}><Icon type="edit" /></span>
+            <span className="operation-btn" title={this.props.dict['header.form.up']} onClick={() => this.handleUpDown(record, 'contrast', 'up')} style={{color: '#1890ff'}}><Icon type="arrow-up" /></span>
+            <span className="operation-btn" title={this.props.dict['header.form.down']} onClick={() => this.handleUpDown(record, 'contrast', 'down')} style={{color: '#ff4d4f'}}><Icon type="arrow-down" /></span>
+            <span className="operation-btn" title={this.props.dict['header.form.status.change']} onClick={() => this.handleStatus(record, 'contrast')} style={{color: '#8E44AD'}}><Icon type="swap" /></span>
+            <Popconfirm
+              title={this.props.dict['header.form.query.delete']}
+              okText={this.props.dict['model.confirm']}
+              cancelText={this.props.dict['header.cancel']}
+              onConfirm={() => this.handleDelete(record, 'contrast')
+            }>
+              <span className="operation-btn" style={{color: '#ff4d4f'}}><Icon type="delete" /></span>
+            </Popconfirm>
+          </div>)
+      }
+    ],
+    customColumns: [
+      {
+        title: 'SQL',
+        dataIndex: 'sql',
+        width: '45%',
+        render: (text) => (
+          <Paragraph copyable ellipsis={{ rows: 5, expandable: true }}>{text}</Paragraph>
+        )
+      },
+      {
+        title: '缁撴灉澶勭悊',
+        dataIndex: 'resultName',
+        width: '9%'
+      },
+      {
+        title: '鎻愮ず淇℃伅',
+        dataIndex: 'errmsg',
+        width: '13%'
+      },
+      {
+        title: '鎶ラ敊缂栫爜',
+        dataIndex: 'errorCode',
+        width: '9%'
+      },
+      {
+        title: '鐘舵��',
+        dataIndex: 'status',
+        width: '9%',
+        render: (text, record) => record.status === 'false' ?
+          (
+            <div>
+              {this.props.dict['header.form.status.forbidden']}
+              <Icon style={{marginLeft: '5px'}} type="stop" theme="twoTone" twoToneColor="#ff4d4f" />
+            </div>
+          ) :
+          (
+            <div>
+              {this.props.dict['header.form.status.open']}
+              <Icon style={{marginLeft: '5px'}} type="check-circle" theme="twoTone" twoToneColor="#52c41a" />
+            </div>
+          )
+      },
+      {
+        title: '鎿嶄綔',
+        align: 'center',
+        width: '15%',
+        dataIndex: 'operation',
+        render: (text, record) =>
+          (<div>
+            <span className="operation-btn" title={this.props.dict['model.edit']} onClick={() => this.handleEdit(record, 'customverify')} style={{color: '#1890ff'}}><Icon type="edit" /></span>
+            <span className="operation-btn" title={this.props.dict['header.form.up']} onClick={() => this.handleUpDown(record, 'customverify', 'up')} style={{color: '#1890ff'}}><Icon type="arrow-up" /></span>
+            <span className="operation-btn" title={this.props.dict['header.form.down']} onClick={() => this.handleUpDown(record, 'customverify', 'down')} style={{color: '#ff4d4f'}}><Icon type="arrow-down" /></span>
+            <span className="operation-btn" title={this.props.dict['header.form.status.change']} onClick={() => this.handleStatus(record, 'customverify')} style={{color: '#8E44AD'}}><Icon type="swap" /></span>
+            <Popconfirm
+              title={this.props.dict['header.form.query.delete']}
+              okText={this.props.dict['model.confirm']}
+              cancelText={this.props.dict['header.cancel']}
+              onConfirm={() => this.handleDelete(record, 'customverify')
+            }>
+              <span className="operation-btn" style={{color: '#ff4d4f'}}><Icon type="delete" /></span>
+            </Popconfirm>
+          </div>)
+      }
+    ],
+    scriptsColumns: [
+      {
+        title: 'SQL',
+        dataIndex: 'sql',
+        width: '60%',
+        render: (text) => (
+          <Paragraph copyable ellipsis={{ rows: 5, expandable: true }}>{text}</Paragraph>
+        )
+      },
+      {
+        title: '鎵ц浣嶇疆',
+        dataIndex: 'position',
+        width: '10%',
+        render: (text, record) => {
+          if (record.position === 'init') {
+            return '鍒濆鍖�'
+          } else if (record.position === 'front') {
+            return 'sql鍓�'
+          } else {
+            return 'sql鍚�'
+          }
+        }
+      },
+      {
+        title: '鐘舵��',
+        dataIndex: 'status',
+        width: '10%',
+        render: (text, record) => record.status === 'false' ?
+          (
+            <div>
+              {this.props.dict['header.form.status.forbidden']}
+              <Icon style={{marginLeft: '5px'}} type="stop" theme="twoTone" twoToneColor="#ff4d4f" />
+            </div>
+          ) :
+          (
+            <div>
+              {this.props.dict['header.form.status.open']}
+              <Icon style={{marginLeft: '5px'}} type="check-circle" theme="twoTone" twoToneColor="#52c41a" />
+            </div>
+          )
+      },
+      {
+        title: '鎿嶄綔',
+        align: 'center',
+        width: '20%',
+        dataIndex: 'operation',
+        render: (text, record) =>
+          (<div>
+            <span className="operation-btn" title={this.props.dict['model.edit']} onClick={() => this.handleEdit(record, 'scripts')} style={{color: '#1890ff'}}><Icon type="edit" /></span>
+            <span className="operation-btn" title={this.props.dict['header.form.up']} onClick={() => this.handleUpDown(record, 'scripts', 'up')} style={{color: '#1890ff'}}><Icon type="arrow-up" /></span>
+            <span className="operation-btn" title={this.props.dict['header.form.down']} onClick={() => this.handleUpDown(record, 'scripts', 'down')} style={{color: '#ff4d4f'}}><Icon type="arrow-down" /></span>
+            <span className="operation-btn" title={this.props.dict['header.form.status.change']} onClick={() => this.handleStatus(record, 'scripts')} style={{color: '#8E44AD'}}><Icon type="swap" /></span>
+            <Popconfirm
+              title={this.props.dict['header.form.query.delete']}
+              okText={this.props.dict['model.confirm']}
+              cancelText={this.props.dict['header.cancel']}
+              onConfirm={() => this.handleDelete(record, 'scripts')
+            }>
+              <span className="operation-btn" style={{color: '#ff4d4f'}}><Icon type="delete" /></span>
+            </Popconfirm>
+          </div>)
+      }
+    ],
+    orderColumns: [
+      {
+        title: this.props.dict['header.form.funcvar'],
+        dataIndex: 'fieldName',
+        width: '12%',
+        render: (text, record) => (`${record.fieldName || ''}(${record.field})`)
+      },
+      {
+        title: '绫诲瀷',
+        dataIndex: 'billType',
+        width: '6%',
+      },
+      {
+        title: '鍑瘉绫诲瀷',
+        dataIndex: 'ModularCodeName',
+        width: '11%'
+      },
+      {
+        title: '鍑瘉鏍囪瘑',
+        dataIndex: 'ModularDetailCode',
+        width: '11%'
+      },
+      {
+        title: '鍏宠仈瀛楁',
+        dataIndex: 'linkFieldName',
+        width: '10%',
+        render: (text, record) => (record.linkField ? `${record.linkFieldName || ''}(${record.linkField})` : '')
+      },
+      {
+        title: '浣嶆暟',
+        dataIndex: 'Type',
+        width: '6%'
+      },
+      {
+        title: '绀轰緥',
+        dataIndex: 'example',
+        width: '13%',
+        render: (text, record) => {
+          let _text = ''
+
+          let _type = record.Type
+          if (_type && typeof(_type) === 'string') {
+            _type = parseInt(_type)
+          } else {
+            _type = 4
+          }
+
+          if (record.TypeCharOne === 'n') {
+            _text = record.ModularDetailCode + Array(_type).join('0') + '1'
+          } else if (record.TypeCharOne === 'Y') {
+            _text = record.ModularDetailCode + moment().format('YYYYMMDD') + Array(_type).join('0') + '1'
+          } else if (record.TypeCharOne === 'Lp') {
+            _text = Array(_type).join('0') + '10'
+          } else if (record.TypeCharOne === 'BN') {
+            _text = moment().format('YYYYMMDD') + Array(_type).join('0') + '1'
+          }
+          return _text
+        }
+      },
+      {
+        title: '鏍囪瘑',
+        dataIndex: 'mark',
+        width: '8%'
+      },
+      {
+        title: '鐘舵��',
+        dataIndex: 'status',
+        width: '8%',
+        render: (text, record) => record.status === 'false' ?
+          (
+            <div>
+              {this.props.dict['header.form.status.forbidden']}
+              <Icon style={{marginLeft: '5px'}} type="stop" theme="twoTone" twoToneColor="#ff4d4f" />
+            </div>
+          ) :
+          (
+            <div>
+              {this.props.dict['header.form.status.open']}
+              <Icon style={{marginLeft: '5px'}} type="check-circle" theme="twoTone" twoToneColor="#52c41a" />
+            </div>
+          )
+      },
+      {
+        title: '鎿嶄綔',
+        align: 'center',
+        width: '15%',
+        dataIndex: 'operation',
+        render: (text, record) =>
+          (<div>
+            <span className="operation-btn" title={this.props.dict['model.edit']} onClick={() => this.handleEdit(record, 'ordercode')} style={{color: '#1890ff'}}><Icon type="edit" /></span>
+            <span className="operation-btn" title={this.props.dict['header.form.up']} onClick={() => this.handleUpDown(record, 'ordercode', 'up')} style={{color: '#1890ff'}}><Icon type="arrow-up" /></span>
+            <span className="operation-btn" title={this.props.dict['header.form.down']} onClick={() => this.handleUpDown(record, 'ordercode', 'down')} style={{color: '#ff4d4f'}}><Icon type="arrow-down" /></span>
+            <span className="operation-btn" title={this.props.dict['header.form.status.change']} onClick={() => this.handleStatus(record, 'ordercode')} style={{color: '#8E44AD'}}><Icon type="swap" /></span>
+            <Popconfirm
+              title={this.props.dict['header.form.query.delete']}
+              okText={this.props.dict['model.confirm']}
+              cancelText={this.props.dict['header.cancel']}
+              onConfirm={() => this.handleDelete(record, 'ordercode')
+            }>
+              <span className="operation-btn" style={{color: '#ff4d4f'}}><Icon type="delete" /></span>
+            </Popconfirm>
+          </div>)
+      }
+    ]
+  }
+
+  UNSAFE_componentWillMount() {
+
+  }
+
+  componentDidMount() {
+    
+  }
+
+  getsysScript = () => {
+    const { defaultsql } = this.state
+
+    let _scriptSql = `Select distinct func+Remark as funcname,longparam, s.Sort from聽 s_custom_script s inner join (select OpenID from sapp where ID=@Appkey@) p on s.openid = case when s.appkey='' then s.openid else p.OpenID end order by s.Sort`
+
+    _scriptSql = Utils.formatOptions(_scriptSql)
+
+    let _sParam = {
+      func: 'sPC_Get_SelectedList',
+      LText: _scriptSql,
+      obj_name: 'data',
+      arr_field: 'funcname,longparam'
+    }
+    
+    _sParam.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') + '.000'
+    _sParam.secretkey = Utils.encrypt(_sParam.LText, _sParam.timestamp)
+
+    _sParam.open_key = Utils.encrypt(_sParam.secretkey, _sParam.timestamp, true) // 浜戠鏁版嵁楠岃瘉
+    
+    Api.getSystemConfig(_sParam).then(res => {
+      if (res.status) {
+        let _scripts = []
+
+        if (defaultsql) {
+          _scripts.push({
+            name: '榛樿sql',
+            value: defaultsql
+          })
+        }
+
+        res.data.forEach(item => {
+          let _item = {
+            name: item.funcname,
+            value: Utils.formatOptions(item.longparam, true)
+          }
+
+          _scripts.push(_item)
+        })
+
+        this.setState({
+          systemScripts: _scripts
+        })
+      } else {
+        notification.warning({
+          top: 92,
+          message: res.message,
+          duration: 5
+        })
+      }
+    })
+  }
+
+  uniqueChange = (values) => {
+    let verify = JSON.parse(JSON.stringify(this.state.verify))
+
+    if (values.uuid) {
+      verify.uniques = verify.uniques.map(item => {
+        if (item.uuid === values.uuid) {
+          return values
+        } else {
+          return item
+        }
+      })
+    } else {
+      values.uuid = Utils.getuuid()
+      verify.uniques.push(values)
+    }
+
+    this.setState({
+      verify: verify
+    })
+  }
+
+  contrastChange = (values) => {
+    let verify = JSON.parse(JSON.stringify(this.state.verify))
+
+    if (values.uuid) {
+      verify.contrasts = verify.contrasts.map(item => {
+        if (item.uuid === values.uuid) {
+          return values
+        } else {
+          return item
+        }
+      })
+    } else {
+      values.uuid = Utils.getuuid()
+      verify.contrasts.push(values)
+    }
+
+    this.setState({
+      verify: verify
+    })
+  }
+
+  customChange = (values) => {
+    let verify = JSON.parse(JSON.stringify(this.state.verify))
+
+    if (values.uuid) {
+      verify.customverifys = verify.customverifys.map(item => {
+        if (item.uuid === values.uuid) {
+          return values
+        } else {
+          return item
+        }
+      })
+    } else {
+      values.uuid = Utils.getuuid()
+      verify.customverifys.push(values)
+    }
+
+    this.setState({
+      verify: verify
+    })
+  }
+
+  scriptsChange = (values) => {
+    let verify = JSON.parse(JSON.stringify(this.state.verify))
+
+    if (values.uuid) {
+      verify.scripts = verify.scripts.map(item => {
+        if (item.uuid === values.uuid) {
+          return values
+        } else {
+          return item
+        }
+      })
+    } else {
+      values.uuid = Utils.getuuid()
+      verify.scripts.push(values)
+    }
+
+    this.setState({
+      verify: verify
+    })
+  }
+
+  orderChange = (values) => {
+    let verify = JSON.parse(JSON.stringify(this.state.verify))
+
+    if (values.uuid) {
+      verify.billcodes = verify.billcodes.map(item => {
+        if (item.uuid === values.uuid) {
+          return values
+        } else {
+          return item
+        }
+      })
+    } else {
+      values.uuid = Utils.getuuid()
+      verify.billcodes.push(values)
+    }
+
+    this.setState({
+      verify: verify
+    })
+  }
+
+  onOptionChange = (e, key) => {
+    const { verify } = this.state
+    let value = e.target.value
+
+    this.setState({
+      verify: {...verify, [key]: value}
+    })
+  }
+
+  handleDelete = (record, type) => {
+    const { verify } = this.state
+
+    if (type === 'customverify') {
+      verify.customverifys = verify.customverifys.filter(item => item.uuid !== record.uuid)
+    } else if (type === 'unique') {
+      verify.uniques = verify.uniques.filter(item => item.uuid !== record.uuid)
+    } else if (type === 'ordercode') {
+      verify.billcodes = verify.billcodes.filter(item => item.uuid !== record.uuid)
+    } else if (type === 'scripts') {
+      verify.scripts = verify.scripts.filter(item => item.uuid !== record.uuid)
+    } else if (type === 'contrast') {
+      verify.contrasts = verify.contrasts.filter(item => item.uuid !== record.uuid)
+    }
+
+    this.setState({ verify: verify })
+  }
+
+  handleEdit = (record, type) => {
+    if (type === 'customverify') {
+      this.customForm.edit(record)
+    } else if (type === 'unique') {
+      this.uniqueForm.edit(record)
+    } else if (type === 'ordercode') {
+      this.orderForm.edit(record)
+    } else if (type === 'scripts') {
+      this.scriptsForm.edit(record)
+    } else if (type === 'contrast') {
+      this.contrastForm.edit(record)
+    }
+
+    let node = document.getElementById('verify-card-box-tab').parentNode
+
+    if (node && node.scrollTop) {
+      let inter = Math.ceil(node.scrollTop / 10)
+
+      let timer = setInterval(() => {
+        if (node.scrollTop - inter > 0) {
+          node.scrollTop = node.scrollTop - inter
+        } else {
+          node.scrollTop = 0
+          clearInterval(timer)
+        }
+      }, 10)
+    }
+  }
+
+  handleStatus = (record, type) => {
+    let verify = JSON.parse(JSON.stringify(this.state.verify))
+    record.status = record.status === 'false' ? 'true' : 'false'
+
+    if (type === 'customverify') {
+      verify.customverifys = verify.customverifys.map(item => {
+        if (item.uuid === record.uuid) {
+          return record
+        } else {
+          return item
+        }
+      })
+    } else if (type === 'unique') {
+      verify.uniques = verify.uniques.map(item => {
+        if (item.uuid === record.uuid) {
+          return record
+        } else {
+          return item
+        }
+      })
+    } else if (type === 'contrast') {
+      verify.contrasts = verify.contrasts.map(item => {
+        if (item.uuid === record.uuid) {
+          return record
+        } else {
+          return item
+        }
+      })
+    } else if (type === 'ordercode') {
+      verify.billcodes = verify.billcodes.map(item => {
+        if (item.uuid === record.uuid) {
+          return record
+        } else {
+          return item
+        }   
+      })
+    } else if (type === 'scripts') {
+      verify.scripts = verify.scripts.map(item => {
+        if (item.uuid === record.uuid) {
+          return record
+        } else {
+          return item
+        }
+      })
+    }
+
+    this.setState({
+      verify: verify
+    })
+  }
+
+  handleUpDown = (record, type, direction) => {
+    let verify = JSON.parse(JSON.stringify(this.state.verify))
+    let index = 0
+
+    if (type === 'customverify') {
+      verify.customverifys = verify.customverifys.filter((item, i) => {
+        if (item.uuid === record.uuid) {
+          index = i
+        }
+
+        return item.uuid !== record.uuid
+      })
+      if ((index === 0 && direction === 'up') || (index === verify.customverifys.length && direction === 'down')) {
+        return
+      }
+
+      if (direction === 'up') {
+        verify.customverifys.splice(index - 1, 0, record)
+      } else {
+        verify.customverifys.splice(index + 1, 0, record)
+      }
+    } else if (type === 'unique') {
+      verify.uniques = verify.uniques.filter((item, i) => {
+        if (item.uuid === record.uuid) {
+          index = i
+        }
+
+        return item.uuid !== record.uuid
+      })
+      if ((index === 0 && direction === 'up') || (index === verify.uniques.length && direction === 'down')) {
+        return
+      }
+
+      if (direction === 'up') {
+        verify.uniques.splice(index - 1, 0, record)
+      } else {
+        verify.uniques.splice(index + 1, 0, record)
+      }
+    } else if (type === 'contrast') {
+      verify.contrasts = verify.contrasts.filter((item, i) => {
+        if (item.uuid === record.uuid) {
+          index = i
+        }
+
+        return item.uuid !== record.uuid
+      })
+      if ((index === 0 && direction === 'up') || (index === verify.contrasts.length && direction === 'down')) {
+        return
+      }
+
+      if (direction === 'up') {
+        verify.contrasts.splice(index - 1, 0, record)
+      } else {
+        verify.contrasts.splice(index + 1, 0, record)
+      }
+    } else if (type === 'ordercode') {
+      verify.billcodes = verify.billcodes.filter((item, i) => {
+        if (item.uuid === record.uuid) {
+          index = i
+        }
+
+        return item.uuid !== record.uuid
+      })
+      if ((index === 0 && direction === 'up') || (index === verify.billcodes.length && direction === 'down')) {
+        return
+      }
+
+      if (direction === 'up') {
+        verify.billcodes.splice(index - 1, 0, record)
+      } else {
+        verify.billcodes.splice(index + 1, 0, record)
+      }
+    } else if (type === 'scripts') {
+      verify.scripts = verify.scripts.filter((item, i) => {
+        if (item.uuid === record.uuid) {
+          index = i
+        }
+
+        return item.uuid !== record.uuid
+      })
+      if ((index === 0 && direction === 'up') || (index === verify.scripts.length && direction === 'down')) {
+        return
+      }
+
+      if (direction === 'up') {
+        verify.scripts.splice(index - 1, 0, record)
+      } else {
+        verify.scripts.splice(index + 1, 0, record)
+      }
+    }
+
+    this.setState({
+      verify: verify
+    })
+  }
+
+  voucherChange = (voucher) => {
+    const { verify } = this.state
+
+    this.setState({
+      verify: {
+        ...verify,
+        voucher: voucher
+      }
+    })
+  }
+
+  showError = (errorType) => {
+    if (errorType === 'S') {
+      notification.success({
+        top: 92,
+        message: '鎵ц鎴愬姛锛�',
+        duration: 2
+      })
+    } else if (errorType === 'Y') {
+      Modal.success({
+        title: '鎵ц鎴愬姛锛�'
+      })
+    } else if (errorType === 'F') {
+      notification.error({
+        className: 'notification-custom-error',
+        top: 92,
+        message: '鎵ц澶辫触锛�',
+        duration: 10
+      })
+    } else if (errorType === 'N') {
+      notification.error({
+        top: 92,
+        message: '鎵ц澶辫触锛�',
+        duration: 10
+      })
+    } else if (errorType === 'E') {
+      Modal.error({
+        title: '鎵ц澶辫触锛�'
+      })
+    } else if (errorType === 'NM') {
+      message.error('鎵ц澶辫触锛�')
+    }
+  }
+
+  timeChange = (val, type) => {
+    const { verify } = this.state
+
+    this.setState({
+      verify: {...verify, [type]: val}
+    })
+  }
+
+  handleConfirm = () => {
+    let verify = JSON.parse(JSON.stringify(this.state.verify))
+    
+    // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭�
+    return new Promise((resolve, reject) => {
+      if (verify.default === 'false' && verify.scripts.length === 0) {
+        notification.warning({
+          top: 92,
+          message: '涓嶆墽琛岄粯璁ql鏃讹紝蹇呴』璁剧疆鑷畾涔夎剼鏈紒',
+          duration: 5
+        })
+        return
+      }
+
+      let _loading = false
+      if (this.customForm && this.customForm.state.editItem) {
+        _loading = true
+      } else if (this.uniqueForm && this.uniqueForm.state.editItem) {
+        _loading = true
+      } else if (this.orderForm && this.orderForm.state.editItem) {
+        _loading = true
+      } else if (this.scriptsForm && this.scriptsForm.state.editItem) {
+        _loading = true
+      } else if (this.contrastForm && this.contrastForm.state.editItem) {
+        _loading = true
+      }
+
+      if (this.scriptsForm && this.scriptsForm.props.form.getFieldValue('sql')) {
+        _loading = true
+      } else if (this.customForm && this.customForm.props.form.getFieldValue('sql')) {
+        _loading = true
+      }
+
+      if (_loading) {
+        confirm({
+          content: `瀛樺湪鏈繚瀛橀」锛岀‘瀹氭彁浜ゅ悧锛焋,
+          okText: this.props.dict['model.confirm'],
+          cancelText: this.props.dict['header.cancel'],
+          onOk() {
+            resolve(verify)
+          },
+          onCancel() {}
+        })
+      } else {
+        resolve(verify)
+      }
+    })
+  }
+
+  /**
+   * @description 缁勪欢閿�姣侊紝娓呴櫎state鏇存柊
+   */
+  componentWillUnmount () {
+    this.setState = () => {
+      return
+    }
+  }
+
+  render() {
+    const { card } = this.props
+    const { verify, fields, uniqueColumns, onceUniqueColumns, columnsFields, contrastColumns, customColumns, orderColumns, scriptsColumns, orderModular, orderModularDetail, voucher, voucherDetail } = this.state
+    const formItemLayout = {
+      labelCol: {
+        xs: { span: 24 },
+        sm: { span: 8 }
+      },
+      wrapperCol: {
+        xs: { span: 24 },
+        sm: { span: 16 }
+      }
+    }
+
+    return (
+      <div id="verify-card-box-tab">
+        <Tabs defaultActiveKey="1" className="verify-card-box">
+          <TabPane tab="鍩虹楠岃瘉" key="1">
+            <Form {...formItemLayout}>
+              <Row gutter={24}>
+                {this.props.card.sqlType !== 'custom' ? <Col span={8}>
+                  <Form.Item label={
+                    <Tooltip placement="bottomLeft" title={'榛樿sql鎵ц椤哄簭涓鸿嚜瀹氫箟鑴氭湰涔嬪墠'}>
+                      <Icon type="question-circle" style={{color: '#c49f47', marginRight: '5px'}} />
+                      榛樿sql
+                    </Tooltip>
+                  }>
+                    <Radio.Group value={verify.default} onChange={(e) => {this.onOptionChange(e, 'default')}}>
+                      <Radio value="true">鎵ц</Radio>
+                      <Radio value="false">涓嶆墽琛�</Radio>
+                    </Radio.Group>
+                  </Form.Item>
+                </Col> : null}
+                <Col span={8}>
+                  <Form.Item label={'璐︽湡楠岃瘉'}>
+                    <Radio.Group value={verify.accountdate} onChange={(e) => {this.onOptionChange(e, 'accountdate')}}>
+                      <Radio value="true">寮�鍚�</Radio>
+                      <Radio value="false">涓嶅紑鍚�</Radio>
+                    </Radio.Group>
+                  </Form.Item>
+                </Col>
+                <Col span={8}>
+                  <Form.Item label={'澶辨晥楠岃瘉'}>
+                    <Radio.Group value={verify.invalid} onChange={(e) => {this.onOptionChange(e, 'invalid')}}>
+                      <Radio value="true">寮�鍚�</Radio>
+                      <Radio value="false">涓嶅紑鍚�</Radio>
+                    </Radio.Group>
+                  </Form.Item>
+                </Col>
+              </Row>
+            </Form>
+          </TabPane>
+          <TabPane tab="姣旇緝楠岃瘉" key="2x">
+            <ContrastForm
+              dict={this.props.dict}
+              contrastChange={this.contrastChange}
+              wrappedComponentRef={(inst) => this.contrastForm = inst}
+            />
+            <Table
+              bordered
+              rowKey="uuid"
+              className="custom-table"
+              dataSource={verify.contrasts}
+              columns={contrastColumns}
+              pagination={false}
+            />
+          </TabPane>
+          <TabPane tab={card.Ot !== 'requiredOnce' ? '鍞竴鎬ч獙璇�' : '鍚岀被鏁版嵁楠岃瘉'} key="2">
+            <UniqueForm
+              btn={card}
+              fields={card.Ot !== 'requiredOnce' ? fields : columnsFields}
+              dict={this.props.dict}
+              uniqueChange={this.uniqueChange}
+              wrappedComponentRef={(inst) => this.uniqueForm = inst}
+            />
+            <Table
+              bordered
+              rowKey="uuid"
+              className="custom-table"
+              dataSource={verify.uniques}
+              columns={card.Ot !== 'requiredOnce' ? uniqueColumns : onceUniqueColumns}
+              pagination={false}
+            />
+          </TabPane>
+          <TabPane tab="鑷畾涔夐獙璇�" key="3">
+            <CustomForm
+              dict={this.props.dict}
+              btn={this.props.card}
+              initsql={this.state.initsql}
+              usefulfields={this.state.usefulfields}
+              customChange={this.customChange}
+              wrappedComponentRef={(inst) => this.customForm = inst}
+            />
+            <Table
+              bordered
+              rowKey="uuid"
+              className="custom-table"
+              dataSource={verify.customverifys}
+              columns={customColumns}
+              pagination={false}
+            />
+          </TabPane>
+          <TabPane tab="鍗曞彿鐢熸垚" key="4">
+            <BillcodeForm
+              fields={fields}
+              btn={this.props.card}
+              billcodes={verify.billcodes}
+              columns={this.props.columns}
+              dict={this.props.dict}
+              modular={orderModular}
+              modularDetail={orderModularDetail}
+              orderChange={this.orderChange}
+              wrappedComponentRef={(inst) => this.orderForm = inst}
+            />
+            <Table
+              bordered
+              rowKey="uuid"
+              className="custom-table"
+              dataSource={verify.billcodes}
+              columns={orderColumns}
+              pagination={false}
+            />
+          </TabPane>
+          <TabPane tab="鍒涘缓鍑瘉" key="5">
+            <VoucherForm
+              dict={this.props.dict}
+              voucher={voucher}
+              columns={this.props.columns}
+              voucherobj={verify.voucher}
+              voucherDetail={voucherDetail}
+              voucherChange={this.voucherChange}
+              wrappedComponentRef={(inst) => this.voucherForm = inst}
+            />
+          </TabPane>
+          <TabPane tab="鑷畾涔夎剼鏈�" key="6">
+            <CustomScript
+              usefulfields={this.state.usefulfields}
+              initsql={this.state.initsql}
+              dict={this.props.dict}
+              btn={this.props.card}
+              customScripts={verify.scripts}
+              systemScripts={this.state.systemScripts}
+              scriptsChange={this.scriptsChange}
+              wrappedComponentRef={(inst) => this.scriptsForm = inst}
+            />
+            <Table
+              bordered
+              rowKey="uuid"
+              className="custom-table"
+              dataSource={verify.scripts}
+              columns={scriptsColumns}
+              pagination={false}
+            />
+          </TabPane>
+        </Tabs>
+      </div>
+    )
+  }
+}
+
+export default Form.create()(VerifyCard)
\ No newline at end of file
diff --git a/src/mob/datasource/verifycard/index.scss b/src/mob/datasource/verifycard/index.scss
new file mode 100644
index 0000000..a915727
--- /dev/null
+++ b/src/mob/datasource/verifycard/index.scss
@@ -0,0 +1,66 @@
+.verify-card-box {
+  .ant-tabs-nav-scroll {
+    text-align: center;
+  }
+  .ant-tabs-content {
+    min-height: 40vh;
+  }
+  table tr td {
+    word-wrap: break-word;
+    word-break: break-word;
+  }
+  .verify-form {
+    .ant-input-number {
+      width: 100%;
+    }
+    .sql {
+      .ant-col-sm-8 {
+        width: 10.5%;
+      }
+      .ant-col-sm-16 {
+        width: 89.5%;
+        padding-top: 4px;
+      }
+    }
+    .sqlfield {
+      .ant-form-item {
+        margin-bottom: 5px;
+      }
+      .ant-form-item-control {
+        line-height: 24px;
+      }
+      .ant-form-item-label {
+        line-height: 25px;
+      }
+      .ant-form-item-children {
+        line-height: 22px;
+      }
+      .ant-col-sm-8 {
+        width: 10.5%;
+      }
+      .ant-col-sm-16 {
+        width: 89.5%;
+      }
+    }
+    .add {
+      padding-top: 4px;
+    }
+    .anticon-question-circle {
+      color: #c49f47;
+      margin-right: 3px;
+    }
+  }
+  .custom-table .ant-empty {
+    margin: 20px 8px!important;
+  }
+  .errorval {
+    display: inline-block;
+    width: 30px;
+  }
+  .operation-btn {
+    display: inline-block;
+    font-size: 16px;
+    padding: 0 5px;
+    cursor: pointer;
+  }
+}
\ No newline at end of file
diff --git a/src/mob/datasource/verifycard/uniqueform/index.jsx b/src/mob/datasource/verifycard/uniqueform/index.jsx
new file mode 100644
index 0000000..5468de8
--- /dev/null
+++ b/src/mob/datasource/verifycard/uniqueform/index.jsx
@@ -0,0 +1,157 @@
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
+import { Form, Row, Col, Select, Button } from 'antd'
+import './index.scss'
+
+
+class UniqueForm extends Component {
+  static propTpyes = {
+    btn: PropTypes.object,       // 瀛楀吀椤�
+    dict: PropTypes.object,       // 瀛楀吀椤�
+    fields: PropTypes.array,      // 琛ㄥ崟瀛楁
+    uniqueChange: PropTypes.func  // 淇敼鍑芥暟
+  }
+
+  state = {
+    editItem: null // 缂栬緫鍏冪礌
+  }
+
+  edit = (record) => {
+    const { btn } = this.props
+
+    this.setState({
+      editItem: record
+    })
+
+    let _value = {
+      field: record.field.split(',')
+    }
+
+    if (btn.Ot !== 'requiredOnce') {
+      _value.errorCode = record.errorCode
+      _value.verifyType = record.verifyType || 'physical'
+    }
+
+    this.props.form.setFieldsValue(_value)
+  }
+
+
+  handleConfirm = () => {
+    const { fields } = this.props
+    // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭�
+    this.props.form.validateFieldsAndScroll((err, values) => {
+      if (!err) {
+        values.uuid = this.state.editItem ? this.state.editItem.uuid : ''
+        values.fieldlabel = values.field.map(field => {
+          let item = fields.filter(cell => cell.field === field)[0]
+          let label = ''
+          if (item) {
+            label = item.label
+          }
+          return label
+        })
+
+        values.fieldlabel = values.fieldlabel.join(',')
+        values.field = values.field.join(',')
+
+        this.setState({
+          editItem: null
+        }, () => {
+          this.props.uniqueChange(values)
+        })
+        this.props.form.setFieldsValue({
+          field: [],
+        })
+      }
+    })
+  }
+
+  render() {
+    const { getFieldDecorator } = this.props.form
+    const { fields, btn } = this.props
+
+    const formItemLayout = {
+      labelCol: {
+        xs: { span: 24 },
+        sm: { span: 8 }
+      },
+      wrapperCol: {
+        xs: { span: 24 },
+        sm: { span: 16 }
+      }
+    }
+
+    return (
+      <Form {...formItemLayout} className="verify-form" id="verifycard1">
+        <Row gutter={24}>
+          <Col span={8}>
+            <Form.Item label={'瀛楁鍚�'}>
+              {getFieldDecorator('field', {
+                initialValue: [],
+                rules: [
+                  {
+                    required: true,
+                    message: this.props.dict['form.required.select'] + '瀛楁鍚�!'
+                  }
+                ]
+              })(
+                <Select
+                  mode="multiple"
+                >
+                  {fields.map(item => (
+                    <Select.Option key={item.uuid} value={item.field}>{item.field}</Select.Option>
+                  ))}
+                </Select>
+              )}
+            </Form.Item>
+          </Col>
+          {btn.Ot !== 'requiredOnce' ? <Col span={6}>
+            <Form.Item label={'鎶ラ敊缂栫爜'}>
+              {getFieldDecorator('errorCode', {
+                initialValue: 'E',
+                rules: [
+                  {
+                    required: true,
+                    message: this.props.dict['form.required.select'] + '鎶ラ敊缂栫爜!'
+                  }
+                ]
+              })(
+                <Select>
+                  <Select.Option value="E"> E </Select.Option>
+                  <Select.Option value="N"> N </Select.Option>
+                  <Select.Option value="F"> F </Select.Option>
+                  <Select.Option value="NM"> NM </Select.Option>
+                </Select>
+              )}
+            </Form.Item>
+          </Col> : null}
+          {btn.Ot !== 'requiredOnce' ? <Col span={6}>
+            <Form.Item label={'楠岃瘉绫诲瀷'}>
+              {getFieldDecorator('verifyType', {
+                initialValue: 'physical',
+                rules: [
+                  {
+                    required: true,
+                    message: this.props.dict['form.required.select'] + '楠岃瘉绫诲瀷!'
+                  }
+                ]
+              })(
+                <Select>
+                  <Select.Option value="physical"> 鐗╃悊楠岃瘉 </Select.Option>
+                  <Select.Option value="logic"> 閫昏緫楠岃瘉 </Select.Option>
+                </Select>
+              )}
+            </Form.Item>
+          </Col> : null}
+          <Col span={4} className="add">
+            <Button onClick={this.handleConfirm} className="mk-green">
+              淇濆瓨
+            </Button>
+          </Col>
+        </Row>
+      </Form>
+    )
+  }
+}
+
+export default Form.create()(UniqueForm)
\ No newline at end of file
diff --git a/src/mob/datasource/verifycard/uniqueform/index.scss b/src/mob/datasource/verifycard/uniqueform/index.scss
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/mob/datasource/verifycard/uniqueform/index.scss
diff --git a/src/mob/datasource/verifycard/voucherform/index.jsx b/src/mob/datasource/verifycard/voucherform/index.jsx
new file mode 100644
index 0000000..6341055
--- /dev/null
+++ b/src/mob/datasource/verifycard/voucherform/index.jsx
@@ -0,0 +1,269 @@
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
+import { is, fromJS } from 'immutable'
+import { Form, Row, Col, Select, Switch, notification } from 'antd'
+import './index.scss'
+
+class UniqueForm extends Component {
+  static propTpyes = {
+    dict: PropTypes.object,         // 瀛楀吀椤�
+    voucherobj: PropTypes.object,   // 鍑瘉淇℃伅
+    voucher: PropTypes.array,       // 琛ㄥ崟
+    columns: PropTypes.array,       // 琛ㄥ崟
+    voucherDetail: PropTypes.array, // 琛ㄥ崟
+    voucherChange: PropTypes.func   // 琛ㄥ崟
+  }
+
+  state = {
+    voucher: [],
+    voucherDetail: [],
+    columns: []
+  }
+
+  UNSAFE_componentWillMount() {
+    let _voucher = []
+    let _voucherDetail = []
+    if (this.props.voucherobj.BVoucherType && this.props.voucher.length > 0) {
+      _voucher = this.props.voucher.filter(item => item.TypeCharOne === this.props.voucherobj.BVoucherType)
+      _voucherDetail = this.props.voucherDetail.filter(item => item.BID === this.props.voucherobj.VoucherType)
+    } else if (this.props.voucher.length > 0) {
+      _voucher = this.props.voucher.filter(item => item.TypeCharOne === 'MES')
+      _voucherDetail = this.props.voucherDetail.filter(item => _voucher[0] && item.BID === _voucher[0].ID)
+    }
+
+    this.setState({
+      voucher: _voucher,
+      voucherDetail: _voucherDetail,
+      columns: this.props.columns.filter(col => col.type === 'text')
+    })
+  }
+
+  UNSAFE_componentWillReceiveProps (nextProps) {
+    if (!is(fromJS(this.props.voucher), fromJS(nextProps.voucher)) && nextProps.voucher.length > 0) {
+      if (this.props.voucherobj.BVoucherType) {
+        let _voucher = nextProps.voucher.filter(item => item.TypeCharOne === this.props.voucherobj.BVoucherType)
+        let _voucherDetail = nextProps.voucherDetail.filter(item => item.BID === this.props.voucherobj.VoucherType)
+        
+        this.setState({
+          voucher: _voucher,
+          voucherDetail: _voucherDetail
+        })
+      } else {
+        let _voucher = nextProps.voucher.filter(item => item.TypeCharOne === 'MES')
+        let _voucherDetail = nextProps.voucherDetail.filter(item => _voucher[0] && item.BID === _voucher[0].ID)
+
+        this.setState({
+          voucher: _voucher,
+          voucherDetail: _voucherDetail
+        })
+        this.props.form.setFieldsValue({
+          VoucherType: _voucher[0] ? _voucher[0].ID : '',
+          VoucherTypeOne: _voucherDetail[0] ? _voucherDetail[0].ModularDetailCode : ''
+        })
+      }
+    }
+  }
+
+  voucherTypeChange = (value) => {
+    const { voucherobj } = this.props
+
+    let _voucher = this.props.voucher.filter(item => item.TypeCharOne === value)
+    let _voucherDetail = this.props.voucherDetail.filter(item => _voucher[0] && item.BID === _voucher[0].ID)
+
+    this.setState({
+      voucher: _voucher,
+      voucherDetail: _voucherDetail
+    })
+    this.props.form.setFieldsValue({
+      VoucherType: _voucher[0] ? _voucher[0].ID : '',
+      VoucherTypeOne: _voucherDetail[0] ? _voucherDetail[0].ModularDetailCode : ''
+    })
+
+    if (voucherobj.enabled) {
+      this.props.voucherChange({...voucherobj, enabled: false})
+    }
+  }
+
+  voucherSChange = (value) => {
+    const { voucherobj } = this.props
+    let _detail = this.props.voucherDetail.filter(item => item.BID === value)
+
+    this.setState({
+      voucherDetail: _detail
+    })
+    this.props.form.setFieldsValue({
+      VoucherTypeOne: _detail[0] ? _detail[0].ModularDetailCode : ''
+    })
+
+    if (voucherobj.enabled) {
+      this.props.voucherChange({...voucherobj, enabled: false})
+    }
+  }
+
+  contentChange = () => {
+    const { voucherobj } = this.props
+
+    if (voucherobj.enabled) {
+      this.props.voucherChange({...voucherobj, enabled: false})
+    }
+  }
+
+  onEnabledChange = () => {
+    const { voucherobj } = this.props
+
+    if (voucherobj.enabled) {
+      this.props.voucherChange({...voucherobj, enabled: false})
+    } else {
+      this.handleConfirm()
+    }
+  }
+
+
+  handleConfirm = () => {
+    // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭�
+    this.props.form.validateFieldsAndScroll((err, values) => {
+      if (!err) {
+        values.enabled = true
+        let _detail = this.state.voucherDetail.filter(item => item.ModularDetailCode === values.VoucherTypeOne)[0]
+
+        if (!_detail) {
+          notification.warning({
+            top: 92,
+            message: '鍑瘉绫诲瀷鎴栧嚟璇佹爣璇嗕笉瀛樺湪锛�',
+            duration: 5
+          })
+          return
+        }
+        values.VoucherTypeTwo = _detail.VoucherTypeTwo
+        values.Type = _detail.IDefine1
+
+        this.props.voucherChange(values)
+      }
+    })
+  }
+
+  render() {
+    const { getFieldDecorator } = this.props.form
+    const { voucherobj } = this.props
+    const { columns } = this.state
+    const formItemLayout = {
+      labelCol: {
+        xs: { span: 24 },
+        sm: { span: 10 }
+      },
+      wrapperCol: {
+        xs: { span: 24 },
+        sm: { span: 14 }
+      }
+    }
+
+    return (
+      <Form {...formItemLayout} className="verify-form">
+        <Row gutter={24}>
+          <Col span={11}>
+            <Form.Item label={'涓荤被鍨�'}>
+              {getFieldDecorator('BVoucherType', {
+                initialValue: voucherobj.BVoucherType || 'MES',
+                rules: [
+                  {
+                    required: true,
+                    message: this.props.dict['form.required.select'] + '涓荤被鍨�!'
+                  }
+                ]
+              })(
+                <Select onChange={(value) => {this.voucherTypeChange(value)}}>
+                  <Select.Option value="MES"> 涓氬姟绫诲嚟璇� </Select.Option>
+                  <Select.Option value="FCC"> 璐㈠姟绫诲嚟璇� </Select.Option>
+                  <Select.Option value="WMS"> 鐗╂祦绫诲嚟璇� </Select.Option>
+                  <Select.Option value="Z"> 鑷畾涔� </Select.Option>
+                </Select>
+              )}
+            </Form.Item>
+          </Col>
+          <Col span={11}>
+            <Form.Item label={'鍑瘉绫诲瀷'}>
+              {getFieldDecorator('VoucherType', {
+                initialValue: voucherobj.VoucherType || (this.state.voucher[0] && this.state.voucher[0].ID) || '',
+                rules: [
+                  {
+                    required: true,
+                    message: this.props.dict['form.required.input'] + '鍑瘉绫诲瀷!'
+                  }
+                ]
+              })(
+                <Select
+                  showSearch
+                  filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0}
+                  onChange={(value) => {this.voucherSChange(value)}}
+                >
+                  {this.state.voucher.map(option =>
+                    <Select.Option title={option.NameNO} id={option.ID} key={option.ID} value={option.ID}>
+                      {option.NameNO}
+                    </Select.Option>
+                  )}
+                </Select>
+              )}
+            </Form.Item>
+          </Col>
+          <Col span={11}>
+            <Form.Item label={'鍑瘉鏍囪瘑'}>
+              {getFieldDecorator('VoucherTypeOne', {
+                initialValue: voucherobj.VoucherTypeOne || (this.state.voucherDetail[0] && this.state.voucherDetail[0].ModularDetailCode) || '',
+                rules: [
+                  {
+                    required: true,
+                    message: this.props.dict['form.required.input'] + '鍑瘉鏍囪瘑!'
+                  }
+                ]
+              })(
+                <Select
+                  showSearch
+                  filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0}
+                  onChange={this.contentChange}
+                >
+                  {this.state.voucherDetail.map(option =>
+                    <Select.Option title={option.CodeName} id={option.ModularDetailCode} key={option.ModularDetailCode} value={option.ModularDetailCode}>
+                      {option.CodeName}
+                    </Select.Option>
+                  )}
+                </Select>
+              )}
+            </Form.Item>
+          </Col>
+          <Col span={11}>
+            <Form.Item label={'鍏宠仈瀛楁'}>
+              {getFieldDecorator('linkField', {
+                initialValue: voucherobj.linkField || (columns[0] && columns[0].field) || '',
+                rules: [
+                  {
+                    required: true,
+                    message: this.props.dict['form.required.input'] + '鍏宠仈瀛楁!'
+                  }
+                ]
+              })(
+                <Select
+                  showSearch
+                  filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0}
+                  onChange={this.contentChange}
+                >
+                  {columns.map((option, index) =>
+                    <Select.Option title={option.label} id={index + option.uuid} key={index + option.uuid} value={option.field}>
+                      {option.label}
+                    </Select.Option>
+                  )}
+                </Select>
+              )}
+            </Form.Item>
+          </Col>
+          <Col span={11}>
+            <Form.Item label={'鏄惁鍚敤'}>
+              <Switch checkedChildren="鍚�" unCheckedChildren="鍋�" checked={voucherobj.enabled} onChange={this.onEnabledChange} />
+            </Form.Item>
+          </Col>
+        </Row>
+      </Form>
+    )
+  }
+}
+
+export default Form.create()(UniqueForm)
\ No newline at end of file
diff --git a/src/mob/datasource/verifycard/voucherform/index.scss b/src/mob/datasource/verifycard/voucherform/index.scss
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/mob/datasource/verifycard/voucherform/index.scss
diff --git a/src/mob/dragsource/index.jsx b/src/mob/dragsource/index.jsx
new file mode 100644
index 0000000..ab22158
--- /dev/null
+++ b/src/mob/dragsource/index.jsx
@@ -0,0 +1,13 @@
+import React from 'react'
+import { useDrag } from 'react-dnd'
+import './index.scss'
+
+const SourceElement = ({content}) => {
+  const [, drag] = useDrag({ item: content })
+  return (
+    <div ref={drag} className="common-source-item">
+      {content.label}
+    </div>
+  )
+}
+export default SourceElement
\ No newline at end of file
diff --git a/src/mob/dragsource/index.scss b/src/mob/dragsource/index.scss
new file mode 100644
index 0000000..a2e19e6
--- /dev/null
+++ b/src/mob/dragsource/index.scss
@@ -0,0 +1,9 @@
+.common-source-item {
+  display: block;
+  box-shadow: 0px 0px 2px #bcbcbc;
+  padding: 0.4rem 0.7rem;
+  background-color: white;
+  margin: 0px 0px 10px;
+  cursor: move;
+  border-radius: 4px;
+}
\ No newline at end of file
diff --git a/src/mob/header/index.jsx b/src/mob/header/index.jsx
index 0777948..1b7c9eb 100644
--- a/src/mob/header/index.jsx
+++ b/src/mob/header/index.jsx
@@ -3,7 +3,7 @@
 import { is, fromJS } from 'immutable'
 import { connect } from 'react-redux'
 import { withRouter } from 'react-router-dom'
-import {Dropdown, Menu, Icon, Modal } from 'antd'
+import {Dropdown, Menu, Icon, Modal, Tooltip, Button } from 'antd'
 
 import { logout } from '@/store/action'
 import zhCN from '@/locales/zh-CN/mob.js'
@@ -16,6 +16,9 @@
 class MobHeader extends Component {
   static propTpyes = {
     view: PropTypes.string,
+    saveIng: PropTypes.any,
+    triggerSave: PropTypes.func,
+    jumpToManage: PropTypes.func
   }
 
   state = {
@@ -54,9 +57,27 @@
         <div className="header-logo"><img src={this.state.logourl} alt=""/></div>
         {view === 'manage' ?
           <div className="mob-manage-title">
-            绉诲姩绔鐞�
+            搴旂敤绠$悊
           </div> :null
         }
+        {view === 'design' ?
+          <Menu
+            mode="inline"
+            theme="dark"
+            inlineCollapsed={this.state.collapsed}
+          >
+            <Menu.Item key="1">
+              <Tooltip placement="bottom" title="杩斿洖搴旂敤绠$悊">
+                <Icon type="arrow-left" onClick={this.props.jumpToManage} />
+              </Tooltip>
+            </Menu.Item>
+            <Menu.Item key="2">
+              <Tooltip placement="bottom" title="淇濆瓨">
+                <Button icon="save" loading={this.props.saveIng} onClick={this.props.triggerSave}></Button>
+              </Tooltip>
+            </Menu.Item>
+          </Menu> : null
+        }
         <Dropdown className="header-setting" overlay={
           <Menu>
             <Menu.Item key="2" onClick={this.logout}>{this.state.dict['mob.header.logout']}</Menu.Item>
diff --git a/src/mob/header/index.scss b/src/mob/header/index.scss
index b25948b..f6a1e0e 100644
--- a/src/mob/header/index.scss
+++ b/src/mob/header/index.scss
@@ -50,4 +50,41 @@
     line-height: 48px;
     letter-spacing: 2px;
   }
+  >.ant-menu {
+    float: left;
+    width: unset;
+    .ant-menu-item {
+      margin-bottom: 0;
+      float: left;
+      width: unset;
+      cursor: default;
+      .anticon-arrow-left {
+        height: 24px;
+        cursor: pointer;
+      }
+      .ant-btn {
+        color: #fff;
+        width: unset;
+        cursor: pointer;
+        height: 37px;
+        background: transparent;
+        border: 0;
+        .anticon-save {
+          margin-right: 0;
+        }
+      }
+      .ant-btn[ant-click-animating-without-extra-node="true"]::after {
+        display: none!important;
+      }
+      .ant-btn::before {
+        display: none!important;
+      }
+    }
+    .ant-menu-item.ant-menu-item-selected {
+      background-color: transparent;
+    }
+    .ant-menu-item:not(:last-child) {
+      border-right: 1px solid #353535;
+    }
+  }
 }
\ No newline at end of file
diff --git a/src/mob/mobcard/index.jsx b/src/mob/mobcard/index.jsx
index 3cbb63d..2186629 100644
--- a/src/mob/mobcard/index.jsx
+++ b/src/mob/mobcard/index.jsx
@@ -1,15 +1,30 @@
 import React, {Component} from 'react'
 import { is, fromJS } from 'immutable'
-import { Button, Card, Spin, Icon, Row, Col } from 'antd'
+import PropTypes from 'prop-types'
+import { Card, Spin, Icon, Row, Col, Modal, notification } from 'antd'
 
 import Api from '@/api'
-// import Utils from '@/utils/utils.js'
+import Utils from '@/utils/utils.js'
+import zhCN from '@/locales/zh-CN/mob.js'
+import enUS from '@/locales/en-US/mob.js'
+import asyncComponent from '@/utils/asyncSpinComponent'
 import './index.scss'
 
+const { confirm } = Modal
+const MutilForm = asyncComponent(() => import('./mutilform'))
+
 class CardChart extends Component {
+  static propTpyes = {
+    jumpMenu: PropTypes.func  // 椤甸潰璺宠浆
+  }
+
   state = {
-    loading: false,
-    data: []
+    dict: localStorage.getItem('lang') !== 'en-US' ? zhCN : enUS,
+    loading: true,
+    visible: false,
+    confirmloading: false,
+    data: [],
+    card: null
   }
 
   shouldComponentUpdate (nextProps, nextState) {
@@ -24,18 +39,131 @@
     let param = {
       func: 's_get_kei'
     }
+
+    Api.getCloudConfig(param).then(result => {
+      if (result.status) {
+        this.setState({
+          loading: false,
+          data: result.data.map(item => {
+            return {
+              uuid: item.ID,
+              keiNo: item.kei_no,
+              name: item.remark,
+              type: item.typename
+            }
+          })
+        })
+
+      } else {
+        this.setState({
+          loading: false
+        })
+        notification.warning({
+          top: 92,
+          message: result.message,
+          duration: 5
+        })
+      }
+    })
+  }
+
+  editCard = (card) => {
+    this.setState({
+      card: card || null,
+      visible: true
+    })
+  }
+
+  deleteCard = (card) => {
+    let _this = this
+
+    confirm({
+      title: '纭畾鍒犻櫎銆�' + card.name + '銆嬪悧锛�',
+      content: '',
+      okText: this.state.dict['mob.confirm'],
+      cancelText: this.state.dict['mob.cancel'],
+      onOk() {
+        return new Promise(resolve => {
+          let param = {
+            func: 's_kei_del',
+            ID: card.uuid,
+            kei_no: card.keiNo
+          }
     
-    // _param.LText = Utils.formatOptions(_param.LText)                   // 鍏抽敭瀛楃鏇挎崲锛宐ase64鍔犲瘑
-    // _param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') + '.000' // 鏃堕棿鎴�
-    // _param.secretkey = Utils.encrypt(_param.LText, _param.timestamp)   // md5瀵嗛挜
+          Api.getCloudConfig(param).then(result => {
+            if (result.status) {
+              notification.success({
+                top: 92,
+                message: '鍒犻櫎鎴愬姛锛�',
+                duration: 5
+              })
 
-    Api.getCloudConfig(param).then(res => {
+              _this.getMobCards()
+            } else {
+              notification.warning({
+                top: 92,
+                message: result.message,
+                duration: 5
+              })
+            }
+            resolve()
+          })
+        })
+      },
+      onCancel() {}
+    })
+  }
 
+  submitCard = () => {
+    const { card } = this.state
+
+    this.mobcardRef.handleConfirm().then(res => {
+      this.setState({
+        confirmloading: true
+      })
+
+      let param = {
+        func: 's_kei_addupt',
+        ID: card ? card.uuid : Utils.getuuid(),
+        TypeName: res.type,
+        remark: res.name,
+        kei_no: res.type
+      }
+
+      Api.getCloudConfig(param).then(result => {
+        if (result.status) {
+          notification.success({
+            top: 92,
+            message: card ? '淇敼鎴愬姛锛�' : '娣诲姞鎴愬姛锛�',
+            duration: 5
+          })
+
+          this.setState({
+            confirmloading: false,
+            visible: false,
+            loading: true
+          })
+          this.getMobCards()
+        } else {
+          this.setState({
+            confirmloading: false
+          })
+          notification.warning({
+            top: 92,
+            message: result.message,
+            duration: 5
+          })
+        }
+      }, () => {
+        this.setState({
+          confirmloading: false
+        })
+      })
     })
   }
 
   render() {
-    const { data, loading } = this.state
+    const { data, loading, card, dict } = this.state
 
     return (
       <div className="mob-card-row-box">
@@ -47,17 +175,22 @@
         }
         <Row gutter={24}>
           {data && data.length > 0 &&
-            data.map((item, i) => (
-              <Col key={i} span={6}>
+            data.map(item => (
+              <Col key={item.uuid} span={6}>
                 <Card
                   size="small"
                   className="chart-card"
                   actions={[
-                    <Button />,
+                    <Icon title="edit" onClick={() => this.editCard(item)} type="edit" />,
+                    <Icon title="delete" onClick={() => this.deleteCard(item)} type="close" />,
+                    <Icon title="detail" onClick={() => this.props.jumpMenu(item)} type="arrow-right" />
                   ]}
                 >
-                  <div className="ant-card-meta-detail">
-                    
+                  <div className="mk-mob-card-title">
+                    {item.name}
+                  </div>
+                  <div className="mk-mob-card-type">
+                    {item.type === 'mob' ? '绉诲姩绔�' : 'PC绔�'}
                   </div>
                 </Card>
               </Col>
@@ -65,11 +198,26 @@
           }
           
           <Col span={6} key="insert">
-            <div className="chart-card insert" onClick={() => {}}>
+            <div className="chart-card insert" onClick={() => this.editCard()}>
               <Icon type="plus" />
             </div>
           </Col>
         </Row>
+        <Modal
+          className="mob-card-modal"
+          title={card ? '缂栬緫搴旂敤' : '鏂板缓搴旂敤'}
+          width={'600px'}
+          maskClosable={false}
+          visible={this.state.visible}
+          okText={this.state.dict['mob.confirm']}
+          cancelText={this.state.dict['mob.cancel']}
+          onCancel={() => this.setState({visible: false})}
+          confirmLoading={this.state.confirmloading}
+          onOk={this.submitCard}
+          destroyOnClose
+        >
+          <MutilForm card={card} dict={dict} wrappedComponentRef={(inst) => this.mobcardRef = inst} inputSubmit={this.submitCard} />
+        </Modal>
       </div>
     )
   }
diff --git a/src/mob/mobcard/index.scss b/src/mob/mobcard/index.scss
index 09ccb9e..54c55cc 100644
--- a/src/mob/mobcard/index.scss
+++ b/src/mob/mobcard/index.scss
@@ -1,9 +1,33 @@
 .mob-card-row-box {
   padding: 40px 20px;
+  position: relative;
 
   .chart-card {
     height: 250px;
     border: 1px solid #e8e8e8;
+    .ant-card-body {
+      height: 201px;
+      .mk-mob-card-title {
+        margin-top: 40px;
+        font-size: 24px;
+        font-weight: 600;
+        text-align: center;
+      }
+      .mk-mob-card-type {
+        font-size: 14px;
+        color: rgba(0, 0 , 0, 0.55);
+        text-align: center;
+      }
+    }
+
+    .ant-card-actions > li > span {
+      > .anticon-close:hover {
+        color: #ff4d4f;
+      }
+      > .anticon-arrow-right:hover {
+        color: rgb(38, 194, 129);
+      }
+    }
   }
 
   .chart-card.insert {
diff --git a/src/mob/mobcard/mutilform/index.jsx b/src/mob/mobcard/mutilform/index.jsx
new file mode 100644
index 0000000..bbc2592
--- /dev/null
+++ b/src/mob/mobcard/mutilform/index.jsx
@@ -0,0 +1,90 @@
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
+import { Form, Row, Col, Input, Select } from 'antd'
+import './index.scss'
+
+class MainSearch extends Component {
+  static propTpyes = {
+    dict: PropTypes.object,      // 瀛楀吀椤�
+    card: PropTypes.any,         // 缂栬緫搴旂敤
+    inputSubmit: PropTypes.func  // input鍥炶溅鎻愪氦
+  }
+
+  state = {}
+
+  /**
+   * @description 鑾峰彇琛ㄥ崟鍊�
+   */
+  handleConfirm = () => {
+    return new Promise(resolve => {
+      this.props.form.validateFieldsAndScroll((err, values) => {
+        if (!err) {
+          resolve(values)
+        }
+      })
+    })
+  }
+
+  /**
+   * @description 鍥炶溅鎻愪氦
+   */
+  handleSubmit = (e) => {
+    e.preventDefault()
+    this.props.inputSubmit()
+  }
+
+  render() {
+    const { card } = this.props
+    const { getFieldDecorator } = this.props.form
+    const formItemLayout = {
+      labelCol: {
+        xs: { span: 24 },
+        sm: { span: 8 }
+      },
+      wrapperCol: {
+        xs: { span: 24 },
+        sm: { span: 16 }
+      }
+    }
+    return (
+      <Form {...formItemLayout} className="mob-card-edit-form">
+        <Row gutter={24}>
+          <Col span={24}>
+            <Form.Item label="搴旂敤鍚�">
+              {getFieldDecorator('name', {
+                initialValue: card ? card.name : '',
+                rules: [{
+                  required: true,
+                  message: this.props.dict['mob.required.input'] + '搴旂敤鍚�!'
+                }, {
+                  max: 20,
+                  message: '搴旂敤鍚嶄笉鍙秴杩�20涓瓧绗�!'
+                }]
+              })(<Input placeholder="" autoComplete="off" onPressEnter={this.handleSubmit} />)}
+            </Form.Item>
+          </Col>
+          <Col span={24}>
+            <Form.Item label="搴旂敤绫诲瀷">
+              {getFieldDecorator('type', {
+                initialValue: card ? card.type : 'mob',
+                rules: [
+                  {
+                    required: true,
+                    message: this.props.dict['mob.required.select'] + '搴旂敤绫诲瀷!'
+                  }
+                ]
+              })(
+                <Select>
+                  <Select.Option value="mob">绉诲姩绔�</Select.Option>
+                  <Select.Option value="pc">PC绔�</Select.Option>
+                </Select>
+              )}
+            </Form.Item>
+          </Col>
+        </Row>
+      </Form>
+    )
+  }
+}
+
+export default Form.create()(MainSearch)
\ No newline at end of file
diff --git a/src/mob/mobcard/mutilform/index.scss b/src/mob/mobcard/mutilform/index.scss
new file mode 100644
index 0000000..28344fe
--- /dev/null
+++ b/src/mob/mobcard/mutilform/index.scss
@@ -0,0 +1,4 @@
+.mob-card-edit-form {
+  padding: 0px 24px 20px;
+
+}
\ No newline at end of file
diff --git a/src/mob/mobshell/card.jsx b/src/mob/mobshell/card.jsx
new file mode 100644
index 0000000..10c2fff
--- /dev/null
+++ b/src/mob/mobshell/card.jsx
@@ -0,0 +1,57 @@
+import React from 'react'
+import { useDrag, useDrop } from 'react-dnd'
+// import { Icon } from 'antd'
+
+import asyncComponent from '@/utils/asyncComponent'
+
+import './index.scss'
+
+// const Home = asyncComponent(() => import('@/mob/home'))
+const Login = asyncComponent(() => import('@/mob/login'))
+
+const Card = ({ id, card, moveCard, findCard, editCard, delCard, hasDrop, doubleClickCard }) => {
+  const originalIndex = null
+  // const originalIndex = findCard(id).index
+  const [{ isDragging }, drag] = useDrag({
+    item: { type: 'action', id, originalIndex },
+    collect: monitor => ({
+      isDragging: monitor.isDragging(),
+    }),
+  })
+  const [, drop] = useDrop({
+    accept: 'action',
+    canDrop: () => true,
+    drop: (item) => {
+      if (!item.hasOwnProperty('originalIndex')) {
+        hasDrop(card)
+      }
+    },
+    hover({ id: draggedId }) {
+      if (!draggedId) return
+      if (draggedId !== id) {
+        const { index: overIndex } = findCard(id)
+        moveCard(draggedId, overIndex)
+      }
+    },
+  })
+  const opacity = isDragging ? 0.3 : 1
+
+  return (
+    <div ref={node => drag(drop(node))} style={{ opacity: opacity, height: '100%'}}>
+      <Login />
+      {/* <div className="page-card">
+        <Button
+          className={'mk-btn mk-' + card.class}
+          icon={card.icon}
+          key={card.uuid}
+          onDoubleClick={() => doubleClickCard(id)}
+        >
+          {card.label}{card.position === 'grid' && <Icon type="table" />}
+        </Button>
+      </div> */}
+      {/* <Icon className="edit" title="edit" type="edit" onClick={() => editCard(id)} />
+      <Icon className="edit close" title="close" type="close" onClick={() => delCard(id)} /> */}
+    </div>
+  )
+}
+export default Card
diff --git a/src/mob/mobshell/index.jsx b/src/mob/mobshell/index.jsx
new file mode 100644
index 0000000..1d64cca
--- /dev/null
+++ b/src/mob/mobshell/index.jsx
@@ -0,0 +1,103 @@
+import React from 'react'
+// import React, { useState } from 'react'
+import { useDrop } from 'react-dnd'
+// import { is, fromJS } from 'immutable'
+// import update from 'immutability-helper'
+// import Utils from '@/utils/utils.js'
+import Card from './card'
+import './index.scss'
+
+const Container = ({list, placeholder, handleList, handleMenu, deleteMenu, doubleClickCard }) => {
+  // let target = null
+
+  // const [cards, setCards] = useState(list)
+  // const moveCard = (id, atIndex) => {
+  //   const { card, index } = findCard(id)
+  //   const _cards = update(cards, { $splice: [[index, 1], [atIndex, 0, card]] })
+  //   handleList(_cards)
+  // }
+
+  // if (!is(fromJS(cards), fromJS(list))) {
+  //   setCards(list)
+  // }
+  
+  // const findCard = id => {
+  //   const card = cards.filter(c => `${c.uuid}` === id)[0]
+  //   return {
+  //     card,
+  //     index: cards.indexOf(card),
+  //   }
+  // }
+
+  // const doubleClickBtn = id => {
+  //   const { card } = findCard(id)
+  //   doubleClickCard(card)
+  // }
+
+  // const editCard = id => {
+  //   const { card } = findCard(id)
+  //   handleMenu(card)
+  // }
+
+  // const delCard = id => {
+  //   const { card } = findCard(id)
+  //   deleteMenu(card)
+  // }
+
+  // const hasDrop = (item) => {
+  //   target = item
+  // }
+
+  const [, drop] = useDrop({
+    accept: 'action',
+    drop(item) {
+      if (item.hasOwnProperty('originalIndex')) {
+        return
+      }
+
+      // let newcard = {}
+      // newcard.uuid = Utils.getuuid()
+      
+      // let targetId = cards.length > 0 ? cards[cards.length - 1].uuid : 0
+      // if (target) {
+      //   targetId = target.uuid
+      // }
+
+      // const { index: overIndex } = findCard(`${targetId}`)
+      // let targetIndex = overIndex
+
+      // targetIndex++
+
+      // const _cards = update(cards, { $splice: [[targetIndex, 0, newcard]] })
+
+      // handleList(_cards, newcard)
+      // target = null
+    }
+  })
+
+  return (
+    <div ref={drop} className="mob-shell-inner">
+      {/* {cards.map(card => (
+        <Card
+          id={card.uuid}
+          key={card.uuid}
+          card={card}
+          moveCard={moveCard}
+          editCard={editCard}
+          delCard={delCard}
+          findCard={findCard}
+          hasDrop={hasDrop}
+          doubleClickCard={doubleClickBtn}
+        />
+      ))} */}
+      <Card />
+      
+      {/* {cards.length === 0 ?
+        <div className="common-drawarea-placeholder">
+          {placeholder}
+        </div> : null
+      } */}
+    </div>
+  )
+}
+export default Container
diff --git a/src/mob/mobshell/index.scss b/src/mob/mobshell/index.scss
new file mode 100644
index 0000000..369ae98
--- /dev/null
+++ b/src/mob/mobshell/index.scss
@@ -0,0 +1,6 @@
+.common-drawarea-placeholder {
+  width: 100%;
+  line-height: 65px;
+  text-align: center;
+  color: #bcbcbc;
+}
\ No newline at end of file
diff --git a/src/mob/modelsource/dragsource/index.jsx b/src/mob/modelsource/dragsource/index.jsx
new file mode 100644
index 0000000..1a00725
--- /dev/null
+++ b/src/mob/modelsource/dragsource/index.jsx
@@ -0,0 +1,18 @@
+import React from 'react'
+import { useDrag } from 'react-dnd'
+import { Tooltip } from 'antd'
+import './index.scss'
+
+const SourceElement = ({content}) => {
+  const [, drag] = useDrag({ item: content })
+  return (
+    <div ref={drag} className="mob-source-item" style={{backgroundImage: 'url(' + content.url + ')', ...content.style}}>
+      <Tooltip placement="right" overlayClassName="mob-source-tooltip-box" mouseEnterDelay={0.3} mouseLeaveDelay={0} title={
+        <div><img style={{width: '100%'}} src={content.url} alt=""/></div>
+      }>
+        <div className="tooltip-block"></div>
+      </Tooltip>
+    </div>
+  )
+}
+export default SourceElement
\ No newline at end of file
diff --git a/src/mob/modelsource/dragsource/index.scss b/src/mob/modelsource/dragsource/index.scss
new file mode 100644
index 0000000..3b86b2a
--- /dev/null
+++ b/src/mob/modelsource/dragsource/index.scss
@@ -0,0 +1,25 @@
+.mob-source-item {
+  display: inline-block;
+  width: 130px;
+  margin-right: 15px;
+  cursor: move;
+  height: 130px;
+  box-shadow: 0px 0px 3px #dddddd;
+
+  background-size: contain;
+  background-position: center center;
+  background-repeat: no-repeat;
+
+  .tooltip-block {
+    width: 100%;
+    height: 100%;
+    background: transparent;
+  }
+}
+
+.mob-source-tooltip-box {
+  margin-left: 20px;
+  .ant-tooltip-content {
+    width: 250px;
+  }
+}
\ No newline at end of file
diff --git a/src/mob/modelsource/index.jsx b/src/mob/modelsource/index.jsx
new file mode 100644
index 0000000..b85bea0
--- /dev/null
+++ b/src/mob/modelsource/index.jsx
@@ -0,0 +1,34 @@
+import React, {Component} from 'react'
+import { is, fromJS } from 'immutable'
+import PropTypes from 'prop-types'
+
+import { mobOptions } from './option'
+import SourceWrap from './dragsource'
+import './index.scss'
+
+class CardChart extends Component {
+  static propTpyes = {
+    appType: PropTypes.string  // 搴旂敤绫诲瀷
+  }
+
+  state = {}
+
+  shouldComponentUpdate (nextProps, nextState) {
+    return !is(fromJS(this.props), fromJS(nextProps)) || !is(fromJS(this.state), fromJS(nextState))
+  }
+
+  render() {
+    return (
+      <div className="mob-card-source-box">
+        {mobOptions.map((item, index) => (
+          <div key={index}>
+            <p>{item.title}</p>
+            {item.options.map((cell, i) => (<SourceWrap key={i} content={cell} />))}
+          </div>
+        ))}
+      </div>
+    )
+  }
+}
+
+export default CardChart
\ No newline at end of file
diff --git a/src/mob/modelsource/index.scss b/src/mob/modelsource/index.scss
new file mode 100644
index 0000000..db58054
--- /dev/null
+++ b/src/mob/modelsource/index.scss
@@ -0,0 +1,9 @@
+.mob-card-source-box {
+  padding: 20px 0px 20px 15px;
+  position: relative;
+
+  p {
+    color: rgba(0, 0, 0, 0.85);
+    margin-bottom: 10px;
+  }
+}
diff --git a/src/mob/modelsource/option.jsx b/src/mob/modelsource/option.jsx
new file mode 100644
index 0000000..7855e27
--- /dev/null
+++ b/src/mob/modelsource/option.jsx
@@ -0,0 +1,14 @@
+import zhCN from '@/locales/zh-CN/mob.js'
+import enUS from '@/locales/en-US/mob.js'
+import mobLogin1 from '@/assets/mobimg/mob-login1.png'
+
+const _dict =  sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS
+
+// 琛ㄥ崟鏍¢獙瑙勫垯
+export const mobOptions = [{
+  title: _dict['mob.login'],
+  type: 'login',
+  options: [
+    {type: 'mob-login-1', sourceType: 'mob', url: mobLogin1,  style: {}},
+  ]
+}]
diff --git a/src/router/index.js b/src/router/index.js
index 221e91f..4e042d3 100644
--- a/src/router/index.js
+++ b/src/router/index.js
@@ -18,7 +18,7 @@
   {path: '/ssologin/:param', name: 'ssologin', auth: true},
   {path: '/main', name: 'main', component: Main, auth: true},
   {path: '/mobmanage', name: 'mobmanage', component: MobManage, auth: true},
-  {path: '/mobdesign', name: 'mobdesign', component: MobDesign, auth: true},
+  {path: '/mobdesign/:appId/:appType', name: 'mobdesign', component: MobDesign, auth: true},
   {path: '/main/:param', name: 'pmain', component: Main, auth: true}
 ]
 
diff --git a/src/tabviews/rolemanage/index.jsx b/src/tabviews/rolemanage/index.jsx
index 85a4fe4..792d229 100644
--- a/src/tabviews/rolemanage/index.jsx
+++ b/src/tabviews/rolemanage/index.jsx
@@ -118,7 +118,12 @@
       // ParentID锛堢埗绾d锛夈�丼elected锛堟槸鍚﹂�変腑-宸插け鏁堬級銆乀abs锛� 鏍囩绫诲瀷锛夈�乀ypeCharOne 鑿滃崟绫诲瀷PC鎴栧叾浠�
       let _tree = this.getTree(fromJS(mainMenus).toJS(), result.data)
       if (_tree[0]) {
-        this.getOpenNode(_tree[0], _openKeys)
+        if (_tree[0].key === 'PC' && _tree[0].children) {
+          // _openKeys = _tree[0].children.map(cell => cell.key)
+          this.getOpenNode(_tree[0].children[0], _openKeys)
+        } else {
+          this.getOpenNode(_tree[0], _openKeys)
+        }
       }
 
       this.setState({
@@ -163,7 +168,11 @@
         this.getCheckedKeys(fromJS(menuTrees).toJS(), _initKeys)
 
         if (menuTrees[0]) {
-          this.getOpenNode(menuTrees[0], _openKeys)
+          if (menuTrees[0].key === 'PC' && menuTrees[0].children) {
+            this.getOpenNode(menuTrees[0].children[0], _openKeys)
+          } else {
+            this.getOpenNode(menuTrees[0], _openKeys)
+          }
         }
 
         this.setState({
@@ -177,7 +186,11 @@
         let _tree = this.getSelectTree(fromJS(menuTrees).toJS(), Keys)
 
         if (_tree[0]) {
-          this.getOpenNode(_tree[0], _openKeys)
+          if (_tree[0].key === 'PC' && _tree[0].children) {
+            this.getOpenNode(_tree[0].children[0], _openKeys)
+          } else {
+            this.getOpenNode(_tree[0], _openKeys)
+          }
         }
 
         this.setState({
diff --git a/src/tabviews/zshare/actionList/printbutton/index.jsx b/src/tabviews/zshare/actionList/printbutton/index.jsx
index 5da7e95..4b898f7 100644
--- a/src/tabviews/zshare/actionList/printbutton/index.jsx
+++ b/src/tabviews/zshare/actionList/printbutton/index.jsx
@@ -554,7 +554,7 @@
       } catch (e) {
         configParam = ''
       }
-  
+
       if (!configParam) {
         error = '鎵撳嵃妯℃澘瑙f瀽閿欒锛�'
       } else {
@@ -611,7 +611,7 @@
             item.LabelSize = element.fontSize
           } else if (item.Type === 'qrcode') {
             item.Type = 'barcode'
-            item.BarcodeType = element.barcodeType
+            item.BarcodeType = element.qrcodeType
             item.BarcodeWidth = element.qrcodeWidth
             item.BarcodeHeight = element.qrcodeWidth
             item.BarcodeLabel = false
diff --git a/src/tabviews/zshare/mutilform/index.jsx b/src/tabviews/zshare/mutilform/index.jsx
index 4b6948c..29bd63c 100644
--- a/src/tabviews/zshare/mutilform/index.jsx
+++ b/src/tabviews/zshare/mutilform/index.jsx
@@ -935,12 +935,25 @@
     let _formlist = []
     let rowIndex = 0
     let colIndex = 0
+    let filtration = {}
 
     // 琛ㄥ崟鍒嗚锛岄伩鍏嶆帓鍒椾笉鏁撮綈
     formlist.forEach(item => {
       if ((!item.field && item.type !== 'title') || item.hidden === 'true' || item.type === 'funcvar') return
+      if (item.supField) { // 澶氬眰琛ㄥ崟鎺у埗
+        let _supVal = this.props.form.getFieldValue(item.supField)
 
-      if (item.supField && !item.supvalue.includes(this.props.form.getFieldValue(item.supField))) return
+        if (_supVal === undefined && filtration[item.supField]) {
+          _supVal = filtration[item.supField]
+        }
+
+        if (item.supvalue.includes(_supVal)) {
+          let _subVal = this.props.form.getFieldValue(item.field)
+          filtration[item.field] = _subVal === undefined ? item.initval : _subVal
+        } else {
+          return
+        }
+      }
 
       _formlist[rowIndex] = _formlist[rowIndex] || []
       if (item.type === 'textarea' || item.type === 'title') {
diff --git a/src/templates/comtableconfig/index.jsx b/src/templates/comtableconfig/index.jsx
index 0ff3ba4..8f6904e 100644
--- a/src/templates/comtableconfig/index.jsx
+++ b/src/templates/comtableconfig/index.jsx
@@ -1311,9 +1311,7 @@
               {/* 鎼滅储鏉′欢娣诲姞 */}
               <Panel header={this.state.dict['header.menu.search']} key="1">
                 <div className="search-element">
-                  {Source.searchItems.map((item, index) => {
-                    return (<SourceElement key={index} content={item}/>)
-                  })}
+                  {Source.searchItems.map((item, index) => (<SourceElement key={index} content={item}/>))}
                 </div>
                 <FieldsComponent
                   config={config}
@@ -1325,9 +1323,7 @@
               {/* 鎸夐挳娣诲姞 */}
               <Panel header={this.state.dict['header.menu.action']} key="2">
                 <div className="search-element">
-                  {Source.actionItems.map((item, index) => {
-                    return (<SourceElement key={index} content={item}/>)
-                  })}
+                  {Source.actionItems.map((item, index) => (<SourceElement key={index} content={item}/>))}
                 </div>
                 <div className="config-btn">
                   {confActions.length > 0 ?
@@ -1355,9 +1351,7 @@
               {/* 娣诲姞鏄剧ず鍒� */}
               <Panel header={this.state.dict['header.menu.column']} key="3">
                 <div className="search-element">
-                  {Source.columnItems.map((item, index) => {
-                    return (<SourceElement key={index} content={item}/>)
-                  })}
+                  {Source.columnItems.map((item, index) => (<SourceElement key={index} content={item}/>))}
                 </div>
                 <FieldsComponent
                   config={config}
@@ -1369,9 +1363,7 @@
               {/* 娣诲姞鏍囩 */}
               <Panel header={this.state.dict['header.menu.tab']} key="4">
                 <div className="search-element">
-                  {Source.tabItems.map((item, index) => {
-                    return (<SourceElement key={index} content={item}/>)
-                  })}
+                  {Source.tabItems.map((item, index) => (<SourceElement key={index} content={item}/>))}
                 </div>
                 {configTabs.length > 0 ?
                   <p className="config-btn-title">
diff --git a/src/templates/zshare/formconfig.jsx b/src/templates/zshare/formconfig.jsx
index e009610..54aab87 100644
--- a/src/templates/zshare/formconfig.jsx
+++ b/src/templates/zshare/formconfig.jsx
@@ -6,8 +6,12 @@
 
 /**
  * @description 鑾峰彇椤甸潰璁剧疆琛ㄥ崟閰嶇疆淇℃伅
- * @param {object} setting   // 鑿滃崟鍏ㄥ眬璁剧疆淇℃伅
- * @param {string} type      // 鑿滃崟绫诲瀷
+ * @param {object} setting       // 鑿滃崟鍏ㄥ眬璁剧疆淇℃伅
+ * @param {array}  usefulFields  // 鍐呴儴鍑芥暟鍙敤鐨勫紑澶村瓧绗�
+ * @param {string} MenuID        // 鑿滃崟ID
+ * @param {string} primaryKey    // 涓婚敭
+ * @param {zrray}  columns       // 鏄剧ず鍒�
+ * @param {string} type          // 鑿滃崟绫诲瀷锛宮ain锛堜富琛級
  */
 export function getSettingForm (setting, usefulFields = [], MenuID, primaryKey, columns, type) {
   let str = '^(' + usefulFields.join('|') + ')'
@@ -237,8 +241,9 @@
 
 /**
  * @description 鑾峰彇鏍戝舰椤甸潰璁剧疆琛ㄥ崟閰嶇疆淇℃伅
- * @param {object} setting   // 鑿滃崟鍏ㄥ眬璁剧疆淇℃伅
- * @param {string} type      // 鑿滃崟绫诲瀷
+ * @param {object} setting       // 鑿滃崟鍏ㄥ眬璁剧疆淇℃伅
+ * @param {array}  usefulFields  // 鍙敤寮�濮嬪瓧绗�
+ * @param {string} MenuID        // 鑿滃崟ID
  */
 export function getTreeSettingForm (setting, usefulFields = [], MenuID) {
   let str = '^(' + usefulFields.join('|') + ')'
@@ -1505,6 +1510,7 @@
  * @description 鑾峰彇鍥捐〃瑙嗗浘澶栭儴閰嶇疆琛ㄥ崟
  * @param {object} card       // 鎼滅储鏉′欢瀵硅薄
  * @param {Array}  roleList   // 瑙掕壊鍒楄〃-榛戝悕鍗�
+ * @param {Array}  columns    // 鏄剧ず鍒�
  */
 export function getChartViewForm (card, roleList = [], _columns) {
   let _charts = [{
@@ -1931,7 +1937,6 @@
       label: '閲嶅鏁版嵁',
       initVal: card.repeat || 'unrepeat',
       required: false,
-      // forbid: !['bar', 'pie', 'line'].includes(card.chartType),
       options: [{
         value: 'unrepeat',
         text: '鍘婚噸'
@@ -2367,7 +2372,12 @@
 
 /**
  * @description 鑾峰彇瀛愯彍鍗曞熀鏈俊鎭〃鍗曢厤缃俊鎭�
- * @param {object} card  // 鏍囩閰嶇疆淇℃伅
+ * @param {object} card      // 鏍囩閰嶇疆淇℃伅
+ * @param {string} supMenu   // 涓婄骇鑿滃崟ID
+ * @param {array}  menus     // 鍙�夌殑涓婄骇鑿滃崟鍒楄〃
+ * @param {array}  equalTab  // 鍚岀骇鑿滃崟IDs
+ * @param {array}  equalTabs // 鍙�夌殑鍚岀骇鑿滃崟鍒楄〃
+ * @param {string} type      // 鑿滃崟绫诲瀷锛屼富琛ㄦ垨鏍戝舰缁撴瀯
  */
 export function getTabForm (card, supMenu, menus, equalTab, equalTabs, type) {
   return [
@@ -2477,7 +2487,11 @@
 
 /**
  * @description 鑾峰彇鍗$墖璇︽儏琛ㄥ崟閰嶇疆淇℃伅
- * @param {object} card  // 鏍囩閰嶇疆淇℃伅
+ * @param {object}  card        // 鏍囩閰嶇疆淇℃伅
+ * @param {array}   _columns    // 鏄剧ず鍒�
+ * @param {string}  _type       // 绫诲瀷锛屽崱鐗囩殑閮ㄤ綅
+ * @param {array}   _actions    // 鎸夐挳鍒楄〃
+ * @param {boolean} isRatioCard // 琛ㄦ牸瀹藉害绫诲瀷锛屾槸鍚︿负姣斾緥
  */
 export function getCardDetailForm (card, _columns, _type, _actions = [], isRatioCard) {
   let actions = ''
@@ -2716,7 +2730,6 @@
         value: 'all',
         text: '鍏ㄩ儴'
       }]
-    },
-    
+    }
   ]
 }
\ No newline at end of file
diff --git a/src/views/login/index.jsx b/src/views/login/index.jsx
index 0e9ccb9..ae80f67 100644
--- a/src/views/login/index.jsx
+++ b/src/views/login/index.jsx
@@ -1,4 +1,4 @@
-import React, {Component} from 'react'
+import React, { Component } from 'react'
 import { message, Modal } from 'antd'
 import { connect } from 'react-redux'
 import md5 from 'md5'
diff --git a/src/views/mobdesign/index.jsx b/src/views/mobdesign/index.jsx
index c90ada7..f22c849 100644
--- a/src/views/mobdesign/index.jsx
+++ b/src/views/mobdesign/index.jsx
@@ -1,27 +1,34 @@
-import React, {Component} from 'react'
-import {connect} from 'react-redux'
-import { Icon } from 'antd'
+import React, { Component } from 'react'
+import { connect } from 'react-redux'
+import { DndProvider } from 'react-dnd'
+import HTML5Backend from 'react-dnd-html5-backend'
+import { Icon, Tabs } from 'antd'
 
-import zhCN from '@/locales/zh-CN/login.js'
-import enUS from '@/locales/en-US/login.js'
+import Api from '@/api'
+import zhCN from '@/locales/zh-CN/mob.js'
+import enUS from '@/locales/en-US/mob.js'
 import asyncComponent from '@/utils/asyncComponent'
 
 import './index.scss'
 
+const { TabPane } = Tabs
+
 const Header = asyncComponent(() => import('@/mob/header'))
-const Home = asyncComponent(() => import('@/mob/home'))
-const Login = asyncComponent(() => import('@/mob/login'))
+const MobShell = asyncComponent(() => import('@/mob/mobshell'))
+const SourceWrap = asyncComponent(() => import('@/mob/modelsource'))
+const DataSource = asyncComponent(() => import('@/mob/datasource'))
 
 class Mobile extends Component {
   state = {
     dict: localStorage.getItem('lang') !== 'en-US' ? zhCN : enUS,
-    view: null
+    appId: this.props.match.params.appId,
+    appType: this.props.match.params.appType,
+    saveIng: false,
+    config: null
   }
 
   UNSAFE_componentWillMount() {
-    this.setState({
-      view: {uuid: 'login', type: 'home', parentId: null, parentType: null}
-    })
+    this.getPageParam(this.props.match.params.appId)
   }
 
   /**
@@ -33,31 +40,64 @@
     }
   }
 
+  jumpToManage = () => {
+    this.props.history.replace('/mobmanage')
+    // this.props.history.push('/mobdesign/sdafadjfidsf/dsfsdf')
+  }
+
+  triggerSave = () => {
+    this.setState({
+      saveIng: true
+    })
+  }
+
+  getPageParam = (id) => {
+    Api.getSystemConfig({
+      func: 'sPC_Get_LongParam',
+      MenuID: id
+    }).then(result => {
+
+    })
+  }
+
+  updateConfig = () => {
+    
+  }
+
   render () {
-    const { view } = this.state
+    const { saveIng, appType, config } = this.state
 
     return (
       <div className="mobile-view">
-        <Header />
-        <div className="mob-body">
-          <div className="mob-tool">
-            <div className="mob-tool-content">
-              <div className="plus-content">
-                <Icon type="plus-circle" />娣� 鍔� 鍐� 瀹�
+        <Header view="design" jumpToManage={this.jumpToManage} triggerSave={this.triggerSave} saveIng={saveIng} />
+        <DndProvider backend={HTML5Backend}>
+          <div className="mob-body">
+            <div className="mob-tool">
+              <div className="mob-tool-content">
+                <div className="plus-content">
+                  <Icon type="plus-circle" />娣� 鍔� 鍐� 瀹�
+                </div>
+                <div className="useable-component">
+                  <SourceWrap appType={appType} />
+                </div>
               </div>
-              <div className="useable-component"></div>
+              <div className="mob-tool-other"></div>
             </div>
-            <div className="mob-tool-other"></div>
+            <div className="mob-shell">
+              <MobShell />
+            </div>
+            <div className="mob-setting">
+              <Tabs defaultActiveKey="2" animated={false} size="small">
+                <TabPane tab="閰嶇疆" key="1">
+                  Content of Tab Pane 1
+                </TabPane>
+                <TabPane tab="鏁版嵁婧�" key="2">
+                  <DataSource config={config} updateConfig={this.updateConfig} />
+                </TabPane>
+              </Tabs>
+            </div>
           </div>
-          <div className="mob-shell">
-            {view ? <div className="mob-shell-inner">
-              {view.type === 'login' ? <Login /> : null}
-              {view.type === 'home' ? <Home /> : null}
-            </div> : null}
-          </div>
-          <div className="mob-setting">
-          </div>
-        </div>
+        </DndProvider>
       </div>
     )
   }
diff --git a/src/views/mobdesign/index.scss b/src/views/mobdesign/index.scss
index 6322f93..085ccf3 100644
--- a/src/views/mobdesign/index.scss
+++ b/src/views/mobdesign/index.scss
@@ -38,13 +38,14 @@
 
         .useable-component {
           position: absolute;
-          width: 300px;
+          width: 305px;
           top: 0;
           bottom: 0;
           left: -340px;
           background: #fff;
           opacity: 0;
-          transition: left 0.3s, opacity 0.3s;
+          transition: left 0.3s linear 0.1s, opacity 0.3s linear 0.1s;
+          overflow-y: auto;
         }
       }
       .mob-tool-content:hover {
@@ -67,7 +68,7 @@
       top: 0;
       height: 100%;
       width: 300px;
-      background: #262626;
+      background: #ffffff;
       box-shadow: 0px 2px 2px #000;
     }
 
diff --git a/src/views/mobmanage/index.jsx b/src/views/mobmanage/index.jsx
index 7d81aa0..0120da3 100644
--- a/src/views/mobmanage/index.jsx
+++ b/src/views/mobmanage/index.jsx
@@ -15,11 +15,15 @@
     }
   }
 
+  jumpMenu = (card) => {
+    this.props.history.replace('/mobdesign/' + card.uuid + '/' + card.type)
+  }
+
   render () {
     return (
       <div className="mobile-manage">
         <Header view="manage" />
-        <MobCard />
+        <MobCard jumpMenu={this.jumpMenu}/>
       </div>
     )
   }
diff --git a/src/views/mobmanage/index.scss b/src/views/mobmanage/index.scss
index d553fdd..0dff349 100644
--- a/src/views/mobmanage/index.scss
+++ b/src/views/mobmanage/index.scss
@@ -1,4 +1,4 @@
 .mobile-manage {
   background: #fff;
-  
+  min-height: 100vh;
 }

--
Gitblit v1.8.0