king
2020-11-10 5df578ff69f6b02e821d59a8883bc75d78695a62
2020-11-10
38个文件已修改
4个文件已添加
1593 ■■■■ 已修改文件
package-lock.json 95 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
package.json 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/sidemenu/config.jsx 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/locales/en-US/model.js 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/locales/zh-CN/model.js 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/actioncomponent/formconfig.jsx 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/cardcellcomponent/dragaction/index.scss 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/datasource/verifycard/columnform/index.jsx 34 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/datasource/verifycard/index.jsx 119 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/datasource/verifycard/index.scss 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/menuform/index.jsx 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/menushell/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/modalconfig/index.jsx 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/modelsource/index.jsx 23 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/modelsource/option.jsx 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/padcontroller/index.jsx 12 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/router/index.js 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/card/cardcellList/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/card/cardcellList/index.scss 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/card/table-card/index.jsx 47 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/card/table-card/index.scss 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/actionList/newpagebutton/index.jsx 16 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/comtableconfig/source.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/actioncomponent/actionform/index.jsx 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/actioncomponent/index.jsx 57 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/actioncomponent/verifyprint/index.jsx 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/fieldscomponent/index.jsx 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/settingcalcomponent/verifycard/index.jsx 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/settingcalcomponent/verifycard/index.scss 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/settingcomponent/settingform/index.jsx 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/settingcomponent/settingform/index.scss 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/treesettingcomponent/settingform/index.jsx 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/treesettingcomponent/settingform/index.scss 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/subtableconfig/source.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/editTable/index.jsx 257 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/editTable/index.scss 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/formconfig.jsx 20 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/verifycard/index.jsx 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/billprint/index.jsx 345 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/billprint/index.scss 160 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/menudesign/index.jsx 221 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/menudesign/index.scss 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
package-lock.json
@@ -4128,6 +4128,58 @@
        }
      }
    },
    "braft-convert": {
      "version": "2.3.0",
      "resolved": "https://registry.npmjs.org/braft-convert/-/braft-convert-2.3.0.tgz",
      "integrity": "sha512-5km+dLHk8iYDv2iEYDrDQ2ld/ZoUx66QLql0qdm5PqZEcNXc8dBHGLORfzeu3iMw1jLeAiHxtdY5+ypuIhczVg==",
      "requires": {
        "draft-convert": "^2.0.0",
        "draft-js": "^0.10.3"
      }
    },
    "braft-editor": {
      "version": "2.3.9",
      "resolved": "https://registry.npmjs.org/braft-editor/-/braft-editor-2.3.9.tgz",
      "integrity": "sha512-mqdPk/zI2dhFK8tW/A4Qj/AkkARLh5L/niNw+iif5wFqb6zh15rMlrShgz1nWO/QXyAKr8XtDgxiBbR0zWwtRg==",
      "requires": {
        "@babel/runtime": "^7.0.0",
        "braft-convert": "^2.3.0",
        "braft-finder": "^0.0.19",
        "braft-utils": "^3.0.8",
        "draft-convert": "^2.0.0",
        "draft-js": "^0.10.3",
        "draft-js-multidecorators": "^1.0.0",
        "draftjs-utils": "^0.9.4",
        "immutable": "~3.7.4"
      },
      "dependencies": {
        "immutable": {
          "version": "3.7.6",
          "resolved": "https://registry.npmjs.org/immutable/-/immutable-3.7.6.tgz",
          "integrity": "sha1-E7TTyxK++hVIKib+Gy665kAHHks="
        }
      }
    },
    "braft-extensions": {
      "version": "0.1.0",
      "resolved": "https://registry.npmjs.org/braft-extensions/-/braft-extensions-0.1.0.tgz",
      "integrity": "sha512-i7/GjJY2FCJUKqdHiFeohasWQvY1BMK1BU4KGDZo+K+d3i55sIsiBmmRRDrOazDLWBVqYi1rBu2uqFQvxJu1jw==",
      "requires": {
        "@babel/runtime": "^7.0.0",
        "braft-convert": "^2.1.10",
        "braft-utils": "^3.0.12"
      }
    },
    "braft-finder": {
      "version": "0.0.19",
      "resolved": "https://registry.npmjs.org/braft-finder/-/braft-finder-0.0.19.tgz",
      "integrity": "sha512-0kzI6/KbomJJhYX1hpjn4edCKhblyUyWdUrsgBmOrwy0vrj+pPkm69+Uf8Uj6KGAULM6LF0ooC++p7fqUGgFHw=="
    },
    "braft-utils": {
      "version": "3.0.12",
      "resolved": "https://registry.npmjs.org/braft-utils/-/braft-utils-3.0.12.tgz",
      "integrity": "sha512-O2cKysURNC4HSEMKgNmQ2RluwcrxvYrztlEmyPN5SzktiNX3vaLFQoo0Ez3PlIhvjaGrIBSIT2Oyh2N6mn6TFg=="
    },
    "brorand": {
      "version": "1.1.0",
      "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz",
@@ -5972,6 +6024,36 @@
      "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-4.2.0.tgz",
      "integrity": "sha1-3vHxyl1gWdJKdm5YeULCEQbOEnU="
    },
    "draft-convert": {
      "version": "2.1.10",
      "resolved": "https://registry.npmjs.org/draft-convert/-/draft-convert-2.1.10.tgz",
      "integrity": "sha512-PRdcjBqFUfEb2jlPM+bOyyCNlTzGaHdyhvKsw5nur6Dj1YclmuAiTwJ8yTsEa95YI9kwzbO5ccZ/+tYj/LlS0A==",
      "requires": {
        "@babel/runtime": "^7.5.5",
        "immutable": "~3.7.4",
        "invariant": "^2.2.1"
      },
      "dependencies": {
        "@babel/runtime": {
          "version": "7.12.5",
          "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.12.5.tgz",
          "integrity": "sha512-plcc+hbExy3McchJCEQG3knOsuh3HH+Prx1P6cLIkET/0dLuQDEnrT+s27Axgc9bqfsmNUNHfscgMUdBpC9xfg==",
          "requires": {
            "regenerator-runtime": "^0.13.4"
          }
        },
        "immutable": {
          "version": "3.7.6",
          "resolved": "https://registry.npmjs.org/immutable/-/immutable-3.7.6.tgz",
          "integrity": "sha1-E7TTyxK++hVIKib+Gy665kAHHks="
        },
        "regenerator-runtime": {
          "version": "0.13.7",
          "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz",
          "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew=="
        }
      }
    },
    "draft-js": {
      "version": "0.10.5",
      "resolved": "https://registry.npmjs.org/draft-js/-/draft-js-0.10.5.tgz",
@@ -5989,6 +6071,19 @@
        }
      }
    },
    "draft-js-multidecorators": {
      "version": "1.0.0",
      "resolved": "https://registry.npmjs.org/draft-js-multidecorators/-/draft-js-multidecorators-1.0.0.tgz",
      "integrity": "sha1-bEvo17eN0rlm7lHubMF5ubU15hI=",
      "requires": {
        "immutable": "*"
      }
    },
    "draftjs-utils": {
      "version": "0.9.4",
      "resolved": "https://registry.npmjs.org/draftjs-utils/-/draftjs-utils-0.9.4.tgz",
      "integrity": "sha512-KYjABSbGpJrwrwmxVj5UhfV37MF/p0QRxKIyL+/+QOaJ8J9z1FBKxkblThbpR0nJi9lxPQWGg+gh+v0dAsSCCg=="
    },
    "dragact": {
      "version": "0.2.12",
      "resolved": "https://registry.npmjs.org/dragact/-/dragact-0.2.12.tgz",
package.json
@@ -19,6 +19,8 @@
    "babel-plugin-import": "^1.11.0",
    "babel-plugin-named-asset-import": "^0.3.3",
    "babel-preset-react-app": "9.0.0",
    "braft-editor": "^2.3.9",
    "braft-extensions": "^0.1.0",
    "browserslist": "^4.13.0",
    "camelcase": "^5.2.0",
    "caniuse-lite": "^1.0.30001102",
src/components/sidemenu/config.jsx
@@ -55,6 +55,14 @@
      text: '标签打印模板'
    }, {
      src: '',
      PageParam: {OpenType: 'newtab', Template: 'ManageTable'},
      type: 'ManageTable',
      MenuID: '16044812935562g807p3p12huk8kokmb',
      MenuNo: 'sPrintTemplate_webM',
      MenuName: '单据打印模板',
      text: '单据打印模板'
    }, {
      src: '',
      systems: ['SSO', 'cloud'],
      PageParam: {OpenType: 'newtab', Template: 'ManageTable'},
      type: 'ManageTable',
src/locales/en-US/model.js
@@ -22,6 +22,7 @@
  'model.true': 'True',
  'model.false': 'False',
  'model.add': 'Add ',
  'model.batchAdd': 'BatchAdd',
  'model.update': 'Update ',
  'model.thaw': 'Thaw ',
  'model.menu': 'Menu ',
@@ -34,6 +35,7 @@
  'model.window': 'Window',
  'model.empty': 'Empty',
  'model.pay': 'Pay',
  'model.operation': 'Action',
  'model.switch.open': 'Open',
  'model.switch.close': 'Close',
  'model.menu.level1': 'Level 1 menu',
@@ -74,13 +76,11 @@
  'header.menu.datasource': 'The data source',
  'header.menu.maintable': 'The main table',
  'header.menu.query': 'The query',
  'header.menu.printTemplate': 'Printed template',
  'model.form.tabType': 'The tag type',
  'header.form.search.placeholder': 'Please add search criteria',
  'header.form.modal.placeholder': 'Please add the form',
  'header.form.action.placeholder': 'Please add buttons',
  'header.form.column.placeholder': 'Please add columns',
  'model.form.column.action': 'Action',
  'model.form.width': 'Width',
  'header.form.title': 'Title',
  'model.form.field': 'Field',
src/locales/zh-CN/model.js
@@ -22,6 +22,7 @@
  'model.true': '是',
  'model.false': '否',
  'model.add': '添加',
  'model.batchAdd': '批量添加',
  'model.update': '修改',
  'model.thaw': '解冻',
  'model.menu': '菜单',
@@ -34,6 +35,7 @@
  'model.window': '窗口',
  'model.empty': '空',
  'model.pay': '支付',
  'model.operation': '操作',
  'model.switch.open': '开',
  'model.switch.close': '关',
  'model.menu.level1': '一级菜单',
@@ -74,13 +76,11 @@
  'header.menu.datasource': '数据来源',
  'header.menu.maintable': '主表',
  'header.menu.query': '查询',
  'header.menu.printTemplate': '打印模板',
  'model.form.tabType': '标签类型',
  'header.form.search.placeholder': '请添加搜索条件',
  'header.form.modal.placeholder': '请添加表单',
  'header.form.action.placeholder': '请添加按钮',
  'header.form.column.placeholder': '请添加显示列',
  'model.form.column.action': '操作',
  'model.form.width': '宽度',
  'header.form.title': '标题',
  'model.form.field': '字段',
src/menu/actioncomponent/formconfig.jsx
@@ -150,8 +150,8 @@
      initVal: card.pageTemplate || '',
      required: true,
      options: [{
        value: 'print',
        text: Formdict['header.menu.printTemplate']
        value: 'billprint',
        text: '单据打印'
      }, {
        value: 'pay',
        text: Formdict['model.pay']
src/menu/components/card/cardcellcomponent/dragaction/index.scss
@@ -88,6 +88,9 @@
  }
  .ant-mk-splitline {
    border-top: 1px solid;
    border-bottom: 0;
    border-left: 0;
    border-right: 0;
  }
  .ant-mk-picture {
    background-size: cover;
src/menu/datasource/verifycard/columnform/index.jsx
@@ -10,34 +10,13 @@
    columnChange: PropTypes.func  // 修改函数
  }
  state = {
    editItem: null // 编辑元素
  }
  edit = (record) => {
    this.setState({
      editItem: record
    })
    this.props.form.setFieldsValue({
      label: record.label,
      field: record.field,
      datatype: record.datatype
    })
  }
  state = {}
  handleConfirm = () => {
    // 表单提交时检查输入值是否正确
    this.props.form.validateFieldsAndScroll((err, values) => {
      if (!err) {
        values.uuid = this.state.editItem ? this.state.editItem.uuid : ''
        this.setState({
          editItem: null
        }, () => {
          this.props.columnChange(values)
        })
        this.props.columnChange(values)
        this.props.form.setFieldsValue({
          label: '',
          field: ''
@@ -47,6 +26,7 @@
  }
  render() {
    const { dict } = this.props
    const { getFieldDecorator } = this.props.form
    const formItemLayout = {
      labelCol: {
@@ -69,7 +49,7 @@
                rules: [
                  {
                    required: true,
                    message: this.props.dict['form.required.input'] + '名称!'
                    message: dict['form.required.input'] + '名称!'
                  }
                ]
              })(<Input placeholder="" autoComplete="off" />)}
@@ -82,7 +62,7 @@
                rules: [
                  {
                    required: true,
                    message: this.props.dict['form.required.input'] + '字段!'
                    message: dict['form.required.input'] + '字段!'
                  }
                ]
              })(<Input placeholder="" autoComplete="off" />)}
@@ -95,7 +75,7 @@
                rules: [
                  {
                    required: true,
                    message: this.props.dict['form.required.select'] + '数据类型!'
                    message: dict['form.required.select'] + '数据类型!'
                  }
                ]
              })(
@@ -133,7 +113,7 @@
          </Col>
          <Col span={3} className="add">
            <Button onClick={this.handleConfirm} type="primary" className="mk-green">
              保存
              {dict['model.add']}
            </Button>
          </Col>
        </Row>
src/menu/datasource/verifycard/index.jsx
@@ -18,6 +18,7 @@
const { Paragraph } = Typography
const FieldsComponent = asyncComponent(() => import('@/templates/sharecomponent/fieldscomponent'))
const EditTable = asyncComponent(() => import('@/templates/zshare/editTable'))
class VerifyCard extends Component {
  static propTpyes = {
@@ -41,34 +42,51 @@
      {
        title: '名称',
        dataIndex: 'label',
        width: '25%'
        inputType: 'input',
        editable: true,
        width: '28%'
      },
      {
        title: '字段',
        dataIndex: 'field',
        width: '25%'
        inputType: 'input',
        editable: true,
        width: '28%'
      },
      {
        title: '数据类型',
        dataIndex: 'datatype',
        inputType: 'select',
        options: [
          { value: 'Nvarchar(50)', text: 'Nvarchar(50)' },
          { value: 'Nvarchar(100)', text: 'Nvarchar(100)' },
          { value: 'Nvarchar(512)', text: 'Nvarchar(512)' },
          { value: 'Nvarchar(1024)', text: 'Nvarchar(1024)' },
          { value: 'Nvarchar(2048)', text: 'Nvarchar(2048)' },
          { value: 'Nvarchar(max)', text: 'Nvarchar(max)' },
          { value: 'Int', text: 'Int' },
          { value: 'Decimal(18,0)', text: 'Decimal(18,0)' },
          { value: 'Decimal(18,1)', text: 'Decimal(18,1)' },
          { value: 'Decimal(18,2)', text: 'Decimal(18,2)' },
          { value: 'Decimal(18,3)', text: 'Decimal(18,3)' },
          { value: 'Decimal(18,4)', text: 'Decimal(18,4)' },
          { value: 'Decimal(18,5)', text: 'Decimal(18,5)' },
          { value: 'Decimal(18,6)', text: 'Decimal(18,6)' },
          { value: 'Decimal(18,7)', text: 'Decimal(18,7)' },
          { value: 'Decimal(18,8)', text: 'Decimal(18,8)' },
          { value: 'Decimal(18,9)', text: 'Decimal(18,9)' },
          { value: 'Decimal(18,10)', text: 'Decimal(18,10)' },
          { value: 'Decimal(18,11)', text: 'Decimal(18,11)' },
          { value: 'Decimal(18,12)', text: 'Decimal(18,12)' },
          { value: 'Decimal(18,13)', text: 'Decimal(18,13)' },
          { value: 'Decimal(18,14)', text: 'Decimal(18,14)' },
          { value: 'Decimal(18,15)', text: 'Decimal(18,15)' },
          { value: 'Decimal(18,16)', text: 'Decimal(18,16)' },
          { value: 'Decimal(18,17)', text: 'Decimal(18,17)' },
          { value: 'Decimal(18,18)', text: 'Decimal(18,18)' },
        ],
        editable: true,
        width: '25%',
      },
      {
        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, 'columns')} style={{color: '#1890ff'}}><Icon type="edit" /></span>
            <Popconfirm
              overlayClassName="popover-confirm"
              title={this.props.dict['model.query.delete']}
              onConfirm={() => this.deleteColumn(record)
            }>
              <span className="operation-btn" style={{color: '#ff4d4f'}}><Icon type="delete" /></span>
            </Popconfirm>
          </div>)
      }
    ],
    scriptsColumns: [
@@ -105,7 +123,7 @@
        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['model.edit']} onClick={() => this.handleEdit(record)} style={{color: '#1890ff'}}><Icon type="edit" /></span>
            <span className="operation-btn" onClick={() => this.handleUpDown(record, 'up')} style={{color: '#1890ff'}}><Icon type="arrow-up" /></span>
            <span className="operation-btn" onClick={() => this.handleUpDown(record, 'down')} style={{color: '#ff4d4f'}}><Icon type="arrow-down" /></span>
            <span className="operation-btn" title={this.props.dict['model.status.change']} onClick={() => this.handleStatus(record)} style={{color: '#8E44AD'}}><Icon type="swap" /></span>
@@ -135,13 +153,13 @@
      if (!conf.parentId && box.Template === 'CustomPage') {
        box.components.forEach(item => {
          if (item.uuid !== conf.uuid && item.setting && item.setting.varMark) {
            Marks.push(item.setting.varMark)
            Marks.push(item.setting.varMark.toLowerCase())
          }
        })
      } else if (conf.parentId === box.parentId && conf.tabId === box.uuid) {
        box.components.forEach(item => {
          if (item.uuid !== conf.uuid && item.setting && item.setting.varMark) {
            Marks.push(item.setting.varMark)
            Marks.push(item.setting.varMark.toLowerCase())
          }
        })
      } else {
@@ -239,39 +257,20 @@
  }
  columnChange = (values) => {
    let columns = fromJS(this.state.columns).toJS()
    const { columns } = this.state
    if (values.uuid) {
      columns = columns.map(item => {
        if (item.uuid === values.uuid) {
          return values
        } else {
          return item
        }
      })
    } else {
      values.uuid = Utils.getuuid()
      columns.push(values)
    }
    values.uuid = Utils.getuuid()
    this.setState({ columns })
  }
  deleteColumn = (record) => {
    this.setState({ columns: this.state.columns.filter(item => item.uuid !== record.uuid) })
    this.setState({ columns: [...columns, values] })
  }
  deleteScript = (record) => {
    this.setState({ scripts: this.state.scripts.filter(item => item.uuid !== record.uuid) })
  }
  handleEdit = (record, type) => {
    if (type === 'scripts') {
      this.scriptsForm.edit(record)
    } else if (type === 'columns') {
      this.contrastForm.edit(record)
    }
  handleEdit = (record) => {
    this.scriptsForm.edit(record)
    let node = document.getElementById('model-verify-card-box-tab').parentNode
    if (node && node.scrollTop) {
@@ -379,7 +378,7 @@
          search = [...search, ...mainSearch]
        }
        if (res.varMark && varMarks.includes(res.varMark)) {
        if (res.varMark && varMarks.includes(res.varMark.toLowerCase())) {
          notification.warning({
            top: 92,
            message: '变量标识不可重复!',
@@ -455,7 +454,7 @@
            search = [...search, ...mainSearch]
          }
          if (res.varMark && varMarks.includes(res.varMark)) {
          if (res.varMark && varMarks.includes(res.varMark.toLowerCase())) {
            notification.warning({
              top: 92,
              message: '变量标识不可重复!',
@@ -588,27 +587,21 @@
            />
          </TabPane>
          <TabPane tab="字段集" key="columns">
            <ColForm
              dict={this.props.dict}
              columnChange={this.columnChange}
              wrappedComponentRef={(inst) => this.contrastForm = inst}
            />
            <ColForm dict={this.props.dict} columnChange={this.columnChange}/>
            <FieldsComponent
              config={{...config, columns}}
              type="fields"
              tableFields={menu.tableFields}
              updatefield={this.updatefields}
            />
            <Table
              bordered
              rowKey="uuid"
              className="custom-table"
              dataSource={columns}
              columns={colColumns}
              pagination={false}
            />
            <EditTable data={columns} columns={colColumns} onChange={(columns) => this.setState({columns})}/>
          </TabPane>
          <TabPane tab="自定义脚本" key="scripts">
          <TabPane tab={
            <span>
              自定义脚本
              {scripts.length ? <span className="count-tip">{scripts.length}</span> : null}
            </span>
          } key="scripts">
            <CustomScriptsForm
              setting={setting}
              searches={searches}
src/menu/datasource/verifycard/index.scss
@@ -9,6 +9,12 @@
    .ant-tabs-nav-scroll {
      text-align: center;
    }
    .count-tip {
      position: absolute;
      top: 0px;
      color: #1890ff;
      font-size: 12px;
    }
    .ant-tabs-content {
      min-height: 40vh;
    }
src/menu/menuform/index.jsx
@@ -128,7 +128,7 @@
  }
  render() {
    const { dict, MenuName, MenuNo } = this.props
    const { dict, MenuName, MenuNo, config } = this.props
    const { menulist, smenulist } = this.state
    const { getFieldDecorator } = this.props.form
    const formItemLayout = {
@@ -216,7 +216,7 @@
          <Col span={24}>
            <Form.Item label={dict['mob.menu.easycode']}>
              {getFieldDecorator('easyCode', {
                initialValue: ''
                initialValue: config.easyCode
              })(<Input placeholder="" autoComplete="off" onChange={this.changeEasyCode}/>)}
            </Form.Item>
          </Col>
src/menu/menushell/index.jsx
@@ -131,7 +131,7 @@
  })
  return (
    <div ref={drop} className="menu-shell-inner" style={menu.style}>
    <div ref={drop} className="menu-shell-inner" id="menu-shell-inner" style={menu.style}>
      <div className="ant-row">
        {cards.map(card => (
          <Card
src/menu/modalconfig/index.jsx
@@ -747,7 +747,7 @@
                    return (<SourceElement key={index} content={item}/>)
                  })}
                </div>
                <Button type="primary" block onClick={() => this.queryField()}>{this.state.dict['header.menu.form.add']}</Button>
                <Button type="primary" block onClick={() => this.queryField()}>{this.state.dict['model.batchAdd']}</Button>
                <Button type="primary" block onClick={() => this.handleGroup()}>{this.state.dict['header.menu.group.add']}</Button>
              </Panel>
            </Collapse>
@@ -828,7 +828,7 @@
        <Modal
          title={this.state.dict['model.edit']}
          visible={this.state.visible}
          width={700}
          width={850}
          onCancel={this.editModalCancel}
          onOk={this.handleSubmit}
          confirmLoading={this.state.sqlVerifing}
src/menu/modelsource/index.jsx
@@ -5,12 +5,29 @@
import SourceWrap from './dragsource'
import './index.scss'
class CardChart extends Component {
class ModelSource extends Component {
  state = {
    menuOptions: null
  }
  UNSAFE_componentWillMount () {
    const { MenuType } = this.props
    let options = fromJS(menuOptions).toJS()
    options = options.filter(item => !item.forbid || !item.forbid.includes(MenuType))
    this.setState({
      menuOptions: options
    })
  }
  shouldComponentUpdate (nextProps, nextState) {
    return !is(fromJS(this.props), fromJS(nextProps)) || !is(fromJS(this.state), fromJS(nextState))
    return !is(fromJS(this.state), fromJS(nextState))
  }
  render() {
    const { menuOptions } = this.state
    return (
      <div className="mob-card-source-box">
        {menuOptions.map((item, index) => (<SourceWrap key={index} content={item} />))}
@@ -19,4 +36,4 @@
  }
}
export default CardChart
export default ModelSource
src/menu/modelsource/option.jsx
@@ -17,8 +17,8 @@
// 组件配置信息
export const menuOptions = [
  { type: 'menu', url: tabs, component: 'tabs', subtype: 'tabs', title: '标签页', width: 24 },
  { type: 'menu', url: Mainsearch, component: 'search', subtype: 'mainsearch', title: '搜索条件', width: 24 },
  { type: 'menu', url: tabs, component: 'tabs', subtype: 'tabs', title: '标签页', width: 24, forbid: ['billPrint'] },
  { type: 'menu', url: Mainsearch, component: 'search', subtype: 'mainsearch', title: '搜索条件', width: 24, forbid: ['billPrint'] },
  { type: 'menu', url: card1, component: 'card', subtype: 'datacard', title: '数据卡', config: `[{"uuid":"160135809128212dm7i29fim9ksto9od","setting":{"width":6},"style":{"paddingTop":"15px","marginTop":"4px","paddingRight":"15px","marginRight":"8px","marginLeft":"8px","backgroundColor":"rgba(255, 255, 255, 1)","borderColor":"#e8e8e8","paddingLeft":"15px","marginBottom":"4px","borderWidth":"1px","paddingBottom":"10px"},"backStyle":{},"elements":[{"datatype":"static","width":12,"marks":null,"height":1,"value":"关单","style":{},"prefix":"","postfix":"","format":"","eleType":"text","uuid":"160231860159931untbea62sgokunc5s"},{"datatype":"dynamic","width":12,"marks":null,"style":{"color":"rgba(250, 219, 20, 1)","textAlign":"right"},"btnstyle":{},"eleType":"icon","icon":"question-circle","field":"nvarchar2","uuid":"1602318768361nv8ql4t47sgcsn88b0u"},{"datatype":"static","width":24,"marks":null,"height":1,"innerHeight":36,"value":"100","style":{"fontSize":"24px","fontWeight":"500","color":"rgba(0, 0, 0, 1)"},"prefix":"","btnstyle":{},"postfix":"","format":"","eleType":"text","uuid":"1602318817884v70gtgb65ubnm8mbcvv"},{"color":"#1890ff","width":24,"marks":null,"maxValue":100,"style":{"color":"rgba(250, 140, 22, 1)","paddingTop":"20px","paddingBottom":"10px"},"btnstyle":{},"eleType":"slider","field":"int1","uuid":"16023188871233rkktuvpp1h077igrsu"},{"eleType":"splitline","width":24,"color":"#e8e8e8","uuid":"1602320017038n31bk9o831ggug0tu0b","marks":null,"style":{"marginTop":"10px","marginBottom":"10px"},"btnstyle":{}},{"datatype":"static","width":12,"marks":null,"height":1,"value":"100","style":{"marginTop":"6px"},"prefix":"关单","btnstyle":{},"postfix":"","format":"","eleType":"text","uuid":"1602320061243drd7lf3agvn04kgr175"}],"backElements":[]}]` },
  { type: 'menu', url: card2, component: 'card', subtype: 'propcard', title: '属性卡', config: `[{"uuid":"1603681387259qaqf1127f72esmtchge","setting":{"width":6,"type":"simple"},"style":{"paddingTop":"15px","marginTop":"8px","paddingRight":"15px","marginRight":"8px","marginLeft":"8px","borderColor":"#e8e8e8","paddingLeft":"15px","marginBottom":"8px","borderWidth":"1px","paddingBottom":"15px"},"backStyle":{},"elements":[{"datatype":"static","width":12,"marks":null,"height":1,"value":"超时工单","style":{"color":"rgba(67, 67, 67, 0.51)"},"prefix":"","postfix":"","format":"","eleType":"text","uuid":"1603681402945qnkgm7q8cng65evn5ev"},{"eleType":"icon","datatype":"static","width":12,"icon":"question-circle","tooltip":"超时工单","uuid":"1603681473384i2crkbtofg4pu76k06a","marks":null,"style":{"textAlign":"right","color":"rgba(250, 219, 20, 1)"}},{"datatype":"static","width":24,"marks":null,"height":1,"innerHeight":36,"value":"100","style":{"fontSize":"24px","color":"rgba(0, 0, 0, 1)"},"prefix":"","postfix":"","format":"","eleType":"number","uuid":"1603681539870d704ufqf98kc6t7537t"},{"color":"rgba(250, 219, 20, 1)","datatype":"static","width":24,"marks":null,"maxValue":100,"value":50,"style":{"paddingTop":"10px","paddingBottom":"10px"},"eleType":"slider","uuid":"1603683067556mvupau0odvrtv45u7o8"},{"eleType":"splitline","width":24,"color":"#e8e8e8","uuid":"1603683117981t9k55k8an430fuppmci","marks":null,"style":{"paddingTop":"5px","paddingBottom":"5px"}},{"datatype":"static","width":12,"marks":null,"height":1,"value":"100","style":{"color":"rgba(0, 0, 0, 0.65)","marginTop":"10px"},"prefix":"超时工单  ","postfix":"","format":"","eleType":"text","uuid":"1603683136553uvsmkfohkft9idbfkhu"}],"backElements":[]}]` },
  { type: 'menu', url: TableCard, component: 'table', subtype: 'tablecard', title: '表格', width: 12 },
src/menu/padcontroller/index.jsx
@@ -45,18 +45,18 @@
    const formItemLayout = {
      labelCol: {
        xs: { span: 24 },
        sm: { span: 6 }
        sm: { span: 4 }
      },
      wrapperCol: {
        xs: { span: 24 },
        sm: { span: 18 }
        sm: { span: 20 }
      }
    }
    return (
      <div className="menu-padding-controller">
        <Form {...formItemLayout}>
          <Col span={12}>
          <Col span={24}>
            <Form.Item
              colon={false}
              label={<Icon title="上边距" type="arrow-up"/>}
@@ -64,7 +64,7 @@
              <StyleInput defaultValue={config.style.paddingTop || '0px'} options={['px', 'vh', 'vw']} onChange={(val) => this.changePadding(val, 'paddingTop')}/>
            </Form.Item>
          </Col>
          <Col span={12}>
          <Col span={24}>
            <Form.Item
              colon={false}
              label={<Icon title="下边距" type="arrow-down"/>}
@@ -72,7 +72,7 @@
              <StyleInput defaultValue={config.style.paddingBottom || '0px'} options={['px', 'vh', 'vw']} onChange={(val) => this.changePadding(val, 'paddingBottom')}/>
            </Form.Item>
          </Col>
          <Col span={12}>
          <Col span={24}>
            <Form.Item
              colon={false}
              label={<Icon title="左边距" type="arrow-left"/>}
@@ -80,7 +80,7 @@
              <StyleInput defaultValue={config.style.paddingLeft || '0px'} options={['px', 'vh', 'vw']} onChange={(val) => this.changePadding(val, 'paddingLeft')}/>
            </Form.Item>
          </Col>
          <Col span={12}>
          <Col span={24}>
            <Form.Item
              colon={false}
              label={<Icon title="右边距" type="arrow-right"/>}
src/router/index.js
@@ -13,6 +13,7 @@
const MobManage = asyncLoadComponent(() => import('@/views/mobmanage'))
const MobDesign = asyncLoadComponent(() => import('@/views/mobdesign'))
const MenuDesign = asyncLoadComponent(() => import('@/views/menudesign'))
const BillPrint = asyncLoadComponent(() => import('@/views/billprint'))
const PrintT = asyncLoadComponent(() => import('@/views/printTemplate'))
const routers = [
@@ -24,6 +25,7 @@
  {path: '/mobmanage', name: 'mobmanage', component: MobManage, auth: true},
  {path: '/mobdesign/:appId/:appType/:appCode/:appName', name: 'mobdesign', component: MobDesign, auth: true},
  {path: '/menudesign/:param', name: 'menudesign', component: MenuDesign, auth: true},
  {path: '/billprint/:param', name: 'billprint', component: BillPrint, auth: true},
  {path: '/paramsmain/:param', name: 'pmain', component: Main, auth: true}
]
src/tabviews/custom/components/card/cardcellList/index.jsx
@@ -47,7 +47,7 @@
  }
  shouldComponentUpdate (nextProps, nextState) {
    return !is(fromJS(this.state), fromJS(nextState))
    return !is(fromJS(this.state), fromJS(nextState)) || !is(fromJS(this.props), fromJS(nextProps))
  }
  /**
src/tabviews/custom/components/card/cardcellList/index.scss
@@ -93,6 +93,9 @@
  }
  .ant-mk-splitline {
    border-top: 1px solid;
    border-bottom: 0;
    border-left: 0;
    border-right: 0;
  }
  .ant-slider {
    margin: 0px;
src/tabviews/custom/components/card/table-card/index.jsx
@@ -1,7 +1,7 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { is, fromJS } from 'immutable'
import { Spin, notification, Col, Empty } from 'antd'
import { Spin, notification, Col, Empty, Pagination } from 'antd'
import asyncComponent from '@/utils/asyncComponent'
import Api from '@/api'
@@ -24,6 +24,9 @@
  state = {
    config: null,              // 图表配置信息
    loading: false,            // 数据加载状态
    preIndex: 0,               // 开始索引
    pageIndex: 1,              // 页码
    total: 0,                  // 总数
    sync: false,               // 是否统一请求数据
    data: null,                // 数据
    title: '',                 // 标题
@@ -46,6 +49,12 @@
    let showHeader = false
    if (_config.wrap.title || _config.search.length > 0) {
      showHeader = true
    }
    if (_config.setting.laypage) {
      _config.wrap.contentHeight = _config.wrap.height - (showHeader ? 85 : 40)
    } else {
      _config.wrap.contentHeight = _config.wrap.height - (showHeader ? 45 : 0)
    }
    _config.columns.forEach(item => {
@@ -121,12 +130,16 @@
    if (syncId && syncId !== config.uuid) return
    this.loadData()
    this.setState({
      pageIndex: 1
    }, () => {
      this.loadData()
    })
  }
  async loadData () {
    const { mainSearch, BID, menuType, dataManager } = this.props
    const { config, arr_field } = this.state
    const { config, arr_field, pageIndex } = this.state
    let searches = []
    if (mainSearch && mainSearch.length > 0) { // 主表搜索条件
@@ -143,12 +156,19 @@
    })
    let _orderBy = config.setting.order || ''
    let param = UtilsDM.getQueryDataParams(config.setting, arr_field, searches, _orderBy, 1, 1, BID, menuType, dataManager)
    let param = UtilsDM.getQueryDataParams(config.setting, arr_field, searches, _orderBy, pageIndex, config.setting.pageSize, BID, menuType, dataManager)
    let result = await Api.genericInterface(param)
    if (result.status) {
      let _preIndex = 0
      if (config.setting.laypage) {
        _preIndex = config.setting.pageSize * (pageIndex - 1)
      }
      this.setState({
        data: result.data,
        total: result.total,
        preIndex: _preIndex,
        loading: false
      })
    } else {
@@ -175,6 +195,14 @@
        }
      }
    }
  }
  changePageIndex = (page) => {
    this.setState({
      pageIndex: page
    }, () => {
      this.loadData()
    })
  }
  getLines = (data, seq) => {
@@ -219,7 +247,7 @@
  }
  render() {
    const { config, loading, data, title, showHeader } = this.state
    const { config, loading, data, title, showHeader, pageIndex, preIndex, total } = this.state
    return (
      <div className="custom-table-card-box" style={{...config.style, height: config.wrap.height}}>
@@ -233,10 +261,13 @@
          <span className="table-title">{title}</span>
          {/* <searchLine /> */}
        </div> : null}
        {data && data.length > 0 ? <div className="card-row-list" style={{height: config.wrap.height - (showHeader ? 45 : 0)}}>
          {data.map((item, index) => this.getLines(item, index + 1))}
        {data && data.length > 0 ? <div className="card-row-list" style={{height: config.wrap.contentHeight}}>
          {data.map((item, index) => this.getLines(item, preIndex + index + 1))}
        </div> : null}
        {data && data.length === 0 ? <Empty description={false}/> : null}
        {data && data.length === 0 ? <div className="card-row-list" style={{height: config.wrap.contentHeight}}>
          <Empty description={false}/>
        </div> : null}
        {config.setting.laypage ? <Pagination size="small" current={pageIndex} total={total} onChange={this.changePageIndex} /> : null}
      </div>
    )
  }
src/tabviews/custom/components/card/table-card/index.scss
@@ -22,6 +22,10 @@
      font-style: inherit;
    }
  }
  >.ant-pagination {
    margin-top: 10px;
    float: right;
  }
  .card-row-list::after {
    content: ' ';
src/tabviews/zshare/actionList/newpagebutton/index.jsx
@@ -80,11 +80,23 @@
    }
    let Id = ''
    if (btn.Ot === 'requiredSgl') {
    let name = ''
    let MenuNo = ''
    let Remark = ''
    if (btn.Ot === 'requiredSgl' && data[0]) {
      Id = data[0][setting.primaryKey] || ''
      name = data[0].PrintTempName || ''
      MenuNo = data[0].PrintTempNO || ''
      Remark = data[0].Remark || ''
    }
    if (btn.pageTemplate === 'print') {
    if (btn.pageTemplate === 'billprint') {
      let src = '#/billprint/' + window.btoa(window.encodeURIComponent(JSON.stringify({ id: Id, tempId: btn.printTemp })))
      window.open(src)
    } else if (btn.pageTemplate === 'billprintTemp') {
      let src = '#/menudesign/' + window.btoa(window.encodeURIComponent(JSON.stringify({ MenuType: 'billPrint', MenuId: Id, MenuNo: MenuNo, MenuName: name || '打印', Remark: Remark })))
      window.open(src)
    } else if (btn.pageTemplate === 'print') {
      let cloudmsg = '&cuid=' + (sessionStorage.getItem('CloudUserID') || '') + '&clid=' + (sessionStorage.getItem('CloudLoginUID') || '') + '&cun=' + (sessionStorage.getItem('CloudUserName') || '')
      let msg = '&uid=' + sessionStorage.getItem('UserID') + '&lid=' + sessionStorage.getItem('LoginUID') + '&un=' + sessionStorage.getItem('User_Name')
      let src = '#/print/' + window.btoa('ID=' + Id + msg + cloudmsg)
src/templates/comtableconfig/source.jsx
@@ -165,7 +165,7 @@
      Align: 'center',
      IsSort: 'false',
      uuid: Utils.getuuid(),
      label: CommonDict['model.form.column.action'],
      label: CommonDict['model.operation'],
      type: 'action',
      style: 'button',
      show: 'horizontal',
src/templates/sharecomponent/actioncomponent/actionform/index.jsx
@@ -160,6 +160,8 @@
    if (_opentype === 'innerpage') {         // 新页面,可选模板(自定义时,可填入外部链接)
      if (_pageTemplate === 'custom') {
        _options.push('url', 'joint')
      } else if (_pageTemplate === 'billprint') {
        _options.push('printTemp')
      }
    } else if (_opentype === 'blank' || _opentype === 'tab') { // 新标签或当前页面替换
      if (_tabTemplate === 'ThdMenu') {
@@ -355,13 +357,8 @@
        this.props.form.setFieldsValue(_fieldval)
      })
    } else if (key === 'pageTemplate') {
      let _options = null
      let _options = this.getOptions('innerpage', this.state.interType, this.state.funcType, value, card.tabTemplate)
      let _fieldval = {}
      if (value === 'custom') {
        _options = ['label', 'Ot', 'OpenType', 'pageTemplate', 'url', 'joint', 'icon', 'class', 'position']
      } else {
        _options = ['label', 'Ot', 'OpenType', 'pageTemplate', 'icon', 'class', 'position']
      }
      this.setState({
        openType: value,
src/templates/sharecomponent/actioncomponent/index.jsx
@@ -43,6 +43,7 @@
    actionlist: null,    // 按钮组
    copying: false,      // 按钮复制中
    visible: false,      // 模态框控制
    printTemps: [],      // 单据打印模板
    profVisible: false   // 验证信息模态框
  }
@@ -67,6 +68,54 @@
    } else if (!is(fromJS(nextProps.config.action), fromJS(this.props.config.action)) && !is(fromJS(nextProps.config.action), fromJS(actionlist))) {
      this.setState({actionlist: fromJS(nextProps.config.action).toJS()})
    }
  }
  componentDidMount () {
    this.getBillPrintTemp()
  }
  getBillPrintTemp = () => {
    let _sql = `select PrintTempNO,Images,PrintTempNO+PrintTempName as PN from sPrintTemplate
    where appkey= @appkey@ and Deleted=0  and typechartwo='web_print'
    union select ID,Images,a.PrintTempNO+PrintTempName as PN
    from (select * from sPrintTemplate where appkey= '' and Deleted=0  and typechartwo='web_print') a
    left join (select PrintTempNO from sPrintTemplate where appkey= @appkey@  and Deleted=0 ) b
    on a.PrintTempNO=b.PrintTempNO
    left join (select Srcid from sPrintTemplate_Log where appkey='' and apicode= @appkey@ and Deleted=0 ) c
    on a.ID=c.Srcid where b.PrintTempNO is null and c.Srcid is null`
    let param = {
      func: 'sPC_Get_SelectedList',
      LText: Utils.formatOptions(_sql),
      obj_name: 'data',
      arr_field: 'PN,PrintTempNO,Images'
    }
    param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
    param.secretkey = Utils.encrypt(param.LText, param.timestamp)
    param.open_key = Utils.encryptOpenKey(param.secretkey, param.timestamp) // 云端数据验证
    Api.getSystemConfig(param).then(res => {
      if (res.status) {
        let temps = res.data.map(temp => {
          return {
            value: temp.PrintTempNO,
            text: temp.PN
          }
        })
        this.setState({
          printTemps: temps
        })
      } else {
        notification.warning({
          top: 92,
          message: res.message,
          duration: 5
        })
      }
    })
  }
  /**
@@ -154,14 +203,14 @@
        this.setState({
          visible: true,
          card: card,
          formlist: getActionForm(card, functip, this.props.config, this.props.usefulFields, this.props.type, menulist)
          formlist: getActionForm(card, functip, this.props.config, this.props.usefulFields, this.props.type, menulist, this.state.printTemps)
        })
      })
    } else {
      this.setState({
        visible: true,
        card: card,
        formlist: getActionForm(card, functip, this.props.config, this.props.usefulFields, this.props.type, menulist)
        formlist: getActionForm(card, functip, this.props.config, this.props.usefulFields, this.props.type, menulist, this.state.printTemps)
      })
    }
  }
@@ -400,7 +449,7 @@
            Align: 'center',
            IsSort: 'false',
            uuid: Utils.getuuid(),
            label: this.state.dict['model.form.column.action'],
            label: this.state.dict['model.operation'],
            type: 'action',
            style: 'button',
            show: 'horizontal',
@@ -621,7 +670,7 @@
            Align: 'center',
            IsSort: 'false',
            uuid: Utils.getuuid(),
            label: this.state.dict['model.form.column.action'],
            label: this.state.dict['model.operation'],
            type: 'action',
            style: 'button',
            show: 'horizontal',
src/templates/sharecomponent/actioncomponent/verifyprint/index.jsx
@@ -47,10 +47,10 @@
  componentDidMount() {
    let _sql = `select PrintTempNO,Images,PrintTempNO+PrintTempName as PN from sPrintTemplate 
    where appkey= @appkey@ and Deleted=0
    where appkey= @appkey@ and Deleted=0  and typechartwo=''
    union select ID,Images,a.PrintTempNO+PrintTempName as PN 
    from (select * from sPrintTemplate where appkey= '' and Deleted=0 ) a
    left join (select PrintTempNO from sPrintTemplate where appkey= @appkey@ and Deleted=0 ) b
    from (select * from sPrintTemplate where appkey= '' and Deleted=0  and typechartwo='') a
    left join (select PrintTempNO from sPrintTemplate where appkey= @appkey@  and Deleted=0 ) b
    on a.PrintTempNO=b.PrintTempNO 
    left join (select Srcid from sPrintTemplate_Log where appkey='' and apicode= @appkey@ and Deleted=0 ) c 
    on a.ID=c.Srcid where b.PrintTempNO is null and c.Srcid is null`
src/templates/sharecomponent/fieldscomponent/index.jsx
@@ -145,11 +145,6 @@
            resourceType: '0',
            setAll: 'false',
            options: [],
            dataSource: '',
            linkField: '',
            valueField: '',
            valueText: '',
            orderBy: '',
            orderType: 'asc',
            match: _match,
            display: 'dropdown'
@@ -276,18 +271,9 @@
    const { type } = this.props
    const { dict, fields } = this.state
    let label = ''
    if (type === 'search') {
      label = dict['header.menu.search.add']
    } else if (type === 'columns') {
      label = dict['model.menu.column.add']
    } else if (type === 'fields') {
      label = dict['model.menu.field.add']
    }
    return (
      <div className="quickly-add">
        <Button type="primary" block onClick={this.queryField}>{label}</Button>
        <Button type="primary" block onClick={this.queryField}>{dict['model.batchAdd']}</Button>
        {/* 根据字段名添加显示列及搜索条件 */}
        <Modal
          wrapClassName="model-table-fieldmanage-modal"
src/templates/sharecomponent/settingcalcomponent/verifycard/index.jsx
@@ -366,7 +366,12 @@
              pagination={false}
            />
          </TabPane>
          <TabPane tab="自定义脚本" key="scripts">
          <TabPane tab={
            <span>
              自定义脚本
              {scripts.length ? <span className="count-tip">{scripts.length}</span> : null}
            </span>
          } key="scripts">
            <CustomScript
              dict={this.props.dict}
              setting={setting}
src/templates/sharecomponent/settingcalcomponent/verifycard/index.scss
@@ -6,6 +6,12 @@
    z-index: 1;
  }
  .verify-card-box {
    .count-tip {
      position: absolute;
      top: 0px;
      color: #1890ff;
      font-size: 12px;
    }
    .ant-tabs-nav-scroll {
      text-align: center;
    }
src/templates/sharecomponent/settingcomponent/settingform/index.jsx
@@ -395,7 +395,12 @@
              wrappedComponentRef={(inst) => this.settingForm = inst}
            />
          </TabPane>
          <TabPane tab="自定义脚本" key="scripts">
          <TabPane tab={
            <span>
              自定义脚本
              {scripts.length ? <span className="count-tip">{scripts.length}</span> : null}
            </span>
          } key="scripts">
            <CustomScript
              dict={dict}
              setting={setting}
src/templates/sharecomponent/settingcomponent/settingform/index.scss
@@ -6,6 +6,12 @@
    top: 150px;
    left: calc(50% - 16px);
  }
  .count-tip {
    position: absolute;
    top: 0px;
    color: #1890ff;
    font-size: 12px;
  }
  .model-table-setting-form {
    .textarea {
      .ant-form-item-label {
src/templates/sharecomponent/treesettingcomponent/settingform/index.jsx
@@ -248,7 +248,12 @@
              wrappedComponentRef={(inst) => this.settingForm = inst}
            />
          </TabPane>
          <TabPane tab="自定义脚本" key="scripts">
          <TabPane tab={
            <span>
              自定义脚本
              {scripts.length ? <span className="count-tip">{scripts.length}</span> : null}
            </span>
          } key="scripts">
            <CustomScript
              dict={this.props.dict}
              setting={setting}
src/templates/sharecomponent/treesettingcomponent/settingform/index.scss
@@ -16,6 +16,12 @@
      margin-right: 3px;
    }
  }
  .count-tip {
    position: absolute;
    top: 0px;
    color: #1890ff;
    font-size: 12px;
  }
  .operation-btn {
    display: inline-block;
    font-size: 16px;
src/templates/subtableconfig/source.jsx
@@ -164,7 +164,7 @@
      Align: 'center',
      IsSort: 'false',
      uuid: Utils.getuuid(),
      label: CommonDict['model.form.column.action'],
      label: CommonDict['model.operation'],
      type: 'action',
      style: 'button',
      show: 'horizontal',
src/templates/zshare/editTable/index.jsx
New file
@@ -0,0 +1,257 @@
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import { is, fromJS } from 'immutable'
import { Table, Input, InputNumber, Popconfirm, Form, Icon, Select } from 'antd'
import ColorSketch from '@/mob/colorsketch'
// import Utils from '@/utils/utils.js'
import zhCN from '@/locales/zh-CN/model.js'
import enUS from '@/locales/en-US/model.js'
import './index.scss'
const EditableContext = React.createContext()
class EditableCell extends Component {
  getInput = (form) => {
    const { inputType, options } = this.props
    if (inputType === 'number') {
      return <InputNumber min={12} max={50} precision={0} onPressEnter={() => this.getValue(form)} />
    } else if (inputType === 'color') {
      return <ColorSketch />
    } else if (inputType === 'select') {
      return <Select>
        {options.map((item, i) => (<Select.Option key={i} value={item.field || item.value}> {item.label || item.text} </Select.Option>))}
      </Select>
    } else {
      return <Input onPressEnter={() => this.getValue(form)} />
    }
  }
  getValue = (form) => {
    const { record } = this.props
    form.validateFields((error, row) => {
      if (error) {
        return
      }
      this.props.onSave({...record, ...row})
    })
  }
  renderCell = (form) => {
    const { getFieldDecorator } = form
    const { editing, dataIndex, title, record, children, className, required } = this.props
    return (
      <td className={className}>
        {editing ? (
          <Form.Item style={{ margin: 0 }}>
            {getFieldDecorator(dataIndex, {
              rules: [
                {
                  required: required,
                  message: `Please Input ${title}!`,
                }
              ],
              initialValue: record[dataIndex],
            })(this.getInput(form))}
          </Form.Item>
        ) : (
          children
        )}
      </td>
    )
  }
  render() {
    return <EditableContext.Consumer>{this.renderCell}</EditableContext.Consumer>
  }
}
class EditTable extends Component {
  static propTpyes = {
    onChange: PropTypes.func        // 数据变化
  }
  state = {
    data: [],
    editingKey: '',
    columns: []
  }
  UNSAFE_componentWillMount () {
    const { data } = this.props
    let columns = fromJS(this.props.columns).toJS()
    let dict = localStorage.getItem('lang') !== 'en-US' ? zhCN : enUS
    columns.push({
      title: dict['model.operation'],
      dataIndex: 'operation',
      width: '140px',
      render: (text, record) => {
        const { editingKey } = this.state
        const editable = this.isEditing(record)
        return editable ? (
          <span>
            <EditableContext.Consumer>
              {form => (
                <span onClick={() => this.save(form, record.uuid)} style={{ marginRight: 8 , color: '#1890ff', cursor: 'pointer'}}>
                  {dict['model.save']}
                </span>
              )}
            </EditableContext.Consumer>
            <span style={{ color: '#1890ff', cursor: 'pointer'}} onClick={() => this.cancel(record.uuid)}>{dict['model.cancel']}</span>
          </span>
        ) : (
          <div className={'operation-btn' + (editingKey !== '' ? ' disabled' : '')}>
            <span className="primary" onClick={() => {editingKey === '' && this.edit(record.uuid)}}><Icon type="edit" /></span>
            <span className="primary" onClick={() => {editingKey === '' && this.handleUpDown(record.uuid, 'up')}}><Icon type="arrow-up" /></span>
            <span className="danger" onClick={() => {editingKey === '' && this.handleUpDown(record.uuid, 'down')}}><Icon type="arrow-down" /></span>
            {editingKey === '' ? <Popconfirm
              overlayClassName="popover-confirm"
              title={dict['model.query.delete']}
              onConfirm={() => this.handleDelete(record.uuid)
            }>
              <span className="danger"><Icon type="delete" /></span>
            </Popconfirm> : null}
            {editingKey !== '' ? <span className="danger"><Icon type="delete" /></span> : null}
          </div>
        )
      }
    })
    this.setState({
      data: data || [],
      columns,
      dict
    })
  }
  UNSAFE_componentWillReceiveProps (nextProps) {
    if (!is(fromJS(this.state.data), fromJS(nextProps.data))) {
      this.setState({data: nextProps.data, editingKey: ''})
    }
  }
  isEditing = record => record.uuid === this.state.editingKey
  cancel = () => {
    this.setState({ editingKey: '' })
  }
  onSave = (record) => {
    const newData = [...this.state.data]
    const index = newData.findIndex(item => record.uuid === item.uuid)
    if (index === -1) return
    newData.splice(index, 1, record)
    this.setState({ data: newData, editingKey: '' }, () => {
      this.props.onChange(newData)
    })
  }
  handleDelete = (uuid) => {
    const { data } = this.state
    let _data = data.filter(item => uuid !== item.uuid)
    this.setState({
      data: _data
    }, () => {
      this.props.onChange(_data)
    })
  }
  handleUpDown = (uuid, direction) => {
    let _data = fromJS(this.state.data).toJS()
    const index = _data.findIndex(item => uuid === item.uuid)
    if ((index === 0 && direction === 'up') || (index === _data.length - 1 && direction === 'down')) {
      return
    }
    if (direction === 'up') {
      _data.splice(index - 1, 0, ..._data.splice(index, 1))
    } else {
      _data.splice(index + 1, 0, ..._data.splice(index, 1))
    }
    this.setState({
      data: _data
    }, () => {
      this.props.onChange(_data)
    })
  }
  save(form, uuid) {
    form.validateFields((error, row) => {
      if (error) {
        return;
      }
      const newData = [...this.state.data]
      const index = newData.findIndex(item => uuid === item.uuid)
      if (index > -1) {
        const item = newData[index]
        newData.splice(index, 1, {
          ...item,
          ...row,
        })
        this.setState({ data: newData, editingKey: '' }, () => {
          this.props.onChange(newData)
        })
      } else {
        newData.push(row);
        this.setState({ data: newData, editingKey: '' }, () => {
          this.props.onChange(newData)
        })
      }
    })
  }
  edit(uuid) {
    this.setState({ editingKey: uuid })
  }
  render() {
    const components = {
      body: {
        cell: EditableCell,
      }
    }
    const columns = this.state.columns.map(col => {
      if (!col.editable) return col
      return {
        ...col,
        onCell: record => ({
          record,
          inputType: col.inputType,
          dataIndex: col.dataIndex,
          options: col.options || [],
          required: col.required !== false ? true : false,
          title: col.title,
          editing: this.isEditing(record),
          onSave: this.onSave,
        }),
      }
    })
    return (
      <EditableContext.Provider value={this.props.form}>
        <div className="modal-edit-table">
          <Table
            bordered
            rowKey="uuid"
            components={components}
            dataSource={this.state.data}
            columns={columns}
            rowClassName="editable-row"
            pagination={false}
          />
        </div>
      </EditableContext.Provider>
    )
  }
}
export default Form.create()(EditTable)
src/templates/zshare/editTable/index.scss
New file
@@ -0,0 +1,47 @@
.modal-edit-table {
  .editable-row {
    .ant-form-explain {
      position: absolute;
      font-size: 12px;
      margin-top: -4px;
    }
    .color-sketch-block {
      width: 200px;
      position: relative;
      top: 8px;
    }
    .ant-select {
      width: 100%;
    }
    > td {
      padding: 16px 10px;
    }
  }
  .operation-btn {
    span {
      margin-right: 10px;
      cursor: pointer;
    }
    .primary {
      color: #1890ff;
    }
    .danger {
      color: #ff4d4f;
    }
  }
  .operation-btn.disabled {
    cursor: default;
    span {
      cursor: default;
    }
    .primary {
      color: rgba(0, 0, 0, .25);
    }
    .danger {
      color: rgba(0, 0, 0, .25);
    }
  }
  .ant-empty {
    margin: 0;
  }
}
src/templates/zshare/formconfig.jsx
@@ -592,7 +592,7 @@
 * @param {*} permFuncField  存储过程可用的开始字段
 * @param {*} type           按钮类型,用于区分可选的打开方式
 */
export function getActionForm (card, functip, config, permFuncField, type, menulist = []) {
export function getActionForm (card, functip, config, permFuncField, type, menulist = [], printTemps = []) {
  let opentypes = [
    {
      value: 'pop',
@@ -764,8 +764,14 @@
      initVal: card.pageTemplate || '',
      required: true,
      options: [{
        value: 'print',
        text: Formdict['header.menu.printTemplate']
      //   value: 'print',
      //   text: '标签打印模板'
      // }, {
      //   value: 'billprintTemp',
      //   text: '单据打印模板'
      // }, {
        value: 'billprint',
        text: '单据打印'
      }, {
        value: 'pay',
        text: Formdict['model.pay']
@@ -775,6 +781,14 @@
      }]
    },
    {
      type: 'select',
      key: 'printTemp',
      label: '打印模板',
      initVal: card.printTemp || '',
      required: true,
      options: printTemps
    },
    {
      type: 'text',
      key: 'url',
      label: Formdict['model.form.newpage.url'],
src/templates/zshare/verifycard/index.jsx
@@ -643,8 +643,9 @@
      if (card.sqlType === 'insert' || card.sqlType === 'insertOrUpdate') {
        let keys = []
        let values = []
        _fields.forEach(item => {
          if (!item.field) return
          if (!item.field || item.writein === 'false') return
          keys.push(item.field.toLowerCase())
@@ -686,7 +687,7 @@
        let _arr = []
        _fields.forEach(item => {
          if (!item.field) return
          if (!item.field || item.writein === 'false') return
          _arr.push(item.field.toLowerCase())
          _form.push(item.field + '=@' + item.field)
src/views/billprint/index.jsx
New file
@@ -0,0 +1,345 @@
import React, { Component } from 'react'
import { DndProvider } from 'react-dnd'
import { is, fromJS } from 'immutable'
import HTML5Backend from 'react-dnd-html5-backend'
import { ConfigProvider, notification, Collapse, Card, Switch, Button } from 'antd'
import Api from '@/api'
import Utils from '@/utils/utils.js'
import zhCN from '@/locales/zh-CN/mob.js'
import enUS from '@/locales/en-US/mob.js'
import antdEnUS from 'antd/es/locale/en_US'
import antdZhCN from 'antd/es/locale/zh_CN'
import asyncComponent from '@/utils/asyncComponent'
import './index.scss'
const { Panel } = Collapse
const _locale = localStorage.getItem('lang') !== 'en-US' ? antdZhCN : antdEnUS
const Header = asyncComponent(() => import('@/menu/header'))
const MenuForm = asyncComponent(() => import('@/menu/menuform'))
const SourceWrap = asyncComponent(() => import('@/menu/modelsource'))
const MenuShell = asyncComponent(() => import('@/menu/menushell'))
const BgController = asyncComponent(() => import('@/menu/bgcontroller'))
const PaddingController = asyncComponent(() => import('@/menu/padcontroller'))
const StyleController = asyncComponent(() => import('@/menu/stylecontroller'))
const ModalController = asyncComponent(() => import('@/menu/modalconfig/controller'))
const TableComponent = asyncComponent(() => import('@/templates/sharecomponent/tablecomponent'))
class BillPrint extends Component {
  state = {
    dict: localStorage.getItem('lang') !== 'en-US' ? zhCN : enUS,
    BID: '',
    tempId: '',
    config: null,
  }
  UNSAFE_componentWillMount() {
    try {
      let param = JSON.parse(window.decodeURIComponent(window.atob(this.props.match.params.param)))
      this.setState({
        BID: param.id,
        tempId: param.tempId,
      }, () => {
        this.getMenuParam()
      })
    } catch {
      notification.warning({
        top: 92,
        message: '菜单信息解析错误!',
        duration: 5
      })
    }
  }
  shouldComponentUpdate (nextProps, nextState) {
    return !is(fromJS(this.state), fromJS(nextState))
  }
  /**
   * @description 组件销毁,清除state更新
   */
  componentWillUnmount () {
    this.setState = () => {
      return
    }
  }
  getMenuParam = () => {
    const { tempId } = this.state
    let param = {
      func: 's_PrintTemplateMGetData',
      Type: 'Y',
      PrintTempNO: tempId
    }
    if (window.GLOB.mainSystemApi) { // 从单点登录服务器取打印配置信息
      param.rduri = window.GLOB.mainSystemApi
    }
    Api.getLocalConfig(param).then(result => {
      if (result.status) {
        // let config = null
        // try {
        //   config = JSON.parse(window.decodeURIComponent(window.atob(result.ConfigParam)))
        // } catch (e) {
        //   console.warn('Parse Failure')
        //   config = null
        // }
      } else {
        notification.warning({
          top: 92,
          message: result.message,
          duration: 5
        })
      }
    })
    // Api.getSystemConfig(param).then(result => {
    //   if (result.status) {
    //     let config = null
    //     try {
    //       config = JSON.parse(window.decodeURIComponent(window.atob(result.LongParam)))
    //     } catch (e) {
    //       console.warn('Parse Failure')
    //       config = null
    //     }
    //     if (!config) {
    //       config = {
    //         version: 1.0,
    //         uuid: MenuId,
    //         MenuID: MenuId,
    //         parentId: ParentId,
    //         Template: 'CustomPage',
    //         MenuType: MenuType,
    //         easyCode: '',
    //         enabled: false,
    //         MenuName: MenuName,
    //         MenuNo: MenuNo,
    //         tables: [],
    //         components: [],
    //         style: {
    //           backgroundColor: '#ffffff', backgroundImage: '',
    //           paddingTop: '16px', paddingBottom: '80px', paddingLeft: '16px', paddingRight: '16px'
    //         }
    //       }
    //     } else {
    //       config.uuid = MenuId
    //       config.MenuID = MenuId
    //       config.MenuType = config.MenuType || MenuType
    //     }
    //     if (MenuType === 'billPrint') {
    //       config.FstID = 'BillPrintTemp'
    //       config.SndID = 'BillPrintTemp'
    //       config.ParentID = 'BillPrintTemp'
    //     }
    //     this.setState({
    //       oriConfig: config,
    //       config: fromJS(config).toJS(),
    //       openEdition: result.open_edition || '',
    //     })
    //     this.getRoleFields()
    //   } else {
    //     notification.warning({
    //       top: 92,
    //       message: result.message,
    //       duration: 5
    //     })
    //   }
    // })
  }
  getRoleFields = () => {
    Api.getSystemConfig({func: 'sPC_Get_Roles_sModular'}).then(res => {
      if (res.status) {
        let _permFuncField = []
        let _sysRoles = []
        if (res.Roles && res.Roles.length > 0) {
          _sysRoles = res.Roles.map(role => {
            return {
              uuid: Utils.getuuid(),
              value: role.RoleID,
              text: role.RoleName
            }
          })
        }
        if (res.sModular && res.sModular.length > 0) {
          res.sModular.forEach(field => {
            if (field.ModularNo) {
              _permFuncField.push(field.ModularNo)
            }
          })
          _permFuncField = _permFuncField.sort()
        }
        let config = {...this.state.config, sysRoles: _sysRoles, permFuncField: _permFuncField}
        this.setState({config})
      }
    })
  }
  initMenuList = (msg) => {
    let config = {...this.state.config, ...msg}
    this.setState({config})
  }
  onEnabledChange = () => {
    const { config } = this.state
    if (!config.enabled && this.verifyConfig(true)) {
      return
    }
    this.setState({
      config: {...config, enabled: !config.enabled}
    })
  }
  verifyConfig = (show) => {
    const { config } = this.state
    let error = ''
    if (!config.MenuID) {
      notification.warning({
        top: 92,
        message: '请完善菜单基本信息!',
        duration: 5
      })
      return
    } else if (config.MenuType === 'custom' && (!config.MenuName || !config.MenuNo || !config.fstMenuId || !config.parentId)) {
      notification.warning({
        top: 92,
        message: '请完善菜单基本信息!',
        duration: 5
      })
      return
    }
    config.components.forEach(item => {
      if (error) return
      if (item.subtype === 'propcard' && item.wrap.datatype === 'static') return
      if (item.setting) {
        if (item.setting.interType === 'system' && item.setting.execute !== 'false' && !item.setting.dataresource) {
          error = `组件《${item.name}》未设置数据源!`
        } else if (item.setting.interType === 'system' && item.setting.execute === 'false' && item.scripts.length === 0) {
          error = `组件《${item.name}》未设置数据源!`
        } else if (item.setting.interType && !item.setting.primaryKey) {
          error = `组件《${item.name}》未设置主键!`
        }
      }
      if (item.type === 'bar' || item.type === 'line' || item.type === 'pie') {
        if (!item.plot.Xaxis) {
          error = `组件《${item.name}》图表字段尚未设置!`
        }
      }
    })
    if (show && error) {
      notification.warning({
        top: 92,
        message: error,
        duration: 5
      })
    }
    return error
  }
  // 更新配置信息
  updateConfig = (config) => {
    this.setState({
      config: config
    })
  }
  /**
   * @description 更新常用表信息,快捷添加后更新配置信息
   */
  updatetable = (config, fields) => {
    const { tableFields } = this.state
    config.tableFields = fields ? fields : tableFields
    this.setState({
      tableFields: fields ? fields : tableFields,
      config
    })
  }
  render () {
    const { activeKey, MenuType, dict, MenuId, config, ParentId, MenuName, MenuNo, menuloading } = this.state
    return (
      <ConfigProvider locale={_locale}>
        <div className="pc-menu-view" id="view">
          <Header view="design" closeView={this.closeView} />
          <DndProvider backend={HTML5Backend}>
            <div className="menu-body">
              <div className="menu-setting">
                <Collapse accordion activeKey={activeKey} bordered={false} onChange={(key) => this.setState({activeKey: key})}>
                  {/* 基本信息 */}
                  <Panel header={dict['mob.basemsg']} key="basedata">
                    {/* 菜单信息 */}
                    {config && MenuType === 'custom' ? <MenuForm
                      dict={dict}
                      config={config}
                      MenuId={MenuId}
                      parentId={ParentId}
                      MenuName={MenuName}
                      MenuNo={MenuNo}
                      initMenuList={this.initMenuList}
                      updateConfig={this.updateConfig}
                    /> : null}
                    {/* 表名添加 */}
                    {config ? <TableComponent config={config} updatetable={this.updatetable}/> : null}
                  </Panel>
                  {/* 组件添加 */}
                  <Panel header={dict['mob.component']} key="component">
                    <SourceWrap MenuType={MenuType} />
                  </Panel>
                  <Panel header={'背景'} key="background">
                    {config ? <BgController config={config} updateConfig={this.updateConfig} /> : null}
                  </Panel>
                  <Panel header={'内边距'} key="padding">
                    {config ? <PaddingController config={config} updateConfig={this.updateConfig} /> : null}
                  </Panel>
                </Collapse>
              </div>
              <div className={'menu-view ' + (menuloading ? 'saving' : '')}>
                <Card title={
                  <div> {config && config.MenuName} </div>
                } bordered={false} extra={
                  <div>
                    {config ? <Switch className="big" checkedChildren={dict['mob.enable']} unCheckedChildren={dict['mob.disable']} checked={config.enabled} onChange={this.onEnabledChange} /> : null}
                    <Button type="primary" onClick={this.submitConfig} loading={menuloading}>{dict['mob.save']}</Button>
                  </div>
                } style={{ width: '100%' }}>
                  {config && config.components ? <MenuShell menu={config} handleList={this.updateConfig} /> : null}
                </Card>
              </div>
            </div>
          </DndProvider>
          <StyleController />
          <ModalController />
        </div>
      </ConfigProvider>
    )
  }
}
export default BillPrint
src/views/billprint/index.scss
New file
@@ -0,0 +1,160 @@
.pc-menu-view {
  background: #000;
  min-height: 100vh;
  .menu-body {
    width: 100vw;
    height: 100vh;
    overflow-x: hidden;
    position: relative;
    background: #ffffff;
    padding: 50px 0px 0px 0px;
    .menu-setting {
      position: fixed;
      left: 0;
      top: 48px;
      z-index: 10;
      height: calc(100vh - 48px);
      width: 300px;
      background: #ffffff;
      box-shadow: 0px 2px 5px #bcbcbc;
      overflow-y: auto;
      > .ant-collapse {
        .ant-collapse-item.ant-collapse-item-active {
          border-bottom: 1px solid #d9d9d9;
        }
        .ant-collapse-header {
          padding: 11px 16px 10px 40px;
          border-bottom: 1px solid #d9d9d9;
          background: #1890ff;
          color: #ffffff;
        }
        .ant-collapse-content-box {
          .ant-form-item {
            margin-bottom: 10px;
          }
          .model-table-tablemanage-view {
            >.ant-list {
              margin-top: 20px;
              .ant-list-item {
                display: -webkit-box;
                padding-right: 20px;
                position: relative;
                padding-left: 5px;
                overflow: hidden;
                text-overflow: ellipsis;
                -webkit-line-clamp: 2;
                -webkit-box-orient: vertical;
                min-height: 55px;
                width: 100%;
                .anticon {
                  position: absolute;
                  top: 0px;
                  right: 0px;
                  padding: 3px 3px 10px 10px;
                  cursor: pointer;
                }
              }
            }
            >.tables {
              width: 66.66666667%!important;
            }
            >.ant-form-item-label {
              width: 33.33333333%;
            }
          }
        }
      }
      >.ant-tabs {
        >.ant-tabs-bar {
          border-bottom: 1px solid #181F29;
          margin-bottom: 0px;
          min-height: 48px;
          .ant-tabs-tab {
            padding: 14px 16px;
            color: rgba(255, 255, 255, 0.85);
          }
          .ant-tabs-tab-active.ant-tabs-tab {
            color: #1890ff;
          }
        }
      }
    }
    .menu-setting::-webkit-scrollbar {
      width: 4px;
    }
    .menu-setting::-webkit-scrollbar-thumb {
      border-radius: 5px;
      box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.08);
      background: rgba(0, 0, 0, 0.08);
    }
    .menu-setting::-webkit-scrollbar-track {
      box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.05);
      border-radius: 3px;
      border: 1px solid rgba(0, 0, 0, 0.07);
      background: rgba(0, 0, 0, 0);
    }
    .menu-view {
      position: relative;
      width: calc(100vw - 300px);
      margin-left: 300px;
      height: calc(100vh - 50px);
      overflow-y: auto;
      > .ant-card {
        >.ant-card-head {
          margin-bottom: 0px;
          .ant-card-head-title {
            color: #1890ff;
            padding: 5px 0;
          }
          .ant-card-extra {
            padding: 5px 0;
            button {
              margin-left: 20px;
            }
            .ant-switch.big {
              min-width: 60px;
              height: 28px;
              line-height: 28px;
              margin-top: -2px;
              .ant-switch-inner {
                font-size: 14px;
              }
            }
            .ant-switch.big:after {
              width: 24px;
              height: 24px;
            }
          }
        }
        >.ant-card-body {
          padding: 0px;
        }
      }
    }
    .menu-view.saving {
      .anticon-tool {
        display: none;
      }
    }
    .menu-view::-webkit-scrollbar {
      width: 7px;
    }
    .menu-view::-webkit-scrollbar-thumb {
      border-radius: 5px;
      box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.08);
      background: rgba(0, 0, 0, 0.08);
    }
    .menu-view::-webkit-scrollbar-track {
      box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.05);
      border-radius: 3px;
      border: 1px solid rgba(0, 0, 0, 0.07);
      background: rgba(0, 0, 0, 0);
    }
  }
}
src/views/menudesign/index.jsx
@@ -4,7 +4,8 @@
import { is, fromJS } from 'immutable'
import moment from 'moment'
import HTML5Backend from 'react-dnd-html5-backend'
import { ConfigProvider, notification, Modal, Collapse, Card, Icon, Switch, Button } from 'antd'
import { ConfigProvider, notification, Modal, Collapse, Card, Switch, Button } from 'antd'
import html2canvas from 'html2canvas'
import Api from '@/api'
import Utils from '@/utils/utils.js'
@@ -48,7 +49,6 @@
    oriConfig: null,
    openEdition: '',
    config: null,
    editElem: null,
  }
  UNSAFE_componentWillMount() {
@@ -86,10 +86,6 @@
    }
  }
  reloadTab = () => {
  }
  closeView = () => {
    const { oriConfig, config } = this.state
@@ -108,16 +104,16 @@
  }
  submitConfig = () => {
    const { config, MenuType, openEdition } = this.state
    const { config, openEdition } = this.state
    if (!config.MenuID) {
    if (config.MenuType === 'billPrint' && (!config.MenuName || !config.MenuNo)) {
      notification.warning({
        top: 92,
        message: '请完善菜单基本信息!',
        message: '请完善基本信息!',
        duration: 5
      })
      return
    } else if (MenuType === 'custom' && (!config.MenuName || !config.MenuNo || !config.fstMenuId || !config.parentId)) {
    } else if (config.MenuType === 'custom' && (!config.MenuName || !config.MenuNo || !config.fstMenuId || !config.parentId)) {
      notification.warning({
        top: 92,
        message: '请完善菜单基本信息!',
@@ -137,17 +133,19 @@
    delete _config.tableFields
    let funcs = []
    _config.components.forEach(component => {
      if (component.setting && component.setting.innerFunc) {
        funcs.push(`select '${_config.uuid}' as MenuID,'${component.setting.innerFunc}' as ProcName,'${component.setting.name}' as MenuName`)
      }
      if (component.action) {
        component.action.forEach(item => {
          if (!item.innerFunc) return
          funcs.push(`select '${_config.uuid}' as MenuID,'${item.innerFunc}' as ProcName,'${item.label}' as MenuName`)
        })
      }
    })
    if (config.MenuType !== 'billPrint') {
      _config.components.forEach(component => {
        if (component.setting && component.setting.innerFunc) {
          funcs.push(`select '${_config.uuid}' as MenuID,'${component.setting.innerFunc}' as ProcName,'${component.setting.name}' as MenuName`)
        }
        if (component.action) {
          component.action.forEach(item => {
            if (!item.innerFunc) return
            funcs.push(`select '${_config.uuid}' as MenuID,'${item.innerFunc}' as ProcName,'${item.label}' as MenuName`)
          })
        }
      })
    }
    let param = {
      func: 'sPC_TrdMenu_AddUpt',
@@ -155,10 +153,10 @@
      SndID: _config.parentId,
      ParentID: _config.parentId,
      MenuID: _config.uuid,
      MenuNo: _config.MenuNo,
      EasyCode: _config.easyCode,
      MenuNo: _config.MenuNo || '',
      EasyCode: _config.easyCode || '',
      Template: 'CustomPage',
      MenuName: _config.MenuName,
      MenuName: _config.MenuName || '',
      PageParam: JSON.stringify({Template: 'CustomPage', OpenType: 'newtab'}),
      LongParam: window.btoa(window.encodeURIComponent(JSON.stringify(_config))),
      LText: funcs.join(' union all '),
@@ -175,51 +173,123 @@
    this.setState({
      menuloading: true
    }, () => {
      new Promise(resolve => {
        if (config.MenuType === 'billPrint') {
          html2canvas(document.getElementById('menu-shell-inner')).then(canvas => {
            let img = canvas.toDataURL('image/png') // 获取生成的图片
            Api.fileuploadbase64(img, 'cloud').then(result => {
              if (result.status) {
                Api.getSystemConfig({
                  func: 's_PrintTemplateMSub',
                  ID: _config.uuid,
                  Images: Utils.getcloudurl(result.Images),
                  Remark: '',
                  temp_type: 'billprint',
                }).then(response => {
                  if (response.status) {
                    resolve(true)
                  } else {
                    notification.warning({
                      top: 92,
                      message: response.message,
                      duration: 5
                    })
                    this.setState({
                      menuloading: false
                    })
                    resolve(false)
                  }
                })
              } else {
                notification.warning({
                  top: 92,
                  message: result.ErrMesg,
                  duration: 5
                })
                this.setState({
                  menuloading: false
                })
                resolve(false)
              }
            })
          })
        } else {
          resolve(true)
        }
      }).then(res => {
        if (!res) return
        Api.getSystemConfig(param).then(response => {
          if (response.status) {
            this.setState({
              oriConfig: fromJS(config).toJS(),
              openEdition: response.open_edition || '',
              menuloading: false
            })
            notification.success({
              top: 92,
              message: '保存成功',
              duration: 2
            })
          } else {
            this.setState({
              openEdition: response.open_edition || '',
              menuloading: false
            })
            notification.warning({
              top: 92,
              message: response.message,
              duration: 5
            })
          }
        })
      })
    })
    Api.getSystemConfig(param).then(response => {
      if (response.status) {
        this.setState({
          oriConfig: fromJS(config).toJS(),
          openEdition: response.open_edition || '',
          menuloading: false
        })
        notification.success({
          top: 92,
          message: '保存成功',
          duration: 2
        })
      } else {
        this.setState({
          openEdition: response.open_edition || '',
          menuloading: false
        })
        notification.warning({
          top: 92,
          message: response.message,
          duration: 5
        })
      }
    })
    // Api.getSystemConfig(param).then(response => {
    //   if (response.status) {
    //     this.setState({
    //       oriConfig: fromJS(config).toJS(),
    //       openEdition: response.open_edition || '',
    //       menuloading: false
    //     })
    //     notification.success({
    //       top: 92,
    //       message: '保存成功',
    //       duration: 2
    //     })
    //   } else {
    //     this.setState({
    //       openEdition: response.open_edition || '',
    //       menuloading: false
    //     })
    //     notification.warning({
    //       top: 92,
    //       message: response.message,
    //       duration: 5
    //     })
    //   }
    // })
  }
  getMenuParam = () => {
    const { MenuId, ParentId, MenuName, MenuNo } = this.state
    Api.getSystemConfig({
    const { MenuId, ParentId, MenuName, MenuNo, MenuType } = this.state
    let param = {
      func: 'sPC_Get_LongParam',
      MenuID: MenuId
    }).then(result => {
    }
    Api.getSystemConfig(param).then(result => {
      if (result.status) {
        let config = null
        if (result.LongParam) {
          try {
            config = JSON.parse(window.decodeURIComponent(window.atob(result.LongParam)))
          } catch (e) {
            console.warn('Parse Failure')
            config = null
          }
        try {
          config = JSON.parse(window.decodeURIComponent(window.atob(result.LongParam)))
        } catch (e) {
          console.warn('Parse Failure')
          config = null
        }
        if (!config) {
@@ -229,6 +299,7 @@
            MenuID: MenuId,
            parentId: ParentId,
            Template: 'CustomPage',
            MenuType: MenuType,
            easyCode: '',
            enabled: false,
            MenuName: MenuName,
@@ -243,6 +314,13 @@
        } else {
          config.uuid = MenuId
          config.MenuID = MenuId
          config.MenuType = config.MenuType || MenuType
        }
        if (MenuType === 'billPrint') {
          config.FstID = 'BillPrintTemp'
          config.SndID = 'BillPrintTemp'
          config.ParentID = 'BillPrintTemp'
        }
        this.setState({
@@ -302,12 +380,6 @@
    this.props.modifyCustomMenu(config)
  }
  editCard = (element) => {
    this.setState({
      editElem: element
    })
  }
  onEnabledChange = () => {
    const { config } = this.state
@@ -321,7 +393,7 @@
  }
  verifyConfig = (show) => {
    const { config, MenuType } = this.state
    const { config } = this.state
    let error = ''
    if (!config.MenuID) {
@@ -331,7 +403,7 @@
        duration: 5
      })
      return
    } else if (MenuType === 'custom' && (!config.MenuName || !config.MenuNo || !config.fstMenuId || !config.parentId)) {
    } else if (config.MenuType === 'custom' && (!config.MenuName || !config.MenuNo || !config.fstMenuId || !config.parentId)) {
      notification.warning({
        top: 92,
        message: '请完善菜单基本信息!',
@@ -397,7 +469,7 @@
  }
  render () {
    const { activeKey, MenuType, dict, MenuId, config, ParentId, MenuName, MenuNo } = this.state
    const { activeKey, MenuType, dict, MenuId, config, ParentId, MenuName, MenuNo, menuloading } = this.state
    return (
      <ConfigProvider locale={_locale}>
@@ -410,7 +482,7 @@
                  {/* 基本信息 */}
                  <Panel header={dict['mob.basemsg']} key="basedata">
                    {/* 菜单信息 */}
                    {MenuType === 'custom' ? <MenuForm
                    {config && MenuType === 'custom' ? <MenuForm
                      dict={dict}
                      config={config}
                      MenuId={MenuId}
@@ -425,7 +497,7 @@
                  </Panel>
                  {/* 组件添加 */}
                  <Panel header={dict['mob.component']} key="component">
                    <SourceWrap />
                    <SourceWrap MenuType={MenuType} />
                  </Panel>
                  <Panel header={'背景'} key="background">
                    {config ? <BgController config={config} updateConfig={this.updateConfig} /> : null}
@@ -435,16 +507,13 @@
                  </Panel>
                </Collapse>
              </div>
              <div className="menu-view">
              <div className={'menu-view ' + (menuloading ? 'saving' : '')}>
                <Card title={
                  <div>
                    {config && config.MenuName}
                    <Icon type="redo" style={{marginLeft: '10px'}} title="刷新标签列表" onClick={() => this.reloadTab()} />
                  </div>
                  <div> {config && config.MenuName} </div>
                } bordered={false} extra={
                  <div>
                    {config ? <Switch className="big" checkedChildren={dict['mob.enable']} unCheckedChildren={dict['mob.disable']} checked={config.enabled} onChange={this.onEnabledChange} /> : null}
                    <Button type="primary" onClick={this.submitConfig} loading={this.state.menuloading}>{dict['mob.save']}</Button>
                    <Button type="primary" onClick={this.submitConfig} loading={menuloading}>{dict['mob.save']}</Button>
                  </div>
                } style={{ width: '100%' }}>
                  {config && config.components ? <MenuShell menu={config} handleList={this.updateConfig} /> : null}
src/views/menudesign/index.scss
@@ -137,6 +137,11 @@
        }
      }
    }
    .menu-view.saving {
      .anticon-tool {
        display: none;
      }
    }
    .menu-view::-webkit-scrollbar {
      width: 7px;
    }