Browse Source

feat(data-form): 优化表单布局和响应式功能

- 新增 formRows 计算属性,实现表单项的自动换行和布局优化
- 增加 submit 区域的自适应布局,优化表单末尾的样式
- 完善响应式断点监听,实现 columnCount 的动态调整
- 添加 loading 状态的监听和传递
- 优化表单数据的处理和上下文数据的设置
master
lizw-2015 7 months ago
parent
commit
b806b78f6b
  1. 19
      pnpm-lock.yaml
  2. 95
      src/components/data-form/DataForm.vue

19
pnpm-lock.yaml

@ -8,16 +8,16 @@ importers:
.:
dependencies:
'@vueuse/core':
specifier: ^13.2.0
version: 13.2.0(vue@3.5.14(typescript@5.8.3))
devDependencies:
'@ease-forge/runtime':
specifier: ^1.0.12
version: 1.0.12(typescript@5.8.3)
'@ease-forge/shared':
specifier: ^1.0.12
version: 1.0.12
'@vueuse/core':
specifier: ^13.2.0
version: 13.2.0(vue@3.5.14(typescript@5.8.3))
devDependencies:
'@element-plus/icons-vue':
specifier: ^2.3.1
version: 2.3.1(vue@3.5.14(typescript@5.8.3))
@ -570,56 +570,67 @@ packages:
resolution: {integrity: sha512-46OzWeqEVQyX3N2/QdiU/CMXYDH/lSHpgfBkuhl3igpZiaB3ZIfSjKuOnybFVBQzjsLwkus2mjaESy8H41SzvA==}
cpu: [arm]
os: [linux]
libc: [glibc]
'@rollup/rollup-linux-arm-musleabihf@4.41.0':
resolution: {integrity: sha512-lfgW3KtQP4YauqdPpcUZHPcqQXmTmH4nYU0cplNeW583CMkAGjtImw4PKli09NFi2iQgChk4e9erkwlfYem6Lg==}
cpu: [arm]
os: [linux]
libc: [musl]
'@rollup/rollup-linux-arm64-gnu@4.41.0':
resolution: {integrity: sha512-nn8mEyzMbdEJzT7cwxgObuwviMx6kPRxzYiOl6o/o+ChQq23gfdlZcUNnt89lPhhz3BYsZ72rp0rxNqBSfqlqw==}
cpu: [arm64]
os: [linux]
libc: [glibc]
'@rollup/rollup-linux-arm64-musl@4.41.0':
resolution: {integrity: sha512-l+QK99je2zUKGd31Gh+45c4pGDAqZSuWQiuRFCdHYC2CSiO47qUWsCcenrI6p22hvHZrDje9QjwSMAFL3iwXwQ==}
cpu: [arm64]
os: [linux]
libc: [musl]
'@rollup/rollup-linux-loongarch64-gnu@4.41.0':
resolution: {integrity: sha512-WbnJaxPv1gPIm6S8O/Wg+wfE/OzGSXlBMbOe4ie+zMyykMOeqmgD1BhPxZQuDqwUN+0T/xOFtL2RUWBspnZj3w==}
cpu: [loong64]
os: [linux]
libc: [glibc]
'@rollup/rollup-linux-powerpc64le-gnu@4.41.0':
resolution: {integrity: sha512-eRDWR5t67/b2g8Q/S8XPi0YdbKcCs4WQ8vklNnUYLaSWF+Cbv2axZsp4jni6/j7eKvMLYCYdcsv8dcU+a6QNFg==}
cpu: [ppc64]
os: [linux]
libc: [glibc]
'@rollup/rollup-linux-riscv64-gnu@4.41.0':
resolution: {integrity: sha512-TWrZb6GF5jsEKG7T1IHwlLMDRy2f3DPqYldmIhnA2DVqvvhY2Ai184vZGgahRrg8k9UBWoSlHv+suRfTN7Ua4A==}
cpu: [riscv64]
os: [linux]
libc: [glibc]
'@rollup/rollup-linux-riscv64-musl@4.41.0':
resolution: {integrity: sha512-ieQljaZKuJpmWvd8gW87ZmSFwid6AxMDk5bhONJ57U8zT77zpZ/TPKkU9HpnnFrM4zsgr4kiGuzbIbZTGi7u9A==}
cpu: [riscv64]
os: [linux]
libc: [musl]
'@rollup/rollup-linux-s390x-gnu@4.41.0':
resolution: {integrity: sha512-/L3pW48SxrWAlVsKCN0dGLB2bi8Nv8pr5S5ocSM+S0XCn5RCVCXqi8GVtHFsOBBCSeR+u9brV2zno5+mg3S4Aw==}
cpu: [s390x]
os: [linux]
libc: [glibc]
'@rollup/rollup-linux-x64-gnu@4.41.0':
resolution: {integrity: sha512-XMLeKjyH8NsEDCRptf6LO8lJk23o9wvB+dJwcXMaH6ZQbbkHu2dbGIUindbMtRN6ux1xKi16iXWu6q9mu7gDhQ==}
cpu: [x64]
os: [linux]
libc: [glibc]
'@rollup/rollup-linux-x64-musl@4.41.0':
resolution: {integrity: sha512-m/P7LycHZTvSQeXhFmgmdqEiTqSV80zn6xHaQ1JSqwCtD1YGtwEK515Qmy9DcB2HK4dOUVypQxvhVSy06cJPEg==}
cpu: [x64]
os: [linux]
libc: [musl]
'@rollup/rollup-win32-arm64-msvc@4.41.0':
resolution: {integrity: sha512-4yodtcOrFHpbomJGVEqZ8fzD4kfBeCbpsUy5Pqk4RluXOdsWdjLnjhiKy2w3qzcASWd04fp52Xz7JKarVJ5BTg==}

