WidgetConfig.vue 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. <template>
  2. <div class="widget-config">
  3. <el-form label-suffix=":" v-if="this.data && Object.keys(this.data).length > 0" labelPosition="left" labelWidth="90px" size="small">
  4. <el-collapse v-model="collapse">
  5. <el-collapse-item name="1" title="基本属性">
  6. <el-form-item label="类型" v-if="data.type && !data.component">
  7. <el-select v-model="data.type" style="width: 100%" placeholder="请选择类型" @change="handleChangeType">
  8. <el-option-group v-for="group in fields" :key="group.title" :label="group.title">
  9. <el-option v-for="item in group.list" :key="item.type" :label="item.label" :value="item.type"> </el-option>
  10. </el-option-group>
  11. </el-select>
  12. </el-form-item>
  13. <el-form-item label="属性值">
  14. <el-input v-model="data.prop" clearable placeholder="属性值"></el-input>
  15. </el-form-item>
  16. <el-form-item label="标题">
  17. <el-input v-model="data.label" clearable placeholder="标题"></el-input>
  18. </el-form-item>
  19. <el-form-item label="标题宽度" v-if="!['group', 'dynamic', 'title'].includes(data.type)">
  20. <el-input-number
  21. v-model="data.labelWidth"
  22. :min="80"
  23. :step="10"
  24. controls-position="right"
  25. placeholder="标签宽度"
  26. style="width: 100%"
  27. ></el-input-number>
  28. </el-form-item>
  29. <el-form-item label="标签位置" v-if="!data.subfield">
  30. <el-select v-model="data.labelPosition" placeholder="标签位置" clearable>
  31. <el-option label="上" value="top"></el-option>
  32. <el-option label="左" value="left"></el-option>
  33. <el-option label="右" value="right"></el-option>
  34. </el-select>
  35. </el-form-item>
  36. <el-form-item label="宽度" v-if="data.subfield">
  37. <el-input-number style="width: 100%" v-model="data.width" controls-position="right" placeholder="宽度" :min="100"></el-input-number>
  38. </el-form-item>
  39. <el-form-item label="表单栅格" v-if="!data.subfield && !['group'].includes(data.type)">
  40. <el-input-number style="width: 100%" v-model="data.span" controls-position="right" placeholder="表单栅格" :min="2" :max="24"></el-input-number>
  41. </el-form-item>
  42. <el-form-item
  43. label="数据类型"
  44. v-if="
  45. ['cascader', 'checkbox', 'radio', 'select', 'tree', 'upload', 'img', 'array', 'slider', 'timerange', 'daterange', 'datetimerange'].includes(
  46. data.type
  47. )
  48. "
  49. >
  50. <template slot="label">
  51. <el-link :underline="false" href="https://avuejs.com/docs/datatype.html" target="_blank">数据类型 <i class="el-icon-question"></i></el-link>
  52. </template>
  53. <el-select v-model="data.dataType" placeholder="数据类型" clearable>
  54. <el-option label="String" value="string"></el-option>
  55. <el-option label="Number" value="number"></el-option>
  56. <el-option label="Array" value="array"></el-option>
  57. </el-select>
  58. </el-form-item>
  59. <el-form-item label="字段提示">
  60. <template slot="label">
  61. <el-link :underline="false" href="https://avuejs.com/form/form-tip.html" target="_blank">字段提示 <i class="el-icon-question"></i></el-link>
  62. </template>
  63. <el-input v-model="data.tip" clearable placeholder="字段提示"></el-input>
  64. </el-form-item>
  65. <el-form-item v-if="data.tip && !['upload'].includes(data.type)" label="字段提示位置" label-width="110px">
  66. <el-select v-model="data.tipPlacement" placeholder="字段提示位置" clearable>
  67. <el-option label="上" value="top"></el-option>
  68. <el-option label="下" value="bottom"></el-option>
  69. <el-option label="左" value="left"></el-option>
  70. <el-option label="右" value="right"></el-option>
  71. </el-select>
  72. </el-form-item>
  73. <el-form-item label="标题提示">
  74. <template slot="label">
  75. <el-link :underline="false" href="https://avuejs.com/form/form-tip.html" target="_blank">标题提示 <i class="el-icon-question"></i></el-link>
  76. </template>
  77. <el-input v-model="data.labelTip" clearable placeholder="标题提示"></el-input>
  78. </el-form-item>
  79. <el-form-item v-if="data.labelTip && !['upload'].includes(data.type)" label="标题提示位置" label-width="110px">
  80. <el-select v-model="data.labelTipPlacement" placeholder="标题提示位置" clearable>
  81. <el-option label="上" value="top"></el-option>
  82. <el-option label="下" value="bottom"></el-option>
  83. <el-option label="左" value="left"></el-option>
  84. <el-option label="右" value="right"></el-option>
  85. </el-select>
  86. </el-form-item>
  87. <el-form-item v-if="!['color', 'dynamic', 'group', 'ueditor', 'upload', 'map'].includes(data.type)" label="默认值">
  88. <template v-if="defaultValues && defaultValues[data.type]">
  89. <el-select v-model="data.value" allow-create clearable filterable placeholder="默认值">
  90. <el-option v-for="item in defaultValues[data.type]" :key="item.value" :label="item.label" :value="item.value"> </el-option>
  91. </el-select>
  92. </template>
  93. <template v-else>
  94. <el-input v-model="data.value" clearable placeholder="默认值"></el-input>
  95. </template>
  96. </el-form-item>
  97. <el-form-item label="详情模式">
  98. <el-switch v-model="data.detail"></el-switch>
  99. </el-form-item>
  100. <el-form-item label="是否只读">
  101. <el-switch v-model="data.readonly"></el-switch>
  102. </el-form-item>
  103. <el-form-item label="是否禁用">
  104. <el-switch v-model="data.disabled"></el-switch>
  105. </el-form-item>
  106. <el-form-item label="是否可见">
  107. <el-switch v-model="data.display"></el-switch>
  108. </el-form-item>
  109. <el-form-item label="是否必填">
  110. <el-switch v-model="data.required"></el-switch>
  111. <el-input v-if="data.required" v-model.lazy="data.pattern" placeholder="正则表达式"></el-input>
  112. </el-form-item>
  113. </el-collapse-item>
  114. <el-collapse-item name="2" title="组件属性">
  115. <component :is="getComponent" :data="data" :default-values="defaultValues"></component>
  116. </el-collapse-item>
  117. <el-collapse-item name="3" title="事件属性" v-if="!['group'].includes(data.type)">
  118. <config-event :data="data"></config-event>
  119. </el-collapse-item>
  120. </el-collapse>
  121. </el-form>
  122. <avue-empty v-else desc="拖拽字段进行配置" style="margin-top: 100%"></avue-empty>
  123. </div>
  124. </template>
  125. <script>
  126. import fields from './fieldsConfig.js'
  127. const dateArr = ['year', 'month', 'week', 'date', 'datetime', 'time', 'daterange', 'timerange', 'datetimerange', 'dates']
  128. export default {
  129. name: 'widget-config',
  130. props: ['data', 'defaultValues'],
  131. computed: {
  132. getComponent() {
  133. const prefix = 'config-'
  134. const { type, component } = this.data
  135. if ((!type || component) && type != 'ueditor') return prefix + 'custom'
  136. let result = 'input'
  137. if ([undefined, 'input', 'password', 'url'].includes(type)) result = 'input'
  138. else if (dateArr.includes(type)) result = 'date'
  139. else if (['array', 'img'].includes(type)) result = 'array'
  140. else if (['tree', 'cascader'].includes(type)) result = 'tree'
  141. else if (['radio', 'checkbox', 'select'].includes(type)) result = 'select'
  142. else result = type
  143. return prefix + result
  144. },
  145. },
  146. watch: {
  147. 'data.required'(val) {
  148. if (val) this.validator.required = { required: true, message: `${this.data.label}必须填写` }
  149. else this.validator.required = null
  150. this.generateRule()
  151. },
  152. 'data.pattern'(val) {
  153. if (val) this.validator.pattern = { pattern: new RegExp(val), message: `${this.data.label}格式不匹配` }
  154. else this.validator.pattern = null
  155. this.generateRule()
  156. },
  157. },
  158. data() {
  159. return {
  160. fields,
  161. collapse: ['1', '2', '3'],
  162. validator: {
  163. type: null,
  164. required: null,
  165. pattern: null,
  166. length: null,
  167. },
  168. }
  169. },
  170. methods: {
  171. handleChangeType(type) {
  172. if (!type) return
  173. const config = this.fields.find((f) => f.list.find((l) => l.type == type))
  174. if (!config) return
  175. for (let key in config) {
  176. if (config && Object.prototype.hasOwnProperty.call(config, key) && !['icon', 'label', 'span'].includes(key)) this.data[key] = config[key]
  177. }
  178. },
  179. generateRule() {
  180. const rules = []
  181. Object.keys(this.validator).forEach((key) => {
  182. if (this.validator[key]) rules.push(this.validator[key])
  183. })
  184. if (rules.length == 0) delete this.data.rules
  185. else this.data.rules = rules
  186. },
  187. },
  188. }
  189. </script>