Blame view

src/components/Generator/render/render.js 3.61 KB
5330d757   monkeyhouyi   公司信息管理完成
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
  import { deepClone } from '@/utils'
  
  const componentChild = {}
  /**
   * ./slots中的文件挂载到对象componentChild
   * 文件名为key,对应JSON配置中的__config__.tag
   * 文件内容为value,解析JSON配置中的__slot__
   */
  const slotsFiles = require.context('./slots', false, /\.js$/)
  const keys = slotsFiles.keys() || []
  keys.forEach(key => {
    const tag = key.replace(/^\.\/(.*)\.\w+$/, '$1')
    const value = slotsFiles(key).default
    componentChild[tag] = value
  })
  
  function vModel(dataObject, defaultValue) {
    dataObject.props.value = defaultValue
  
    dataObject.on.input = val => {
      this.$emit('input', val)
    }
  }
  
  function mountSlotFiles(h, confClone, children) {
    const childObjs = componentChild[confClone.__config__.tag]
    if (childObjs) {
      Object.keys(childObjs).forEach(key => {
        const childFunc = childObjs[key]
        if (confClone.__slot__ && confClone.__slot__[key]) {
          children.push(childFunc(h, confClone, key))
        }
      })
    }
  }
  
  function emitEvents(confClone) {
    ['on', 'nativeOn'].forEach(attr => {
      const eventKeyList = Object.keys(confClone[attr] || {})
      eventKeyList.forEach(key => {
        const val = confClone[attr][key]
        if (typeof key === 'string') {
          confClone[attr][key] = event => this.$emit(key, event)
        }
      })
    })
  }
  
  function buildDataObject(confClone, dataObject, formData) {
    Object.keys(confClone).forEach(key => {
      const val = confClone[key]
      if (key === '__vModel__') {
        vModel.call(this, dataObject, confClone.__config__.defaultValue)
      } else if (dataObject[key] !== undefined) {
        if (dataObject[key] === null ||
          dataObject[key] instanceof RegExp || ['boolean', 'string', 'number', 'function'].includes(typeof dataObject[key])) {
          dataObject[key] = val
        } else if (Array.isArray(dataObject[key])) {
          dataObject[key] = [...dataObject[key], ...val]
        } else {
          dataObject[key] = { ...dataObject[key], ...val }
        }
      } else {
        dataObject.attrs[key] = val
      }
    })
    if (confClone.__config__.nccKey === 'NCCText') {
      vModel.call(this, dataObject, confClone.__config__.defaultValue)
    }
    if (confClone.__config__.nccKey === 'calculate' || confClone.__config__.nccKey === 'table') {
      dataObject.attrs['formData'] = formData
    }
    if (confClone.__config__.nccKey === 'relationForm' || confClone.__config__.nccKey === 'relationFlow') {
      dataObject.attrs['field'] = confClone.__vModel__
    }
  
    // 清理属性
    clearAttrs(dataObject)
  }
  
  function clearAttrs(dataObject) {
    delete dataObject.attrs.__config__
    delete dataObject.attrs.__slot__
    delete dataObject.attrs.__methods__
  }
  
  function makeDataObject() {
    return {
      class: {},
      attrs: {},
      props: {},
      domProps: {},
      nativeOn: {},
      on: {},
      style: {},
      directives: [],
      scopedSlots: {},
      slot: null,
      key: null,
      ref: null,
      refInFor: true
    }
  }
  
  export default {
    props: {
      conf: {
        type: Object,
        required: true
      },
      formData: {
        type: Object,
        default: () => {}
      },
    },
    render(h) {
      const dataObject = makeDataObject()
      const confClone = deepClone(this.conf)
      const children = this.$slots.default || []
  
      // 如果slots文件夹存在与当前tag同名的文件,则执行文件中的代码
      mountSlotFiles.call(this, h, confClone, children)
  
      // 将字符串类型的事件,发送为消息
      emitEvents.call(this, confClone)
  
      // 将json表单配置转化为vue render可以识别的 “数据对象(dataObject)”
      buildDataObject.call(this, confClone, dataObject, this.formData)
  
      return h(this.conf.__config__.tag, dataObject, children)
    }
  }