index.vue 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. <!--
  2. * @Author: Gui
  3. * @Date: 2023-03-01 19:20:44
  4. * @LastEditors: guicheng 1625811865@qq.com
  5. * @LastEditTime: 2025-03-12 16:28:04
  6. * @Description: kxs files
  7. * @filePath:
  8. -->
  9. <script setup lang="ts">
  10. import { ref, watch } from "vue";
  11. import { useRenderIcon } from "@/components/ReIcon/src/hooks";
  12. import { ElMessage } from "element-plus";
  13. import Search from "@iconify-icons/ep/search";
  14. import Refresh from "@iconify-icons/ep/refresh";
  15. const props = defineProps({
  16. formData: {
  17. type: Object,
  18. default: () => {}
  19. },
  20. refresh: {
  21. type: Boolean,
  22. default: true
  23. },
  24. loading: {
  25. type: Boolean,
  26. default: false
  27. },
  28. size: {
  29. type: String,
  30. default: "default"
  31. },
  32. formWidth: {
  33. type: String,
  34. default: "!w-[230px]"
  35. },
  36. labelWidth: {
  37. type: String,
  38. default: "100px"
  39. },
  40. labelPosition: {
  41. type: String,
  42. default: "left"
  43. },
  44. searchAll: {
  45. type: Boolean,
  46. default: true
  47. },
  48. searchText: {
  49. type: String,
  50. default: "搜索"
  51. }
  52. });
  53. // 表单实例
  54. const formRef = ref();
  55. // 循环挂载每一个表单值
  56. const formState = ref({});
  57. // 传入的搜索方法
  58. const emit = defineEmits(["search"]);
  59. // 提交表单
  60. const onSearch = type => {
  61. // 对空值做处理
  62. const object = {};
  63. for (const key in formState.value) {
  64. if (Object.prototype.hasOwnProperty.call(formState.value, key)) {
  65. object[key] = formState.value[key] || "";
  66. }
  67. }
  68. if (type === "all") {
  69. // all类型表单提交
  70. formRef.value.resetFields();
  71. emit("search", {}, type);
  72. } else {
  73. // search类型表单提交并做表单校验
  74. formRef.value.validate(async valid => {
  75. if (valid) {
  76. emit("search", object, type);
  77. } else {
  78. //表单校验失败回调
  79. ElMessage({
  80. message: "请输入完整表单信息",
  81. type: "error"
  82. });
  83. }
  84. });
  85. }
  86. };
  87. // 格式化表单校验规则;
  88. const rules = ref({});
  89. watch(props.formData, () => {
  90. for (const key in props.formData) {
  91. if (Object.prototype.hasOwnProperty.call(props.formData, key)) {
  92. formState.value[key] = props.formData[key]["value"];
  93. const rule = props.formData[key]["rules"];
  94. if (rule) {
  95. rules.value[key] = rule;
  96. }
  97. }
  98. }
  99. });
  100. // 抛出当前组件表单实例
  101. defineExpose(
  102. new Proxy(
  103. {},
  104. {
  105. get(_target, prop) {
  106. return formRef.value?.[prop];
  107. },
  108. has(_target, prop) {
  109. return prop in formRef.value;
  110. }
  111. }
  112. )
  113. );
  114. </script>
  115. <template>
  116. <div class="bg-bg_color pl-8 pt-4 pr-8">
  117. <el-form
  118. :inline="true"
  119. :model="formState"
  120. :label-position="labelPosition"
  121. :label-width="labelWidth"
  122. class="w-[99/100]"
  123. ref="formRef"
  124. :rules="rules"
  125. >
  126. <template v-for="(value, key, i) in formData" :key="i">
  127. <el-form-item :label="value.label" :prop="key">
  128. <el-input
  129. v-if="value.type === 'input' || value.type === ''"
  130. v-model="formState[key]"
  131. :placeholder="`请输入${value.label}`"
  132. clearable
  133. :size="size"
  134. :class="formWidth"
  135. />
  136. <el-select
  137. v-if="value.type === 'select'"
  138. v-model="formState[key]"
  139. :placeholder="`请选择${value.label}`"
  140. :size="size"
  141. :multiple="value.disposition?.multiple || false"
  142. clearable
  143. :class="formWidth"
  144. >
  145. <el-option
  146. v-for="item in value.options"
  147. :key="item.value"
  148. :label="item.label"
  149. :value="item.value"
  150. />
  151. </el-select>
  152. <el-date-picker
  153. v-if="value.type === 'picker'"
  154. v-model="formState[key]"
  155. :type="value.disposition?.type || 'datetime'"
  156. :placeholder="`请选择${value.label}`"
  157. :range-separator="value.disposition['range-separator'] || '-'"
  158. :start-placeholder="
  159. value.disposition['start-placeholder'] || '开始时间'
  160. "
  161. :end-placeholder="
  162. value.disposition['end-placeholder'] || '结束时间'
  163. "
  164. clearable
  165. :class="formWidth"
  166. />
  167. <el-input-number
  168. v-if="value.type === 'number'"
  169. v-model="formState[key]"
  170. :min="1"
  171. :max="10"
  172. />
  173. </el-form-item>
  174. </template>
  175. <el-form-item>
  176. <el-button
  177. type="primary"
  178. :icon="useRenderIcon(Search)"
  179. :loading="loading"
  180. @click="onSearch('search')"
  181. >{{ searchText }}</el-button
  182. >
  183. </el-form-item>
  184. <el-form-item v-if="searchAll">
  185. <el-button
  186. type="primary"
  187. :icon="useRenderIcon(Refresh)"
  188. :loading="loading"
  189. @click="onSearch('all')"
  190. >全部</el-button
  191. >
  192. </el-form-item>
  193. </el-form>
  194. </div>
  195. </template>
  196. <style scoped></style>