From c5a378919ea922fd3216e70d9c5479edfe0d7178 Mon Sep 17 00:00:00 2001
From: king <18310653075@163.com>
Date: 星期三, 04 八月 2021 15:44:34 +0800
Subject: [PATCH] 2021-08-04

---
 src/components/normalform/modalform/index.scss                   |  112 ++++
 src/components/normalform/modalform/mkInput/index.jsx            |   71 ++
 src/components/normalform/modalform/styleInput/index.jsx         |  144 +++++
 src/menu/components/card/cardcellcomponent/dragaction/index.scss |   17 
 src/menu/components/card/cardcellcomponent/dragaction/action.jsx |    2 
 src/menu/components/card/cardcellcomponent/dragaction/index.jsx  |    3 
 src/components/normalform/index.scss                             |    3 
 src/menu/components/card/balcony/options.jsx                     |  195 +++++++
 src/components/normalform/modalform/mkInput/index.scss           |   27 +
 src/menu/components/card/cardcellcomponent/dragaction/card.jsx   |    6 
 src/tabviews/zshare/mutilform/mkSelect/index.jsx                 |    2 
 src/components/normalform/modalform/mkSelect/index.scss          |    0 
 src/tabviews/zshare/mutilform/mkNumberInput/index.jsx            |    4 
 src/components/normalform/modalform/mkSelect/index.jsx           |  140 +++++
 src/menu/components/card/balcony/index.jsx                       |   45 +
 src/components/normalform/modalform/index.jsx                    |  250 +++++++++
 src/menu/components/card/cardcellcomponent/index.jsx             |  170 +++---
 src/templates/zshare/verifycard/index.jsx                        |    8 
 src/components/normalform/modalform/mkNumberInput/index.jsx      |   62 ++
 src/components/normalform/modalform/mkRadio/index.jsx            |   94 +++
 src/menu/components/card/cardcomponent/index.jsx                 |    2 
 /dev/null                                                        |   36 -
 src/tabviews/zshare/mutilform/index.jsx                          |    2 
 src/menu/components/card/cardcellcomponent/formconfig.jsx        |    1 
 src/components/normalform/index.jsx                              |   88 +++
 src/components/normalform/modalform/mkRadio/index.scss           |    0 
 src/tabviews/custom/components/card/cardcellList/index.scss      |   16 
 src/components/normalform/modalform/styleInput/index.scss        |   11 
 src/components/normalform/modalform/mkNumberInput/index.scss     |   27 +
 29 files changed, 1,401 insertions(+), 137 deletions(-)

