index.vue 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. <template>
  2. <ElForm :inline="false" :model="formInline" class="demo-form-inline" label-width="100px">
  3. <ElRow :gutter="20">
  4. <ElCol v-for="(field, index) in fields" :key="index" :md="span">
  5. <ElFormItem :label="field.label">
  6. <component v-if="field.type === 'input'" is="el-input" v-model="formInline[field.model]"
  7. :placeholder="field.placeholder" clearable class="el-inputs" />
  8. <component v-else-if="field.type === 'select'" is="el-select" v-model="formInline[field.model]"
  9. :placeholder="field.placeholder" clearable class="el-inputs" v-bind="field">
  10. <el-option v-for="(item, index) in field.options" :key="index" :label="item.label" :value="item.value" />
  11. </component>
  12. <component v-else-if="field.type === 'cascader'" is="el-cascader" v-model="formInline[field.model]"
  13. :options="field.options" :props="field.props" :placement="field.placement" filterable clearable @change="field.onChange"
  14. class="el-inputs" />
  15. <component v-else-if="field.type === 'date'" is="el-date-picker" v-model="formInline[field.model]"
  16. :type="field.dateType" range-separator="至" :start-placeholder="field.startplaceholder"
  17. format="YYYY-MM-DD HH:mm:ss" value-format="YYYY-MM-DD HH:mm:ss" time-format="HH:mm:ss"
  18. :end-placeholder="field.endplaceholder" clearable @change="field.onChange" />
  19. </ElFormItem>
  20. </ElCol>
  21. <ElCol :md="isOffset ? span : span / 2" :offset="btnOffset">
  22. <ElFormItem>
  23. <div class="flex j-end" style="width: 100%;">
  24. <el-button type="primary" @click="handleSearch">
  25. <template #icon>
  26. <SvgIcon name="i-ep:search" />
  27. </template>
  28. 查询
  29. </el-button>
  30. <el-button type="default" @click="handleReset">重置</el-button>
  31. </div>
  32. </ElFormItem>
  33. </ElCol>
  34. </ElRow>
  35. </ElForm>
  36. </template>
  37. <script lang="ts" setup>
  38. const props = withDefaults(defineProps<{
  39. fields: Array<{
  40. label: string; // 字段标签
  41. model: string; // v-model 绑定的字段名
  42. type: string; // 字段类型 ('input', 'select', 'cascader', 'date')
  43. placeholder?: string; // 占位符
  44. options?: Array<{ [key: string]: any }>; // 选项列表
  45. props?: any; // Cascader 组件的其他 props
  46. onChange?: (value: any) => void; // 变化事件
  47. dateType?: string; // 日期选择器类型
  48. [key: string]: any,
  49. }>; // 字段信息数组
  50. formInline: any; // 表单数据
  51. onSearch: () => void; // 查询事件
  52. onReset: () => void; // 重置事件
  53. span?: number;
  54. isOffset?: boolean; // 是否正规化按钮位置,而不是紧贴formItem后面
  55. }>(), {
  56. span: 8,
  57. isOffset: false,
  58. });
  59. const windowWidth = ref(window.innerWidth);
  60. onBeforeMount(() => {
  61. console.log(props)
  62. });
  63. onMounted(() => {
  64. window.addEventListener('resize', updateWindowWidth)
  65. });
  66. onUnmounted(() => {
  67. window.removeEventListener('resize', updateWindowWidth)
  68. });
  69. // 定义更新窗口宽度的函数
  70. const updateWindowWidth = () => {
  71. windowWidth.value = window.innerWidth;
  72. };
  73. // 计算按钮组的左侧偏移量
  74. const btnOffset = computed(() => {
  75. // 为了保持原有页面的样子
  76. if (!props.isOffset) return 0;
  77. // 因为栅格布局,代码使用的md,所以监听宽度
  78. if (windowWidth.value < 992) {
  79. return 0;
  80. }
  81. // 计算逻辑
  82. const items = props.fields.length;
  83. const columns = 24 / props.span; // 列布局
  84. const spanPerItem = props.span; // 每列的span
  85. const itemsOnLastRow = items % columns;
  86. if (itemsOnLastRow === 0) {
  87. // 如果刚好占满最后一行,按钮就需要另起一行,并偏移3个位置
  88. return (columns - 1) * spanPerItem;
  89. } else {
  90. // 如果最后一行没占满,计算需要空出的位置数量
  91. const emptySlots = columns - 1 - itemsOnLastRow;
  92. return emptySlots * spanPerItem;
  93. }
  94. });
  95. const handleSearch = () => {
  96. props.onSearch(); // 调用父组件的查询事件
  97. };
  98. const handleReset = () => {
  99. props.onReset(); // 调用父组件的重置事件
  100. };
  101. </script>
  102. <style lang="scss">
  103. .el-inputs {
  104. width: 100% !important;
  105. }
  106. </style>