js.js 7.3 KB

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