diff --git a/src/components/normalform/index.jsx b/src/components/normalform/index.jsx
new file mode 100644
index 0000000..6c2d87a
--- /dev/null
+++ b/src/components/normalform/index.jsx
@@ -0,0 +1,88 @@
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
+import { is, fromJS } from 'immutable'
+import { Modal } from 'antd'
+
+import zhCN from '@/locales/zh-CN/model.js'
+import enUS from '@/locales/en-US/model.js'
+import ModalForm from './modalform'
+import './index.scss'
+
+class NormalFormComponent extends Component {
+  static propTpyes = {
+    width: PropTypes.any,
+    check: PropTypes.any,
+    title: PropTypes.string,
+    getForms: PropTypes.func,
+    update: PropTypes.func
+  }
+
+  state = {
+    dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS,
+    visible: false,
+    formlist: []
+  }
+
+  shouldComponentUpdate (nextProps, nextState) {
+    return !is(fromJS(this.state), fromJS(nextState))
+  }
+
+  trigger = () => {
+    this.setState({
+      visible: true,
+      formlist: this.props.getForms()
+    })
+  }
+
+  submit = () => {
+    const { check } = this.props
+
+    this.Ref.handleConfirm().then(res => {
+      if (check) {
+        this.props.update(res, () => {
+          this.setState({
+            visible: false,
+            formlist: []
+          })
+        })
+      } else {
+        this.setState({
+          visible: false,
+          formlist: []
+        })
+        this.props.update(res)
+      }
+    })
+  }
+
+  render () {
+    const { title, width, children } = this.props
+    const { visible, dict, formlist } = this.state
+
+    return (
+      <div className="normal-form-wrap">
+        <span onClick={this.trigger}>{children}</span>
+        <Modal
+          wrapClassName="popview-modal"
+          title={title}
+          visible={visible}
+          width={width}
+          maskClosable={false}
+          okText={dict['model.submit']}
+          onOk={this.submit}
+          onCancel={() => { this.setState({ visible: false }) }}
+          destroyOnClose
+        >
+          <ModalForm
+            dict={dict}
+            formlist={formlist}
+            inputSubmit={this.submit}
+            wrappedComponentRef={(inst) => this.Ref = inst}
+          />
+        </Modal>
+      </div>
+    )
+  }
+}
+
+export default NormalFormComponent
\ No newline at end of file
diff --git a/src/components/normalform/index.scss b/src/components/normalform/index.scss
new file mode 100644
index 0000000..57c7b66
--- /dev/null
+++ b/src/components/normalform/index.scss
@@ -0,0 +1,3 @@
+.normal-form-wrap {
+  display: inline-block;
+}
\ No newline at end of file
diff --git a/src/components/normalform/modalform/index.jsx b/src/components/normalform/modalform/index.jsx
new file mode 100644
index 0000000..9ad6f5d
--- /dev/null
+++ b/src/components/normalform/modalform/index.jsx
@@ -0,0 +1,250 @@
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
+// import { fromJS } from 'immutable'
+import { Form, Row, Col, Tooltip, Icon, Cascader } from 'antd'
+
+import asyncComponent from '@/utils/asyncComponent'
+import MKEInput from './mkInput'
+import MKNumberInput from './mkNumberInput'
+import MKSelect from './mkSelect'
+import './index.scss'
+
+const MKRadio = asyncComponent(() => import('./mkRadio'))
+const StyleInput = asyncComponent(() => import('./styleInput'))
+const MKFileUpload = asyncComponent(() => import('@/tabviews/zshare/fileupload'))
+const MKColor = asyncComponent(() => import('@/tabviews/zshare/mutilform/mkColor'))
+
+class ModalForm extends Component {
+  static propTpyes = {
+    formlist: PropTypes.array,   // 琛ㄥ崟鍒楄〃
+    inputSubmit: PropTypes.func  // input鍥炶溅鎻愪氦
+  }
+
+  state = {
+    formlist: [],    // 琛ㄥ崟椤�
+  }
+
+  record = {}
+
+  componentDidMount () {
+    let record = {}
+    let controlFields = {}
+    let fieldMap = new Map()
+
+    let formlist = this.props.formlist.filter(item => {
+      if (item.controlFields) { // 澶氬眰琛ㄥ崟鎺у埗
+        controlFields[item.field] = item.controlFields
+      }
+      
+      item.hidden = false
+
+      if (item.type === 'text') {
+        let _rules = [{
+          required: item.required,
+          message: item.label + '涓嶅彲涓虹┖!'
+        }]
+        
+        item.rules = _rules
+      } else if (item.type === 'number') {
+        item.rules = [{
+          required: item.required,
+          message: item.label + '涓嶅彲涓虹┖!'
+        }, {
+          validator: (rule, value, callback) => this.handleConfirmPassword(rule, value, callback, item)
+        }]
+      } else if (item.type === 'textarea') {
+        let _rules = [
+          {
+            required: item.required,
+            message: item.label + '涓嶅彲涓虹┖!'
+          }
+        ]
+        item.rules = _rules
+      } else {
+        item.rules = [
+          {
+            required: item.required,
+            message: '璇烽�夋嫨' + item.label + '!'
+          }
+        ]
+      }
+
+      record[item.field] = item.initval
+
+      fieldMap.set(item.field, item)
+
+      return true
+    })
+
+    Object.keys(controlFields).forEach(key => {
+      if (!fieldMap.has(key)) return
+
+      let supItem = fieldMap.get(key)
+      let fields = []
+      
+      controlFields[key].forEach(item => {
+        if (!fieldMap.has(item.field)) return
+
+        let cell = fieldMap.get(item.field)
+
+        if (cell.hidden) return
+
+        if (supItem.hidden || !item.values.includes(supItem.initval)) {
+          cell.hidden = true
+          fieldMap.set(item.field, cell)
+        }
+
+        fields.push(item)
+      })
+
+      supItem.controlFields = fields
+      
+      fieldMap.set(key, supItem)
+    })
+
+    formlist = formlist.map(cell => {
+      return fieldMap.get(cell.field) || cell
+    })
+
+    this.record = record
+
+    this.setState({ formlist })
+  }
+
+  handleConfirmPassword = (rule, value, callback, item) => {
+    let val = parseFloat(value)
+
+    if (!isNaN(val)) {
+      if (typeof(item.min) === 'number' && val < item.min) {
+        callback(item.label + '鏈�灏忓�间负 ' + item.min)
+      } else if (typeof(item.max) === 'number' && val > item.max) {
+        callback(item.label + '鏈�澶у�间负 ' + item.max)
+      }
+    }
+    callback()
+  }
+
+  recordChange = (values, item) => {
+    this.record = {...this.record, ...values}
+
+    if (item && item.controlFields) {
+      let map = new Map()
+      this.state.formlist.forEach(cell => {
+        if (!cell.field) return
+        map.set(cell.field, cell)
+      })
+
+      let reset = (current) => {
+        let val = this.record[current.field]
+
+        current.controlFields.forEach(cell => {
+          let m = map.get(cell.field)
+          m.hidden = current.hidden || !cell.values.includes(val)
+
+          if (m.hidden) {
+            m.initval = this.record[m.field]
+          }
+
+          map.set(cell.field, m)
+
+          if (m.controlFields) {
+            reset(m)
+          }
+        })
+      }
+
+      reset(item)
+
+      this.setState({
+        formlist: this.state.formlist.map(cell => {
+          if (cell.field) {
+            return map.get(cell.field)
+          }
+          return cell
+        })
+      })
+    }
+  }
+
+  getFields() {
+    const { getFieldDecorator } = this.props.form
+    const { formlist } = this.state
+
+    const fields = []
+
+    formlist.forEach((item, index) => {
+      if (item.hidden) return
+
+      let content = null
+      let label = item.tooltip ? <Tooltip placement="topLeft" title={item.tooltip}><Icon type="question-circle" />{item.label}</Tooltip> : item.label
+    
+      if (item.type === 'text') {
+        content = (<MKEInput config={item} onChange={(val, defer) => !defer && this.recordChange({[item.field]: val})} onSubmit={this.props.inputSubmit} />)
+      } else if (item.type === 'number') {
+        content = (<MKNumberInput config={item} onChange={(val, defer) => !defer && this.recordChange({[item.field]: val})} onSubmit={this.props.inputSubmit} />)
+      } else if (item.type === 'select' || item.type === 'multiselect') {
+        content = (<MKSelect config={item} onChange={(val, other) => this.recordChange({[item.field]: val, ...other}, item)} />)
+      } else if (item.type === 'color') {
+        content = (<MKColor config={item} onChange={(val) => this.recordChange({[item.field]: val})}/>)
+      } else if (item.type === 'styleInput') {
+        content = (<StyleInput config={item} onChange={(val) => this.recordChange({[item.field]: val})}/>)
+      } else if (item.type === 'radio') {
+        content = (<MKRadio config={item} onChange={(val, other) => this.recordChange({[item.field]: val, ...other}, item)}/>)
+      } else if (item.type === 'fileupload') {
+        content = (<MKFileUpload config={item} onChange={(val) => this.recordChange({[item.field]: val})} />)
+      } else if (item.type === 'cascader') {
+        content = (<Cascader options={item.options} expandTrigger="hover" placeholder="" />)
+      }
+
+      if (!content) return
+
+      fields.push(
+        <Col span={item.span || 12} key={index}>
+          <Form.Item label={label}>
+            {getFieldDecorator(item.field, {
+              initialValue: item.initval,
+              rules: item.rules
+            })(content)}
+          </Form.Item>
+        </Col>
+      )
+    })
+    
+    return fields
+  }
+
+  handleConfirm = () => {
+    // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭�
+    return new Promise((resolve, reject) => {
+      this.props.form.validateFieldsAndScroll((err, values) => {
+        if (err) {
+          reject(err)
+          return
+        }
+
+        resolve(values)
+      })
+    })
+  }
+
+  render() {
+    const formItemLayout = {
+      labelCol: {
+        xs: { span: 24 },
+        sm: { span: 8 }
+      },
+      wrapperCol: {
+        xs: { span: 24 },
+        sm: { span: 16 }
+      }
+    }
+
+    return (
+      <Form {...formItemLayout} className="normal-form-field">
+        <Row gutter={24}>{this.getFields()}</Row>
+      </Form>
+    )
+  }
+}
+
+export default Form.create()(ModalForm)
\ No newline at end of file
diff --git a/src/components/normalform/modalform/index.scss b/src/components/normalform/modalform/index.scss
new file mode 100644
index 0000000..b9b9b6c
--- /dev/null
+++ b/src/components/normalform/modalform/index.scss
@@ -0,0 +1,112 @@
+.normal-form-field {
+  position: relative;
+  padding: 0px 24px 20px;
+  >.ant-row >.ant-col {
+    display: inline-block;
+    float: none;
+    vertical-align: top;
+    padding-left: 1.2%!important;
+    padding-right: 1.2%!important;
+  }
+  .ant-form-item-label .anticon-question-circle {
+    color: #c49f47;
+    margin-right: 3px;
+  }
+  .ant-checkbox-group {
+    line-height: unset;
+    .ant-checkbox-wrapper {
+      margin-right: 8px;
+    }
+    .ant-checkbox-wrapper + .ant-checkbox-wrapper {
+      margin-left: 0;
+    }
+  }
+  .ant-form-item {
+    display: flex;
+  }
+  .ant-form-item.checkcard {
+    margin-bottom: 10px;
+    .ant-form-item-control {
+      line-height: 1.5;
+    }
+  }
+  .ant-form-item.hint {
+    margin-bottom: 0px;
+    .message {
+      margin-top: 9px;
+      line-height: 1.5;
+      color: rgba(0, 0, 0, 0.85);
+    }
+  }
+  .ant-form-item-control-wrapper {
+    flex: 1;
+  }
+  .ant-form-item-label {
+    overflow: hidden;
+    display: inline-block;
+    text-overflow: ellipsis;
+    white-space: nowrap;
+    width: 33.3%;
+  }
+  >.ant-row.cols2 .ant-col-24 {
+    .ant-form-item {
+      .ant-form-item-label {
+        width: 16%;
+      }
+    }
+  }
+  >.ant-row.cols3 .ant-col-24 {
+    .ant-form-item {
+      .ant-form-item-label {
+        width: 10.5%;
+      }
+    }
+  }
+  >.ant-row.cols4 .ant-col-24 {
+    .ant-form-item {
+      .ant-form-item-label {
+        width: 7.5%;
+      }
+    }
+  }
+  .ant-input-number {
+    width: 100%;
+  }
+  .ant-form-explain {
+    overflow:hidden;
+    text-overflow:ellipsis;
+    white-space:nowrap;
+  }
+  .color-sketch-block {
+    margin-top: 7px;
+    overflow: hidden;
+    .color-sketch-block-box {
+      min-width: 100px;
+    }
+  }
+  .normal-braft-editor {
+    border: 1px solid #d9d9d9;
+    border-radius: 4px;
+    overflow-x: hidden;
+  }
+  p {
+    color: #1890ff;
+    font-size: 15px;
+    padding-left: 10px;
+    border-bottom: 1px solid #e9e9e9;
+  }
+  .ant-input-disabled {
+    color: rgba(0, 0, 0, 0.65)!important;
+    cursor: default!important;
+  }
+  .ant-input-number-input {
+    color: rgba(0, 0, 0, 0.65)!important;
+    cursor: default!important;
+  }
+  .ant-select-disabled {
+    color: rgba(0, 0, 0, 0.65)!important;
+    .ant-select-selection--multiple .ant-select-selection__choice {
+      color: rgba(0, 0, 0, 0.65)!important;
+    }
+  }
+}
\ No newline at end of file
diff --git a/src/components/normalform/modalform/mkInput/index.jsx b/src/components/normalform/modalform/mkInput/index.jsx
new file mode 100644
index 0000000..2df60f7
--- /dev/null
+++ b/src/components/normalform/modalform/mkInput/index.jsx
@@ -0,0 +1,71 @@
+import React, { Component } from 'react'
+import { is, fromJS } from 'immutable'
+import { Input } from 'antd'
+
+import MKEmitter from '@/utils/events.js'
+
+import './index.scss'
+
+/**
+ * @description 鑷畾涔夋枃鏈緭鍏�
+ */
+class MKEInput extends Component {
+  constructor(props) {
+    super(props)
+    
+    const config = props.config
+    
+    this.state = {
+      value: config.initval
+    }
+  }
+  
+  inputRef = React.createRef()
+
+  shouldComponentUpdate (nextProps, nextState) {
+    return !is(fromJS(this.state), fromJS(nextState))
+  }
+
+  componentDidMount () {
+    const { config } = this.props
+    MKEmitter.addListener('mkFC', this.mkFormHandle)
+
+    if (config.focus) {
+      this.inputRef.current.select()
+    }
+  }
+
+  componentWillUnmount () {
+    this.setState = () => {
+      return
+    }
+    MKEmitter.removeListener('mkFC', this.mkFormHandle)
+  }
+
+  mkFormHandle = (type, field, value) => {
+    if (field !== this.props.config.field) return
+
+    if (type === 'focus') {
+      this.inputRef.current.select()
+    } else if (type === 'input') {
+      this.setState({value})
+      this.props.onChange(value, true)
+    }
+  }
+
+  handleChange = (e) => {
+    let val = e.target.value
+
+    this.setState({value: val})
+    this.props.onChange(val)
+  }
+
+  render() {
+    const { config } = this.props
+    const { value } = this.state
+
+    return <Input ref={this.inputRef} placeholder={config.placeholder || ''} value={value} autoComplete="off" onChange={this.handleChange} onPressEnter={this.props.onSubmit} />
+  }
+}
+
+export default MKEInput
\ No newline at end of file
diff --git a/src/components/normalform/modalform/mkInput/index.scss b/src/components/normalform/modalform/mkInput/index.scss
new file mode 100644
index 0000000..93dcc24
--- /dev/null
+++ b/src/components/normalform/modalform/mkInput/index.scss
@@ -0,0 +1,27 @@
+.am-list-item.am-input-item {
+  .am-input-control {
+    height: 100%;
+    input {
+      height: 100%;
+    }
+  }
+  .am-input-label {
+    width: 28%;
+    max-width: 120px;
+    text-overflow: ellipsis;
+  }
+  .am-input-extra {
+    max-height: 40px;
+    .anticon-scan {
+      font-size: 22px;
+      padding: 8px 5px;
+    }
+  }
+}
+.am-input-item.right {
+  .am-input-control {
+    input {
+      text-align: right;
+    }
+  }
+}
\ No newline at end of file
diff --git a/src/components/normalform/modalform/mkNumberInput/index.jsx b/src/components/normalform/modalform/mkNumberInput/index.jsx
new file mode 100644
index 0000000..ae5e040
--- /dev/null
+++ b/src/components/normalform/modalform/mkNumberInput/index.jsx
@@ -0,0 +1,62 @@
+import React, { Component } from 'react'
+import { is, fromJS } from 'immutable'
+import { InputNumber } from 'antd'
+
+import MKEmitter from '@/utils/events.js'
+
+import './index.scss'
+
+class MKNumberInput extends Component {
+  constructor(props) {
+    super(props)
+
+    const config = props.config
+
+    this.state = {
+      value: config.initval,
+      precision: config.precision
+    }
+  }
+
+  inputNumberRef = React.createRef()
+
+  shouldComponentUpdate (nextProps, nextState) {
+    return !is(fromJS(this.state), fromJS(nextState))
+  }
+
+  componentDidMount () {
+    MKEmitter.addListener('mkFC', this.mkFormHandle)
+  }
+
+  componentWillUnmount () {
+    this.setState = () => {
+      return
+    }
+    MKEmitter.removeListener('mkFC', this.mkFormHandle)
+  }
+
+  mkFormHandle = (type, field, value) => {
+    if (field !== this.props.config.field) return
+    
+    if (type === 'focus') {
+      this.inputNumberRef.current.focus()
+    } else if (type === 'input') {
+      this.setState({value})
+      this.props.onChange(value, true)
+    }
+  }
+
+  handleChange = (val) => {
+    this.setState({value: val})
+    this.props.onChange(val)
+  }
+
+  render() {
+    const { onSubmit } = this.props
+    const { value, precision } = this.state
+
+    return (<InputNumber ref={this.inputNumberRef} value={value} precision={precision} onChange={this.handleChange} onPressEnter={onSubmit} />)
+  }
+}
+
+export default MKNumberInput
\ No newline at end of file
diff --git a/src/components/normalform/modalform/mkNumberInput/index.scss b/src/components/normalform/modalform/mkNumberInput/index.scss
new file mode 100644
index 0000000..93dcc24
--- /dev/null
+++ b/src/components/normalform/modalform/mkNumberInput/index.scss
@@ -0,0 +1,27 @@
+.am-list-item.am-input-item {
+  .am-input-control {
+    height: 100%;
+    input {
+      height: 100%;
+    }
+  }
+  .am-input-label {
+    width: 28%;
+    max-width: 120px;
+    text-overflow: ellipsis;
+  }
+  .am-input-extra {
+    max-height: 40px;
+    .anticon-scan {
+      font-size: 22px;
+      padding: 8px 5px;
+    }
+  }
+}
+.am-input-item.right {
+  .am-input-control {
+    input {
+      text-align: right;
+    }
+  }
+}
\ No newline at end of file
diff --git a/src/components/normalform/modalform/mkRadio/index.jsx b/src/components/normalform/modalform/mkRadio/index.jsx
new file mode 100644
index 0000000..aab46a3
--- /dev/null
+++ b/src/components/normalform/modalform/mkRadio/index.jsx
@@ -0,0 +1,94 @@
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
+import { is, fromJS } from 'immutable'
+import { Radio } from 'antd'
+
+import MKEmitter from '@/utils/events.js'
+import './index.scss'
+
+class MKRadio extends Component {
+  static propTpyes = {
+    config: PropTypes.object,
+    onChange: PropTypes.func
+  }
+
+  state = {
+    value: this.props.config.initval,
+    config: fromJS(this.props.config).toJS(),
+    options: fromJS(this.props.config.options).toJS(),
+  }
+
+  componentDidMount () {
+    MKEmitter.addListener('mkFP', this.mkFormHandle)
+  }
+
+  shouldComponentUpdate (nextProps, nextState) {
+    return !is(fromJS(this.state), fromJS(nextState))
+  }
+
+  componentWillUnmount () {
+    this.setState = () => {
+      return
+    }
+    MKEmitter.removeListener('mkFP', this.mkFormHandle)
+  }
+
+  mkFormHandle = (field, parentId) => {
+    const { config } = this.state
+
+    if (field !== config.field) return
+
+    let options = config.oriOptions ? config.oriOptions.filter(option => option.ParentID === parentId) : []
+    let val = options[0] ? options[0].value : ''
+
+    this.setState({
+      options,
+      value: val
+    })
+
+    this.props.onChange(val)
+
+    config.linkFields && config.linkFields.forEach((m, i) => {
+      setTimeout(() => {
+        MKEmitter.emit('mkFP', m, val)
+      }, (i + 1) * 70)
+    })
+  }
+
+  onChange = (e) => {
+    const { config } = this.state
+    let value = e.target.value
+    let other = {}
+
+    if (config.subFields) {
+      let option = this.state.options.filter(m => m.value === value)[0]
+      option && config.subFields.forEach((n, i) => {
+        other[n] = option[n] || ''
+        setTimeout(() => {
+          MKEmitter.emit('mkFC', 'input', n, option[n] || '')
+        }, i * 5)
+      })
+    }
+
+    config.linkFields && config.linkFields.forEach((m, i) => {
+      setTimeout(() => {
+        MKEmitter.emit('mkFP', m, value)
+      }, (i + 1) * 100)
+    })
+
+    this.setState({value})
+    this.props.onChange(value, other)
+  }
+
+  render() {
+    const { value, options } = this.state
+
+    return (
+      <Radio.Group value={value} onChange={this.onChange}>
+        {options.map(option => <Radio key={option.value} value={option.value}>{option.label}</Radio>)}
+      </Radio.Group>
+    )
+  }
+}
+
+export default MKRadio
\ No newline at end of file
diff --git a/src/components/normalform/modalform/mkRadio/index.scss b/src/components/normalform/modalform/mkRadio/index.scss
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/components/normalform/modalform/mkRadio/index.scss
diff --git a/src/components/normalform/modalform/mkSelect/index.jsx b/src/components/normalform/modalform/mkSelect/index.jsx
new file mode 100644
index 0000000..69439b4
--- /dev/null
+++ b/src/components/normalform/modalform/mkSelect/index.jsx
@@ -0,0 +1,140 @@
+import React, {Component} from 'react'
+import { is, fromJS } from 'immutable'
+import { Select } from 'antd'
+
+import MKEmitter from '@/utils/events.js'
+import './index.scss'
+
+class MKSelect extends Component {
+  constructor(props) {
+    super(props)
+    
+    const config = props.config
+    let value = config.initval
+
+    if (config.type === 'multiselect') {
+      value = value || []
+    }
+
+    this.state = {
+      config: fromJS(config).toJS(),
+      options: fromJS(config.options).toJS(),
+      value,
+    }
+  }
+
+  componentDidMount () {
+    const { config } = this.state
+
+    if (config.type !== 'multiselect') {
+      MKEmitter.addListener('mkFP', this.mkFormHandle)
+    }
+    MKEmitter.addListener('mkFC', this.mkFormControl)
+  }
+
+  shouldComponentUpdate (nextProps, nextState) {
+    return !is(fromJS(this.state), fromJS(nextState))
+  }
+
+  componentWillUnmount () {
+    this.setState = () => {
+      return
+    }
+    MKEmitter.removeListener('mkFP', this.mkFormHandle)
+    MKEmitter.removeListener('mkFC', this.mkFormControl)
+  }
+
+  mkFormControl = (type, field, value) => {
+    if (field !== this.props.config.field) return
+    
+    if (type === 'input') {
+      this.setState({value})
+      this.props.onChange(value, {})
+    }
+  }
+
+  mkFormHandle = (field, parentId) => {
+    if (field !== this.state.config.field) return
+
+    const { config } = this.state
+
+    let options = config.oriOptions ? config.oriOptions.filter(option => option.ParentID === parentId) : []
+    let val = options[0] ? options[0].value : ''
+
+    this.setState({
+      options,
+      value: val
+    })
+
+    this.props.onChange(val)
+
+    config.linkFields && config.linkFields.forEach((m, i) => {
+      setTimeout(() => {
+        MKEmitter.emit('mkFP', m, val)
+      }, (i + 1) * 70)
+    })
+  }
+
+  selectChange = (val) => {
+    const { config } = this.state
+    let other = {}
+
+    if (config.subFields) {
+      let option = this.state.options.filter(m => m.value === val)[0]
+      option && config.subFields.forEach((n, i) => {
+        other[n] = option[n] || ''
+        setTimeout(() => {
+          MKEmitter.emit('mkFC', 'input', n, option[n] || '')
+        }, i * 5)
+      })
+    }
+
+    config.linkFields && config.linkFields.forEach((m, i) => {
+      setTimeout(() => {
+        MKEmitter.emit('mkFP', m, val)
+      }, (i + 1) * 100)
+    })
+
+    this.setState({value: val})
+    this.props.onChange(val, other)
+  }
+
+  mutilselectChange = (val) => {
+    this.props.onChange(val)
+  }
+
+  render() {
+    const { value, config, options } = this.state
+
+    if (config.type !== 'multiselect') {
+      return (
+        <Select
+          showSearch
+          allowClear
+          value={value}
+          filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0}
+          onSelect={this.selectChange}
+          onChange={(val) => val === undefined && this.selectChange('')}
+        >
+          {options.map(option =>
+            <Select.Option id={option.value} title={option.label} key={option.value} value={option.value}>{option.label || option.text}</Select.Option>
+          )}
+        </Select>
+      )
+    } else {
+      return (<Select
+        showSearch
+        mode="multiple"
+        defaultValue={value}
+        filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0}
+        onChange={this.mutilselectChange}
+      >
+        {options.map(option =>
+          <Select.Option id={option.value} title={option.label} key={option.value} value={option.value}>{option.label || option.text}</Select.Option>
+        )}
+      </Select>)
+    }
+  }
+}
+
+export default MKSelect
\ No newline at end of file
diff --git a/src/components/normalform/modalform/mkSelect/index.scss b/src/components/normalform/modalform/mkSelect/index.scss
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/components/normalform/modalform/mkSelect/index.scss
diff --git a/src/components/normalform/modalform/styleInput/index.jsx b/src/components/normalform/modalform/styleInput/index.jsx
new file mode 100644
index 0000000..3925b2a
--- /dev/null
+++ b/src/components/normalform/modalform/styleInput/index.jsx
@@ -0,0 +1,144 @@
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
+import { is, fromJS } from 'immutable'
+import { Select, Input } from 'antd'
+
+import MKEmitter from '@/utils/events.js'
+import './index.scss'
+
+const { Option } = Select
+
+class StyleInput extends Component {
+  static propTpyes = {
+    config: PropTypes.object,
+    onChange: PropTypes.func,
+  }
+
+  state = {
+    value: '',
+    unit: '',
+    options: []
+  }
+
+  UNSAFE_componentWillMount () {
+    const { config } = this.props
+
+    let val = config.initval || ''
+    let options = config.options || ['px', 'vh', 'vw', '%']
+    let unit = options[0]
+
+    if (val) {
+      if (val.indexOf('px') > -1) {
+        unit = 'px'
+      } else if (val.indexOf('%') > -1) {
+        unit = '%'
+      } else if (val.indexOf('vw') > -1) {
+        unit = 'vw'
+      } else if (val.indexOf('vh') > -1) {
+        unit = 'vh'
+      }
+    }
+
+    let _val = parseFloat(val)
+
+    if (isNaN(_val)) {
+      _val = ''
+    }
+
+    this.setState({value: _val, options: options, unit})
+  }
+
+  shouldComponentUpdate (nextProps, nextState) {
+    return !is(fromJS(this.state), fromJS(nextState))
+  }
+
+  componentDidMount () {
+    MKEmitter.addListener('mkFC', this.mkFormHandle)
+  }
+
+  componentWillUnmount () {
+    this.setState = () => {
+      return
+    }
+    MKEmitter.removeListener('mkFC', this.mkFormHandle)
+  }
+
+  mkFormHandle = (type, field, value) => {
+    if (field !== this.props.config.field) return
+    
+    if (type === 'input') {
+      let val = value
+      let unit = this.state.unit
+
+      if (val) {
+        if (val.indexOf('px') > -1) {
+          unit = 'px'
+        } else if (val.indexOf('%') > -1) {
+          unit = '%'
+        } else if (val.indexOf('vw') > -1) {
+          unit = 'vw'
+        } else if (val.indexOf('vh') > -1) {
+          unit = 'vh'
+        }
+      }
+
+      let _val = parseFloat(val)
+    
+      if (isNaN(_val)) {
+        _val = ''
+      }
+      this.setState({value: _val, unit})
+
+      this.props.onChange(value, true)
+    }
+  }
+
+  changeValue = (e) => {
+    const { unit } = this.state
+    let val = e.target.value
+
+    if (/\d+\.$/.test(val)) {
+      this.setState({
+        value: val
+      })
+      return
+    }
+    let _val = parseFloat(val)
+    
+    if (isNaN(_val)) {
+      _val = ''
+    }
+
+    this.setState({
+      value: _val,
+    })
+
+    this.props.onChange(_val !== '' ? `${_val}${unit}` : '')
+  }
+
+  changeUnit = (val) => {
+    const { value } = this.state
+
+    this.setState({unit: val})
+
+    this.props.onChange(value !== '' ? `${value}${val}` : '')
+  }
+
+  render () {
+    const { value, options, unit } = this.state
+
+    return (
+      <div className="style-input-wrap">
+        <Input value={value} addonAfter={
+          options.length > 1 ?
+          <Select value={unit} onChange={this.changeUnit}>
+            {options.map(item => <Option key={item} value={item}>{item}</Option>)}
+          </Select> :
+          <div className="single-unit">{unit}</div>
+        } onChange={this.changeValue}/>
+      </div>
+    )
+  }
+}
+
+export default StyleInput
\ No newline at end of file
diff --git a/src/components/normalform/modalform/styleInput/index.scss b/src/components/normalform/modalform/styleInput/index.scss
new file mode 100644
index 0000000..b058a37
--- /dev/null
+++ b/src/components/normalform/modalform/styleInput/index.scss
@@ -0,0 +1,11 @@
+.style-input-wrap {
+  line-height: 32px;
+  .ant-select {
+    width: 60px!important;
+  }
+  .single-unit {
+    width: 38px;
+    text-align: left;
+    color: rgba(255, 255, 255, 0.65);
+  }
+}
diff --git a/src/menu/components/card/balcony/index.jsx b/src/menu/components/card/balcony/index.jsx
index 9b2971a..6ab10d0 100644
--- a/src/menu/components/card/balcony/index.jsx
+++ b/src/menu/components/card/balcony/index.jsx
@@ -8,12 +8,14 @@
 import { resetStyle } from '@/utils/utils-custom.js'
 import MKEmitter from '@/utils/events.js'
 import Utils from '@/utils/utils.js'