95
src/components/data-form/DataForm.vue

@ -1,6 +1,6 @@
<script setup lang="ts">
import lodash from "lodash";
import { getCurrentInstance, reactive } from "vue";
import { computed, getCurrentInstance, onMounted, reactive, watch } from "vue";
import { breakpointsTailwind, useBreakpoints } from "@vueuse/core";
import { Expression, Typeof } from "@ease-forge/shared";
import { calcBreakpointValue, toVNode } from "@/utils/Utils.ts";
@ -60,6 +60,21 @@ const data: DataFormData = {
//
const breakpoints = useBreakpoints(props.breakpoints ?? breakpointsTailwind);
//
const formRows = computed(() => getFormRows(state.dataFormItems, state.columnCount));
//
if (Typeof.isObj(props.columnCount)) {
watch(breakpoints.current(), current => state.columnCount = calcColumnCount(props.columnCount, current), { immediate: true });
}
//
// if (props.autoLoadData && props.dataApi) reload().finally();
// data
// watch(() => state.data, newData => dataChange(state.dataFormItems, newData), { immediate: true, deep: true });
// loading
watch(() => state.loading, loading => emit("loadingChange", loading));
// ctxData()
onMounted(() => data.ctxData.instance = instance!);
/** bothFixed:label和input都固定宽度布局 */
function isBothFixed() {
@ -150,6 +165,82 @@ function resolveInputComponent(input: any) {
}
/**
* 根据 dataFormItems columnCount 配置计算出表单行渲染内容
* @param dataFormItems 表单项数组
* @param columnCount 一行显示的字段数量
*/
function getFormRows(dataFormItems: Array<DataFormItem>, columnCount: number) {
if (columnCount < 1) columnCount = 1;
const formRows: Array<Array<DataFormItem>> = [];
let formRow: Array<DataFormItem> | undefined;
let columnIndex = 0;
for (let formItem of dataFormItems) {
if (formItem.hidden) {
continue;
}
//
if (!formRow) {
formRow = [];
formRows.push(formRow);
}
//
if (columnIndex >= columnCount) {
columnIndex = 0;
formRow = [];
formRows.push(formRow);
}
//
const leftOverColumnCount = columnCount - columnIndex;
//
let currentColumnCount = Math.min(formItem.widthCount, columnCount);
//
if (currentColumnCount > leftOverColumnCount) {
columnIndex = 0;
formRow = [];
formRows.push(formRow);
}
//
columnIndex += currentColumnCount;
// formItem
formRow.push(formItem);
}
// submit
if (slots.submit && formRows.length > 0) {
formRow = formRows[formRows.length - 1];
const nextRow = formRow.length >= columnCount;
const submitFormItem: DataFormItem = {
widthCount: nextRow ? columnCount : columnCount - formRow.length,
inputRef: "__submit",
input: slots.submit,
inputProps: {},
formItemProps: {
autoLink: false,
...props.submitFormItemProps,
},
};
if (nextRow) {
formRows.push([submitFormItem]);
} else {
// submit
if (!submitFormItem.formItemProps.style) submitFormItem.formItemProps.style = {};
if (!submitFormItem.formItemProps.style.paddingLeft && !submitFormItem.formItemProps.style["padding-left"]) {
submitFormItem.formItemProps.style.paddingLeft = "12px";
}
formRow.push(submitFormItem);
}
// submit ()
if (formRows.length === 1) {
if (submitFormItem.formItemProps.class) {
submitFormItem.formItemProps.class = `${submitFormItem.formItemProps.class} data-form-item-auto`;
} else {
submitFormItem.formItemProps.class = "data-form-item-auto";
}
}
}
return formRows;
}
/**
* 根据响应式断点配置计算一行显示的字段数量
* @param columnCount 响应式断点配置
* @param current 当前响应式断点值
@ -178,7 +269,9 @@ export type {
<template>
<div class="data-form">
<Loading>
</Loading>
</div>
</template>

Loading…
Cancel
Save