king
2021-11-02 2f952c67cb4eddd4ad916a8418b3aee4cae82111
2021-11-02
42个文件已修改
449 ■■■■ 已修改文件
public/README.txt 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/header/index.jsx 12 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/header/resetpwd/index.jsx 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/locales/en-US/main.js 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/locales/zh-CN/main.js 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/datasource/index.jsx 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/datasource/verifycard/settingform/index.jsx 11 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/mob/components/formdragelement/card.jsx 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/mob/components/menubar/normal-menubar/index.jsx 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/mob/components/menubar/normal-menubar/index.scss 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/mob/components/menubar/normal-menubar/menucomponent/index.jsx 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/mob/components/menubar/normal-menubar/menucomponent/options.jsx 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/mob/components/menubar/normal-menubar/options.jsx 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/card/balcony/index.jsx 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/card/data-card/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/card/prop-card/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/card/table-card/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/carousel/data-card/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/carousel/prop-card/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/chart/antv-bar-line/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/chart/antv-dashboard/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/chart/antv-pie/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/chart/antv-scatter/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/chart/custom-chart/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/form/normal-form/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/form/tab-form/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/table/edit-table/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/table/normal-table/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/tree/antd-tree/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/subtable/index.jsx 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/automatic/index.jsx 21 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/actioncomponent/dragaction/index.jsx 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/settingcomponent/index.jsx 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/createinterface/index.jsx 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/formconfig.jsx 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/modalform/index.jsx 40 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/unattended/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/unattended/settingform/index.jsx 30 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/verifycard/index.jsx 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/utils.js 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/login/index.jsx 67 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mobdesign/index.jsx 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
public/README.txt
@@ -2,14 +2,14 @@
appId             -- 云端生成的应用ID
appkey            -- 云端生成的应用密钥
mainSystemApi     -- sso系统的接口路径,注:业务系统需要填写,且值为通用接口的完整路径
systemType        -- 判断业务系统为测试 (空) 或正式 (production) ,正式系统开发权限只含有系统升级等限定功能
mainSystemApi     -- 业务系统的单点登录链接地址,开发系统地址为http://sso.mk9h.cn/cloud/webapi/dostars,生产系统需要依据搭建的单点登录系统自行修改配置
systemType        -- 系统类型,正式系统是填production,开发系统为空,开发系统会有一部分的数据模糊化
externalDatabase  -- 外联库,不使用时默认为false
lineColor         -- 登录页分割线颜色
filter            -- 页面滤镜,值为'true'时,页面显示为黑白色
defaultApp        -- 默认应用,系统需默认打开某个子应用时需填写应用编码,空值时跳转到管理后台
defaultLang       -- 默认打开的子应用语言类型,填入defaultApp时有效
defaultApp        -- 默认应用,系统默认打开某个子应用时需填写应用编码
defaultLang       -- 打开的子应用语言类型,默认为zh-CN
WXAppID           -- 使用公众号时,绑定的公众号ID
debugger          -- debugger模式是否开启,开启后移动端子应用中会有控制台
debugger          -- 值为true时开启调试模式,开启后移动端子应用中会有控制台
licenseKey        -- 许可密钥,在内部网络中使用系统时,会跳过epc验证
probation         -- 试用期(YYYY-MM-DD),在正式系统中,试用期内调用系统接口的脚本会记录下来
src/components/header/index.jsx
@@ -13,6 +13,7 @@
  initMenuPermission,
  logout
} from '@/store/action'
import asyncComponent from '@/utils/asyncComponent'
import Api from '@/api'
import MKEmitter from '@/utils/events.js'
import options from '@/store/options.js'
@@ -20,12 +21,12 @@
import enUS from '@/locales/en-US/main.js'
import Utils from '@/utils/utils.js'
import avatar from '@/assets/img/avatar.jpg'
import Resetpwd from './resetpwd'
import LoginForm from './loginform'
import './index.scss'
const { confirm } = Modal
const { Search } = Input
const Resetpwd = asyncComponent(() => import('./resetpwd'))
const LoginForm = asyncComponent(() => import('./loginform'))
class Header extends Component {
  static propTpyes = {
@@ -87,9 +88,14 @@
        if (result.status) {
          notification.success({
            top: 92,
            message: this.state.dict['main.password.resetsuccess'],
            message: '修改成功,请重新登录。',
            duration: 2
          })
          setTimeout(() => {
            sessionStorage.clear()
            this.props.logout()
            this.props.history.replace('/login')
          }, 2000)
        } else {
          notification.warning({
            top: 92,
src/components/header/resetpwd/index.jsx
@@ -1,15 +1,11 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { Form, Input } from 'antd'
class Resetpwd extends Component {
  static propTpyes = {
    dict: PropTypes.object
  }
  state = {
    confirmDirty: false,
    autoCompleteResult: []
    autoCompleteResult: [],
    level: localStorage.getItem(window.location.href.split('#')[0] + 'pwdlevel') || ''
  }
  onEnterSubmit = (e) => {
@@ -61,7 +57,7 @@
  compareToFirstPassword = (rule, value, callback) => {
    const { form } = this.props
    if (value && value !== form.getFieldValue('password')) {
      callback(this.props.dict['main.password.diff'])
      callback('两次输入密码不一致!')
    } else {
      callback()
    }
@@ -69,14 +65,24 @@
  validateToNextPassword = (rule, value, callback) => {
    const { form } = this.props
    const { level } = this.state
    if (value && this.state.confirmDirty) {
      form.validateFields(['confirm'], { force: true })
    }
    callback()
    if (level === 'letter_num' && value && /^[0-9a-zA-Z!@#$%^&*()_]*$/.test(value) && /^([^0-9]*|[^a-zA-Z]*)$/.test(value)) {
      callback('密码中必须含有数字和字母。')
    } else if ((level === 'char_num' || level === 'char_num_90') && value && /^[0-9a-zA-Z!@#$%^&*()_]*$/.test(value) && /^([^0-9]*|[^a-zA-Z]*|[^!@#$%^&*()_]*)$/.test(value)) {
      callback('密码中必须含有数字、字母和特殊字符。')
    } else {
      callback()
    }
  }
  render() {
    const { getFieldDecorator } = this.props.form
    const { level } = this.state
    const formItemLayout = {
      labelCol: {
@@ -89,32 +95,41 @@
      }
    }
    let rules = []
    if (level) {
      rules.push({
        min: 8,
        message: '密码长度不可小于8位!'
      })
    }
    return (
      <Form {...formItemLayout} onKeyDown={this.onEnterSubmit} id="reset-password-form">
        <Form.Item label={this.props.dict['main.password.origin']}>
        <Form.Item label="原密码">
          {getFieldDecorator('originpwd', {
            rules: [
              {
                required: true,
                message: this.props.dict['main.password.origin.required']
                message: '请输入原密码!'
              }
            ]
          })(<Input.Password autoFocus/>)}
        </Form.Item>
        <Form.Item label={this.props.dict['main.password.new']} hasFeedback>
        <Form.Item label="新密码" hasFeedback>
          {getFieldDecorator('password', {
            rules: [
              {
                required: true,
                message: this.props.dict['main.password.new.required']
                message: '请输入新密码!'
              },
              {
                pattern: /^[0-9a-zA-Z!@#$%^&*()_]*$/ig,
                message: '密码只允许包含数字、字母以及!@#$%&*()_。'
              },
              ...rules,
              {
                max: 50,
                message: this.props.dict['main.password.maxlen']
                message: '最大密码长度为50位!'
              },
              {
                validator: this.validateToNextPassword
@@ -122,12 +137,12 @@
            ]
          })(<Input.Password />)}
        </Form.Item>
        <Form.Item label={this.props.dict['main.password.confirm']} hasFeedback>
        <Form.Item label="确认密码" hasFeedback>
          {getFieldDecorator('confirm', {
            rules: [
              {
                required: true,
                message: this.props.dict['main.password.confirm.required']
                message: '请确认密码!'
              },
              {
                validator: this.compareToFirstPassword
src/locales/en-US/main.js
@@ -13,15 +13,6 @@
  'main.logout.hint': 'Are you sure you want to log out?',
  'main.verup': 'Version upgrade',
  'main.password': 'Change the password',
  'main.password.origin': 'Original Password',
  'main.password.origin.required': 'Please input your original password!',
  'main.password.new': 'Password',
  'main.password.new.required': 'Please input your password!',
  'main.password.confirm': 'Confirm Password',
  'main.password.confirm.required': 'Please confirm your password!',
  'main.password.maxlen': 'The maximum password length is 12 bits!',
  'main.password.diff': 'Two passwords that you enter is inconsistent!',
  'main.password.resetsuccess': 'Password modified successfully!',
  'main.login.develop': 'Login developer',
  'main.revert.default': 'Restore default Settings',
  'main.copy.success': 'Copy success',
src/locales/zh-CN/main.js
@@ -13,15 +13,6 @@
  'main.logout.hint': '您确定要退出吗?',
  'main.verup': '版本升级',
  'main.password': '修改密码',
  'main.password.origin': '原密码',
  'main.password.origin.required': '请输入原密码!',
  'main.password.new': '新密码',
  'main.password.new.required': '请输入新密码!',
  'main.password.confirm': '确认密码',
  'main.password.confirm.required': '请确认密码!',
  'main.password.maxlen': '最大密码长度为12位!',
  'main.password.diff': '两次输入密码不一致!',
  'main.password.resetsuccess': '密码修改成功!',
  'main.login.develop': '登录开发机',
  'main.revert.default': '恢复默认设置',
  'main.copy.success': '复制成功',
src/menu/datasource/index.jsx
@@ -189,6 +189,8 @@
        })
      }
      let maxScript = 0
      if (window.GLOB.funcs && window.GLOB.funcs.length > 0) {
        window.GLOB.funcs.forEach(m => {
          let reg = new RegExp('\\$ex@' + m.func_code + '@ex\\$', 'ig')
@@ -197,10 +199,20 @@
          }
          res.scripts.forEach(item => {
            item.sql = item.sql.replace(reg, `/*$ex@${m.func_code}-begin*/\n${m.key_sql}\n/*@ex$-end*/`)
            if (item.status === 'false') return
            if (/exec\s/ig.test(item.sql)) {
              maxScript = 100
            } else if (item.sql.length > maxScript) {
              maxScript = item.sql.length
            }
          })
        })
      }
      res.setting.maxScript = maxScript
      this.setState({loading: false, visible: false})
      this.props.updateConfig({...config, ...res})
    }, () => {
src/menu/datasource/verifycard/settingform/index.jsx
@@ -59,6 +59,7 @@
    return new Promise((resolve, reject) => {
      this.props.form.validateFieldsAndScroll((err, values) => {
        if (!err) {
          values.sync = values.sync || 'false'
          // 数据源前端验证
          if (values.interType === 'system' && values.execute !== 'false' && !values.dataresource) {
            notification.warning({
@@ -369,7 +370,7 @@
                </Radio.Group>)}
              </Form.Item>
            </Col> : null}
            {config.type !== 'navbar' && config.type !== 'balcony' ? <Col span={8}>
            {!['navbar', 'balcony', 'menubar'].includes(config.type) ? <Col span={8}>
              <Form.Item label={
                <Tooltip placement="topLeft" title={'该组件如果受其他组件控制,请选项相应的组件,没有时选“无”。'}>
                  <Icon type="question-circle" />
@@ -420,7 +421,7 @@
              </Form.Item>
            </Col> : null}
            {/* 1、不分页且不存在上级模块 */}
            {config.type !== 'navbar' && (!config.pageable || (config.pageable && laypage === 'false')) && (!supModule || supModule.length === 0 || supModule[0] === 'empty') ? <Col span={8}>
            {!['navbar', 'menubar'].includes(config.type) && (!config.pageable || (config.pageable && laypage === 'false')) && (!supModule || supModule.length === 0 || supModule[0] === 'empty') ? <Col span={8}>
              <Form.Item label={
                <Tooltip placement="topLeft" title={'初始化加载时,是否与其他组件一同加载数据,注:仅在使用系统函数,且初始化加载数据时有效,分页请求时无效。'}>
                  <Icon type="question-circle" />
@@ -437,7 +438,7 @@
                )}
              </Form.Item>
            </Col> : null}
            {config.type !== 'navbar' && config.type !== 'balcony' ? <Col span={8}>
            {!['navbar', 'balcony', 'menubar'].includes(config.type) ? <Col span={8}>
              <Form.Item label={
                <Tooltip placement="topLeft" title={'优先使用同级的搜索条件组件,同级搜索不存在时,依次向上选取,与当前组件的搜索条件一同用作数据过滤(当前组件的搜索条件优先)。'}>
                  <Icon type="question-circle" />
@@ -454,7 +455,7 @@
                )}
              </Form.Item>
            </Col> : null}
            {config.type !== 'navbar' && config.type !== 'balcony' && useMSearch === 'true' ? <Col span={8}>
            {!['navbar', 'balcony', 'menubar'].includes(config.type) && useMSearch === 'true' ? <Col span={8}>
              <Form.Item label={
                <Tooltip placement="topLeft" title={'外层搜索条件改变时,是否刷新当前组件数据。'}>
                  <Icon type="question-circle" />
@@ -482,7 +483,7 @@
                </Radio.Group>)}
              </Form.Item>
            </Col>
            {config.type !== 'navbar' && config.type !== 'balcony' ? <Col span={8}>
            {!['navbar', 'balcony', 'menubar'].includes(config.type) ? <Col span={8}>
              <Form.Item label="初始化数据">
                {getFieldDecorator('onload', {
                  initialValue: setting.onload || 'true'
src/mob/components/formdragelement/card.jsx
@@ -185,8 +185,9 @@
      </div>
    } trigger="hover">
      <div className="page-card" style={{ opacity: opacity}}>
        <div ref={node => drag(drop(node))}>
        <div ref={node => drag(drop(node))} style={{ border: '0.5px solid transparent'}}>
          {card.type === 'split' ? formItem : <Form.Item
            style={{marginTop: card.marginTop || 0, marginBottom: card.marginBottom || 0}}
            className={'ant-form-item' + (card.required === 'true' ? ' required' : '') + (card.splitline === 'false' ? ' no-boder' : '')}
          >
            {formItem}
src/mob/components/menubar/normal-menubar/index.jsx
@@ -19,6 +19,7 @@
const PasteComponent = asyncIconComponent(() => import('@/menu/components/share/pastecomponent'))
const UserComponent = asyncIconComponent(() => import('@/menu/components/share/usercomponent'))
const NormalHeader = asyncComponent(() => import('@/menu/components/share/normalheader'))
const SettingComponent = asyncIconComponent(() => import('@/menu/datasource'))
const { confirm } = Modal
@@ -45,10 +46,14 @@
        floor: card.floor,
        tabId: '',
        parentId: '',
        format: 'object',   // 组件属性 - 数据格式
        pageable: false,    // 组件属性 - 是否可分页
        switchable: false,  // 组件属性 - 数据是否可切换
        dataName: card.dataName || '',
        width: card.width || 24,
        name: card.name,
        subtype: card.subtype,
        setting: { interType: 'system' },
        wrap: { name: card.name, width: card.width || 24, title: '' },
        style: { marginLeft: '0px', marginRight: '0px', marginTop: '8px', marginBottom: '8px' },
        headerStyle: { fontSize: '16px', borderBottomWidth: '1px', borderBottomColor: '#e8e8e8' },
@@ -227,7 +232,16 @@
  }
  updateWrap = (res) => {
    this.updateComponent({...this.state.card, wrap: res})
    let card = {...this.state.card, wrap: res}
    if (res.datatype === 'dynamic' && !card.format) {
      card.format = 'object'
      card.pageable = false
      card.switchable = false
      card.setting = { interType: 'system' }
      card.columns = []
      card.scripts = []
    }
    this.updateComponent(card)
  }
  clickComponent = (e) => {
@@ -268,6 +282,8 @@
            <Icon className="style" title="调整样式" onClick={this.changeStyle} type="font-colors" />
            <UserComponent config={card}/>
            <Icon className="close" title="删除组件" type="delete" onClick={() => this.props.deletecomponent(card.uuid)} />
            {card.wrap.datatype === 'dynamic' ? <SettingComponent config={card} updateConfig={this.updateComponent} /> : null}
            {card.wrap.datatype !== 'dynamic' ? <Icon style={{color: '#eeeeee', cursor: 'not-allowed'}} type="setting"/> : null}
          </div>
        } trigger="hover">
          <Icon type="tool" />
src/mob/components/menubar/normal-menubar/index.scss
@@ -41,6 +41,7 @@
      text-overflow: ellipsis;
    }
    .menu-sign {
      position: relative;
      text-align: center;
      .anticon {
        border-radius: 15%;
@@ -48,6 +49,14 @@
      img {
        border-radius: 15%;
      }
      .am-badge-text {
        position: absolute;
        height: 8px;
        width: 8px;
        border-radius: 100%;
        background: #ff5b05;
        z-index: 1;
      }
    }
  }
}
src/mob/components/menubar/normal-menubar/menucomponent/index.jsx
@@ -80,9 +80,10 @@
  }
  getSettingForms = () => {
    const { cards } = this.props
    const { card } = this.state
    return getSettingForm(card.setting)
    return getSettingForm(card.setting, cards.columns || [])
  }
  updateSetting = (res) => {
@@ -150,8 +151,10 @@
                color: card.setting.color,
                borderRadius: card.setting.borderRadius || '15%'
              }} type={card.setting.icon}/>
              {card.setting.tip ? <sup className="am-badge-text"></sup> : null}
            </div> : <div className="menu-sign">
              <img style={{width: card.setting.imgWidth, height: card.setting.imgWidth, borderRadius: card.setting.borderRadius || '15%'}} src={card.setting.url} alt=""/>
              {card.setting.tip ? <sup className="am-badge-text"></sup> : null}
            </div>}
            <div className="menu-name">{card.setting.name}</div>
          </div>
src/mob/components/menubar/normal-menubar/menucomponent/options.jsx
@@ -1,7 +1,7 @@
/**
 * @description Setting表单配置信息
 */
export default function (setting) {
export default function (setting, columns) {
  let menulist = sessionStorage.getItem('appMenus')
  if (menulist) {
@@ -180,6 +180,15 @@
      precision: 0,
      required: false
    },
    {
      type: 'select',
      field: 'tip',
      label: '提示',
      initval: setting.tip || '',
      tooltip: '绑定提示字段后,会在菜单右上角显示红色标记。',
      required: false,
      options: columns
    },
  ]
  return menuWrapForm
src/mob/components/menubar/normal-menubar/options.jsx
@@ -28,6 +28,18 @@
      max: 24,
      precision: 0,
      required: true
    },
    {
      type: 'radio',
      field: 'datatype',
      label: '数据来源',
      initval: wrap.datatype || 'static',
      tooltip: '选择静态值,无需配置数据源。',
      required: false,
      options: [
        {value: 'dynamic', label: '动态'},
        {value: 'static', label: '静态'},
      ]
    }
  ]
src/tabviews/custom/components/card/balcony/index.jsx
@@ -251,7 +251,7 @@
    if (syncConfig) {
      if (!syncConfig.setting.supModule || syncConfig.setting.supModule !== MenuID) return
  
      if (id !== this.state.BID) {
      if (id !== this.state.BID || id !== '') {
        this.setState({ BID: id, BData: data }, () => {
          this.loadData()
        })
@@ -263,7 +263,7 @@
        this.setState({ show: id ? true : false })
      }
  
      if (id !== this.state.BID) {
      if (id !== this.state.BID || id !== '') {
        this.setState({ BID: id, BData: data }, () => {
          this.loadData()
        })
src/tabviews/custom/components/card/data-card/index.jsx
@@ -328,7 +328,7 @@
    const { config } = this.state
    if (!config.setting.supModule || config.setting.supModule !== MenuID) return
    if (id !== this.state.BID) {
    if (id !== this.state.BID || id !== '') {
      this.setState({ BID: id, BData: data, pageIndex: 1 }, () => {
        this.loadData()
      })
src/tabviews/custom/components/card/prop-card/index.jsx
@@ -265,7 +265,7 @@
    const { config } = this.state
    if (!config.setting || !config.setting.supModule || config.setting.supModule !== MenuID) return
    if (id !== this.state.BID) {
    if (id !== this.state.BID || id !== '') {
      this.setState({ BID: id, BData: data }, () => {
        this.loadData()
      })
src/tabviews/custom/components/card/table-card/index.jsx
@@ -183,7 +183,7 @@
    const { config } = this.state
    if (!config.setting.supModule || config.setting.supModule !== MenuID) return
    if (id !== this.state.BID) {
    if (id !== this.state.BID || id !== '') {
      this.setState({ BID: id, BData: data, pageIndex: 1 }, () => {
        this.loadData()
      })
src/tabviews/custom/components/carousel/data-card/index.jsx
@@ -165,7 +165,7 @@
    const { config } = this.state
    if (!config.setting.supModule || config.setting.supModule !== MenuID) return
    if (id !== this.state.BID) {
    if (id !== this.state.BID || id !== '') {
      this.setState({ BID: id, BData: data }, () => {
        this.loadData()
      })
src/tabviews/custom/components/carousel/prop-card/index.jsx
@@ -171,7 +171,7 @@
    const { config } = this.state
    if (config.wrap.datatype === 'static' || !config.setting.supModule || config.setting.supModule !== MenuID) return
    if (id !== this.state.BID) {
    if (id !== this.state.BID || id !== '') {
      this.setState({ BID: id, BData: data }, () => {
        this.loadData()
      })
src/tabviews/custom/components/chart/antv-bar-line/index.jsx
@@ -453,7 +453,7 @@
    const { config } = this.state
    if (!config.setting.supModule || config.setting.supModule !== MenuID) return
    if (id !== this.state.BID) {
    if (id !== this.state.BID || id !== '') {
      this.setState({ BID: id }, () => {
        this.loadData()
      })
src/tabviews/custom/components/chart/antv-dashboard/index.jsx
@@ -234,7 +234,7 @@
    const { config } = this.state
    if (!config.setting.supModule || config.setting.supModule !== MenuID) return
    if (id !== this.state.BID) {
    if (id !== this.state.BID || id !== '') {
      this.setState({ BID: id }, () => {
        this.loadData()
      })
src/tabviews/custom/components/chart/antv-pie/index.jsx
@@ -187,7 +187,7 @@
    const { config } = this.state
    if (!config.setting.supModule || config.setting.supModule !== MenuID) return
    if (id !== this.state.BID) {
    if (id !== this.state.BID || id !== '') {
      this.setState({ BID: id }, () => {
        this.loadData()
      })
src/tabviews/custom/components/chart/antv-scatter/index.jsx
@@ -205,7 +205,7 @@
    const { config } = this.state
    if (!config.setting.supModule || config.setting.supModule !== MenuID) return
    if (id !== this.state.BID) {
    if (id !== this.state.BID || id !== '') {
      this.setState({ BID: id }, () => {
        this.loadData()
      })
src/tabviews/custom/components/chart/custom-chart/index.jsx
@@ -203,7 +203,7 @@
    const { config } = this.state
    if (!config.setting.supModule || config.setting.supModule !== MenuID) return
    if (id !== this.state.BID) {
    if (id !== this.state.BID || id !== '') {
      this.setState({ BID: id }, () => {
        this.loadData()
      })
src/tabviews/custom/components/form/normal-form/index.jsx
@@ -217,7 +217,7 @@
  resetParentParam = (MenuID, id) => {
    const { config } = this.state
    if (config.wrap.datatype === 'static' || !config.setting.supModule || config.setting.supModule !== MenuID) return
    if (id !== this.state.BID) {
    if (id !== this.state.BID || id !== '') {
      this.setState({ BID: id }, () => {
        this.loadData()
      })
src/tabviews/custom/components/form/tab-form/index.jsx
@@ -200,7 +200,7 @@
  resetParentParam = (MenuID, id) => {
    const { config } = this.state
    if (config.wrap.datatype === 'static' || !config.setting.supModule || config.setting.supModule !== MenuID) return
    if (id !== this.state.BID) {
    if (id !== this.state.BID || id !== '') {
      this.setState({ BID: id }, () => {
        this.loadData()
      })
src/tabviews/custom/components/table/edit-table/index.jsx
@@ -373,7 +373,7 @@
    const { setting } = this.state
    if (!setting.supModule || setting.supModule !== MenuID) return
    if (id !== this.state.BID) {
    if (id !== this.state.BID || id !== '') {
      this.setState({
        pageIndex: 1,
        BID: id,
src/tabviews/custom/components/table/normal-table/index.jsx
@@ -485,7 +485,7 @@
    const { setting } = this.state
    if (!setting.supModule || setting.supModule !== MenuID) return
    if (id !== this.state.BID) {
    if (id !== this.state.BID || id !== '') {
      this.setState({
        pageIndex: 1,
        BID: id,
src/tabviews/custom/components/tree/antd-tree/index.jsx
@@ -170,7 +170,7 @@
    const { config } = this.state
    if (!config.setting.supModule || config.setting.supModule !== MenuID) return
    if (id !== this.state.BID) {
    if (id !== this.state.BID || id !== '') {
      this.setState({ BID: id }, () => {
        this.loadData()
      })
src/tabviews/subtable/index.jsx
@@ -373,7 +373,7 @@
        return
      }
    }
    if (this.props.Tab.supMenu && !BID) { // 主表ID不存在时,不查询子表
      this.setState({
        data: [],
@@ -916,12 +916,15 @@
  changeTableLine = (ContainerId, tableId, id, data) => {
    const { Tab } = this.props
    const { setting } = this.state
    if (!Tab.supMenu || tableId !== Tab.supMenu) return
    this.setState({BData: data, BID: id})
    if (id !== this.state.BID) {
    if (!setting) return
    if (id !== this.state.BID || id !== '') {
      MKEmitter.emit('resetTable', this.props.Tab.uuid) // 列表重置
      this.setState({
        pageIndex: 1
src/tabviews/zshare/automatic/index.jsx
@@ -15,10 +15,18 @@
  state = {
    running: false,
    line: 1,
    init: true
    gap: 2000
  }
  timer = null
  UNSAFE_componentWillMount() {
    const { autoMatic } = this.props
    if (autoMatic.gap && autoMatic.gap >= 1) {
      this.setState({gap: autoMatic.gap * 1000})
    }
  }
  componentDidMount () {
    MKEmitter.addListener('modifyTabs', this.breakOff)
@@ -60,6 +68,7 @@
  autoExecOver = (btnId, type) => {
    const { autoMatic, config } = this.props
    const { gap } = this.state
    if (!this.state.running || btnId !== autoMatic.action) return
@@ -70,12 +79,12 @@
        this.setState({line: this.state.line + 1}, () => {
          setTimeout(() => {
            MKEmitter.emit('autoQueryData', config.MenuID, this.state.line)
          }, 2000)
          }, gap)
        })
      } else if (autoMatic.onFail === 'stay') {
        setTimeout(() => {
          MKEmitter.emit('autoQueryData', config.MenuID, this.state.line)
        }, 2000)
        }, gap)
      } else {
        this.setState({running: false})
      }
@@ -84,12 +93,12 @@
        this.setState({line: this.state.line + 1}, () => {
          setTimeout(() => {
            MKEmitter.emit('autoQueryData', config.MenuID, this.state.line)
          }, 2000)
          }, gap)
        })
      } else if (autoMatic.onSuccess === 'stay') {
        setTimeout(() => {
          MKEmitter.emit('autoQueryData', config.MenuID, this.state.line)
        }, 2000)
        }, gap)
      } else {
        this.setState({running: false})
      }
@@ -104,7 +113,7 @@
    setTimeout(() => {
      MKEmitter.emit('triggerBtnId', autoMatic.action, [data], 'autoMatic')
      if (['prompt', 'pop'].includes(autoMatic.OpenType)) {
        let delay = this.state.init && autoMatic.OpenType === 'pop' ? 2000 : 200
        let delay = autoMatic.OpenType === 'pop' ? 2000 : 300
        setTimeout(() => {
          if (autoMatic.OpenType === 'prompt') {
src/templates/sharecomponent/actioncomponent/dragaction/index.jsx
@@ -55,8 +55,7 @@
    copycard.copyType = 'action'
    copycard.focus = true
    copycard.originCard = card
    copycard.originCard.appkey = window.GLOB.appkey
    copycard.originCard = {...card, appkey: window.GLOB.appkey}
    if (copycard.OpenType === 'popview') { // 待完善
      copycard.linkTab = ''
src/templates/sharecomponent/settingcomponent/index.jsx
@@ -120,12 +120,21 @@
  resetSetting = (s) => {
    let setting = fromJS(s).toJS()
    let maxScript = 0
    if (window.GLOB.funcs && window.GLOB.funcs.length > 0) {
      window.GLOB.funcs.forEach(m => {
        let reg = new RegExp('\\$ex@' + m.func_code + '@ex\\$', 'ig')
        setting.scripts.forEach(item => {
          item.sql = item.sql.replace(reg, `/*$ex@${m.func_code}-begin*/\n${m.key_sql}\n/*@ex$-end*/`)
          if (item.status === 'false') return
          if (/exec\s/ig.test(item.sql)) {
            maxScript = 100
          } else if (item.sql.length > maxScript) {
            maxScript = item.sql.length
          }
        })
        setting.preScripts.forEach(item => {
          item.sql = item.sql.replace(reg, `/*$ex@${m.func_code}-begin*/\n${m.key_sql}\n/*@ex$-end*/`)
@@ -139,6 +148,8 @@
      })
    }
    setting.maxScript = maxScript
    return setting
  }
src/templates/zshare/createinterface/index.jsx
@@ -1010,6 +1010,9 @@
      if (!_arr.includes('modifyuserid')) {
        _form.push('modifyuserid=@userid@')
      }
      if (!_arr.includes('modifyuser')) {
        _form.push('modifyuser=@username')
      }
      if (hasvoucher) {
        if (!_arr.includes('bvoucher')) {
          _arr.push('bvoucher')
@@ -1058,7 +1061,7 @@
    } else if (_actionType === 'LogicDelete') { // 逻辑删除
      _sql += `
        /* 默认sql */
        update ${btn.sql} set deleted=1,modifydate=getdate(),modifyuserid=@userid@ where ${primaryKey}=@${primaryKey}@;`
        update ${btn.sql} set deleted=1,modifydate=getdate(),modifyuser=@username,modifyuserid=@userid@ where ${primaryKey}=@${primaryKey}@;`
      
    } else if (_actionType === 'delete') {      // 物理删除
      let _msg = ''
src/templates/zshare/formconfig.jsx
@@ -874,6 +874,10 @@
    })
  }
  if (card.OpenType === 'blank') {
    card.OpenType = 'tab'
  }
  return [
    {
      type: 'select',
@@ -2739,11 +2743,11 @@
      label: '光标',
      initVal: card.cursor || 'left',
      options: [{
        value: 'right',
        text: '右对齐'
      }, {
        value: 'left',
        text: '左对齐'
      }, {
        value: 'right',
        text: '右对齐'
      }],
      forbid: appType !== 'mob'
    },
@@ -3115,6 +3119,28 @@
      options: inputfields
    },
    {
      type: 'number',
      key: 'marginTop',
      label: '上边距(px)',
      initVal: card.marginTop || 0,
      min: 0,
      max: 1000,
      precision: 0,
      required: false,
      forbid: appType !== 'mob'
    },
    {
      type: 'number',
      key: 'marginBottom',
      label: '下边距(px)',
      initVal: card.marginBottom || 0,
      min: 0,
      max: 1000,
      precision: 0,
      required: false,
      forbid: appType !== 'mob'
    },
    {
      type: 'multiselect',
      key: 'blacklist',
      label: Formdict['header.form.blacklist'],
src/templates/zshare/modalform/index.jsx
@@ -16,26 +16,26 @@
const DataTable = asyncComponent(() => import('./datatable'))
const modalTypeOptions = {
  text: ['initval', 'readonly', 'required', 'hidden', 'readin', 'fieldlength', 'regular', 'interception', 'span', 'labelwidth', 'tooltip', 'extra', 'enter', 'cursor', 'scan', 'splitline', 'placeholder', 'place'],
  number: ['initval', 'readonly', 'hidden', 'decimal', 'min', 'max', 'readin', 'span', 'labelwidth', 'tooltip', 'extra', 'enter', 'cursor', 'splitline', 'place'],
  select: ['initval', 'readonly', 'required', 'hidden', 'readin', 'resourceType', 'setAll', 'linkSubField', 'span', 'labelwidth', 'tooltip', 'extra', 'emptyText', 'enter', 'splitline', 'dropdown'],
  checkbox: ['initval', 'readonly', 'required', 'hidden', 'readin', 'resourceType', 'span', 'labelwidth', 'tooltip', 'extra', 'splitline', 'arrange'],
  radio: ['initval', 'readonly', 'required', 'hidden', 'readin', 'resourceType', 'linkSubField', 'span', 'labelwidth', 'tooltip', 'extra', 'setAll', 'emptyText', 'splitline', 'arrange'],
  checkcard: ['initval', 'readonly', 'required', 'hidden', 'readin', 'resourceType', 'linkSubField', 'fieldlength', 'span', 'labelwidth', 'display', 'tooltip', 'extra', 'width', 'multiple', 'borderColor', 'splitline'],
  multiselect: ['initval', 'readonly', 'required', 'hidden', 'readin', 'resourceType', 'fieldlength', 'span', 'labelwidth', 'tooltip', 'extra'],
  link: ['initval', 'readonly', 'required', 'hidden', 'readin', 'resourceType', 'setAll', 'linkField', 'linkSubField', 'span', 'labelwidth', 'tooltip', 'extra', 'emptyText', 'enter', 'splitline', 'dropdown'],
  fileupload: ['readonly', 'required', 'readin', 'fieldlength', 'maxfile', 'fileType', 'span', 'labelwidth', 'tooltip', 'extra', 'compress', 'splitline'],
  switch: ['initval', 'openVal', 'closeVal', 'openText', 'closeText', 'readonly', 'hidden', 'readin', 'span', 'labelwidth', 'tooltip', 'extra', 'splitline'],
  date: ['initval', 'readonly', 'required', 'hidden', 'readin', 'span', 'labelwidth', 'tooltip', 'extra', 'declareType', 'mode', 'splitline'],
  datemonth: ['initval', 'readonly', 'required', 'hidden', 'readin', 'span', 'labelwidth', 'tooltip', 'extra', 'declareType', 'splitline'],
  datetime: ['initval', 'readonly', 'required', 'hidden', 'readin', 'span', 'labelwidth', 'tooltip', 'extra', 'declareType', 'mode', 'splitline'],
  textarea: ['initval', 'readonly', 'required', 'hidden', 'readin', 'fieldlength', 'span', 'labelwidth', 'maxRows', 'encryption', 'interception', 'tooltip', 'extra', 'count', 'placeholder'],
  color: ['initval', 'readonly', 'required', 'hidden', 'readin', 'span', 'labelwidth', 'tooltip', 'extra'],
  hint: ['label', 'type', 'blacklist', 'message', 'span', 'labelwidth', 'splitline'],
  split: ['label', 'type'],
  brafteditor: ['required', 'hidelabel', 'hidden', 'readin', 'fieldlength', 'readonly', 'span', 'labelwidth', 'tooltip', 'extra', 'encryption'],
  funcvar: ['span', 'labelwidth', 'splitline'],
  linkMain: ['readonly', 'required', 'hidden', 'fieldlength', 'span', 'labelwidth', 'tooltip', 'extra']
  text: ['initval', 'readonly', 'required', 'hidden', 'readin', 'fieldlength', 'regular', 'interception', 'span', 'labelwidth', 'tooltip', 'extra', 'enter', 'cursor', 'scan', 'splitline', 'placeholder', 'place', 'marginTop', 'marginBottom'],
  number: ['initval', 'readonly', 'hidden', 'decimal', 'min', 'max', 'readin', 'span', 'labelwidth', 'tooltip', 'extra', 'enter', 'cursor', 'splitline', 'place', 'marginTop', 'marginBottom'],
  select: ['initval', 'readonly', 'required', 'hidden', 'readin', 'resourceType', 'setAll', 'linkSubField', 'span', 'labelwidth', 'tooltip', 'extra', 'emptyText', 'enter', 'splitline', 'dropdown', 'marginTop', 'marginBottom'],
  checkbox: ['initval', 'readonly', 'required', 'hidden', 'readin', 'resourceType', 'span', 'labelwidth', 'tooltip', 'extra', 'splitline', 'arrange', 'marginTop', 'marginBottom'],
  radio: ['initval', 'readonly', 'required', 'hidden', 'readin', 'resourceType', 'linkSubField', 'span', 'labelwidth', 'tooltip', 'extra', 'setAll', 'emptyText', 'splitline', 'arrange', 'marginTop', 'marginBottom'],
  checkcard: ['initval', 'readonly', 'required', 'hidden', 'readin', 'resourceType', 'linkSubField', 'fieldlength', 'span', 'labelwidth', 'display', 'tooltip', 'extra', 'width', 'multiple', 'borderColor', 'splitline', 'marginTop', 'marginBottom'],
  multiselect: ['initval', 'readonly', 'required', 'hidden', 'readin', 'resourceType', 'fieldlength', 'span', 'labelwidth', 'tooltip', 'extra', 'marginTop', 'marginBottom'],
  link: ['initval', 'readonly', 'required', 'hidden', 'readin', 'resourceType', 'setAll', 'linkField', 'linkSubField', 'span', 'labelwidth', 'tooltip', 'extra', 'emptyText', 'enter', 'splitline', 'dropdown', 'marginTop', 'marginBottom'],
  fileupload: ['readonly', 'required', 'readin', 'fieldlength', 'maxfile', 'fileType', 'span', 'labelwidth', 'tooltip', 'extra', 'compress', 'splitline', 'marginTop', 'marginBottom'],
  switch: ['initval', 'openVal', 'closeVal', 'openText', 'closeText', 'readonly', 'hidden', 'readin', 'span', 'labelwidth', 'tooltip', 'extra', 'splitline', 'marginTop', 'marginBottom'],
  date: ['initval', 'readonly', 'required', 'hidden', 'readin', 'span', 'labelwidth', 'tooltip', 'extra', 'declareType', 'mode', 'splitline', 'marginTop', 'marginBottom'],
  datemonth: ['initval', 'readonly', 'required', 'hidden', 'readin', 'span', 'labelwidth', 'tooltip', 'extra', 'declareType', 'splitline', 'marginTop', 'marginBottom'],
  datetime: ['initval', 'readonly', 'required', 'hidden', 'readin', 'span', 'labelwidth', 'tooltip', 'extra', 'declareType', 'mode', 'splitline', 'marginTop', 'marginBottom'],
  textarea: ['initval', 'readonly', 'required', 'hidden', 'readin', 'fieldlength', 'span', 'labelwidth', 'maxRows', 'encryption', 'interception', 'tooltip', 'extra', 'count', 'placeholder', 'marginTop', 'marginBottom'],
  color: ['initval', 'readonly', 'required', 'hidden', 'readin', 'span', 'labelwidth', 'tooltip', 'extra', 'marginTop', 'marginBottom'],
  hint: ['label', 'type', 'blacklist', 'message', 'span', 'labelwidth', 'splitline', 'marginTop', 'marginBottom'],
  split: ['label', 'type', 'marginTop', 'marginBottom'],
  brafteditor: ['required', 'hidelabel', 'hidden', 'readin', 'fieldlength', 'readonly', 'span', 'labelwidth', 'tooltip', 'extra', 'encryption', 'marginTop', 'marginBottom'],
  funcvar: ['span', 'labelwidth', 'splitline', 'marginTop', 'marginBottom'],
  linkMain: ['readonly', 'required', 'hidden', 'fieldlength', 'span', 'labelwidth', 'tooltip', 'extra', 'marginTop', 'marginBottom']
}
class MainSearch extends Component {
src/templates/zshare/unattended/index.jsx
@@ -61,7 +61,7 @@
          title="无人值守"
          wrapClassName="unattended-field-modal"
          visible={visible}
          width={600}
          width={800}
          maskClosable={false}
          onOk={this.submit}
          onCancel={() => { this.setState({ visible: false })}}
src/templates/zshare/unattended/settingform/index.jsx
@@ -47,7 +47,7 @@
    return (
      <Form {...formItemLayout}>
        <Row gutter={24}>
          <Col span={20}>
          <Col span={12}>
            <Form.Item label="是否启用">
              {getFieldDecorator('enable', {
                initialValue: autoMatic.enable,
@@ -59,7 +59,7 @@
              )}
            </Form.Item>
          </Col>
          {enable === 'true' ? <Col span={20}>
          {enable === 'true' ? <Col span={12}>
            <Form.Item label={
              <Tooltip placement="topLeft" title="用于自动执行的按钮。">
                <Icon type="question-circle" style={{color: '#c49f47', marginRight: '3px'}} />
@@ -81,7 +81,7 @@
              )}
            </Form.Item>
          </Col> : null}
          {enable === 'true' ? <Col span={20}>
          {enable === 'true' ? <Col span={12}>
            <Form.Item label={
              <Tooltip placement="topLeft" title="按钮执行成功,后续的处理方式。">
                <Icon type="question-circle" style={{color: '#c49f47', marginRight: '3px'}} />
@@ -98,7 +98,7 @@
              )}
            </Form.Item>
          </Col> : null}
          {enable === 'true' ? <Col span={20}>
          {enable === 'true' ? <Col span={12}>
            <Form.Item label={
              <Tooltip placement="topLeft" title="按钮执行失败时,后续的处理方式。">
                <Icon type="question-circle" style={{color: '#c49f47', marginRight: '3px'}} />
@@ -108,7 +108,7 @@
              {getFieldDecorator('onFail', {
                initialValue: autoMatic.onFail || 'stop',
              })(
                <Radio.Group>
                <Radio.Group style={{whiteSpace: 'nowrap'}}>
                  <Radio value="next">下一行</Radio>
                  <Radio value="stay">当前行</Radio>
                  <Radio value="stop">停止</Radio>
@@ -116,7 +116,21 @@
              )}
            </Form.Item>
          </Col> : null}
          {enable === 'true' ? <Col span={20}>
          {enable === 'true' ? <Col span={12}>
            <Form.Item label={
              <Tooltip placement="topLeft" title="相邻两条数据,执行时的间隔时间,最小为1s。">
                <Icon type="question-circle" style={{color: '#c49f47', marginRight: '3px'}} />
                数据间隔(s)
              </Tooltip>
            }>
              {getFieldDecorator('gap', {
                initialValue: autoMatic.gap || 2,
              })(
                <InputNumber style={{width: '100%'}} min={1} precision={0}/>
              )}
            </Form.Item>
          </Col> : null}
          {enable === 'true' ? <Col span={12}>
            <Form.Item label="完成后">
              {getFieldDecorator('onFinish', {
                initialValue: autoMatic.onFinish || 'over',
@@ -128,7 +142,7 @@
              )}
            </Form.Item>
          </Col> : null}
          {enable === 'true' && onFinish === 'restart' ? <Col span={20}>
          {enable === 'true' && onFinish === 'restart' ? <Col span={12}>
            <Form.Item label="启动间隔(s)">
              {getFieldDecorator('interval', {
                initialValue: autoMatic.interval === 0 ? 0 : (autoMatic.interval || 600),
@@ -137,7 +151,7 @@
              )}
            </Form.Item>
          </Col> : null}
          {enable === 'true' && onFinish === 'restart' ? <Col span={20}>
          {enable === 'true' && onFinish === 'restart' ? <Col span={12}>
            <Form.Item label="重启时">
              {getFieldDecorator('restart', {
                initialValue: autoMatic.restart || 'first',
src/templates/zshare/verifycard/index.jsx
@@ -35,6 +35,7 @@
  state = {
    initsql: '',            // sql验证时变量声明及赋值
    notes: [],              // 短信模板
    setting: null,
    verify: {},
    fields: [],
    usefulfields: '',
@@ -572,6 +573,7 @@
    }
    this.setState({
      setting: config.setting || {},
      verify: _verify
    })
@@ -806,9 +808,15 @@
          if (!_arr.includes('submituserid')) {
            _form.push('submituserid=@userid@')
          }
          if (!_arr.includes('submituser')) {
            _form.push('submituser=@username')
          }
        } else {
          if (!_arr.includes('modifydate')) {
            _form.push('modifydate=getdate()')
          }
          if (!_arr.includes('modifyuser')) {
            _form.push('modifyuser=@username')
          }
          if (!_arr.includes('modifyuserid')) {
            _form.push('modifyuserid=@userid@')
@@ -852,7 +860,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 || 'id'}${card.Ot !== 'requiredOnce' ? '=@ID@' : ' in (select ID  from dbo.SplitComma(@ID@))'};`
        _defaultsql = `update ${card.sql} set deleted=1,modifydate=getdate(),modifyuser=@username,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') {
@@ -1310,6 +1318,7 @@
  handleConfirm = () => {
    const { card } = this.props
    const { setting } = this.state
    let verify = fromJS(this.state.verify).toJS()
    
    // 表单提交时检查输入值是否正确
@@ -1328,6 +1337,13 @@
          duration: 5
        })
        return
      } else if (verify.invalid === 'true' && setting.maxScript && setting.maxScript >= 100) {
        notification.warning({
          top: 92,
          message: '数据源中自定义脚本过于复杂,不能使用失效验证!',
          duration: 5
        })
        return
      }
      let msg = ''
src/utils/utils.js
@@ -1899,9 +1899,15 @@
      if (!_arr.includes('submituserid')) {
        _form.push('submituserid=@userid@')
      }
      if (!_arr.includes('submituser')) {
        _form.push('submituser=@username')
      }
    } else {
      if (!_arr.includes('modifydate')) {
        _form.push('modifydate=getdate()')
      }
      if (!_arr.includes('modifyuser')) {
        _form.push('modifyuser=@username')
      }
      if (!_arr.includes('modifyuserid')) {
        _form.push('modifyuserid=@userid@')
@@ -1950,7 +1956,7 @@
    _sql += `
      /* 默认sql */
      update ${btn.sql} set deleted=1,modifydate=getdate(),modifyuserid=@userid@ where ${primaryKey}${_ID};`
      update ${btn.sql} set deleted=1,modifydate=getdate(),modifyuser=@username,modifyuserid=@userid@ where ${primaryKey}${_ID};`
  
  } else if (_actionType === 'delete') {      // 物理删除
    let _msg = ''
@@ -2266,7 +2272,7 @@
      form = `
        insert into ${param.name} (${field1},createuserid) select ${field2},@UserID
        
        update ${param.name} set ${field3},modifydate=getdate(),modifyuserid=@UserID
        update ${param.name} set ${field3},modifydate=getdate(),modifyuser=@username,modifyuserid=@UserID
      `
    } else if (btn.OpenType === 'prompt' || btn.OpenType === 'exec') {
      form = `
src/views/login/index.jsx
@@ -1,5 +1,5 @@
import React, { Component } from 'react'
import { message, Modal } from 'antd'
import { message, Modal, notification } from 'antd'
import { connect } from 'react-redux'
import md5 from 'md5'
import moment from 'moment'
@@ -9,12 +9,14 @@
import options, { styles } from '@/store/options.js'
import zhCN from '@/locales/zh-CN/login.js'
import enUS from '@/locales/en-US/login.js'
import asyncComponent from '@/utils/asyncComponent'
import asyncLoadComponent from '@/utils/asyncLoadComponent'
import { modifyMemberLevel } from '@/store/action'
import './index.scss'
const LoginForm = asyncLoadComponent(() => import('./loginform'))
const LoginCloudForm = asyncLoadComponent(() => import('./logincloudform'))
const Resetpwd = asyncLoadComponent(() => import('@/components/header/resetpwd'))
const LoginCloudForm = asyncComponent(() => import('./logincloudform'))
const iszhCN = sessionStorage.getItem('lang') !== 'en-US'
const _href = window.location.href.split('#')[0]
@@ -42,7 +44,8 @@
    loginWays: null,
    touristLogin: false,
    syncing: false,
    visible: false
    visible: false,
    resetLoading: false
  }
  UNSAFE_componentWillMount() {
@@ -466,7 +469,7 @@
              app_version: res.app_version
            }
            let level = res.pwd_level || 'char_num_90'
            let level = res.pwd_level || ''
            if (level && !['letter_num', 'char_num', 'char_num_90'].includes(level)) {
              level = ''
@@ -635,7 +638,6 @@
      param.rduri = options.cloudServiceApi.replace('dostars', 'dostar')
    }
    this.logincloudRef.handleConfirm().then(result => {
      param.UserName = result.cloudusername
      param.Password = result.cloudpassword
@@ -678,6 +680,48 @@
        }
      })
    })
  }
  resetPwdSubmit = () => {
    this.formRef.handleConfirm().then(res => {
      this.setState({
        resetLoading: true
      })
      let _param = {
        func: 's_PwdUpt',
        LText: `select '${res.originpwd}','${res.password}'`
      }
      _param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')          // 时间戳
      _param.LText = Utils.formatOptions(_param.LText)                   // 关键字符替换,base64加密
      _param.secretkey = Utils.encrypt(_param.LText, _param.timestamp)   // md5密钥
      Api.getSystemConfig(_param).then(result => {
        this.setState({
          visible: !result.status,
          resetLoading: false
        })
        if (result.status) {
          notification.success({
            top: 92,
            message: '修改成功,请重新登录。',
            duration: 2
          })
          const input = document.getElementById('password')
          if (input) {
            input.select()
          }
        } else {
          notification.warning({
            top: 92,
            message: result.message,
            duration: 5
          })
        }
      })
    }, () => {})
  }
  /**
@@ -737,6 +781,19 @@
        >
          <LoginCloudForm handleSubmit={() => this.syncSubmit()} wrappedComponentRef={(inst) => this.logincloudRef = inst}/>
        </Modal>
        {/* 修改密码 */}
        <Modal
          title="修改密码"
          okText={this.state.dict['login.ok']}
          cancelText={this.state.dict['login.cancel']}
          visible={this.state.visible}
          onOk={this.resetPwdSubmit}
          confirmLoading={this.state.resetLoading}
          onCancel={() => this.setState({visible: false, resetLoading: false})}
          destroyOnClose
        >
          <Resetpwd wrappedComponentRef={(inst) => this.formRef = inst} resetPwdSubmit={this.resetPwdSubmit}/>
        </Modal>
      </div>
    )
  }
src/views/mobdesign/index.jsx
@@ -1135,6 +1135,7 @@
        if (['propcard', 'brafteditor', 'sandbox', 'tabbar', 'stepform', 'tabform'].includes(item.subtype) && item.wrap.datatype === 'static') return
        if (['balcony'].includes(item.type) && item.wrap.datatype === 'static') return
        if (['menubar'].includes(item.type) && item.wrap.datatype !== 'dynamic') return
        if (item.setting) {
          if (item.setting.interType === 'system' && item.setting.execute !== 'false' && !item.setting.dataresource) {
@@ -1143,7 +1144,7 @@
            error = `组件《${item.name}》未设置数据源!`
          } else if (!item.setting.primaryKey) {
            error = `组件《${item.name}》未设置主键!`
          } else if (!item.setting.supModule && item.type !== 'navbar' && item.type !== 'balcony') {
          } else if (!item.setting.supModule && !['navbar', 'balcony', 'menubar'].includes(item.type)) {
            error = `组件《${item.name}》未设置上级组件!`
          }
        }