+import MenuUtils from '@/utils/utils-custom.js'
+import { balconyWrapForm } from './options'
 import zhCN from '@/locales/zh-CN/model.js'
 import enUS from '@/locales/en-US/model.js'
 import './index.scss'
 
 const SettingComponent = asyncIconComponent(() => import('@/menu/datasource'))
-const WrapComponent = asyncIconComponent(() => import('./wrapsetting'))
+const NormalForm = asyncIconComponent(() => import('@/components/normalform'))
 const CardCellComponent = asyncComponent(() => import('../cardcellcomponent'))
 const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent'))
 const PasteComponent = asyncIconComponent(() => import('@/components/paste'))
@@ -204,6 +206,43 @@
     resolve({status: true})
   }
 
+  getWrapForms = () => {
+    const { wrap } = this.state.card
+    
+    let modules = MenuUtils.getLinkModules(fromJS(window.GLOB.customMenu).toJS().components) || []
+    let supmodules = MenuUtils.getSupModules(fromJS(window.GLOB.customMenu).toJS().components, '') || []
+    let roleList = sessionStorage.getItem('sysRoles')
+
+    if (roleList) {
+      try {
+        roleList = JSON.parse(roleList)
+      } catch {
+        roleList = []
+      }
+    } else {
+      roleList = []
+    }
+
+    return fromJS(balconyWrapForm).toJS().map(item => {
+      item.initval = wrap[item.field] || item.initval
+
+      if (item.field === 'blacklist') {
+        item.options = roleList
+      } else if (item.field === 'syncModule') {
+        item.options = modules
+      } else if (item.field === 'supModule') {
+        item.options = supmodules
+      }
+
+      return item
+    })
+  }
+
+  updateWrap = (res) => {
+    delete res.quick
+    this.updateComponent({...this.state.card, wrap: res})
+  }
+
   render() {
     const { card } = this.state
 
@@ -215,7 +254,9 @@
           <div className="mk-popover-control">
             <Icon className="plus" title="娣诲姞鍏冪礌" onClick={this.addElement} type="plus" />
             <Icon className="plus" title="娣诲姞鎸夐挳" onClick={this.addButton} type="plus-square" />
-            <WrapComponent config={card} updateConfig={this.updateComponent} />
+            <NormalForm title="鍗$墖璁剧疆" width={800} update={this.updateWrap} getForms={this.getWrapForms}>
+              <Icon type="edit" style={{color: '#1890ff'}} title="缂栬緫"/>
+            </NormalForm>
             <CopyComponent type="balcony" card={card}/>
             <PasteComponent options={['action', 'customCardElement']} updateConfig={this.pasteComponent} />
             <Icon className="style" title="璋冩暣鏍峰紡" onClick={this.changeStyle} type="font-colors" />
diff --git a/src/menu/components/card/balcony/options.jsx b/src/menu/components/card/balcony/options.jsx
new file mode 100644
index 0000000..ecd14d8
--- /dev/null
+++ b/src/menu/components/card/balcony/options.jsx
@@ -0,0 +1,195 @@
+/**
+ * @description Wrap琛ㄥ崟閰嶇疆淇℃伅
+ */
+export const balconyWrapForm = [
+  {
+    type: 'text',
+    field: 'name',
+    label: '缁勪欢鍚嶇О',
+    initval: '',
+    tooltip: '鐢ㄤ簬缁勪欢闂寸殑鍖哄垎銆�',
+    required: true
+  },
+  {
+    type: 'number',
+    field: 'width',
+    label: '瀹藉害',
+    initval: '',
+    tooltip: '鏍呮牸甯冨眬锛屾瘡琛岀瓑鍒嗕负24鍒椼��',
+    min: 1,
+    max: 24,
+    precision: 0,
+    required: true
+  },
+  {
+    type: 'radio',
+    field: 'datatype',
+    label: '鏁版嵁鏉ユ簮',
+    initval: '',
+    tooltip: '閫夋嫨闈欐�佸�硷紝鏃犻渶閰嶇疆鏁版嵁婧愩��',
+    required: false,
+    options: [
+      {value: 'dynamic', label: '鍔ㄦ��'},
+      {value: 'static', label: '闈欐��'},
+    ]
+  },
+  {
+    type: 'radio',
+    field: 'linkType',
+    label: '鍙楁帶绫诲瀷',
+    initval: 'static',
+    tooltip: '缁勪欢涓庡叾浠栫粍浠朵箣闂寸殑鎺у埗绫诲瀷锛岀嫭绔嬭〃绀轰笌鍏朵粬娌℃湁鍏宠仈銆�',
+    required: false,
+    options: [
+      {value: 'static', label: '鐙珛'},
+      {value: 'sync', label: '鍚屾'},
+      {value: 'sup', label: '涓婄骇'},
+    ],
+    controlFields: [
+      {field: 'supModule', values: ['sup']},
+      {field: 'supControl', values: ['sup']},
+      {field: 'syncModule', values: ['sync']},
+      {field: 'checkAll', values: ['sync']},
+    ]
+  },
+  {
+    type: 'cascader',
+    field: 'supModule',
+    label: '涓婄骇缁勪欢',
+    initval: '',
+    required: true,
+    options: []
+  },
+  {
+    type: 'radio',
+    field: 'supControl',
+    label: '鏄剧ず鎺у埗',
+    tooltip: '褰撳墠缁勪欢鍦ㄤ富琛ㄩ�変腑琛屾椂鏄剧ず锛岃繕鏄缁堟樉绀恒��',
+    initval: 'show',
+    required: false,
+    options: [
+      {value: 'hidden', label: '閫夎'},
+      {value: 'show', label: '濮嬬粓'},
+    ]
+  },
+  {
+    type: 'cascader',
+    field: 'syncModule',
+    label: '鍚屾缁勪欢',
+    initval: '',
+    required: true,
+    options: []
+  },
+  {
+    type: 'radio',
+    field: 'checkAll',
+    label: '鍏ㄩ��',
+    initval: 'hidden',
+    tooltip: '褰撳悓姝ョ粍浠跺彲澶氶�夋椂锛岃缃叏閫夋湁鏁堛��',
+    required: false,
+    options: [
+      {value: 'hidden', label: '闅愯棌'},
+      {value: 'show', label: '鏄剧ず'},
+    ]
+  },
+  {
+    type: 'radio',
+    field: 'position',
+    label: '浣嶇疆',
+    initval: 'relative',
+    tooltip: '浣跨敤鍥哄畾瀹氫綅鏃讹紝璇峰湪娴嬭瘯鐜涓煡鐪嬪畾浣嶆晥鏋溿��',
+    required: false,
+    options: [
+      {value: 'relative', label: '鐩稿瀹氫綅'},
+      {value: 'fixed', label: '鍥哄畾瀹氫綅'},
+    ],
+    controlFields: [
+      {field: 'quick', values: ['fixed']},
+      {field: 'top', values: ['fixed']},
+      {field: 'right', values: ['fixed']},
+      {field: 'bottom', values: ['fixed']},
+      {field: 'left', values: ['fixed']},
+      {field: 'realwidth', values: ['fixed']},
+      {field: 'transform', values: ['fixed']},
+    ]
+  },
+  {
+    type: 'select',
+    field: 'quick',
+    label: '蹇嵎閫夋嫨',
+    initval: '',
+    required: false,
+    subFields: ['top', 'left', 'right', 'bottom', 'transform'],
+    options: [
+      {value: 'top', label: '涓�', top: '0px', left: '0px', right: '0px', bottom: '', transform: ''},
+      {value: 'top-left', label: '宸︿笂', top: '0px', left: '0px', right: '', bottom: '', transform: ''},
+      {value: 'top-right', label: '鍙充笂', top: '0px', left: '', right: '0px', bottom: '', transform: ''},
+      {value: 'left-middle', label: '宸︿腑', top: '50%', left: '0px', right: '', bottom: '', transform: 'translateY(-50%)'},
+      {value: 'right-middle', label: '鍙充腑', top: '50%', left: '', right: '0px', bottom: '', transform: 'translateY(-50%)'},
+      {value: 'bottom-left', label: '宸︿笅', top: '', left: '0px', right: '', bottom: '0px', transform: ''},
+      {value: 'bottom-right', label: '鍙充笅', top: '', left: '', right: '0px', bottom: '0px', transform: ''},
+      {value: 'bottom', label: '涓�', top: '', left: '0px', right: '0px', bottom: '0px', transform: ''},
+      {value: 'middle', label: '涓棿', top: '50%', left: '50%', right: '', bottom: '', transform: 'translate(-50%, -50%)'}
+    ]
+  },
+  {
+    type: 'styleInput',
+    field: 'top',
+    label: '璺濅笂',
+    initval: '',
+    required: false
+  },
+  {
+    type: 'styleInput',
+    field: 'right',
+    label: '璺濆彸',
+    initval: '',
+    required: false
+  },
+  {
+    type: 'styleInput',
+    field: 'bottom',
+    label: '璺濅笅',
+    initval: '',
+    required: false
+  },
+  {
+    type: 'styleInput',
+    field: 'left',
+    label: '璺濆乏',
+    initval: '',
+    required: false
+  },
+  {
+    type: 'styleInput',
+    field: 'realwidth',
+    label: '瀹為檯瀹藉害',
+    initval: '',
+    required: false
+  },
+  {
+    type: 'select',
+    field: 'transform',
+    label: '鍙樻崲',
+    initval: '',
+    required: false,
+    options: [
+      {value: 'translateY(-50%)', label: '涓婄Щ50%'},
+      {value: 'translateY(50%)', label: '涓嬬Щ50%'},
+      {value: 'translateX(-50%)', label: '宸︾Щ50%'},
+      {value: 'translateX(50%)', label: '鍙崇Щ50%'},
+      {value: 'translate(-50%, -50%)', label: '宸︿笂绉�50%'},
+      {value: 'translate(-50%, 50%)', label: '宸︿笅绉�50%'},
+      {value: 'translate(50%, -50%)', label: '鍙充笂绉�50%'},
+      {value: 'translate(50%, 50%)', label: '鍙充笅绉�50%'},
+    ]
+  },
+  {
+    type: 'multiselect',
+    field: 'blacklist',
+    label: '榛戝悕鍗�',
+    initval: '',
+    required: false,
+    options: []
+  },
+]
\ No newline at end of file
diff --git a/src/menu/components/card/balcony/wrapsetting/index.jsx b/src/menu/components/card/balcony/wrapsetting/index.jsx
deleted file mode 100644
index a8332db..0000000
--- a/src/menu/components/card/balcony/wrapsetting/index.jsx
+++ /dev/null
@@ -1,83 +0,0 @@
-import React, {Component} from 'react'
-import PropTypes from 'prop-types'
-import { is, fromJS } from 'immutable'
-import { Icon, Modal } from 'antd'
-
-import zhCN from '@/locales/zh-CN/model.js'
-import enUS from '@/locales/en-US/model.js'
-import SettingForm from './settingform'
-import './index.scss'
-
-class BalconyWrapSetting extends Component {
-  static propTpyes = {
-    config: PropTypes.any,
-    updateConfig: PropTypes.func
-  }
-
-  state = {
-    dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS,
-    visible: false,
-    wrap: null
-  }
-
-  UNSAFE_componentWillMount () {
-    const { config } = this.props
-
-    this.setState({wrap: fromJS(config.wrap).toJS()})
-  }
-
-  shouldComponentUpdate (nextProps, nextState) {
-    return !is(fromJS(this.props), fromJS(nextProps)) || !is(fromJS(this.state), fromJS(nextState))
-  }
-
-  editDataSource = () => {
-    this.setState({
-      visible: true
-    })
-  }
-
-  verifySubmit = () => {
-    const { config } = this.props
-
-    this.verifyRef.handleConfirm().then(res => {
-
-      this.setState({
-        wrap: res,
-        visible: false
-      })
-      this.props.updateConfig({...config, wrap: res})
-    })
-  }
-
-  render () {
-    const { config } = this.props
-    const { visible, dict, wrap } = this.state
-
-    return (
-      <div className="model-menu-setting-wrap">
-        <Icon type="edit" title="缂栬緫" onClick={() => this.editDataSource()} />
-        <Modal
-          wrapClassName="popview-modal"
-          title="鍗$墖璁剧疆"
-          visible={visible}
-          width={800}
-          maskClosable={false}
-          okText={dict['model.submit']}
-          onOk={this.verifySubmit}
-          onCancel={() => { this.setState({ visible: false }) }}
-          destroyOnClose
-        >
-          <SettingForm
-            dict={dict}
-            wrap={wrap}
-            config={config}
-            inputSubmit={this.verifySubmit}
-            wrappedComponentRef={(inst) => this.verifyRef = inst}
-          />
-        </Modal>
-      </div>
-    )
-  }
-}
-
-export default BalconyWrapSetting
\ No newline at end of file
diff --git a/src/menu/components/card/balcony/wrapsetting/index.scss b/src/menu/components/card/balcony/wrapsetting/index.scss
deleted file mode 100644
index 04372e6..0000000
--- a/src/menu/components/card/balcony/wrapsetting/index.scss
+++ /dev/null
@@ -1,7 +0,0 @@
-.model-menu-setting-wrap {
-  display: inline-block;
-
-  >.anticon-edit {
-    color: #1890ff;
-  }
-}
\ No newline at end of file
diff --git a/src/menu/components/card/balcony/wrapsetting/settingform/index.jsx b/src/menu/components/card/balcony/wrapsetting/settingform/index.jsx
deleted file mode 100644
index d0124d5..0000000
--- a/src/menu/components/card/balcony/wrapsetting/settingform/index.jsx
+++ /dev/null
@@ -1,415 +0,0 @@
-import React, {Component} from 'react'
-import PropTypes from 'prop-types'
-import { fromJS } from 'immutable'
-import { Form, Row, Col, Input, Radio, Tooltip, Icon, InputNumber, Select, Cascader } from 'antd'
-
-import MenuUtils from '@/utils/utils-custom.js'
-import StyleInput from '@/menu/components/share/styleInput'
-import './index.scss'
-
-class SettingForm extends Component {
-  static propTpyes = {
-    dict: PropTypes.object,
-    config: PropTypes.object,
-    wrap: PropTypes.object,
-    inputSubmit: PropTypes.func
-  }
-
-  state = {
-    roleList: [],
-    modules: [],
-    supmodules: [],
-    appType: sessionStorage.getItem('appType'),
-    linkType: this.props.wrap.linkType,
-    position: this.props.wrap.position,
-  }
-
-  UNSAFE_componentWillMount () {
-    let roleList = sessionStorage.getItem('sysRoles')
-    if (roleList) {
-      try {
-        roleList = JSON.parse(roleList)
-      } catch {
-        roleList = []
-      }
-    } else {
-      roleList = []
-    }
-
-    let menu = fromJS(window.GLOB.customMenu).toJS()
-
-    let modules = MenuUtils.getLinkModules(menu.components)
-    if (!modules) {
-      modules = []
-    }
-
-    let _menu = fromJS(window.GLOB.customMenu).toJS()
-
-    let supmodules = MenuUtils.getSupModules(_menu.components, '')
-    if (!supmodules) {
-      supmodules = []
-    }
-
-    this.setState({roleList, modules, supmodules})
-  }
-
-  handleConfirm = () => {
-    // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭�
-    return new Promise((resolve, reject) => {
-      this.props.form.validateFieldsAndScroll((err, values) => {
-        if (!err) {
-          resolve(values)
-        } else {
-          reject(err)
-        }
-      })
-    })
-  }
-
-  handleSubmit = (e) => {
-    e.preventDefault()
-
-    if (this.props.inputSubmit) {
-      this.props.inputSubmit()
-    }
-  }
-
-  chose = (val) => {
-    let values = {}
-    if (val === 'top') {
-      values = {
-        top: '0px',
-        left: '50%',
-        right: '',
-        bottom: '',
-        transform: 'translateX(-50%)'
-      }
-    } else if (val === 'top-left') {
-      values = {
-        top: '0px',
-        left: '0px',
-        right: '',
-        bottom: '',
-        transform: ''
-      }
-    } else if (val === 'top-right') {
-      values = {
-        top: '0px',
-        left: '',
-        right: '0px',
-        bottom: '',
-        transform: ''
-      }
-    } else if (val === 'left-middle') {
-      values = {
-        top: '50%',
-        left: '0px',
-        right: '',
-        bottom: '',
-        transform: 'translateY(-50%)'
-      }
-    } else if (val === 'right-middle') {
-      values = {
-        top: '50%',
-        left: '',
-        right: '0px',
-        bottom: '',
-        transform: 'translateY(-50%)'
-      }
-    } else if (val === 'bottom-left') {
-      values = {
-        top: '',
-        left: '0px',
-        right: '',
-        bottom: '0px',
-        transform: ''
-      }
-    } else if (val === 'bottom-right') {
-      values = {
-        top: '',
-        left: '',
-        right: '0px',
-        bottom: '0px',
-        transform: ''
-      }
-    } else if (val === 'bottom') {
-      values = {
-        top: '',
-        left: '50%',
-        right: '',
-        bottom: '0px',
-        transform: 'translateX(-50%)'
-      }
-    } else if (val === 'middle') {
-      values = {
-        top: '50%',
-        left: '50%',
-        right: '',
-        bottom: '',
-        transform: 'translate(-50%, -50%)'
-      }
-    }
-    this.props.form.setFieldsValue(values)
-  }
-
-  render() {
-    const { wrap } = this.props
-    const { getFieldDecorator } = this.props.form
-    const { roleList, modules, supmodules, linkType, position } = this.state
-
-    const formItemLayout = {
-      labelCol: {
-        xs: { span: 24 },
-        sm: { span: 8 }
-      },
-      wrapperCol: {
-        xs: { span: 24 },
-        sm: { span: 16 }
-      }
-    }
-
-    return (
-      <div className="model-menu-setting-form">
-        <Form {...formItemLayout}>
-          <Row gutter={24}>
-            <Col span={12}>
-              <Form.Item label={
-                <Tooltip placement="topLeft" title="鐢ㄤ簬缁勪欢闂寸殑鍖哄垎銆�">
-                  <Icon type="question-circle" />
-                  缁勪欢鍚嶇О
-                </Tooltip>
-              }>
-                {getFieldDecorator('name', {
-                  initialValue: wrap.name,
-                  rules: [
-                    {
-                      required: true,
-                      message: this.props.dict['form.required.input'] + '缁勪欢鍚嶇О!'
-                    }
-                  ]
-                })(<Input placeholder={''} autoComplete="off" onPressEnter={this.handleSubmit} />)}
-              </Form.Item>
-            </Col>
-            <Col span={12}>
-              <Form.Item label={
-                <Tooltip placement="topLeft" title="鏍呮牸甯冨眬锛屾瘡琛岀瓑鍒嗕负24鍒椼��">
-                  <Icon type="question-circle" />
-                  瀹藉害
-                </Tooltip>
-              }>
-                {getFieldDecorator('width', {
-                  initialValue: wrap.width || 24,
-                  rules: [
-                    {
-                      required: true,
-                      message: this.props.dict['form.required.input'] + '瀹藉害!'
-                    }
-                  ]
-                })(<InputNumber min={1} max={24} precision={0} onPressEnter={this.handleSubmit} />)}
-              </Form.Item>
-            </Col>
-            <Col span={12}>
-              <Form.Item label={
-                <Tooltip placement="topLeft" title="閫夋嫨闈欐�佸�硷紝鏃犻渶閰嶇疆鏁版嵁婧愩��">
-                  <Icon type="question-circle" />
-                  鏁版嵁鏉ユ簮
-                </Tooltip>
-              }>
-                {getFieldDecorator('datatype', {
-                  initialValue: wrap.datatype
-                })(
-                  <Radio.Group>
-                    <Radio value="dynamic">鍔ㄦ��</Radio>
-                    <Radio value="static">闈欐��</Radio>
-                  </Radio.Group>
-                )}
-              </Form.Item>
-            </Col>
-            <Col span={12}>
-              <Form.Item label={
-                <Tooltip placement="topLeft" title="缁勪欢涓庡叾浠栫粍浠朵箣闂寸殑鎺у埗绫诲瀷锛岀嫭绔嬭〃绀轰笌鍏朵粬娌℃湁鍏宠仈銆�">
-                  <Icon type="question-circle" />
-                  鍙楁帶绫诲瀷
-                </Tooltip>
-              }>
-                {getFieldDecorator('linkType', {
-                  initialValue: wrap.linkType || 'static'
-                })(
-                  <Radio.Group onChange={(e) => this.setState({linkType: e.target.value})}>
-                    <Radio value="static">鐙珛</Radio>
-                    <Radio value="sync">鍚屾</Radio>
-                    <Radio value="sup">涓婄骇</Radio>
-                  </Radio.Group>
-                )}
-              </Form.Item>
-            </Col>
-            {linkType === 'sup' ? <Col span={12}>
-              <Form.Item label="涓婄骇缁勪欢">
-                {getFieldDecorator('supModule', {
-                  initialValue: wrap.supModule,
-                  rules: [
-                    {
-                      required: true,
-                      message: this.props.dict['form.required.select'] + '涓婄骇缁勪欢!'
-                    }
-                  ]
-                })(
-                  <Cascader options={supmodules} expandTrigger="hover" placeholder="" />
-                )}
-              </Form.Item>
-            </Col> : null}
-            {linkType === 'sup' ? <Col span={12}>
-              <Form.Item label="鏄剧ず鎺у埗">
-                {getFieldDecorator('supControl', {
-                  initialValue: wrap.supControl || 'show'
-                })(
-                  <Radio.Group>
-                    <Radio key="hidden" value="hidden"> 閫夎鏄剧ず </Radio>
-                    <Radio key="show" value="show"> 濮嬬粓鏄剧ず </Radio>
-                  </Radio.Group>
-                )}
-              </Form.Item>
-            </Col> : null}
-            {linkType === 'sync' ? <Col span={12}>
-              <Form.Item label="鍚屾缁勪欢">
-                {getFieldDecorator('syncModule', {
-                  initialValue: wrap.syncModule,
-                  rules: [
-                    {
-                      required: true,
-                      message: this.props.dict['form.required.select'] + '鍚屾缁勪欢!'
-                    }
-                  ]
-                })(
-                  <Cascader options={modules} expandTrigger="hover" placeholder="" />
-                )}
-              </Form.Item>
-            </Col> : null}
-            {linkType === 'sync' ? <Col span={12}>
-              <Form.Item label={
-                <Tooltip placement="topLeft" title="褰撳悓姝ョ粍浠跺彲澶氶�夋椂锛岃缃叏閫夋湁鏁堛��">
-                  <Icon type="question-circle" />
-                  鍏ㄩ��
-                </Tooltip>
-              }>
-                {getFieldDecorator('checkAll', {
-                  initialValue: wrap.checkAll || 'hidden'
-                })(
-                  <Radio.Group>
-                    <Radio key="hidden" value="hidden"> 闅愯棌 </Radio>
-                    <Radio key="show" value="show"> 鏄剧ず </Radio>
-                  </Radio.Group>
-                )}
-              </Form.Item>
-            </Col> : null}
-            <Col span={12}>
-              <Form.Item label={
-                <Tooltip placement="topLeft" title="浣跨敤鍥哄畾瀹氫綅鏃讹紝璇峰湪娴嬭瘯鐜涓煡鐪嬪畾浣嶆晥鏋溿��">
-                  <Icon type="question-circle" />
-                  浣嶇疆
-                </Tooltip>
-              }>
-                {getFieldDecorator('position', {
-                  initialValue: wrap.position || 'relative'
-                })(
-                  <Radio.Group onChange={(e) => this.setState({position: e.target.value})}>
-                    <Radio value="relative">鐩稿瀹氫綅</Radio>
-                    <Radio value="fixed">鍥哄畾瀹氫綅</Radio>
-                  </Radio.Group>
-                )}
-              </Form.Item>
-            </Col>
-            {position === 'fixed' ? <Col span={12}>
-              <Form.Item label="蹇嵎閫夋嫨">
-                <Select onSelect={this.chose}>
-                  <Select.Option key='1' value={'top'}>涓�</Select.Option>
-                  <Select.Option key='2' value={'top-left'}>宸︿笂</Select.Option>
-                  <Select.Option key='3' value={'top-right'}>鍙充笂</Select.Option>
-                  <Select.Option key='4' value={'left-middle'}>宸︿腑</Select.Option>
-                  <Select.Option key='5' value={'right-middle'}>鍙充腑</Select.Option>
-                  <Select.Option key='6' value={'bottom-left'}>宸︿笅</Select.Option>
-                  <Select.Option key='7' value={'bottom-right'}>鍙充笅</Select.Option>
-                  <Select.Option key='8' value={'bottom'}>涓�</Select.Option>
-                  <Select.Option key='9' value={'middle'}>涓棿</Select.Option>
-                </Select>
-              </Form.Item>
-            </Col> : null}
-            {position === 'fixed' ? <Col span={12}>
-              <Form.Item label="璺濅笂">
-                {getFieldDecorator('top', {
-                  initialValue: wrap.top || ''
-                })(<StyleInput options={['px', 'vh', 'vw', '%']} />)}
-              </Form.Item>
-            </Col> : null}
-            {position === 'fixed' ? <Col span={12}>
-              <Form.Item label="璺濆彸">
-                {getFieldDecorator('right', {
-                  initialValue: wrap.right || ''
-                })(<StyleInput options={['px', 'vh', 'vw', '%']} />)}
-              </Form.Item>
-            </Col> : null}
-            {position === 'fixed' ? <Col span={12}>
-              <Form.Item label="璺濅笅">
-                {getFieldDecorator('bottom', {
-                  initialValue: wrap.bottom || ''
-                })(<StyleInput options={['px', 'vh', 'vw', '%']} />)}
-              </Form.Item>
-            </Col> : null}
-            {position === 'fixed' ? <Col span={12}>
-              <Form.Item label="璺濆乏">
-                {getFieldDecorator('left', {
-                  initialValue: wrap.left || ''
-                })(<StyleInput options={['px', 'vh', 'vw', '%']} />)}
-              </Form.Item>
-            </Col> : null}
-            {position === 'fixed' ? <Col span={12}>
-              <Form.Item label="瀹為檯瀹藉害">
-                {getFieldDecorator('realwidth', {
-                  initialValue: wrap.realwidth || ''
-                })(<StyleInput options={['px', 'vh', 'vw', '%']} />)}
-              </Form.Item>
-            </Col> : null}
-            {position === 'fixed' ? <Col span={12}>
-              <Form.Item label="鍙樻崲">
-                {getFieldDecorator('transform', {
-                  initialValue: wrap.transform || ''
-                })(
-                  <Select>
-                    <Select.Option key='1' value={''}>鏃�</Select.Option>
-                    <Select.Option key='2' value={'translateY(-50%)'}>涓婄Щ50%</Select.Option>
-                    <Select.Option key='3' value={'translateY(50%)'}>涓嬬Щ50%</Select.Option>
-                    <Select.Option key='4' value={'translateX(-50%)'}>宸︾Щ50%</Select.Option>
-                    <Select.Option key='5' value={'translateX(50%)'}>鍙崇Щ50%</Select.Option>
-                    <Select.Option key='6' value={'translate(-50%, -50%)'}>宸︿笂绉�50%</Select.Option>
-                    <Select.Option key='7' value={'translate(-50%, 50%)'}>宸︿笅绉�50%</Select.Option>
-                    <Select.Option key='8' value={'translate(50%, -50%)'}>鍙充笂绉�50%</Select.Option>
-                    <Select.Option key='9' value={'translate(50%, 50%)'}>鍙充笅绉�50%</Select.Option>
-                  </Select>
-                )}
-              </Form.Item>
-            </Col> : null}
-            <Col span={12}>
-              <Form.Item label="榛戝悕鍗�">
-                {getFieldDecorator('blacklist', {
-                  initialValue: wrap.blacklist || []
-                })(
-                  <Select
-                    showSearch
-                    mode="multiple"
-                    filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0}
-                  >
-                    {roleList.map(option =>
-                      <Select.Option key={option.uuid} value={option.value}>{option.text}</Select.Option>
-                    )}
-                  </Select>
-                )}
-              </Form.Item>
-            </Col>
-          </Row>
-        </Form>
-      </div>
-    )
-  }
-}
-
-export default Form.create()(SettingForm)
\ No newline at end of file
diff --git a/src/menu/components/card/balcony/wrapsetting/settingform/index.scss b/src/menu/components/card/balcony/wrapsetting/settingform/index.scss
deleted file mode 100644
index 9644e12..0000000
--- a/src/menu/components/card/balcony/wrapsetting/settingform/index.scss
+++ /dev/null
@@ -1,36 +0,0 @@
-.model-menu-setting-form {
-  position: relative;
-
-  .anticon-question-circle {
-    color: #c49f47;
-    margin-right: 3px;
-  }
-  .ant-input-number {
-    width: 100%;
-  }
-  .css {
-    padding-top: 10px;
-    .css-class {
-      position: absolute;
-      right: 13px;
-      top: -15px;
-      z-index: 1;
-      button {
-        height: 25px;
-      }
-    }
-    .ant-form-item {
-      margin-bottom: 0;
-    }
-    .ant-form-item-label {
-      width: 16%;
-    }
-    .ant-form-item-control-wrapper {
-      width: 84%;
-      .code-mirror-wrap .code-mirror-area .CodeMirror {
-        height: 100px;
-        min-height: 100px;
-      }
-    }
-  }
-}
\ No newline at end of file
diff --git a/src/menu/components/card/cardcellcomponent/dragaction/action.jsx b/src/menu/components/card/cardcellcomponent/dragaction/action.jsx
index 2eb2c8e..60cf952 100644
--- a/src/menu/components/card/cardcellcomponent/dragaction/action.jsx
+++ b/src/menu/components/card/cardcellcomponent/dragaction/action.jsx
@@ -48,7 +48,7 @@
 
   return (
     <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={
-      <div className="mk-popover-control">
+      <div className="mk-popover-control" onDoubleClick={(e) => e.stopPropagation()}>
         <Icon className="edit" title="缂栬緫" type="edit" onClick={() => editCard(id)} />
         <Icon className="copy" title="澶嶅埗" type="copy" onClick={() => copyCard(id)} />
         <Icon className="close" title="鍒犻櫎" type="close" onClick={() => delCard(id)} />
diff --git a/src/menu/components/card/cardcellcomponent/dragaction/card.jsx b/src/menu/components/card/cardcellcomponent/dragaction/card.jsx
index 9ee5976..9982b08 100644
--- a/src/menu/components/card/cardcellcomponent/dragaction/card.jsx
+++ b/src/menu/components/card/cardcellcomponent/dragaction/card.jsx
@@ -24,7 +24,7 @@
   '10:1': '10%', '3:4': '133.33%', '2:3': '150%', '9:16': '177.78%'
 }
 
-const Card = ({ id, parent, fields, card, moveCard, findCard, editCard, delCard, copyCard, changeStyle, updateMarks, doubleClickCard }) => {
+const Card = ({ id, parent, fields, card, moveCard, findCard, editCard, delCard, copyCard, changeStyle, updateMarks }) => {
   const originalIndex = findCard(id).index
   const [{ isDragging }, drag] = useDrag({
     item: { type: 'action', id, originalIndex },
@@ -153,7 +153,7 @@
 
   return (
     <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={
-      <div className="mk-popover-control">
+      <div className="mk-popover-control" onDoubleClick={(e) => e.stopPropagation()}>
         <Icon className="edit" title="缂栬緫" type="edit" onClick={() => editCard(id)} />
         <Icon className="copy" title="澶嶅埗" type="copy" onClick={() => copyCard(id)} />
         <Icon className="close" title="鍒犻櫎" type="close" onClick={() => delCard(id)} />
@@ -162,7 +162,7 @@
       </div>
     } trigger="hover">
       <div ref={node => drag(drop(node))} className={'ant-col card-cell ant-col-' + card.width}>
-        <div style={_style} onClick={clickComponent} onDoubleClick={() => doubleClickCard(id)} id={card.uuid}>
+        <div style={_style} onClick={clickComponent} id={card.uuid}>
           {getContent()}
         </div>
       </div>
diff --git a/src/menu/components/card/cardcellcomponent/dragaction/index.jsx b/src/menu/components/card/cardcellcomponent/dragaction/index.jsx
index 96eea80..64bb8d9 100644
--- a/src/menu/components/card/cardcellcomponent/dragaction/index.jsx
+++ b/src/menu/components/card/cardcellcomponent/dragaction/index.jsx
@@ -85,7 +85,7 @@
   const doubleClickCard = id => {
     const { card } = findCard(id)
 
-    if (card.eleType !== 'button' && card.eleType !== 'text' && card.eleType !== 'picture') {
+    if (card.eleType !== 'button') {
       return
     }
     
@@ -139,7 +139,6 @@
               editCard={editCard}
               updateMarks={updateMarks}
               changeStyle={changeStyle}
-              doubleClickCard={doubleClickCard}
               delCard={delCard}
               findCard={findCard}
             />
diff --git a/src/menu/components/card/cardcellcomponent/dragaction/index.scss b/src/menu/components/card/cardcellcomponent/dragaction/index.scss
index 2b2ec2c..b851536 100644
--- a/src/menu/components/card/cardcellcomponent/dragaction/index.scss
+++ b/src/menu/components/card/cardcellcomponent/dragaction/index.scss
@@ -100,6 +100,23 @@
     font-weight: inherit;
     font-style: inherit;
   }
+  .ant-mk-check {
+    white-space: nowrap;
+    overflow: hidden;
+    word-break: break-word;
+    text-overflow: ellipsis;
+    font-weight: inherit;
+    font-style: inherit;
+    .ant-checkbox-wrapper {
+      font-weight: inherit;
+      font-size: inherit;
+      font-style: inherit;
+      color: inherit;
+      span {
+        font-weight: inherit;
+      }
+    }
+  }
   .ant-mk-picture {
     background-size: cover;
     background-position: center center;
diff --git a/src/menu/components/card/cardcellcomponent/formconfig.jsx b/src/menu/components/card/cardcellcomponent/formconfig.jsx
index 526d6e6..25e2135 100644
--- a/src/menu/components/card/cardcellcomponent/formconfig.jsx
+++ b/src/menu/components/card/cardcellcomponent/formconfig.jsx
@@ -25,6 +25,7 @@
   if (type === 'table' || (type === 'card' && subtype === 'datacard')) {
     _options.push({value: 'sequence', text: '搴忓彿'})
   }
+
   let appMenus = []
   const isApp = sessionStorage.getItem('appType') === 'pc'
 
diff --git a/src/menu/components/card/cardcellcomponent/index.jsx b/src/menu/components/card/cardcellcomponent/index.jsx
index e46935d..3c5154c 100644
--- a/src/menu/components/card/cardcellcomponent/index.jsx
+++ b/src/menu/components/card/cardcellcomponent/index.jsx
@@ -595,94 +595,96 @@
           handleSubConfig={this.handleSubConfig}
           deleteMenu={this.deleteElement}
         />
-        {/* 缂栬緫鎸夐挳锛氬鍒躲�佺紪杈� */}
-        <Modal
-          title={'缂栬緫鍏冪礌'}
-          visible={visible}
-          width={800}
-          maskClosable={false}
-          onCancel={this.editModalCancel}
-          onOk={this.handleSubmit}
-          destroyOnClose
-        >
-          <ElementForm
-            dict={dict}
-            card={card}
-            formlist={this.state.formlist}
-            inputSubmit={this.handleSubmit}
-            config={cards}
-            wrappedComponentRef={(inst) => this.elementFormRef = inst}
-          />
-        </Modal>
-        {/* 缂栬緫鎸夐挳锛氬鍒躲�佺紪杈� */}
-        <Modal
-          title={dict['model.action'] + '-' + (card && card.copyType === 'action' ? dict['model.copy'] : dict['model.edit'])}
-          visible={actvisible}
-          width={800}
-          maskClosable={false}
-          onCancel={this.editModalCancel}
-          footer={[
-            <Button key="cancel" onClick={this.editModalCancel}>{dict['model.cancel']}</Button>,
-            <Button key="confirm" type="primary" onClick={this.handleActionSubmit}>{dict['model.confirm']}</Button>
-          ]}
-          destroyOnClose
-        >
-          <ActionForm
-            dict={dict}
-            type={cards.type === 'balcony' ? '' : 'card'}
-            card={card}
-            formlist={this.state.formlist}
-            inputSubmit={this.handleActionSubmit}
-            setting={cards.setting}
-            wrappedComponentRef={(inst) => this.actionFormRef = inst}
-          />
-        </Modal>
-        {/* 鎸夐挳浣跨敤绯荤粺瀛樺偍杩囩▼鏃讹紝楠岃瘉淇℃伅妯℃�佹 */}
-        <Modal
-          wrapClassName="model-table-action-verify-modal"
-          title={'楠岃瘉淇℃伅'}
-          visible={profVisible}
-          width={'75vw'}
-          maskClosable={false}
-          okText={dict['model.submit']}
-          onOk={this.verifySubmit}
-          onCancel={() => { this.setState({ profVisible: false }) }}
-          destroyOnClose
-        >
-          {card && !card.execMode && card.OpenType !== 'excelIn' && card.OpenType !== 'excelOut' ?
-            <VerifyCard
-              card={card}
+        <div onDoubleClick={(e) => e.stopPropagation()}>
+          {/* 缂栬緫鎸夐挳锛氬鍒躲�佺紪杈� */}
+          <Modal
+            title={'缂栬緫鍏冪礌'}
+            visible={visible}
+            width={800}
+            maskClosable={false}
+            onCancel={this.editModalCancel}
+            onOk={this.handleSubmit}
+            destroyOnClose
+          >
+            <ElementForm
               dict={dict}
+              card={card}
+              formlist={this.state.formlist}
+              inputSubmit={this.handleSubmit}
               config={cards}
-              columns={cards.columns}
-              wrappedComponentRef={(inst) => this.verifyRef = inst}
-            /> : null
-          }
-          {card && card.execMode ?
-            <VerifyPrint
-              card={card}
+              wrappedComponentRef={(inst) => this.elementFormRef = inst}
+            />
+          </Modal>
+          {/* 缂栬緫鎸夐挳锛氬鍒躲�佺紪杈� */}
+          <Modal
+            title={dict['model.action'] + '-' + (card && card.copyType === 'action' ? dict['model.copy'] : dict['model.edit'])}
+            visible={actvisible}
+            width={800}
+            maskClosable={false}
+            onCancel={this.editModalCancel}
+            footer={[
+              <Button key="cancel" onClick={this.editModalCancel}>{dict['model.cancel']}</Button>,
+              <Button key="confirm" type="primary" onClick={this.handleActionSubmit}>{dict['model.confirm']}</Button>
+            ]}
+            destroyOnClose
+          >
+            <ActionForm
               dict={dict}
-              columns={cards.columns}
-              wrappedComponentRef={(inst) => this.verifyRef = inst}
-            /> : null
-          }
-          {card && card.OpenType === 'excelIn' ?
-            <VerifyExcelIn
+              type={cards.type === 'balcony' ? '' : 'card'}
               card={card}
-              dict={dict}
-              columns={cards.columns}
-              wrappedComponentRef={(inst) => this.verifyRef = inst}
-            /> : null
-          }
-          {card && card.OpenType === 'excelOut' ?
-            <VerifyExcelOut
-              card={card}
-              dict={dict}
-              config={cards}
-              wrappedComponentRef={(inst) => this.verifyRef = inst}
-            /> : null
-          }
-        </Modal>
+              formlist={this.state.formlist}
+              inputSubmit={this.handleActionSubmit}
+              setting={cards.setting}
+              wrappedComponentRef={(inst) => this.actionFormRef = inst}
+            />
+          </Modal>
+          {/* 鎸夐挳浣跨敤绯荤粺瀛樺偍杩囩▼鏃讹紝楠岃瘉淇℃伅妯℃�佹 */}
+          <Modal
+            wrapClassName="model-table-action-verify-modal"
+            title={'楠岃瘉淇℃伅'}
+            visible={profVisible}
+            width={'75vw'}
+            maskClosable={false}
+            okText={dict['model.submit']}
+            onOk={this.verifySubmit}
+            onCancel={() => { this.setState({ profVisible: false }) }}
+            destroyOnClose
+          >
+            {card && !card.execMode && card.OpenType !== 'excelIn' && card.OpenType !== 'excelOut' ?
+              <VerifyCard
+                card={card}
+                dict={dict}
+                config={cards}
+                columns={cards.columns}
+                wrappedComponentRef={(inst) => this.verifyRef = inst}
+              /> : null
+            }
+            {card && card.execMode ?
+              <VerifyPrint
+                card={card}
+                dict={dict}
+                columns={cards.columns}
+                wrappedComponentRef={(inst) => this.verifyRef = inst}
+              /> : null
+            }
+            {card && card.OpenType === 'excelIn' ?
+              <VerifyExcelIn
+                card={card}
+                dict={dict}
+                columns={cards.columns}
+                wrappedComponentRef={(inst) => this.verifyRef = inst}
+              /> : null
+            }
+            {card && card.OpenType === 'excelOut' ?
+              <VerifyExcelOut
+                card={card}
+                dict={dict}
+                config={cards}
+                wrappedComponentRef={(inst) => this.verifyRef = inst}
+              /> : null
+            }
+          </Modal>
+        </div>
       </div>
     )
   }
diff --git a/src/menu/components/card/cardcomponent/index.jsx b/src/menu/components/card/cardcomponent/index.jsx
index 84a1b6d..6bfc194 100644
--- a/src/menu/components/card/cardcomponent/index.jsx
+++ b/src/menu/components/card/cardcomponent/index.jsx
@@ -251,7 +251,7 @@
       <Col span={card.setting.width || 6} offset={offset || 0}>
         <div className="card-item" style={_style} onClick={this.clickComponent} onDoubleClick={(e) => {e.stopPropagation(); this.doubleClickCard()}} id={card.uuid}>
           <CardCellComponent cards={cards} cardCell={card} side={side} elements={elements} updateElement={this.updateCard}/>
-          <div className="card-control">
+          <div className="card-control" onDoubleClick={(e) => e.stopPropagation()}>
             <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={
               <div className="mk-popover-control">
                 <Icon className="plus" title="娣诲姞鍏冪礌" onClick={this.addElement} type="plus" />
diff --git a/src/tabviews/custom/components/card/cardcellList/index.scss b/src/tabviews/custom/components/card/cardcellList/index.scss
index 97c3ab3..76a5991 100644
--- a/src/tabviews/custom/components/card/cardcellList/index.scss
+++ b/src/tabviews/custom/components/card/cardcellList/index.scss
@@ -118,6 +118,22 @@
     word-break: break-word;
     text-overflow: ellipsis;
   }
+  .ant-mk-check {
+    white-space: nowrap;
+    overflow: hidden;
+    word-break: break-word;
+    text-overflow: ellipsis;
+    font-style: inherit;
+    .ant-checkbox-wrapper {
+      font-weight: inherit;
+      font-size: inherit;
+      font-style: inherit;
+      color: inherit;
+      span {
+        font-weight: inherit;
+      }
+    }
+  }
   .ant-slider {
     margin: 0px;
   }
diff --git a/src/tabviews/zshare/mutilform/index.jsx b/src/tabviews/zshare/mutilform/index.jsx
index 11b09d1..eda166d 100644
--- a/src/tabviews/zshare/mutilform/index.jsx
+++ b/src/tabviews/zshare/mutilform/index.jsx
@@ -663,7 +663,7 @@
         if (item.type === 'text' || item.type === 'linkMain') {
           content = (<MKInput config={item} onChange={(val, defer) => !defer && this.recordChange({[item.field]: val})} onSubmit={this.props.inputSubmit} />)
         } else if (item.type === 'number') {
-          content = (<MKNumberInput config={item} onChange={(val) => this.recordChange({[item.field]: val})} onSubmit={this.props.inputSubmit} />)
+          content = (<MKNumberInput config={item} onChange={(val, defer) => !defer && this.recordChange({[item.field]: val})} onSubmit={this.props.inputSubmit} />)
         } else if (item.type === 'select' || item.type === 'link' || item.type === 'multiselect') {
           content = (<MKSelect config={item} onChange={(val, other) => this.recordChange({[item.field]: val, ...other}, item)} onSubmit={this.props.inputSubmit} />)
         } else if (item.type === 'color') {
diff --git a/src/tabviews/zshare/mutilform/mkNumberInput/index.jsx b/src/tabviews/zshare/mutilform/mkNumberInput/index.jsx
index 7dde469..3bf2183 100644
--- a/src/tabviews/zshare/mutilform/mkNumberInput/index.jsx
+++ b/src/tabviews/zshare/mutilform/mkNumberInput/index.jsx
@@ -43,13 +43,13 @@
       this.inputNumberRef.current.focus()
     } else if (type === 'input') {
       this.setState({value})
+      this.props.onChange(value, true)
     }
   }
 
   handleChange = (val) => {
-
-    this.props.onChange(val)
     this.setState({value: val})
+    this.props.onChange(val)
   }
 
   render() {
diff --git a/src/tabviews/zshare/mutilform/mkSelect/index.jsx b/src/tabviews/zshare/mutilform/mkSelect/index.jsx
index 24da440..d754520 100644
--- a/src/tabviews/zshare/mutilform/mkSelect/index.jsx
+++ b/src/tabviews/zshare/mutilform/mkSelect/index.jsx
@@ -150,7 +150,7 @@
           value={value}
           filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0}
           onSelect={this.selectChange}
-          onClear={() => this.selectChange('')}
+          onChange={(val) => val === undefined && this.selectChange('')}
           disabled={config.readonly}
         >
           {options.map(option =>
diff --git a/src/templates/zshare/verifycard/index.jsx b/src/templates/zshare/verifycard/index.jsx
index 5e448f2..2c97765 100644
--- a/src/templates/zshare/verifycard/index.jsx
+++ b/src/templates/zshare/verifycard/index.jsx
@@ -831,7 +831,7 @@
         }
 
         _form = _form.join(', ')
-        _updatesql = `update ${card.sql} set ${_form} where ${config.setting.primaryKey}${card.Ot !== 'requiredOnce' ? '=@ID@' : ' in (select ID  from dbo.SplitComma(@ID@))'};`
+        _updatesql = `update ${card.sql} set ${_form} where ${config.setting.primaryKey || 'id'}${card.Ot !== 'requiredOnce' ? '=@ID@' : ' in (select ID  from dbo.SplitComma(@ID@))'};`
       }
 
       if (card.sqlType === 'insert') {
@@ -840,7 +840,7 @@
         _defaultsql = _updatesql
       } else if (card.sqlType === 'insertOrUpdate') {
         _defaultsql += `select @tbid=''
-          select @tbid='X' from ${card.sql} where ${config.setting.primaryKey}=@ID@
+          select @tbid='X' from ${card.sql} where ${config.setting.primaryKey || 'id'}=@ID@
           if @tbid=''
             begin
             ${_insertsql}
@@ -855,7 +855,7 @@
         if (_verify.voucher && _verify.voucher.enabled) {
           _voucher = ',BVoucher=@BVoucher,FIBVoucherDate=@FIBVoucherDate,FiYear=@FiYear'
         }
-        _defaultsql = `update ${card.sql} set deleted=1,modifydate=getdate(),modifyuserid=@userid@${_voucher} where ${config.setting.primaryKey}${card.Ot !== 'requiredOnce' ? '=@ID@' : ' in (select ID  from dbo.SplitComma(@ID@))'};`
+        _defaultsql = `update ${card.sql} set deleted=1,modifydate=getdate(),modifyuserid=@userid@${_voucher} where ${config.setting.primaryKey || 'id'}${card.Ot !== 'requiredOnce' ? '=@ID@' : ' in (select ID  from dbo.SplitComma(@ID@))'};`
       } else if (card.sqlType === 'delete') {
         let _msg = ''
         if (columns && columns.length > 0 && card.Ot !== 'notRequired' && card.Ot !== 'requiredOnce') {
@@ -867,7 +867,7 @@
             _index++
           })
         }
-        _defaultsql += `insert into snote (remark,createuserid,CreateUser,CreateStaff) select left('鍒犻櫎琛�:${card.sql} 鏁版嵁: ${_msg}${config.setting.primaryKey}='+@ID@,200),@userid@,@username,@fullname delete ${card.sql} where ${config.setting.primaryKey}${card.Ot !== 'requiredOnce' ? '=@ID@' : ' in (select ID  from dbo.SplitComma(@ID@))'};`
+        _defaultsql += `insert into snote (remark,createuserid,CreateUser,CreateStaff) select left('鍒犻櫎琛�:${card.sql} 鏁版嵁: ${_msg}${config.setting.primaryKey || 'id'}='+@ID@,200),@userid@,@username,@fullname delete ${card.sql} where ${config.setting.primaryKey}${card.Ot !== 'requiredOnce' ? '=@ID@' : ' in (select ID  from dbo.SplitComma(@ID@))'};`
       }
 
       let _columns = []

--
Gitblit v1.8.0