form.vue 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. <template>
  2. <el-form ref="form" :model="form" :rules="rules" v-bind="options">
  3. <slot name="pre"></slot>
  4. <slot>
  5. <el-form-item
  6. v-for="(item, index) in fields"
  7. :key="'form-field-' + index"
  8. :label="item.field.label"
  9. :prop="item.field.name"
  10. :required="item.field.required"
  11. :rules="item.rules"
  12. v-bind="item.formOpts"
  13. v-show="isNew || !item.slots.nonce"
  14. >
  15. <slot name="field" v-if="item.slots.ext" v-bind="{ item, form, handleFieldChange, setFieldValue }">
  16. <span>customEditor</span>
  17. </slot>
  18. <naf-input
  19. v-else
  20. v-model="form[item.field.name]"
  21. :disabled="readonly || item.field.readonly || (!isNew && item.field.editable === false)"
  22. :placeholder="(item.formOpts && item.formOpts.placeholder) || (isNew && item.field.readonly && '--- 系统生成 ---')"
  23. :dict="item.dict"
  24. :type="item.formOpts && item.formOpts.inputType"
  25. v-bind="{ ...item.formOpts, ...mergeLength(item) }"
  26. @change="handleFieldChange(item.field.name, $event)"
  27. ></naf-input>
  28. </el-form-item>
  29. </slot>
  30. <slot name="ext" v-bind:form="form"></slot>
  31. <slot name="submit">
  32. <el-form-item v-show="!readonly">
  33. <el-button type="primary" @click="handleSave">{{ closeOnSaved ? '保存并关闭' : '保存' }}</el-button>
  34. <el-button type="info" @click="$emit('cancel')">取消</el-button>
  35. </el-form-item>
  36. </slot>
  37. </el-form>
  38. </template>
  39. <script>
  40. import { FieldMeta } from './meta-util';
  41. import NafInput from './naf-input';
  42. export default {
  43. name: 'data-form',
  44. components: {
  45. NafInput,
  46. },
  47. props: {
  48. data: { type: Object, required: true },
  49. meta: { type: Array, required: true },
  50. rules: Object,
  51. readonly: { type: Boolean, default: false } /* 是否只读 */,
  52. isNew: { type: Boolean, default: false } /* 是否新创建 */,
  53. options: Object,
  54. onlyModified: { type: Boolean, default: false } /** 是否只保存修改字段 */,
  55. closeOnSaved: { type: Boolean, default: false } /** 保存并关闭 */,
  56. },
  57. data() {
  58. return {
  59. form: {},
  60. modified: {},
  61. };
  62. },
  63. mounted() {
  64. this.reset();
  65. },
  66. methods: {
  67. reset() {
  68. this.form = { ...this.data };
  69. },
  70. handleSave() {
  71. this.$refs['form'].validate(valid => {
  72. if (valid) {
  73. this.$emit('save', {
  74. isNew: this.isNew,
  75. isModified: this.isModified,
  76. data: this.onlyModified ? this.modified : this.form,
  77. closeOnSaved: this.closeOnSaved,
  78. });
  79. } else {
  80. console.warn('form validate error!!!');
  81. }
  82. });
  83. },
  84. mergeRules(meta) {
  85. const rules = meta.rules || [];
  86. if (meta.pattern) {
  87. const pattern = this.$policy(meta.pattern);
  88. if (pattern !== 0) rules.push({ pattern, whitespace: true, message: '请输入正确内容' });
  89. }
  90. if (
  91. meta.field.required &&
  92. (!this.rules || !this.rules[meta.field.name] || !this.rules[meta.field.name].some(p => p.required)) &&
  93. (!meta.rules || !meta.rules || !meta.rules.some(p => p.required))
  94. ) {
  95. rules.push({ required: true, whitespace: true, message: '不能为空' });
  96. return rules;
  97. } else {
  98. return meta.rules;
  99. }
  100. },
  101. mergeLength(meta) {
  102. const rules = [...((this.rules && this.rules[meta.field.name]) || []), ...(meta.rules || [])];
  103. const { max: maxlength, min: minlength } = rules.find(r => r.max || r.min) || {};
  104. return { maxlength, minlength };
  105. },
  106. validateField(payload) {
  107. this.$refs['form'].validateField(payload);
  108. },
  109. handleFieldChange(name, value) {
  110. console.debug(`field ${name} changed:`, value);
  111. if (this.data[name] === value) {
  112. this.$delete(this.modified, name);
  113. } else {
  114. this.$set(this.modified, name, value);
  115. }
  116. },
  117. setFieldValue(name, value) {
  118. this.$set(this.form, name, value);
  119. this.handleFieldChange(name, value);
  120. },
  121. },
  122. computed: {
  123. fields() {
  124. return this.meta
  125. .map(FieldMeta)
  126. .filter(p => p.slots.form)
  127. .sort((a, b) => a.order - b.order || a.index - b.index)
  128. .map(p => ({
  129. ...p,
  130. dict: p.dict || (this.$dict && p.formatter && p.formatter.name === 'dict' && this.$dict(p.formatter.param)),
  131. rules: this.mergeRules(p),
  132. }));
  133. },
  134. isModified() {
  135. return this.getModifiedFields.length > 0;
  136. },
  137. getModifiedFields() {
  138. return Object.keys(this.modified);
  139. },
  140. },
  141. };
  142. </script>