text: import { isArray } from 'util'
  import { exportDefault, titleCase, deepClone } from '@/utils/index'
  import ruleTrigger from './ruleTrigger'
  
  const units = {
    KB: '1024',
    MB: '1024 / 1024',
    GB: '1024 / 1024 / 1024'
  }
  let confGlobal
  const inheritAttrs = {
    file: '',
    dialog: 'inheritAttrs: false,'
  }
  
  /**
   * 组装js 【入口函数】
   * @param {Object} formConfig 整个表单配置
   * @param {String} type 生成类型，文件或弹窗等
   */
  export function makeUpJs(formConfig, type) {
    confGlobal = formConfig = deepClone(formConfig)
    const dataList = []
    const ruleList = []
    const optionsList = []
    const propsList = []
    const methodList = mixinMethod(type)
    const uploadVarList = []
    const created = []
  
    formConfig.fields.forEach(el => {
      buildAttributes(el, dataList, ruleList, optionsList, methodList, propsList, uploadVarList, created)
    })
  
    const script = buildexport(
      formConfig,
      type,
      dataList.join('\n'),
      ruleList.join('\n'),
      optionsList.join('\n'),
      uploadVarList.join('\n'),
      propsList.join('\n'),
      methodList.join('\n'),
      created.join('\n')
    )
    confGlobal = null
    return script
  }
  
  // 构建组件属性
  function buildAttributes(scheme, dataList, ruleList, optionsList, methodList, propsList, uploadVarList, created) {
    const config = scheme.__config__
    const slot = scheme.__slot__
    buildData(scheme, dataList)
    buildRules(scheme, ruleList)
  
    // 特殊处理options属性
    if (scheme.options || (slot && slot.options && slot.options.length)) {
      buildOptions(scheme, optionsList)
      if (config.dataType === 'dynamic') {
        const model = `${scheme.__vModel__}Options`
        const options = titleCase(model)
        const methodName = `get${options}`
        buildOptionMethod(methodName, model, methodList, scheme)
        callInCreated(methodName, created)
      }
    }
  
    // 处理props
    if (scheme.props && scheme.props.props) {
      buildProps(scheme, propsList)
    }
  
    // 处理el-upload的action
    if (scheme.action && config.tag === 'el-upload') {
      uploadVarList.push(
        `${scheme.__vModel__}Action: '${scheme.action}',
        ${scheme.__vModel__}fileList: [],`
      )
      methodList.push(buildBeforeUpload(scheme))
      // 非自动上传时，生成手动上传的函数
      if (!scheme['auto-upload']) {
        methodList.push(buildSubmitUpload(scheme))
      }
    }
  
    // 构建子级组件属性
    if (config.children) {
      config.children.forEach(item => {
        buildAttributes(item, dataList, ruleList, optionsList, methodList, propsList, uploadVarList, created)
      })
    }
  }
  
  // 在Created调用函数
  function callInCreated(methodName, created) {
    created.push(`this.${methodName}()`)
  }
  
  // 混入处理函数
  function mixinMethod(type) {
    const list = [];
    const  minxins = {
        file: confGlobal.formBtns ? {
          submitForm: `submitForm() {
          this.$refs['${confGlobal.formRef}'].validate(valid => {
            if(!valid) return
            // TODO 提交表单
          })
        },`,
          resetForm: `resetForm() {
          this.$refs['${confGlobal.formRef}'].resetFields()
        },`
        } : null,
        dialog: {
          onOpen: 'onOpen() {},',
          onClose: `onClose() {
          this.$refs['${confGlobal.formRef}'].resetFields()
        },`,
          close: `close() {
          this.$emit('update:visible', false)
        },`,
          handelConfirm: `handelConfirm() {
          this.$refs['${confGlobal.formRef}'].validate(valid => {
            if(!valid) return
            this.close()
          })
        },`
        }
      }
  
    const methods = minxins[type]
    if (methods) {
      Object.keys(methods).forEach(key => {
        list.push(methods[key])
      })
    }
  
    return list
  }
  
  // 构建data
  function buildData(scheme, dataList) {
    const config = scheme.__config__
    if (scheme.__vModel__ === undefined) return
    const defaultValue = JSON.stringify(config.defaultValue)
    dataList.push(`${scheme.__vModel__}: ${defaultValue},`)
  }
  
  // 构建校验规则
  function buildRules(scheme, ruleList) {
    const config = scheme.__config__
    if (scheme.__vModel__ === undefined) return
    const rules = []
    if (ruleTrigger[config.tag]) {
      if (config.required) {
        const type = isArray(config.defaultValue) ? 'type: \'array\',' : ''
        let message = isArray(config.defaultValue) ? `请至少选择一个${config.label}` : scheme.placeholder
        if (message === undefined) message = `${config.label}不能为空`
        rules.push(`{ required: true, ${type} message: '${message}', trigger: '${ruleTrigger[config.tag]}' }`)
      }
      if (config.regList && isArray(config.regList)) {
        config.regList.forEach(item => {
          if (item.pattern) {
            rules.push(
              `{ pattern: ${eval(item.pattern)}, message: '${item.message}', trigger: '${ruleTrigger[config.tag]}' }`
            )
          }
        })
      }
      ruleList.push(`${scheme.__vModel__}: [${rules.join(',')}],`)
    }
  }
  
  // 构建options
  function buildOptions(scheme, optionsList) {
    if (scheme.__vModel__ === undefined) return
    // el-cascader直接有options属性，其他组件都是定义在slot中，所以有两处判断
    let { options } = scheme
    if (!options) options = scheme.__slot__.options
    if (scheme.__config__.dataType === 'dynamic') { options = [] }
    const str = `${scheme.__vModel__}Options: ${JSON.stringify(options)},`
    optionsList.push(str)
  }
  
  function buildProps(scheme, propsList) {
    const str = `${scheme.__vModel__}Props: ${JSON.stringify(scheme.props.props)},`
    propsList.push(str)
  }
  
  // el-upload的BeforeUpload
  function buildBeforeUpload(scheme) {
    const config = scheme.__config__
    const unitNum = units[config.sizeUnit]; let rightSizeCode = ''; let acceptCode = ''; const
      returnList = []
    if (config.fileSize) {
      rightSizeCode = `let isRightSize = file.size / ${unitNum} < ${config.fileSize}
      if(!isRightSize){
        this.$message.error('文件大小超过 ${config.fileSize}${config.sizeUnit}')
      }`
      returnList.push('isRightSize')
    }
    if (scheme.accept) {
      acceptCode = `let isAccept = new RegExp('${scheme.accept}').test(file.type)
      if(!isAccept){
        this.$message.error('应该选择${scheme.accept}类型的文件')
      }`
      returnList.push('isAccept')
    }
    const str = `${scheme.__vModel__}BeforeUpload(file) {
      ${rightSizeCode}
      ${acceptCode}
      return ${returnList.join('&&')}
    },`
    return returnList.length ? str : ''
  }
  
  // el-upload的submit
  function buildSubmitUpload(scheme) {
    const str = `submitUpload() {
      this.$refs['${scheme.__vModel__}'].submit()
    },`
    return str
  }
  
  function buildOptionMethod(methodName, model, methodList, scheme) {
    const config = scheme.__config__
    const str = `${methodName}() {
      // 注意：this.$axios是通过Vue.prototype.$axios = axios挂载产生的
      this.$axios({
        method: '${config.method}',
        url: '${config.url}'
      }).then(resp => {
        var { data } = resp
        this.${model} = data.${config.dataPath}
      })
    },`
    methodList.push(str)
  }
  
  // js整体拼接
  function buildexport(conf, type, data, rules, selectOptions, uploadVar, props, methods, created) {
    const str = `${exportDefault}{
    ${inheritAttrs[type]}
    components: {},
    props: [],
    data () {
      return {
        ${conf.formModel}: {
          ${data}
        },
        ${conf.formRules}: {
          ${rules}
        },
        ${uploadVar}
        ${selectOptions}
        ${props}
      }
    },
    computed: {},
    watch: {},
    created () {
      ${created}
    },
    mounted () {},
    methods: {
      ${methods}
    }
  }`
    return str
  }
  