综合办公系统
Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

Parser.vue 8.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283
  1. <script>
  2. import { deepClone } from '../../utils/index'
  3. import render from '../render/render.js'
  4. const ruleTrigger = {
  5. 'el-input': 'blur',
  6. 'el-input-number': 'blur',
  7. 'el-select': 'change',
  8. 'el-radio-group': 'change',
  9. 'el-checkbox-group': 'change',
  10. 'el-cascader': 'change',
  11. 'el-time-picker': 'change',
  12. 'el-date-picker': 'change',
  13. 'el-rate': 'change'
  14. }
  15. const layouts = {
  16. colFormItem(h, scheme) {
  17. const config = scheme.__config__
  18. const listeners = buildListeners.call(this, scheme)
  19. let labelWidth = config.labelWidth ? `${config.labelWidth}px` : null
  20. if (config.showLabel === false) labelWidth = '0'
  21. return (
  22. <el-col span={config.span}>
  23. <el-form-item label-width={labelWidth} prop={scheme.__vModel__}
  24. label={config.showLabel ? config.label : ''}>
  25. <render conf={scheme} on={listeners} />
  26. </el-form-item>
  27. </el-col>
  28. )
  29. },
  30. rowFormItem(h, scheme) {
  31. let child = renderChildren.apply(this, arguments)
  32. if (scheme.type === 'flex') {
  33. child = <el-row type={scheme.type} justify={scheme.justify} align={scheme.align}>
  34. {child}
  35. </el-row>
  36. }
  37. return (
  38. <el-col span={scheme.span}>
  39. <el-row gutter={scheme.gutter}>
  40. {child}
  41. </el-row>
  42. </el-col>
  43. )
  44. },
  45. showFormItem(h, scheme) {
  46. const { activeItem } = this.$listeners
  47. const config = scheme.__config__
  48. const className = this.activeId === config.formId
  49. ? 'drawing-row-item active-from-item'
  50. : 'drawing-row-item'
  51. const spanText = 'row' + config.formId
  52. return (
  53. <el-col span={config.span}>
  54. <el-row>
  55. <h1>
  56. <render key={config.renderKey} conf={scheme} onInput={event => { this.$set(config, 'defaultValue', event) }}></render>
  57. </h1>
  58. </el-row>
  59. </el-col>
  60. )
  61. }
  62. }
  63. function renderFrom(h) {
  64. const { formConfCopy } = this
  65. return (
  66. <el-row gutter={formConfCopy.gutter}>
  67. <el-form
  68. size={formConfCopy.size}
  69. label-position={formConfCopy.labelPosition}
  70. disabled={formConfCopy.disabled}
  71. label-width={`${formConfCopy.labelWidth}px`}
  72. ref={formConfCopy.formRef}
  73. // model不能直接赋值 https://github.com/vuejs/jsx/issues/49#issuecomment-472013664
  74. props={{ model: this[formConfCopy.formModel] }}
  75. rules={this[formConfCopy.formRules]}
  76. >
  77. {renderFormItem.call(this, h, formConfCopy.fields)}
  78. {formConfCopy.formBtns && formBtns.call(this, h)}
  79. </el-form>
  80. </el-row>
  81. )
  82. }
  83. function formBtns(h) {
  84. return <el-col>
  85. <el-form-item size="large">
  86. <el-button type="primary" onClick={this.submitForm}>提交</el-button>
  87. <el-button onClick={this.resetForm}>重置</el-button>
  88. </el-form-item>
  89. </el-col>
  90. }
  91. function renderFormItem(h, elementList) {
  92. if (elementList) {
  93. return elementList.map(scheme => {
  94. const config = scheme.__config__
  95. const layout = layouts[config.layout]
  96. if (layout) {
  97. return layout.call(this, h, scheme)
  98. }
  99. throw new Error(`没有与${config.layout}匹配的layout`)
  100. })
  101. }
  102. }
  103. function renderChildren(h, scheme) {
  104. const config = scheme.__config__
  105. if (!Array.isArray(config.children)) return null
  106. return renderFormItem.call(this, h, config.children)
  107. }
  108. function setValue(event, config, scheme) {
  109. this.$set(config, 'defaultValue', event)
  110. this.$set(this[this.formConf.formModel], scheme.__vModel__, event)
  111. }
  112. function buildListeners(scheme) {
  113. const config = scheme.__config__;
  114. const methods = this.formConf.__methods__ || {};
  115. const listeners = {};
  116. // 给__methods__中的方法绑定this和event
  117. Object.keys(methods).forEach((key) => {
  118. listeners[key] = (event) => methods[key].call(this, event);
  119. });
  120. // 响应 render.js 中的 vModel $emit('input', val)
  121. listeners.input = (event) => setValue.call(this, event, config, scheme);
  122. // 上传表单元素组件的成功、移除和预览事件
  123. if (config.tag === "el-upload") {
  124. listeners.upload = (response, file, fileList) =>
  125. setUpload.call(this, config, scheme, response, file, fileList);
  126. listeners.deleteUpload = (file, fileList) =>
  127. deleteUpload.call(this, config, scheme, file, fileList);
  128. listeners.previewUpload = (file, fileList) =>
  129. window.open(file.url, "_blank");
  130. }
  131. return listeners;
  132. }
  133. //获取上传表单元素组件 上传的文件
  134. function setUpload(config, scheme, response, file, fileList) {
  135. //response: 上传接口返回的数据
  136. let fileObj = {
  137. name: response.fileName,
  138. url: response.url,
  139. fileType: response.contentType,
  140. };
  141. let oldValue = "";
  142. try {
  143. oldValue = JSON.parse(this[this.formConf.formModel][scheme.__vModel__]);
  144. } catch (err) {
  145. console.warn(err);
  146. }
  147. if (oldValue) {
  148. oldValue.push(fileObj);
  149. } else {
  150. oldValue = [fileObj];
  151. }
  152. this.$set(config, "defaultValue", JSON.stringify(oldValue));
  153. this.$set(
  154. this[this.formConf.formModel],
  155. scheme.__vModel__,
  156. JSON.stringify(oldValue)
  157. );
  158. }
  159. //获取上传表单元素组件 删除文件后的文件列表
  160. function deleteUpload(config, scheme, file, fileList) {
  161. let oldValue = JSON.parse(this[this.formConf.formModel][scheme.__vModel__]);
  162. //file 删除的文件
  163. //过滤掉删除的文件
  164. let newValue = oldValue.filter((item) => item.name !== file.name);
  165. this.$set(config, "defaultValue", JSON.stringify(newValue));
  166. this.$set(
  167. this[this.formConf.formModel],
  168. scheme.__vModel__,
  169. JSON.stringify(newValue)
  170. );
  171. }
  172. export default {
  173. components: {
  174. render
  175. },
  176. props: {
  177. formConf: {
  178. type: Object,
  179. required: true
  180. }
  181. },
  182. data() {
  183. const data = {
  184. formConfCopy: deepClone(this.formConf),
  185. [this.formConf.formModel]: {},
  186. [this.formConf.formRules]: {}
  187. }
  188. if (data.formConfCopy.fields) {
  189. this.initFormData(data.formConfCopy.fields, data[this.formConf.formModel])
  190. this.buildRules(data.formConfCopy.fields, data[this.formConf.formRules])
  191. }
  192. return data
  193. },
  194. methods: {
  195. initFormData(componentList, formData) {
  196. componentList.forEach(cur => {
  197. const config = cur.__config__
  198. if (cur.__vModel__) formData[cur.__vModel__] = config.defaultValue
  199. if (config.children) this.initFormData(config.children, formData)
  200. })
  201. },
  202. buildRules(componentList, rules) {
  203. componentList.forEach(cur => {
  204. const config = cur.__config__
  205. if (Array.isArray(config.regList)) {
  206. if (config.required) {
  207. const required = { required: config.required, message: cur.placeholder }
  208. if (Array.isArray(config.defaultValue)) {
  209. required.type = 'array'
  210. required.message = `请至少选择一个${config.label}`
  211. }
  212. required.message === undefined && (required.message = `${config.label}不能为空`)
  213. config.regList.push(required)
  214. }
  215. rules[cur.__vModel__] = config.regList.map(item => {
  216. item.pattern && (item.pattern = eval(item.pattern))
  217. item.trigger = ruleTrigger && ruleTrigger[config.tag]
  218. return item
  219. })
  220. }
  221. if (config.children) this.buildRules(config.children, rules)
  222. })
  223. },
  224. resetForm() {
  225. this.formConfCopy = deepClone(this.formConf)
  226. this.$refs[this.formConf.formRef].resetFields()
  227. },
  228. submitForm() {
  229. this.$refs[this.formConf.formRef].validate(valid => {
  230. if (!valid) return false
  231. // 触发sumit事件
  232. // this.$emit('submit', this[this.formConf.formModel])
  233. const params = {
  234. formData: this.formConfCopy,
  235. valData: this[this.formConf.formModel]
  236. }
  237. this.$emit('submit', params)
  238. return true
  239. })
  240. },
  241. // 传值给父组件
  242. getData() {
  243. this.$emit('getData', this[this.formConf.formModel])
  244. // this.$emit('getData',this.formConfCopy)
  245. }
  246. },
  247. render(h) {
  248. return renderFrom.call(this, h)
  249. }
  250. }
  251. </script>
  252. <style scoped>
  253. ::v-deep.el-form-item {
  254. margin-bottom: 10px;
  255. }
  256. ::v-deep.el-form-item--small.el-form-item {
  257. margin-bottom: 10px;
  258. }
  259. </style>