form.vue 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. <template>
  2. <div id="add">
  3. <el-form ref="form" :model="form" :rules="rules" :label-width="labelWidth" class="form" size="small" @submit.native.prevent :style="styles">
  4. <template v-for="(item, index) in fields">
  5. <template v-if="!loading">
  6. <el-form-item v-if="display(item)" :key="'form-field-' + index" :label="getField('label', item)" :prop="item.model" :required="item.required">
  7. <template v-if="!item.custom">
  8. <el-tooltip class="item" effect="dark" :content="item.tip" placement="top-start" :disabled="!item.tip">
  9. <template v-if="item.type === `date` || item.type === `datetime`">
  10. <el-date-picker v-model="form[item.model]" :type="item.type" placeholder="选择择" format="yyyy-MM-dd" value-format="yyyy-MM-dd">
  11. </el-date-picker>
  12. </template>
  13. <template v-else-if="item.type === `year` || item.type === `week` || item.type === `day`">
  14. <el-date-picker
  15. v-model="form[item.model]"
  16. :type="item.type"
  17. placeholder="选择择"
  18. :format="`${item.type === 'year' ? 'yyyy' : item.type === 'week' ? 'MM' : 'dd'}`"
  19. :value-format="`${item.type === 'year' ? 'yyyy' : item.type === 'week' ? 'MM' : 'dd'}`"
  20. >
  21. </el-date-picker>
  22. </template>
  23. <template v-else-if="item.type === 'radio'">
  24. <el-radio-group v-model="form[item.model]" size="mini" v-bind="item.options">
  25. <slot name="radios" v-bind="{ item, form, fieldChange }"></slot>
  26. </el-radio-group>
  27. </template>
  28. <template v-else-if="item.type === 'checkbox'">
  29. <el-checkbox-group v-model="form[item.model]" v-bind="item.options">
  30. <slot name="checkboxs" v-bind="{ item, form, fieldChange }"></slot>
  31. </el-checkbox-group>
  32. </template>
  33. <template v-else-if="item.type === 'select'">
  34. <el-select v-model="form[item.model]" v-bind="item.options" filterable>
  35. <slot name="options" v-bind="{ item, form, fieldChange }"></slot>
  36. </el-select>
  37. </template>
  38. <template v-else-if="item.type === 'textarea'">
  39. <el-input v-model="form[item.model]" type="textarea" :autosize="{ minRows: 3, maxRows: 5 }"></el-input>
  40. </template>
  41. <template v-else-if="item.type === 'editor'">
  42. <wang-editor v-model="form[item.model]"></wang-editor>
  43. </template>
  44. <template v-else-if="item.type === 'text'">
  45. <el-row>
  46. <el-col :span="24">
  47. {{ form[item.model] }}
  48. </el-col>
  49. </el-row>
  50. </template>
  51. <template v-else>
  52. <el-input
  53. v-model="form[item.model]"
  54. :type="getField('type', item)"
  55. :placeholder="getField('placeholder', item)"
  56. :show-password="getField('type', item) === 'password'"
  57. v-bind="item.options"
  58. ></el-input>
  59. </template>
  60. </el-tooltip>
  61. </template>
  62. <template v-else>
  63. <slot name="custom" v-bind="{ item, form, fieldChange }"></slot>
  64. </template>
  65. </el-form-item>
  66. </template>
  67. </template>
  68. <el-form-item v-if="needSave" class="btn">
  69. <el-row type="flex" align="middle" justify="space-around">
  70. <el-col :span="6">
  71. <el-button type="primary" @click="save">{{ submitText }}</el-button>
  72. </el-col>
  73. </el-row>
  74. </el-form-item>
  75. <el-form-item v-else>
  76. <slot name="submit"></slot>
  77. </el-form-item>
  78. </el-form>
  79. </div>
  80. </template>
  81. <script>
  82. import _ from 'lodash';
  83. import wangEditor from '@frame/components/wang-editor';
  84. export default {
  85. name: 'add',
  86. props: {
  87. fields: { type: Array, default: () => [] },
  88. rules: { type: Object, default: () => {} },
  89. isNew: { type: Boolean, default: true },
  90. data: null,
  91. styles: { type: Object, default: () => {} },
  92. needSave: { type: Boolean, default: true },
  93. labelWidth: { type: String, default: '120px' },
  94. useEnter: { type: Boolean, default: true },
  95. submitText: { type: String, default: '保存' },
  96. },
  97. components: {
  98. wangEditor,
  99. },
  100. data: () => ({
  101. form: {},
  102. show: false,
  103. dateShow: false,
  104. loading: true,
  105. }),
  106. created() {
  107. if (this.useEnter) {
  108. document.onkeydown = () => {
  109. let key = window.event.keyCode;
  110. if (key == 13) {
  111. this.save();
  112. }
  113. };
  114. }
  115. },
  116. computed: {},
  117. mounted() {},
  118. watch: {
  119. fields: {
  120. handler(val) {
  121. this.checkType();
  122. },
  123. immediate: true,
  124. },
  125. data: {
  126. handler(val) {
  127. this.loading = true;
  128. if (val) this.$set(this, `form`, this.data);
  129. this.loading = false;
  130. },
  131. immediate: true,
  132. deep: true,
  133. },
  134. },
  135. methods: {
  136. getField(item, data) {
  137. let res = _.get(data, item, null);
  138. if (item === 'type') res = res === null ? `text` : res;
  139. if (item === 'placeholder') res = res === null ? `请输入${data.label}` : res;
  140. if (item === 'required') res = res === null ? false : res;
  141. if (item === `error`) res = res === null ? `${data.label}错误` : res;
  142. return res;
  143. },
  144. save() {
  145. this.$refs['form'].validate(valid => {
  146. if (valid) {
  147. this.$emit(`save`, { isNew: this.isNew, data: JSON.parse(JSON.stringify(this.form)) });
  148. this.$refs.form.resetFields();
  149. } else {
  150. console.warn('form validate error!!!');
  151. }
  152. });
  153. },
  154. fieldChange({ model, value }) {
  155. this.$set(this.form, model, value);
  156. },
  157. checkType() {
  158. let arr = this.fields.filter(fil => fil.type === 'checkbox');
  159. if (arr.length > 0 && this.isNew) {
  160. for (const item of arr) {
  161. this.$set(this.form, `${item.model}`, []);
  162. }
  163. }
  164. },
  165. display(field) {
  166. let dis = _.get(field, `display`);
  167. if (!_.isFunction(dis)) return true;
  168. else return dis(field, this.form);
  169. },
  170. },
  171. };
  172. </script>
  173. <style lang="less" scoped>
  174. .form {
  175. padding: 2rem 1rem;
  176. background: #fff;
  177. border-radius: 20px;
  178. }
  179. /deep/.btn .el-form-item__content {
  180. margin-left: 0 !important;
  181. }
  182. </style>