houzhongjian
2024-07-11 759b1c71011abd6b58c37d2566f3f3c208c2f1b2
提交 | 用户 | 时间
759b1c 1 import { isArray } from 'util'
H 2 import { exportDefault, titleCase, deepClone } from '@/utils'
3 import ruleTrigger from './ruleTrigger'
4
5 const units = {
6   KB: '1024',
7   MB: '1024 / 1024',
8   GB: '1024 / 1024 / 1024'
9 }
10 let confGlobal
11 const inheritAttrs = {
12   file: '',
13   dialog: 'inheritAttrs: false,'
14 }
15
16 /**
17  * 组装js 【入口函数】
18  * @param {Object} formConfig 整个表单配置
19  * @param {String} type 生成类型,文件或弹窗等
20  */
21 export function makeUpJs(formConfig, type) {
22   confGlobal = formConfig = deepClone(formConfig)
23   const dataList = []
24   const ruleList = []
25   const optionsList = []
26   const propsList = []
27   const methodList = mixinMethod(type)
28   const uploadVarList = []
29   const created = []
30
31   formConfig.fields.forEach(el => {
32     buildAttributes(el, dataList, ruleList, optionsList, methodList, propsList, uploadVarList, created)
33   })
34
35   const script = buildexport(
36     formConfig,
37     type,
38     dataList.join('\n'),
39     ruleList.join('\n'),
40     optionsList.join('\n'),
41     uploadVarList.join('\n'),
42     propsList.join('\n'),
43     methodList.join('\n'),
44     created.join('\n')
45   )
46   confGlobal = null
47   return script
48 }
49
50 // 构建组件属性
51 function buildAttributes(scheme, dataList, ruleList, optionsList, methodList, propsList, uploadVarList, created) {
52   const config = scheme.__config__
53   const slot = scheme.__slot__
54   buildData(scheme, dataList)
55   buildRules(scheme, ruleList)
56
57   // 特殊处理options属性
58   if (scheme.options || (slot && slot.options && slot.options.length)) {
59     buildOptions(scheme, optionsList)
60     if (config.dataType === 'dynamic') {
61       const model = `${scheme.__vModel__}Options`
62       const options = titleCase(model)
63       const methodName = `get${options}`
64       buildOptionMethod(methodName, model, methodList, scheme)
65       callInCreated(methodName, created)
66     }
67   }
68
69   // 处理props
70   if (scheme.props && scheme.props.props) {
71     buildProps(scheme, propsList)
72   }
73
74   // 处理el-upload的action
75   if (scheme.action && config.tag === 'el-upload') {
76     uploadVarList.push(
77       `${scheme.__vModel__}Action: '${scheme.action}',
78       ${scheme.__vModel__}fileList: [],`
79     )
80     methodList.push(buildBeforeUpload(scheme))
81     // 非自动上传时,生成手动上传的函数
82     if (!scheme['auto-upload']) {
83       methodList.push(buildSubmitUpload(scheme))
84     }
85   }
86
87   // 构建子级组件属性
88   if (config.children) {
89     config.children.forEach(item => {
90       buildAttributes(item, dataList, ruleList, optionsList, methodList, propsList, uploadVarList, created)
91     })
92   }
93 }
94
95 // 在Created调用函数
96 function callInCreated(methodName, created) {
97   created.push(`this.${methodName}()`)
98 }
99
100 // 混入处理函数
101 function mixinMethod(type) {
102   const list = []; const
103     minxins = {
104       file: confGlobal.formBtns ? {
105         submitForm: `submitForm() {
106         this.$refs['${confGlobal.formRef}'].validate(valid => {
107           if(!valid) return
108           // TODO 提交表单
109         })
110       },`,
111         resetForm: `resetForm() {
112         this.$refs['${confGlobal.formRef}'].resetFields()
113       },`
114       } : null,
115       dialog: {
116         onOpen: 'onOpen() {},',
117         onClose: `onClose() {
118         this.$refs['${confGlobal.formRef}'].resetFields()
119       },`,
120         close: `close() {
121         this.$emit('update:visible', false)
122       },`,
123         handelConfirm: `handelConfirm() {
124         this.$refs['${confGlobal.formRef}'].validate(valid => {
125           if(!valid) return
126           this.close()
127         })
128       },`
129       }
130     }
131
132   const methods = minxins[type]
133   if (methods) {
134     Object.keys(methods).forEach(key => {
135       list.push(methods[key])
136     })
137   }
138
139   return list
140 }
141
142 // 构建data
143 function buildData(scheme, dataList) {
144   const config = scheme.__config__
145   if (scheme.__vModel__ === undefined) return
146   const defaultValue = JSON.stringify(config.defaultValue)
147   dataList.push(`${scheme.__vModel__}: ${defaultValue},`)
148 }
149
150 // 构建校验规则
151 function buildRules(scheme, ruleList) {
152   const config = scheme.__config__
153   if (scheme.__vModel__ === undefined) return
154   const rules = []
155   if (ruleTrigger[config.tag]) {
156     if (config.required) {
157       const type = isArray(config.defaultValue) ? 'type: \'array\',' : ''
158       let message = isArray(config.defaultValue) ? `请至少选择一个${config.label}` : scheme.placeholder
159       if (message === undefined) message = `${config.label}不能为空`
160       rules.push(`{ required: true, ${type} message: '${message}', trigger: '${ruleTrigger[config.tag]}' }`)
161     }
162     if (config.regList && isArray(config.regList)) {
163       config.regList.forEach(item => {
164         if (item.pattern) {
165           rules.push(
166             `{ pattern: ${eval(item.pattern)}, message: '${item.message}', trigger: '${ruleTrigger[config.tag]}' }`
167           )
168         }
169       })
170     }
171     ruleList.push(`${scheme.__vModel__}: [${rules.join(',')}],`)
172   }
173 }
174
175 // 构建options
176 function buildOptions(scheme, optionsList) {
177   if (scheme.__vModel__ === undefined) return
178   // el-cascader直接有options属性,其他组件都是定义在slot中,所以有两处判断
179   let { options } = scheme
180   if (!options) options = scheme.__slot__.options
181   if (scheme.__config__.dataType === 'dynamic') { options = [] }
182   const str = `${scheme.__vModel__}Options: ${JSON.stringify(options)},`
183   optionsList.push(str)
184 }
185
186 function buildProps(scheme, propsList) {
187   const str = `${scheme.__vModel__}Props: ${JSON.stringify(scheme.props.props)},`
188   propsList.push(str)
189 }
190
191 // el-upload的BeforeUpload
192 function buildBeforeUpload(scheme) {
193   const config = scheme.__config__
194   const unitNum = units[config.sizeUnit]; let rightSizeCode = ''; let acceptCode = ''; const
195     returnList = []
196   if (config.fileSize) {
197     rightSizeCode = `let isRightSize = file.size / ${unitNum} < ${config.fileSize}
198     if(!isRightSize){
199       this.$message.error('文件大小超过 ${config.fileSize}${config.sizeUnit}')
200     }`
201     returnList.push('isRightSize')
202   }
203   if (scheme.accept) {
204     acceptCode = `let isAccept = new RegExp('${scheme.accept}').test(file.type)
205     if(!isAccept){
206       this.$message.error('应该选择${scheme.accept}类型的文件')
207     }`
208     returnList.push('isAccept')
209   }
210   const str = `${scheme.__vModel__}BeforeUpload(file) {
211     ${rightSizeCode}
212     ${acceptCode}
213     return ${returnList.join('&&')}
214   },`
215   return returnList.length ? str : ''
216 }
217
218 // el-upload的submit
219 function buildSubmitUpload(scheme) {
220   const str = `submitUpload() {
221     this.$refs['${scheme.__vModel__}'].submit()
222   },`
223   return str
224 }
225
226 function buildOptionMethod(methodName, model, methodList, scheme) {
227   const config = scheme.__config__
228   const str = `${methodName}() {
229     // 注意:this.$axios是通过Vue.prototype.$axios = axios挂载产生的
230     this.$axios({
231       method: '${config.method}',
232       url: '${config.url}'
233     }).then(resp => {
234       var { data } = resp
235       this.${model} = data.${config.dataPath}
236     })
237   },`
238   methodList.push(str)
239 }
240
241 // js整体拼接
242 function buildexport(conf, type, data, rules, selectOptions, uploadVar, props, methods, created) {
243   const str = `${exportDefault}{
244   ${inheritAttrs[type]}
245   components: {},
246   props: [],
247   data () {
248     return {
249       ${conf.formModel}: {
250         ${data}
251       },
252       ${conf.formRules}: {
253         ${rules}
254       },
255       ${uploadVar}
256       ${selectOptions}
257       ${props}
258     }
259   },
260   computed: {},
261   watch: {},
262   created () {
263     ${created}
264   },
265   mounted () {},
266   methods: {
267     ${methods}
268   }
269 }`
270   return str
271 }