king
2023-10-28 256878280129753b95f7a2c89a236f0ebcf616b1
Merge branch 'develop'
7个文件已修改
2个文件已添加
607 ■■■■■ 已修改文件
src/menu/components/table/edit-table/columns/editColumn/formconfig.jsx 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/table/edit-table/columns/editColumn/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/table/base-table/index.scss 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/table/edit-table/normalTable/index.jsx 53 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/table/edit-table/normalTable/mkPopSelect/index.jsx 383 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/table/edit-table/normalTable/mkPopSelect/index.scss 123 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/table/normal-table/index.scss 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/mutilform/mkPopSelect/index.scss 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/billprint/index.jsx 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/table/edit-table/columns/editColumn/formconfig.jsx
@@ -457,6 +457,35 @@
      required: true
    },
    {
      type: 'radio',
      key: 'laypage',
      label: '分页',
      initVal: card.laypage || 'true',
      required: false,
      options: [{
        value: 'true',
        text: '是'
      }, {
        value: 'false',
        text: '否'
      }]
    },
    {
      type: 'radio',
      key: 'onload',
      label: '初始化',
      initVal: card.onload || 'true',
      tooltip: '当没有设置搜索字段时,初始化加载数据。',
      required: false,
      options: [{
        value: 'true',
        text: '加载'
      }, {
        value: 'false',
        text: '不加载'
      }]
    },
    {
      type: 'text',
      key: 'valueField',
      label: '值·字段',
src/menu/components/table/edit-table/columns/editColumn/index.jsx
@@ -76,7 +76,7 @@
        } else if (this.record.editType === 'date') {
          _options.push('required', 'precision', 'enter', 'declareType')
        } else if (this.record.editType === 'popSelect') {
          _options.push('required', 'enter', 'linkSubField', 'columns', 'dataSource', 'primaryKey', 'order', 'showField', 'controlField', 'searchKey', 'popWidth')
          _options.push('required', 'enter', 'linkSubField', 'columns', 'dataSource', 'primaryKey', 'order', 'showField', 'controlField', 'searchKey', 'popWidth', 'laypage', 'onload')
        } else if (this.record.editType === 'select') {
          _options.push('required', 'enter', 'resourceType', 'linkSubField', 'dropdown')
src/tabviews/custom/components/table/base-table/index.scss
@@ -14,7 +14,7 @@
  }
  .main-table-box {
    position: relative;
    min-height: 150px;
    min-height: 40px;
    .main-pickup {
      position: absolute;
      right: 5px;
src/tabviews/custom/components/table/edit-table/normalTable/index.jsx
@@ -15,6 +15,7 @@
const { Paragraph } = Typography
const MkIcon = asyncComponent(() => import('@/components/mk-icon'))
const MKPopSelect = asyncComponent(() => import('./mkPopSelect'))
const CardCellComponent = asyncComponent(() => import('@/tabviews/custom/components/card/cardcellList'))
class CusSwitch extends Component {
@@ -370,6 +371,25 @@
    }, 10)
  }
  onPopChange = (values) => {
    const { col, record } = this.props
    this.setState({editing: false})
    setTimeout(() => {
      if (/\$next/.test(col.enter)) {
        MKEmitter.emit('nextLine', col, record.$$uuid)
      } else if (col.enter === '$sub') {
        MKEmitter.emit('subLine', col, record)
      } else if (col.enter !== '$noAct') {
        let node = document.getElementById(col.enter + record.$$uuid)
        node && node.click()
      }
    }, 50)
    MKEmitter.emit('changeRecord', col.tableId, {...record, ...values})
  }
  render() {
    let { col, config, record, style, className, ...resProps } = this.props
    const { editing, value, err } = this.state
@@ -445,6 +465,12 @@
            return (<td onClick={(e) => e.stopPropagation()} className="editing_table_cell">
              <CusSwitch config={col} defaultValue={_value} autoFocus={true} onChange={this.onSwitchChange} onBlur={this.switchBlur}/>
            </td>)
          } else if (col.editType === 'popSelect') {
            let _value = record[col.field] !== undefined ? record[col.field] : ''
            return (<td onClick={(e) => e.stopPropagation()} className="editing_table_cell">
              <MKPopSelect mask={true} defaultValue={_value} config={col} BID={record.$$BID} ID={record.$$uuid} onChange={this.onPopChange} blur={() => this.setState({editing: false})}/>
            </td>)
          } else {
            let _value = record[col.field] !== undefined ? record[col.field] : ''
@@ -833,6 +859,23 @@
    MKEmitter.emit('changeRecord', col.tableId, {...record, [col.field]: _val})
  }
  onPopChange = (values) => {
    const { col, record } = this.props
    setTimeout(() => {
      if (/\$next/.test(col.enter)) {
        MKEmitter.emit('nextLine', col, record.$$uuid)
      } else if (col.enter === '$sub') {
        MKEmitter.emit('subLine', col, record)
      } else if (col.enter !== '$noAct') {
        let node = document.getElementById(col.enter + record.$$uuid)
        node && node.click()
      }
    }, 50)
    MKEmitter.emit('changeRecord', col.tableId, {...record, ...values})
  }
  render() {
    let { col, config, record, style, className, ...resProps } = this.props
    const { err } = this.state
@@ -862,6 +905,10 @@
        } else if (col.editType === 'date') {
          children = (
            <CusDatePicker config={col} value={record[col.field] || null} onChange={this.onDateChange} blur={() => {}}/>
          )
        } else if (col.editType === 'popSelect') {
          children = (
            <MKPopSelect config={col} defaultValue={record[col.field] || ''} BID={record.$$BID} ID={record.$$uuid} onChange={this.onPopChange}/>
          )
        } else {
          children = (<>
@@ -2030,11 +2077,7 @@
    })
    if (err) {
      notification.warning({
        top: 92,
        message: err,
        duration: 5
      })
      message.warning(err)
      return null
    }
