index.vue 8.6 KB

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