index.vue 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  1. <template>
  2. <div class="by-form">
  3. <el-form
  4. :model="formData"
  5. :label-width="formOption.labelWidth"
  6. :inline="formOption.inline || false"
  7. :rules="rules"
  8. :labelPosition="formOption.labelPosition || 'top'"
  9. ref="byForm"
  10. >
  11. <el-form-item
  12. :label="i.label"
  13. v-for="i in formConfig"
  14. :key="i.model"
  15. :prop="i.prop"
  16. :style="
  17. i.type == 'title' ? 'width:100%' :
  18. i.itemWidth
  19. ? 'width:' + i.itemWidth + '%'
  20. : formOption.itemWidth
  21. ? 'width:' + formOption.itemWidth + '%'
  22. : '100%'
  23. "
  24. :class="i.isHide ? 'dn' : ''"
  25. >
  26. <el-input
  27. v-if="i.type == 'input'"
  28. v-model="formData[i.prop]"
  29. :placeholder="i.placeholder || '请输入'"
  30. @input="((e)=>commonsEmit(e,i))"
  31. :type="i.itemType ? i.itemType : 'text'"
  32. :disabled="i.disabled ? i.disabled : false"
  33. :max="i.max"
  34. :min="i.min"
  35. :maxlength="i.maxlength"
  36. />
  37. <el-select
  38. v-model="formData[i.prop]"
  39. :multiple="i.multiple || false"
  40. v-else-if="i.type == 'select'"
  41. :placeholder="i.placeholder || '请选择'"
  42. @change="((e)=>commonsEmit(e,i))"
  43. :disabled="i.disabled ? i.disabled : false"
  44. :style="i.style"
  45. >
  46. <el-option :label="j.title || j.name || j.label" :value="j.id || j.value" v-for="j in i.data" :key="j.id">
  47. </el-option>
  48. </el-select>
  49. <el-tree-select
  50. v-model="formData[i.prop]"
  51. v-else-if="i.type == 'treeSelect'"
  52. :data="i.data"
  53. :props="{ value: 'id', label: 'label', children: 'children' }"
  54. value-key="id"
  55. :placeholder="i.placeholder || '请选择'"
  56. check-strictly
  57. />
  58. <el-date-picker
  59. v-model="formData[i.prop]"
  60. v-else-if="i.type == 'date'"
  61. :type="i.itemType"
  62. :placeholder="i.placeholder || '请选择时间'"
  63. @change="commonsEmit"
  64. :disabled="i.disabled ? i.disabled : false"
  65. :format="i.format ? i.format : dateFormatInit(i.itemType)"
  66. :value-format="i.format ? i.format : dateFormatInit(i.itemType)"
  67. />
  68. <el-switch
  69. :disabled="i.disabled ? i.disabled : false"
  70. v-else-if="i.type == 'switch'"
  71. v-model="formData[i.prop]"
  72. />
  73. <el-checkbox-group
  74. v-else-if="i.type == 'checkbox'"
  75. v-model="formData[i.prop]"
  76. :disabled="i.disabled ? i.disabled : false"
  77. >
  78. <el-checkbox v-for="j in i.data" :key="j.id || j.value" ::label="j.id || j.value" name="type">
  79. {{ j.name || j.label }}
  80. </el-checkbox>
  81. </el-checkbox-group>
  82. <el-radio-group
  83. v-else-if="i.type == 'radio'"
  84. v-model="formData[i.prop]"
  85. :disabled="i.disabled ? i.disabled : false"
  86. >
  87. <el-radio
  88. :border="i.border ? i.border : false"
  89. v-for="j in i.data" :key="j.id || j.value" :label="j.id || j.value" name="type"
  90. >
  91. {{ j.name || j.label }}
  92. </el-radio>
  93. </el-radio-group>
  94. <el-input-number
  95. v-else-if="i.type == 'number'"
  96. v-model="formData[i.prop]"
  97. :placeholder="i.placeholder || '请输入'"
  98. @input="commonsEmit"
  99. :disabled="i.disabled ? i.disabled : false"
  100. :min="i.min ? i.min : 0"
  101. :max="i.max ? i.max : 100"
  102. :step="i.step ? i.step : 1">
  103. </el-input-number>
  104. <el-tree
  105. v-else-if="i.type == 'tree'"
  106. :data="i.data"
  107. :props="i.props"
  108. :show-checkbox="i.showCheckbox || true"
  109. >
  110. </el-tree>
  111. <el-cascader
  112. v-else-if="i.type == 'cascader'"
  113. :options="i.data"
  114. :props="i.props"
  115. :placeholder="i.placeholder || '请选择'"
  116. @change="commonsEmit"
  117. :disabled="i.disabled ? i.disabled : false"
  118. :style="i.style">
  119. </el-cascader>
  120. <div class="form-title" v-else-if="i.type == 'title'">
  121. {{ i.title }}
  122. </div>
  123. <slot
  124. :name="i.slotName"
  125. v-else-if="i.type == 'slot'">
  126. {{i.slotName}}插槽占位符
  127. </slot>
  128. </el-form-item>
  129. </el-form>
  130. </div>
  131. </template>
  132. <script setup>
  133. import { set } from '@vueuse/shared'
  134. import { reactive } from 'vue'
  135. defineProps({
  136. modelValue: {
  137. type: Object,
  138. default: false,
  139. },
  140. formConfig: {
  141. type: Array,
  142. default: false,
  143. },
  144. disabled: {
  145. type: Boolean,
  146. default: false,
  147. },
  148. formOption: {
  149. type: Object,
  150. default: false,
  151. },
  152. rules: {
  153. type: Object,
  154. default: false,
  155. },
  156. })
  157. const isInit = ref(false)
  158. const { proxy } = getCurrentInstance()
  159. const emit = defineEmits(['update:modelValue'])
  160. const formData = computed(() => {
  161. return proxy.modelValue
  162. })
  163. const formDataReset = ref({...proxy.modelValue})
  164. const commonsEmit = (prop,item) => {
  165. if(item.fn) {
  166. item.fn(prop)
  167. }
  168. emit('update:modelValue', formData.value)
  169. }
  170. const loadInit = () => {
  171. const v = this
  172. for (let i = 0; i < proxy.formConfig.length; i++) {
  173. const element = proxy.formConfig[i]
  174. if (element.isLoad) {
  175. commonGetdata(element.isLoad, i)
  176. }
  177. }
  178. }
  179. const dateFormatInit = ((itemType) => {
  180. const formatObj = {
  181. year:"YYYY",
  182. month:"YYYY-MM",
  183. date:"YYYY-MM-DD hh:mm:ss",
  184. dates:'YYYY-MM-DD',
  185. datetime:"YYYY-MM-DD hh:mm:ss",
  186. monthrange:"YYYY-MM-DD hh:mm:ss",
  187. datetimerange:"YYYY-MM-DD hh:mm:ss",
  188. daterange:"YYYY-MM-DD hh:mm:ss",
  189. }
  190. return formatObj[itemType]
  191. })
  192. //公用递归,保证key,val统一
  193. const commonRecursive = (arr, labelKey, labelVal, childrenName) => {
  194. for (let i = 0; i < arr.length; i++) {
  195. console.log(arr[i])
  196. if(labelKey == 'stringArray'){
  197. arr[i] = {
  198. label:arr[i],
  199. value:arr[i],
  200. id:arr[i],
  201. title:arr[i],
  202. }
  203. }else{
  204. arr[i].title = arr[i].label = arr[i][labelKey]
  205. arr[i].id = arr[i].value = arr[i][labelVal]
  206. }
  207. if (childrenName) {
  208. arr[i].children = arr[i][childrenName]
  209. }
  210. arr[i].checked = false
  211. typeof arr[i][labelVal] == String
  212. ? (arr[i].key = arr[i][labelVal])
  213. : (arr[i].key = JSON.stringify(arr[i][labelVal]))
  214. if (childrenName) {
  215. this.commonRecursive(
  216. arr[i][childrenName],
  217. labelKey,
  218. labelVal,
  219. childrenName
  220. )
  221. }
  222. }
  223. }
  224. //请求form表单所需数据字典
  225. const commonGetdata = (isLoad,i) => {
  226. proxy[isLoad.method](isLoad.url,isLoad.req).then(message=>{
  227. console.log(message)
  228. if (getFormat(isLoad.resUrl, message) == undefined) {
  229. console.log('请查看isLoad配置是否正确url:' + isLoad.url)
  230. return
  231. }
  232. proxy.formConfig[i].data = getFormat(isLoad.resUrl, message)
  233. if (isLoad.labelKey) {
  234. commonRecursive(
  235. proxy.formConfig[i].data,
  236. isLoad.labelKey,
  237. isLoad.labelVal,
  238. isLoad.childrenName
  239. )
  240. }
  241. console.log(proxy.formConfig[i].data)
  242. })
  243. }
  244. //根据resurl获取数据
  245. const getFormat = (formatStr, props) => {
  246. if(!formatStr) return props
  247. return formatStr
  248. .split('.')
  249. .reduce((total, cur) => (!total ? '' : total[cur]), props)
  250. }
  251. //初始化所有表单
  252. const formDataInit = () => {
  253. var map = {
  254. input: '',
  255. radio: null,
  256. select: null,
  257. checkbox: [],
  258. date: '',
  259. datetime: '',
  260. daterange: [],
  261. datetimerange: [],
  262. year: null,
  263. month: null,
  264. switch: false,
  265. inputNumber: 0,
  266. cascader: [],
  267. Solt: null,
  268. Transfer: [],
  269. Upload: { path: null, id: null, name: null },
  270. password:'',
  271. treeSelect:'',
  272. }
  273. const formDataCopy = { ...formData.value }
  274. for (let i = 0; i < proxy.formConfig.length; i++) {
  275. const element = proxy.formConfig[i]
  276. if(formDataCopy[element.prop] || element.type === 'slot') {
  277. break;
  278. }
  279. if(map[element.itemType] != undefined){
  280. formData.value[element.prop] = map[element.itemType]
  281. }else{
  282. formData.value[element.prop] = element.multiple ? [] : map[element.type]
  283. }
  284. }
  285. emit('update:modelValue', formData.value)
  286. }
  287. const handleSubmit = (onSubmit) => {
  288. proxy.$refs['byForm'].validate((valid) => {
  289. if (valid) {
  290. onSubmit()
  291. } else {
  292. ElMessage({
  293. message: '请检查表单',
  294. type: 'warning',
  295. })
  296. }
  297. })
  298. }
  299. const byform = ref(null) // 延迟使用,因为还没有返回跟挂载
  300. onMounted(()=>{
  301. })
  302. defineExpose({
  303. handleSubmit,
  304. })
  305. formDataInit()
  306. loadInit()
  307. </script>
  308. <style>
  309. .form-title {
  310. font-size: 14px;
  311. font-weight: bold;
  312. margin-top: 22px;
  313. color: #333333;
  314. }
  315. .by-form .el-form--inline .el-form-item {
  316. margin-right: 0px;
  317. padding-right: 32px;
  318. box-sizing: border-box;
  319. }
  320. .dn{
  321. display: none!important;
  322. }
  323. </style>