src/tabviews/custom/components/table/edit-table/normalTable/mkPopSelect/index.jsx
New file
@@ -0,0 +1,383 @@
import React, {Component} from 'react'
import { is, fromJS } from 'immutable'
import { notification, Modal, Table, Input } from 'antd'
import moment from 'moment'
import { TableOutlined, CloseCircleFilled } from '@ant-design/icons'
import Api from '@/api'
import Utils from '@/utils/utils.js'
import './index.scss'
const { Search } = Input
class MKPopSelect extends Component {
  constructor(props) {
    super(props)
    let config = fromJS(props.config).toJS()
    let value = props.defaultValue
    let arrfield = config.columns.map(f => f.field)
    if (config.subFields && config.subFields.length > 0) {
      config.subFields.forEach(n => {
        if (!arrfield.includes(n.field)) {
          arrfield.push(n.field)
        }
      })
    }
    if (sessionStorage.getItem('dataM') === 'true') { // 数据权限
      config.dataSource = config.dataSource.replace(/\$@/ig, '/*').replace(/@\$/ig, '*/').replace(/@datam@/ig, '\'Y\'')
    } else {
      config.dataSource = config.dataSource.replace(/@\$|\$@/ig, '').replace(/@datam@/ig, '\'\'')
    }
    config.dataSource = config.dataSource.replace(/@LoginUID@/ig, `'${sessionStorage.getItem('LoginUID') || ''}'`)
    config.dataSource = config.dataSource.replace(/@SessionUid@/ig, `'${localStorage.getItem('SessionUid') || ''}'`)
    config.dataSource = config.dataSource.replace(/@UserID@/ig, `'${sessionStorage.getItem('UserID') || ''}'`)
    config.dataSource = config.dataSource.replace(/@Appkey@/ig, `'${window.GLOB.appkey || ''}'`)
    if (/\s/.test(config.dataSource)) { // 拼接别名
      config.dataSource = '(' + config.dataSource + ') tb'
    }
    let columns = []
    let labels = {}
    config.columns.forEach(col => {
      labels[col.field] = col.label
      if (col.Hide === 'true') return
      columns.push({
        dataIndex: col.field,
        title: col.label,
        sorter: col.IsSort === 'true',
        width: col.Width || 120
      })
    })
    let placeholder = ''
    if (!config.searchKey) {
      config.onload = 'true'
    } else {
      placeholder = []
      config.searchKey.split(',').forEach(key => {
        if (!labels[key]) {
          placeholder = ''
        } else if (placeholder) {
          placeholder.push(labels[key])
        }
      })
      placeholder = placeholder ? placeholder.join('、') : ''
    }
    this.state = {
      config: config,
      options: [],
      columns,
      value,
      placeholder,
      arr_field: arrfield.join(','),
      searchKey: '',
      pageIndex: 1,
      pageSize: 10,
      orderBy: '',
      visible: false,
      loading: false
    }
    this.timer = null
  }
  componentDidMount () {
    const { mask } = this.props
    if (mask) {
      this.trigger()
    }
  }
  shouldComponentUpdate (nextProps, nextState) {
    return !is(fromJS(this.state), fromJS(nextState))
  }
  componentWillUnmount () {
    this.setState = () => {
      return
    }
  }
  loadData () {
    const { BID, ID } = this.props
    const { config, pageIndex, pageSize, arr_field, searchKey, orderBy } = this.state
    this.setState({
      loading: true
    })
    let param = {
      func: 'sPC_Get_TableData',
      obj_name: 'data',
      exec_type: 'y',
      arr_field: arr_field,
      default_sql: 'true',
      custom_script: '',
      menuname: config.label
    }
    let sql = ''
    let DateCount = ''
    let _search = ''
    let _orderBy = orderBy || config.order || ''
    let _datasource = config.dataSource
    if (config.searchKey && searchKey) {
      let fields = config.searchKey.split(',').map(field => field + ` like '%${searchKey}%'`)
      _search = 'where ' + fields.join(' OR ')
    }
    _datasource = _datasource.replace(/@BID@/ig, `'${BID || ''}'`)
    _datasource = _datasource.replace(/@ID@/ig, `'${ID || ''}'`)
    if (config.laypage === 'true') {
      sql = `/*system_query*/select top ${pageSize} ${arr_field} from (select ${arr_field} ,ROW_NUMBER() over(order by ${_orderBy}) as rows from ${_datasource} ${_search}) tmptable where rows > ${pageSize * (pageIndex - 1)} order by tmptable.rows `
      DateCount = `/*system_query*/select count(1) as total from ${_datasource} ${_search}`
    } else if (_orderBy) {
      sql = `/*system_query*/select ${arr_field} from (select ${arr_field} ,ROW_NUMBER() over(order by ${_orderBy}) as rows from ${_datasource} ${_search}) tmptable order by tmptable.rows `
    } else {
      sql = `/*system_query*/select ${arr_field} from ${_datasource} ${_search}  `
    }
    let departmentcode = sessionStorage.getItem('departmentcode') || ''
    let organization = sessionStorage.getItem('organization') || ''
    let mk_user_type = sessionStorage.getItem('mk_user_type') || ''
    sql = `declare @mk_departmentcode nvarchar(512),@mk_organization nvarchar(512),@mk_user_type nvarchar(20)
      Select @mk_departmentcode='${departmentcode}', @mk_organization='${organization}', @mk_user_type='${mk_user_type}'
      ${sql}`
    // 测试系统打印查询语句
    if (window.GLOB.debugger === true) {
      console.info(`/*${config.label} 数据源*/\n` + sql.replace(/\n\s{6}/ig, '\n'))
      DateCount && console.info(`/*${config.label} 总数查询*/\n` + DateCount.replace(/\n\s{6}/ig, '\n'))
    }
    param.LText = Utils.formatOptions(sql)
    param.DateCount = Utils.formatOptions(DateCount)
    param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
    param.secretkey = Utils.encrypt('', param.timestamp)
    param.username = sessionStorage.getItem('User_Name') || ''
    param.fullname = sessionStorage.getItem('Full_Name') || ''
    Api.genericInterface(param).then(result => {
      if (result.status) {
        let options = result.data.map((item, index) => {
          item.key = index
          item.$$uuid = item[config.primaryKey] || ''
          item.$label = item[config.showField]
          if (config.controlField && item[config.controlField] === 'true') {
            item.$disabled = true
          }
          return item
        })
        this.setState({
          options: options,
          total: result.total || 0,
          loading: false
        })
        if (result.message) {
          if (result.ErrCode === 'Y') {
            Modal.success({
              title: result.message
            })
          } else if (result.ErrCode === 'S') {
            notification.success({
              top: 92,
              message: result.message,
              duration: 2
            })
          }
        }
      } else {
        this.setState({
          loading: false
        })
        if (!result.message) return
        if (result.ErrCode === 'N') {
          Modal.error({
            title: result.message,
          })
        } else if (result.ErrCode !== '-2') {
          notification.error({
            top: 92,
            message: result.message,
            duration: 10
          })
        }
      }
    })
  }
  searchOption = (val) => {
    this.setState({searchKey: val})
    if (this.timer) {
      clearTimeout(this.timer)
    }
    this.timer = setTimeout(() => {
      this.loadData()
    }, 500)
  }
  selectChange = (val, record) => {
    const { config } = this.state
    let values = {[config.field]: val}
    if (config.linkSubField) {
      config.linkSubField.forEach(m => {
        values[m] = record[m] === undefined ? '' : record[m]
      })
    }
    this.props.onChange(values)
    this.setState({value: val})
  }
  trigger = (e) => {
    const { config, options } = this.state
    e && e.stopPropagation()
    this.setState({visible: true}, () => {
      if (config.onload === 'true' && options.length === 0) {
        this.loadData()
      }
    })
  }
  changeRow = (record) => {
    if (record.$disabled) return
    this.selectChange(record.$$uuid, record)
    this.setState({visible: false})
  }
  clear = (e) => {
    const { config } = this.state
    e.stopPropagation()
    let values = {[config.field]: ''}
    if (config.linkSubField) {
      config.linkSubField.forEach(m => {
        values[m] = ''
      })
    }
    this.props.onChange(values)
    this.setState({value: ''})
  }
  changeTable = (pagination, filters, sorter) => {
    let orderBy = ''
    if (sorter.field && sorter.order) {
      if (sorter.order === 'ascend') {
        orderBy = `${sorter.field} asc`
      } else {
        orderBy = `${sorter.field} desc`
      }
    }
    this.setState({
      pageIndex: pagination.current,
      pageSize: pagination.pageSize,
      orderBy: orderBy,
    }, () => {
      this.loadData()
    })
  }
  cancel = () => {
    const { mask } = this.props
    this.setState({visible: false})
    if (mask) {
      this.props.blur()
    }
  }
  render() {
    const { mask } = this.props
    const { value, config, options, visible, loading, total, pageIndex, pageSize, columns, placeholder } = this.state
    return <>
      {mask ? <div className="mk-pop-select-mask" onClick={this.trigger}></div> : null}
      <div className="mk-pop-select-wrap" onClick={this.trigger}>
        {value}
        {value && !mask ? <CloseCircleFilled onClick={this.clear} /> : null}
        <TableOutlined onClick={this.trigger}/>
      </div>
      <Modal
        wrapClassName='mk-pop-select-modal'
        title={config.label}
        visible={visible}
        closable={true}
        centered={true}
        maskClosable={false}
        cancelText="关闭"
        width={config.popWidth < 100 ? config.popWidth + 'vw' : config.popWidth}
        onCancel={this.cancel}
        destroyOnClose
      >
        {config.searchKey ? <Search placeholder={placeholder} onSearch={this.searchOption} enterButton /> : null}
        <Table
          rowKey="$$uuid"
          bordered={true}
          rowSelection={null}
          columns={columns}
          dataSource={options}
          loading={loading}
          onRow={(record) => {
            let className = ''
            if (record.$disabled) {
              className = ' mk-disable-line '
            } else if (value === record.$$uuid) {
              className = ' ant-table-row-selected '
            }
            return {
              className: className,
              onClick: () => {this.changeRow(record)},
            }
          }}
          onChange={this.changeTable}
          pagination={config.laypage === 'true' ? {
            current: pageIndex,
            pageSize: pageSize,
            showSizeChanger: true,
            total: total || 0,
            showTotal: (total, range) => `${range[0]}-${range[1]} 共 ${total} 条`
          } : false}
        />
      </Modal>
    </>
  }
}
export default MKPopSelect
src/tabviews/custom/components/table/edit-table/normalTable/mkPopSelect/index.scss
New file
@@ -0,0 +1,123 @@
.mk-pop-select-wrap {
  position: relative;
  box-sizing: border-box;
  margin: 0;
  padding: 0 30px 0 11px;
  color: rgba(0, 0, 0, 0.65);
  font-size: 14px;
  font-variant: tabular-nums;
  list-style: none;
  font-feature-settings: 'tnum';
  position: relative;
  display: inline-block;
  width: 100%;
  outline: 0;
  border: 1px solid #d9d9d9;
  border-top-width: 1.02px;
  background: #ffffff;
  user-select: none;
  height: 32px;
  cursor: pointer;
  transition: all 0.3s;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  line-height: 30px;
  .anticon-table {
    padding: 7px;
    color: rgba(0, 0, 0, 0.25);
    transition: color 0.3s;
    font-size: 14px;
    position: absolute;
    right: 0px;
    top: 0px;
  }
  .anticon-close-circle {
    color: rgba(0, 0, 0, 0.25);
    transition: all 0.3s;
    padding: 7px;
    opacity: 0;
    position: absolute;
    right: 25px;
  }
  .anticon-close-circle:hover {
    color: rgba(0, 0, 0, 0.45);
  }
}
.mk-pop-select-wrap:hover, .mk-pop-select-mask:hover + .mk-pop-select-wrap {
  border-color: var(--mk-sys-color5);
  box-shadow: 0 0 0 2px var(--mk-sys-color2);
  .anticon-table {
    color: var(--mk-sys-color);
  }
  .anticon-close-circle {
    opacity: 1;
  }
}
.mk-pop-select-mask {
  position: absolute;
  background: #ffffff;
  top: 0px;
  left: 0px;
  right: 0px;
  bottom: 0px;
  height: auto;
  border: 1px solid #d9d9d9;
  cursor: pointer;
}
.mk-pop-select-mask + .mk-pop-select-wrap {
  border: none;
  box-shadow: none!important;
  padding-left: 0px;
}
.mk-pop-select-modal {
  .ant-modal-body {
    min-height: 200px;
    max-height: calc(100vh - 210px);
    overflow-y: auto;
    .ant-input-search {
      max-width: 300px;
      margin-bottom: 20px;
    }
    table {
      td {
        padding: 12px 16px;
      }
      tr:not(.ant-table-row-selected):hover > td {
        background-color: var(--mk-sys-color1);
      }
      tr.ant-table-row-selected td {
        background-color: var(--mk-sys-color3);
      }
      tr:not(.mk-disable-line) {
        cursor: pointer;
      }
      .mk-disable-line {
        color: rgba(0, 0, 0, 0.35);
      }
    }
  }
  .ant-modal-body::-webkit-scrollbar {
    width: 7px;
  }
  .ant-modal-body::-webkit-scrollbar-thumb {
    border-radius: 5px;
    box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.13);
    background: rgba(0, 0, 0, 0.13);
  }
  .ant-modal-body::-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);
  }
  .ant-modal-footer {
    .ant-btn-primary {
      display: none;
    }
  }
}
src/tabviews/custom/components/table/normal-table/index.scss
@@ -14,7 +14,7 @@
  }
  .main-table-box {
    position: relative;
    min-height: 150px;
    min-height: 40px;
    .main-pickup {
      position: absolute;
      right: 5px;
src/tabviews/zshare/mutilform/mkPopSelect/index.scss
@@ -33,6 +33,9 @@
      margin-bottom: 20px;
    }
    table {
      td {
        padding: 12px 16px;
      }
      tr:not(.ant-table-row-selected):hover > td {
        background-color: var(--mk-sys-color1);
      }
src/views/billprint/index.jsx
@@ -553,6 +553,16 @@
          auto: config.printPage === 'auto',
          config
        }, () => {
          if (config.normalcss) {
            let node = document.getElementById(config.uuid)
            node && node.remove()
            let ele = document.createElement('style')
            ele.id = config.uuid
            ele.innerHTML = config.normalcss
            document.getElementsByTagName('head')[0].appendChild(ele)
          }
          if (params.length === 0 && initInters.length === 0) {
            this.setState({loadingview: false, pages: [config.components]})
          } else if (initInters.length > 0) {