byForm.vue 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. <template>
  2. <div class="by-form">
  3. <el-form class="byForm"
  4. :style="{ height: attrs.height ? attrs.height + 'px' : 'auto' }"
  5. :model="value"
  6. ref="byForm"
  7. :validate-on-rule-change="false"
  8. :size="attrs.size ? attrs.size : 'small'"
  9. :inline-message="true"
  10. v-bind="$attrs"
  11. :label-width="attrs.labelWidth"
  12. :rules="attrs.rules"
  13. :label-position="attrs.labelPosition ? attrs.labelPosition : ''">
  14. <el-row class="form-row" v-for="(itemChild,index) of columns" :key="index">
  15. <el-col v-for="(item,_ind) of itemChild" :span="item.span" :key="'itemChild'+_ind">
  16. <el-form-item class="by-form-item"
  17. :label="item.label"
  18. :rules="item.rules"
  19. :prop="item.prop"
  20. :required="item.required"
  21. :error="item.error"
  22. :size="item.size"
  23. :label-width="item.labelWidth?item.labelWidth:'100px'">
  24. <component v-bind:is="item.component"
  25. class="form-comp"
  26. :propConfig="item.compConfig"
  27. :ref="item.prop+'Comp'"
  28. :propValue="value[item.prop]"
  29. @onChange="onChange($event,item)"
  30. v-bind="$attrs"
  31. v-on="$listeners"
  32. />
  33. <slot v-if="item.slot" :name='item.prop' :value='value'></slot>
  34. <!-- <slot :[item.prop]="value" ></slot> -->
  35. </el-form-item>
  36. </el-col>
  37. </el-row>
  38. </el-form>
  39. </div>
  40. </template>
  41. <script lang="ts">
  42. /*
  43. 基础配置
  44. config:{
  45. attr:{
  46. size:medium / small / mini, //表单域下组件的尺寸,
  47. height:'', //高度
  48. labelPosition: right/left/top //标签位置
  49. labelWidth: '' //标签的宽度
  50. rules:[] //验证规则
  51. },
  52. columns: [[{ //表单列
  53. span:'' //分栏,
  54. label:'' //标签
  55. prop:'' //字段
  56. labelWidth:'' 标签的的宽度
  57. rule:{} //验证规则
  58. size:medium / small / mini //表单域下组件的尺寸,
  59. component:'' //组件
  60. compConfig:{} //组件配置
  61. }]]
  62. request:{
  63. url:'',
  64. method:'',
  65. headers:{},
  66. data:{}
  67. }
  68. }
  69. */
  70. import { Component, Prop, Vue, Watch } from "vue-property-decorator";
  71. import VueViews from '@/benyun/utils/VueViews'
  72. @Component
  73. export default class ByForm extends VueViews {
  74. value:any={}
  75. get columns(){
  76. let columns:Array<any> = this.config?.columns ? this.config.columns : []
  77. //分栏设置
  78. if(columns.length > 0){
  79. for (const itemChild of columns) {
  80. let spans = 24
  81. let n = itemChild.length
  82. for(const item of itemChild){
  83. if (item && ((Number(item.span) > 0 && Number(item.span) <= 24))) {
  84. spans = spans - Number(item.span)
  85. n--;
  86. }
  87. }
  88. for(const item of itemChild){
  89. if (Number(item.span) > 0 && Number(item.span) <= 24) {
  90. item.span = Number(item.span)
  91. } else {
  92. item.span = spans / n
  93. }
  94. }
  95. }
  96. }
  97. return columns
  98. }
  99. created(){
  100. if(this.propConfig){
  101. this.setConfig(this.propConfig)
  102. }
  103. }
  104. mounted(){}
  105. //设置数据
  106. setValue(data:any){
  107. this.clearChildrenComp();
  108. if(data){
  109. this.value = (this as any).$lodash.cloneDeep(data);
  110. this.setChildrenComValue();
  111. }else{
  112. this.value = {};
  113. }
  114. }
  115. //获取数据
  116. getValue(){
  117. return (this as any).$lodash.cloneDeep(this.value);
  118. }
  119. //清除下级组件组件值
  120. clearChildrenComp(){
  121. for(const key in this.$refs){
  122. if(key.indexOf('Comp') >= 0 && (this as any).$refs[key][0] && (this as any).$refs[key][0].clearValue){
  123. (this as any).$refs[key][0].clearValue()
  124. }
  125. }
  126. }
  127. //设置下级组件值
  128. setChildrenComValue(){
  129. if(this.value){
  130. for(const key in this.value){
  131. const code = key +'Comp';
  132. if((this as any).$refs[code] && (this as any).$refs[code][0] && (this as any).$refs[code][0].setValue()){
  133. (this as any).$refs[code][0].setValue(this.value[key])
  134. }
  135. }
  136. }
  137. }
  138. //表单数据变化
  139. onChange(v:any,config:any){
  140. let code = config.prop;
  141. if(this.value[code]){
  142. this.value[code] = v;
  143. }else{
  144. Vue.set(this.value, code, v);
  145. }
  146. }
  147. //表单验证
  148. validate():Promise<any>{
  149. return new Promise((resolve:Function, reject:Function) => {
  150. (this as any).$refs.byForm.validate((valid:any) => {
  151. if (valid) {
  152. resolve(true)
  153. } else {
  154. (this as any).$message({
  155. message: '验证未通过,请检查!',
  156. type: 'warning',
  157. })
  158. reject()
  159. }
  160. });
  161. })
  162. }
  163. }
  164. </script>
  165. <style lang="scss" scoped>
  166. .by-form{
  167. width: 100%;
  168. .form-comp{
  169. width: 100%;
  170. }
  171. }
  172. </style>
  173. <style lang="scss">
  174. .by-form-item{
  175. margin-bottom: 10px !important;
  176. }
  177. </style>