king
2019-12-06 d05e0494d938c165d328c37ba452a2a8579ed724
src/templates/modalconfig/index.jsx
@@ -4,11 +4,13 @@
import { DndProvider } from 'react-dnd'
import HTML5Backend from 'react-dnd-html5-backend'
import { Button, Card, Modal, Collapse, notification, Select, List, Icon, Empty } from 'antd'
import moment from 'moment'
import DragElement from './dragelement'
import SourceElement from './dragelement/source'
import Api from '@/api'
import ModalForm from './modalform'
import SettingForm from './settingform'
import GroupForm from './groupform'
import EditCard from './editcard'
import MenuForm from './menuform'
import zhCN from '@/locales/zh-CN/comtable.js'
@@ -30,45 +32,49 @@
  }
  state = {
    operaType: '', // 操作类型,新建或编辑
    dict: CommonDict, // 字典
    config: null, // 页面配置
    visible: false, // 搜索条件、按钮、显示列,模态框显示控制
    tableVisible: false, // 数据表字段模态框
    addType: '', // 添加类型-搜索条件或显示列
    tableColumns: [], // 表格显示列
    fields: null, // 搜索条件及显示列,可选字段
    modalformlist: null, // 基本信息表单字段
    formlist: null, // 搜索条件、按钮、显示列表单字段
    card: null, // 编辑元素
    loading: false, // 搜索条件加载中
    menuloading: false, // 菜单保存中
    dict: CommonDict,      // 字典
    config: null,          // 页面配置,包括模板类型、模态框设置、添加表名、表单列表
    visible: false,        // 表单编辑模态框,显示控制
    tableVisible: false,   // 数据表字段列表模态框,显示控制
    tableColumns: [],      // 表格字段名列表
    fields: null,          // 表单,可选字段(去重后)
    modalformlist: null,   // 基本信息表单字段
    formlist: null,        // 表单编辑模态框,可编辑字段
    card: null,            // 编辑元素
    loading: false,        // 表单刷新时使用
    menuloading: false,    // 菜单保存中
    settingVisible: false, // 全局配置模态框
    closeVisible: false, // 关闭模态框
    tables: [], // 可用表名
    selectedTables: [], // 已选表名
    originMenu: null // 原始菜单
    closeVisible: false,   // 关闭模态框
    tables: [],            // 可用表名
    selectedTables: [],    // 已选表名
    originMenu: null,      // 原始菜单
    groupVisible: false,   // 全局配置模态框
  }
  /**
   * @description 数据预处理
   * 1、按钮配置存在时使用按钮配置,不存在时使用默认配置(示例)
   * 2、模态框标题不存在时,使用按钮标题
   * 3、设置已选表
   * 4、设置按钮基本信息
   */
  UNSAFE_componentWillMount () {
    const {menu, editAction} = this.props
    let _config = ''
    let _operaType = 'add'
    if (editAction.pageParam) {
      _config = editAction.pageParam
      _operaType = 'edit'
    } else {
      _config = JSON.parse(JSON.stringify((Source.baseConfig)))
      _config.groups[0].sublist = _config.fields.map(field => field.uuid)
    }
    if (!_config.setting.title) {
      _config.setting.title = editAction.label
    }
    this.setState({
      config: _config,
      operaType: _operaType,
      selectedTables: _config.tables || [],
      modalformlist: [
        {
@@ -91,11 +97,24 @@
    })
  }
  /**
   * @description 获取数据表信息
   * 1、获取系统中全部表名
   * 2、根据已选表名,获取表格字段列表
   */
  componentDidMount () {
    let _text = 'select TbName ,Remark from sDataDictionary where IsKey!=\'\' and Deleted =0'
    _text = Utils.formatOptions(_text)
    let param = {
      func: 'sPC_Get_SelectedList',
      LText: 'select TbName ,Remark from sDataDictionary where IsKey!=\'\' and Deleted =0',
      obj_name: 'data',
      arr_field: 'TbName,Remark'
    }
    Api.getSystemConfig({func: 'sPC_Get_SelectedList', LText: _text, obj_name: 'data', arr_field: 'TbName,Remark'}).then(res => {
    param.LText = Utils.formatOptions(param.LText)
    param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') + '.000'
    param.secretkey = Utils.encrypt(param.LText, param.timestamp)
    Api.getSystemConfig(param).then(res => {
      if (res.status) {
        this.setState({
          tables: res.data
@@ -117,6 +136,8 @@
        })
      })
    })
    // 获取字段后数据处理,根据类型分为text、number、datetime、date
    Promise.all(deffers).then(response => {
      let _columns = []
      response.forEach(res => {
@@ -133,16 +154,6 @@
              } else if (/^decimal/.test(_type)) {
                _decimal = _type.split(',')[1]
                _decimal = parseInt(_decimal)
                if (_decimal > 4) {
                  _decimal = 4
                }
                _type = 'number'
              } else if (/^decimal/.test(_type)) {
                _decimal = _type.split(',')[1]
                _decimal = parseInt(_decimal)
                if (_decimal > 4) {
                  _decimal = 4
                }
                _type = 'number'
              } else if (/^datetime/.test(_type)) {
                _type = 'datetime'
@@ -176,11 +187,17 @@
    })
  }
  /**
   * @description 表单变化
   * 1、表单拖拽添加时,检查是否存在示例表单,如存在则去除示例
   * 2、表单移动后,保存移动后的顺序
   */
  handleList = (list) => {
    let _config = JSON.parse(JSON.stringify(this.state.config))
    if (list.length > _config.fields.length) {
      _config.fields = list.filter(item => !item.origin)
      this.setState({
        loading: true,
        config: _config
@@ -195,6 +212,12 @@
    }
  }
  /**
   * @description 表单编辑
   * 1、显示编辑弹窗
   * 2、保存编辑项
   * 3、设置编辑参数项
   */
  handleForm = (card) => {
    this.setState({
      visible: true,
@@ -344,10 +367,16 @@
    })
  }
  /**
   * @description 编辑后提交
   * 1、获取编辑后的表单信息
   * 2、去除可能存在的示例表单
   * 3、通过loading刷新
   */
  handleSubmit = () => {
    this.formRef.handleConfirm().then(res => {
      let _config = JSON.parse(JSON.stringify(this.state.config))
      console.log(res)
      _config.fields = _config.fields.map(item => {
        if (item.uuid === res.uuid) {
          return res
@@ -369,6 +398,9 @@
    })
  }
  /**
   * @description 表单删除并刷新
   */
  closeForm = (card) => {
    let _this = this
@@ -396,10 +428,6 @@
      },
      onCancel() {}
    })
  }
  changeTemplate = () => {
    this.props.handleConfig('template')
  }
  submitConfig = () => {
@@ -449,7 +477,6 @@
        if (response.status) {
          this.setState({
            menuloading: false,
            operaType: 'edit',
            originMenu: {
              ...originMenu,
              LongParam: _config,
@@ -476,57 +503,53 @@
        }
      })
      if (this.state.operaType === 'add') {
      } else {
        let param = {
          func: 'sPC_TrdMenu_Upt',
          ParentID: res.parentId,
          MenuID: menu.MenuID,
          MenuNo: res.menuNo,
          Template: menu.PageParam.Template || '',
          MenuName: res.menuName,
          PageParam: JSON.stringify(_pageParam),
          LongParam: _LongParam
        }
        this.setState({
          menuloading: true
        })
      // let param = {
      //   func: 'sPC_TrdMenu_Upt',
      //   ParentID: res.parentId,
      //   MenuID: menu.MenuID,
      //   MenuNo: res.menuNo,
      //   Template: menu.PageParam.Template || '',
      //   MenuName: res.menuName,
      //   PageParam: JSON.stringify(_pageParam),
      //   LongParam: _LongParam
      // }
      this.setState({
        menuloading: true
      })
        Api.getSystemConfig(param).then(response => {
          if (response.status) {
            notification.success({
              top: 92,
              message: '保存成功',
              duration: 10
            })
            if (this.state.closeVisible) {
              this.props.handleConfig('')
            } else {
              this.setState({
                menuloading: false,
                originMenu: {
                  ...originMenu,
                  LongParam: _config,
                  PageParam: _pageParam,
                  MenuName: res.menuName,
                  MenuNo: res.menuNo,
                  ParentID: res.parentId
                }
              })
            }
      Api.getSystemConfig(param).then(response => {
        if (response.status) {
          notification.success({
            top: 92,
            message: '保存成功',
            duration: 10
          })
          if (this.state.closeVisible) {
            this.props.handleConfig('')
          } else {
            this.setState({
              menuloading: false
            })
            notification.warning({
              top: 92,
              message: response.message,
              duration: 10
              menuloading: false,
              originMenu: {
                ...originMenu,
                LongParam: _config,
                PageParam: _pageParam,
                MenuName: res.menuName,
                MenuNo: res.menuNo,
                ParentID: res.parentId
              }
            })
          }
        })
      }
        } else {
          this.setState({
            menuloading: false
          })
          notification.warning({
            top: 92,
            message: response.message,
            duration: 10
          })
        }
      })
    }, () => {
      notification.warning({
        top: 92,
@@ -541,7 +564,8 @@
    const { config, originMenu } = this.state
    let _this = this
    if (this.state.operaType === 'add') {
    let isOrigin = config.fields.filter(item => item.origin).length > 0
    if (isOrigin) {
      confirm({
        content: '菜单尚未提交,确定放弃保存吗?',
        okText: this.state.dict['header.confirm'],
@@ -579,6 +603,12 @@
    }
  }
  /**
   * @description 通过表字段添加表单
   * 1、检查是否已选表名,为选时警告提示
   * 2、表字段名通过map去重
   * 3、检查表单中的已选字段,并标记已选
   */
  queryField = () => {
    const {selectedTables, tableColumns, config} = this.state
    if (selectedTables.length === 0) {
@@ -599,7 +629,7 @@
    config.fields.forEach(item => {
      if (columns.has(item.field)) {
        columns.set(item.field, {...item, selected: true, type: item.type})
        columns.set(item.field, {...item, selected: true})
      }
    })
@@ -609,6 +639,13 @@
    })
  }
  /**
   * @description 选择字段后提交
   * 1、没有可选字段时,直接关闭
   * 2、获取已选字段
   * 3、与已有字段对比
   * 4、添加新增字段
   */
  addFieldSubmit = () => {
    if (!this.state.fields || this.state.fields.length === 0) {
      this.setState({
@@ -629,15 +666,15 @@
      if (columns.has(item.field)) {
        let cell = columns.get(item.field)
        if (cell.selected && cell.type === item.type) { // 数据未修改
        if (cell.selected && cell.type === item.type) { // 数据选择状态及类型未修改时,直接添加
          items.push(item)
        } else if (cell.selected) { // 数据类型修改
        } else if (cell.selected) {                     // 数据类型修改时,重置类型及初始值
          item.type = cell.type
          item.initval = ''
          items.push(item)
        }
        columns.delete(item.field)
      } else if (!item.origin) {
      } else if (!item.origin) {                        // 过滤示例项
        items.push(item)
      }
    })
@@ -646,7 +683,7 @@
    let indexes = items.map(card => {return card.id})
    let id = Math.max(...indexes, 0) + 1
    _columns.forEach(item => {
    _columns.forEach(item => { // 循环添加新增字段
      if (item.selected) {
        let newcard = {
          id: id,
@@ -684,60 +721,70 @@
    })
  }
  /**
   * @description 添加表名
   * 1、获取表信息
   * 2、检验是否已经添加,已添加时跳过
   * 3、通过表名获取字段集,并设置数据类型
   */
  onTableChange = (value) => {
    const {tables, selectedTables, tableColumns} = this.state
    let _table = tables.filter(item => item.TbName === value)[0]
    let isSelected = !!selectedTables.filter(cell => cell.TbName === value)[0]
    if (!isSelected) {
      this.setState({
        selectedTables: [...selectedTables, _table]
      })
      Api.getSystemConfig({func: 'sPC_Get_FieldName', TBName: value}).then(res => {
        if (res.status) {
          let tabmsg = {
            tableName: _table.name,
            columns: res.FDName.map(item => {
              let _type = item.FieldType.toLowerCase()
              let _decimal = 0
              if (/^nvarchar/.test(_type)) {
                _type = 'text'
              } else if (/^int/.test(_type)) {
                _type = 'number'
              } else if (/^decimal/.test(_type)) {
                _decimal = _type.split(',')[1]
                _decimal = parseInt(_decimal)
                _type = 'number'
              } else if (/^datetime/.test(_type)) {
                _type = 'datetime'
              } else if (/^date/.test(_type)) {
                _type = 'date'
              } else {
                _type = 'text'
              }
              return {
                field: item.FieldName,
                label: item.FieldDec,
                type: _type,
                decimal: _decimal
              }
            })
          }
          this.setState({
            tableColumns: [...tableColumns, tabmsg]
          })
        } else {
          notification.warning({
            top: 92,
            message: res.message,
            duration: 10
    if (isSelected) return
    this.setState({
      selectedTables: [...selectedTables, _table]
    })
    Api.getSystemConfig({func: 'sPC_Get_FieldName', TBName: value}).then(res => {
      if (res.status) {
        let tabmsg = {
          tableName: _table.name,
          columns: res.FDName.map(item => {
            let _type = item.FieldType.toLowerCase()
            let _decimal = 0
            if (/^nvarchar/.test(_type)) {
              _type = 'text'
            } else if (/^int/.test(_type)) {
              _type = 'number'
            } else if (/^decimal/.test(_type)) {
              _decimal = _type.split(',')[1]
              _decimal = parseInt(_decimal)
              _type = 'number'
            } else if (/^datetime/.test(_type)) {
              _type = 'datetime'
            } else if (/^date/.test(_type)) {
              _type = 'date'
            } else {
              _type = 'text'
            }
            return {
              field: item.FieldName,
              label: item.FieldDec,
              type: _type,
              decimal: _decimal
            }
          })
        }
      })
    }
        this.setState({
          tableColumns: [...tableColumns, tabmsg]
        })
      } else {
        notification.warning({
          top: 92,
          message: res.message,
          duration: 10
        })
      }
    })
  }
  /**
   * @description 删除表名,删除对应字段集
   */
  deleteTable = (table) => {
    const {selectedTables, tableColumns} = this.state
@@ -747,12 +794,18 @@
    })
  }
  /**
   * @description 全局设置模态框
   */
  changeSetting = () => {
    this.setState({
      settingVisible: true
    })
  }
  /**
   * @description 保存全局设置
   */
  settingSave = () => {
    const {config} = this.state
    this.settingRef.handleConfirm().then(res => {
@@ -763,6 +816,14 @@
    })
  }
  handleGroup = () => {
  }
  handleGroupSave = () => {
  }
  render () {
    const { config } = this.state
@@ -771,26 +832,23 @@
        <DndProvider backend={HTML5Backend}>
          <div className="tools">
            <Collapse accordion defaultActiveKey="0" bordered={false}>
              <Panel header="基本信息" key="0" id="modal-basedata">
                <MenuForm
                  dict={this.state.dict}
                  formlist={this.state.modalformlist}
                  wrappedComponentRef={(inst) => this.menuformRef = inst}
                />
              <Panel header={this.state.dict['header.menu.basedata']} key="0" id="modal-basedata">
                <MenuForm
                  dict={this.state.dict}
                  formlist={this.state.modalformlist}
                  wrappedComponentRef={(inst) => this.menuformRef = inst}
                />
                <div className="ant-col ant-form-item-label">
                  <label title="添加表名">添加表名</label>
                  <label title={this.state.dict['header.menu.table.add']}>
                    {this.state.dict['header.menu.table.add']}
                  </label>
                </div>
                <Select
                  showSearch
                  className="tables"
                  style={{ width: '100%' }}
                  optionFilterProp="children"
                  value={'请选择表名'}
                  value={this.state.dict['header.menu.table.placeholder']}
                  onChange={this.onTableChange}
                  showArrow={false}
                  getPopupContainer={() => document.getElementById('modal-basedata')}
@@ -813,18 +871,19 @@
                  </List.Item>}
                />}
              </Panel>
              <Panel header="表单" key="1">
              <Panel header={this.state.dict['header.menu.form']} key="1">
                <div className="search-element">
                  {Source.searchItems.map((item, index) => {
                    return (<SourceElement key={index} content={item}/>)
                  })}
                </div>
                <Button type="primary" block onClick={() => this.queryField()}>添加表单</Button>
                <Button type="primary" block onClick={() => this.queryField()}>{this.state.dict['header.menu.form.add']}</Button>
                <Button type="primary" block onClick={() => this.handleGroup()}>{this.state.dict['header.menu.group.add']}</Button>
              </Panel>
            </Collapse>
          </div>
          <div className="setting">
            <Card title="表单配置" bordered={false} extra={
            <Card title={this.state.dict['header.menu.form.configurable']} bordered={false} extra={
              <div>
                <Button type="primary" onClick={this.submitConfig} loading={this.state.menuloading}>{this.state.dict['header.save']}</Button>
                <Button onClick={this.cancelConfig}>{this.state.dict['header.return']}</Button>
@@ -840,7 +899,24 @@
                </div>
                <div className="ant-modal-body">
                  <div className="modal-form">
                    {!this.state.loading ?
                    {!this.state.loading && config.groups.length > 1 &&
                      config.groups.map(group => {
                        return (
                          <div key={group.uuid}>
                            <p className="group-title">{group.label}</p>
                            <DragElement
                              list={config.fields}
                              setting={config.setting}
                              placeholder={this.state.dict['header.form.modal.placeholder']}
                              handleList={this.handleList}
                              handleForm={this.handleForm}
                              closeForm={this.closeForm}
                            />
                          </div>
                        )
                      })
                    }
                    {!this.state.loading && config.groups.length === 1?
                      <DragElement
                        list={config.fields}
                        setting={config.setting}
@@ -854,8 +930,12 @@
                </div>
                <div className="ant-modal-footer">
                  <div>
                    <button type="button" className="ant-btn"><span>取 消</span></button>
                    <button type="button" className="ant-btn ant-btn-primary"><span>确 定</span></button>
                    <button type="button" className="ant-btn">
                      <span>{this.state.dict['header.cancel']}</span>
                    </button>
                    <button type="button" className="ant-btn ant-btn-primary">
                      <span>{this.state.dict['header.confirm']}</span>
                    </button>
                  </div>
                  <div className="action-mask"></div>
                </div>
@@ -867,11 +947,7 @@
          title={this.state.dict['header.edit']}
          visible={this.state.visible}
          width={700}
          onCancel={() => {
            this.setState({
              visible: false
            })
          }}
          onCancel={() => { this.setState({ visible: false }) }}
          onOk={this.handleSubmit}
          destroyOnClose
        >
@@ -888,11 +964,7 @@
          width={'65vw'}
          style={{minWidth: '900px', maxWidth: '1200px'}}
          onOk={this.addFieldSubmit}
          onCancel={() => {
            this.setState({
              tableVisible: false
            })
          }}
          onCancel={() => { this.setState({ tableVisible: false }) }}
          destroyOnClose
        >
          {this.state.fields && this.state.fields.length > 0 ?
@@ -907,11 +979,7 @@
          visible={this.state.settingVisible}
          width={700}
          onOk={this.settingSave}
          onCancel={() => {
            this.setState({
              settingVisible: false
            })
          }}
          onCancel={() => { this.setState({ settingVisible: false }) }}
          destroyOnClose
        >
          <SettingForm
@@ -932,7 +1000,21 @@
          ]}
          destroyOnClose
        >
          菜单配置已修改,是否保存配置信息?
          {this.state.dict['header.menu.config.placeholder']}
        </Modal>
        <Modal
          title={this.state.dict['header.menu.group.manage']}
          visible={this.state.groupVisible}
          width={700}
          onOk={this.handleGroupSave}
          onCancel={() => { this.setState({ groupVisible: false }) }}
          destroyOnClose
        >
          <GroupForm
            data={config.setting}
            dict={this.state.dict}
            wrappedComponentRef={(inst) => this.settingRef = inst}
          />
        </Modal>
      </div>
    )