index.vue 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. <template>
  2. <v-form ref="formRef" v-model="valid" class="login-form" @submit.prevent>
  3. <div>
  4. <v-row dense no-gutters class="justify-space-between">
  5. <template v-for="(item) in props.items.options">
  6. <slot :name="item.prevSlot"></slot>
  7. <v-col :key="item.key" v-if="!item.hide" :cols="item.col || '12'" class="position">
  8. <template v-if="item.slotTitle">
  9. <div :class="item.class" :style="item.slotTitleStyle">{{ item.slotTitle }}</div>
  10. </template>
  11. <div class="d-flex mb-2" :class="item.flexStyle || 'flex-row'">
  12. <!-- <span>{{ item.value }}</span> -->
  13. <textUI
  14. v-if="['text', 'password', 'number', 'phoneNumber'].includes(item.type)"
  15. v-model="item.value"
  16. :item="item"
  17. @blur="item.blur"
  18. @change="handleChange(item)"
  19. @appendInnerClick="item.appendInnerClick"
  20. ></textUI>
  21. <autocompleteUI
  22. v-if="item.type === 'autocomplete'"
  23. v-model="item.value"
  24. :item="item"
  25. @search="v => item.search ? item.search(v) : null"
  26. @change="handleChange(item)"
  27. ></autocompleteUI>
  28. <comboboxUI
  29. v-if="item.type === 'combobox'"
  30. v-model="item.value"
  31. :item="item"
  32. @search="v => item.search ? item.search(v) : null"
  33. @change="handleChange(item)"
  34. ></comboboxUI>
  35. <!-- comboboxZhAndEnUI暂不可用 -->
  36. <!-- <comboboxZhAndEnUI
  37. v-if="item.type === 'comboboxZhAndEn'"
  38. v-model="item.value"
  39. :item="item"
  40. @search="v => item.search ? item.search(v) : null"
  41. @change="handleChange(item)"
  42. ></comboboxZhAndEnUI> -->
  43. <radioGroupUI
  44. v-if="item.type === 'ifRadio'"
  45. v-model="item.value"
  46. :item="item"
  47. @change="handleChange(item)"
  48. ></radioGroupUI>
  49. <checkboxUI
  50. v-if="item.type === 'checkbox'"
  51. v-model="item.value"
  52. :item="item"
  53. @change="handleChange(item)"
  54. ></checkboxUI>
  55. <textareaUI
  56. v-if="item.type === 'textarea'"
  57. v-model="item.value"
  58. :item="item"
  59. @blur="item.blur"
  60. @change="handleChange(item)"
  61. ></textareaUI>
  62. <cascadeUI
  63. v-if="item.type === 'cascade'"
  64. v-model="item.value"
  65. :item="item"
  66. ref="cascadeRef"
  67. @change="handleChange(item)"
  68. ></cascadeUI>
  69. <datePickerUI
  70. v-if="item.type === 'datePicker'"
  71. v-model="item.value"
  72. :item="item"
  73. @change="handleChange(item)"
  74. ></datePickerUI>
  75. <wangEditorUI
  76. v-if="item.type === 'wangEditor'"
  77. v-model="item.value"
  78. :item="item"
  79. @change="handleChange(item)"
  80. ></wangEditorUI>
  81. <areaSelectUI
  82. v-if="item.type === 'areaSelect'"
  83. v-model="item.value"
  84. :item="item"
  85. @change="handleChange(item)"
  86. ></areaSelectUI>
  87. <DatePicker v-if="item.type === 'vueDatePicker'" v-model="item.value" :options="item.options" :width="item.width" :class="item.class"></DatePicker>
  88. <v-file-input
  89. v-if="item.type === 'upload'"
  90. :prepend-icon="item.prependIcon || ''"
  91. :append-icon="item.appendIcon"
  92. :append-outer-icon="item.appendOuterIcon"
  93. :show-size="item.showSize"
  94. variant="outlined"
  95. density="compact"
  96. v-model="item.value"
  97. :placeholder="item.placeholder || item.label"
  98. :hint="item.hint"
  99. :rules="item.rules"
  100. :label="item.label"
  101. color="primary"
  102. :persistent-hint="item.persistentHint"
  103. :loading= "item.loading"
  104. :disabled="item.disabled"
  105. :multiple="item.multiple"
  106. :success="item.success"
  107. :error="item.error"
  108. :accept="item.accept || '.xlsx, .xls, .csv, .pdf, .txt, .doc'"
  109. @change="handleChange(item)"
  110. >
  111. <template v-if="item.selfAppend" #append>
  112. <slot :name="item.selfAppend" :data="item.value"></slot>
  113. </template>
  114. </v-file-input>
  115. <template v-if="item.slotName">
  116. <slot :name="item.slotName" :item="item"></slot>
  117. </template>
  118. </div>
  119. </v-col>
  120. </template>
  121. </v-row>
  122. </div>
  123. <slot></slot>
  124. </v-form>
  125. </template>
  126. <script setup>
  127. defineOptions({ name:'components-ct-form'})
  128. import textUI from './../FormUI/TextInput'
  129. import autocompleteUI from './../FormUI/autocomplete'
  130. import comboboxUI from './../FormUI/combobox'
  131. // import comboboxZhAndEnUI from './../FormUI/comboboxZhAndEn'
  132. import radioGroupUI from './../FormUI/radioGroup'
  133. import checkboxUI from './../FormUI/checkbox'
  134. import textareaUI from './../FormUI/textArea'
  135. import cascadeUI from './../FormUI/cascade'
  136. import datePickerUI from './../FormUI/datePicker'
  137. import DatePicker from '@/components/DatePicker'
  138. import wangEditorUI from './../FormUI/wangEditor'
  139. import areaSelectUI from './../FormUI/areaSelect'
  140. import { ref } from 'vue'
  141. const emit = defineEmits(['change', 'inputUpdateAutocomplete'])// 定义一个或多个自定义事件
  142. const props = defineProps({items: Object})
  143. const valid = ref(false)
  144. const formRef = ref()
  145. const handleChange = (item) => {
  146. // console.log('handleChange', item)
  147. if (item.type === 'date' && item.value) item.option.validate = false
  148. let selectObj = {}
  149. if (item.returnSelect && item.items?.length) {
  150. selectObj = item.items.find(e => e[item.itemValue || 'value'] === item.value)
  151. }
  152. if (item?.change) item.change(item.value, item, selectObj)
  153. emit('change', false)
  154. }
  155. // const isValid = ref(true)
  156. // const validateTime = () => {
  157. // isValid.value = true
  158. // props.items.options.forEach((e) => {
  159. // if (e.type !== 'date' || e.hide || !e.rules) return
  160. // const rules = e.rules[0]
  161. // const check = rules(e.value)
  162. // if (typeof check === 'string') {
  163. // isValid.value = false
  164. // e.option.error = true
  165. // e.option.errorMsg = check
  166. // } else {
  167. // e.option.error = false
  168. // e.option.errorMsg = null
  169. // }
  170. // })
  171. // }
  172. const cascadeRef = ref()
  173. const validateCascade = () => {
  174. let cascadeValid = true
  175. if (cascadeRef.value && Array.isArray(cascadeRef.value) && cascadeRef.value?.length) {
  176. cascadeRef.value.forEach(ref => {
  177. const txt = ref?.handleBlur()
  178. if (txt) cascadeValid = false
  179. })
  180. }
  181. return cascadeValid
  182. }
  183. const validate = async () => {
  184. const form = await formRef.value.validate()
  185. // const time = validateTime()
  186. const cascade = validateCascade()
  187. return form && cascade
  188. }
  189. defineExpose({
  190. validate,
  191. formRef
  192. })
  193. </script>
  194. <style lang="scss" scoped>
  195. .position {
  196. position: relative;
  197. }
  198. .label {
  199. font-size: 14px;
  200. color: rgba(0, 0, 0, .6);
  201. }
  202. </style>