Commit 768c1456 authored by drigle's avatar drigle

feat: support configurable view filter fields

parent 558ad817
...@@ -92,6 +92,7 @@ import { ...@@ -92,6 +92,7 @@ import {
normalizeDelayRequest, normalizeDelayRequest,
normalizeDelayRequestItems, normalizeDelayRequestItems,
normalizeDepartmentRectificationItems, normalizeDepartmentRectificationItems,
resolveProblemRectificationFilterColumns,
getViewRestrictionDefaults, getViewRestrictionDefaults,
} from '../problemRectificationListService'; } from '../problemRectificationListService';
import { import {
...@@ -1058,8 +1059,15 @@ export default function ProblemRectificationListPage() { ...@@ -1058,8 +1059,15 @@ export default function ProblemRectificationListPage() {
[records, activeGridView, subject], [records, activeGridView, subject],
); );
const dynamicFilterSchema = useMemo( const dynamicFilterSchema = useMemo(
() => buildProblemRectificationFilterSchema(configuredView.columns || []), () =>
[configuredView.columns], buildProblemRectificationFilterSchema(
resolveProblemRectificationFilterColumns(
activeGridView,
subject,
configuredView.columns || [],
),
),
[activeGridView, configuredView.columns, subject],
); );
const createFields = useMemo( const createFields = useMemo(
......
...@@ -59,7 +59,7 @@ ...@@ -59,7 +59,7 @@
问题整改列表的新增表单、筛选和表格均读取当前激活 Grid View: 问题整改列表的新增表单、筛选和表格均读取当前激活 Grid View:
- 新增表单按 `settings.columns` 顺序渲染可见字段,并包含记录标题字段;标题是否必填跟随视图列配置,未配置短标题时使用标题作为默认回退值。`settings.shortTitle = true` 时隐藏列表及新增表单的根级记录标题,不校验或提交根级 `title`。 - 新增表单按 `settings.columns` 顺序渲染可见字段,并包含记录标题字段;标题是否必填跟随视图列配置,未配置短标题时使用标题作为默认回退值。`settings.shortTitle = true` 时隐藏列表及新增表单的根级记录标题,不校验或提交根级 `title`。
- 筛选控件由视图列的 Subject 字段类型自动生成。`select` 选项来自 `settings.options`,日期、数字、布尔、用户和引用字段使用对应控件;提交时按 `field:<path>` 通过 `/record/query` 远程筛选,不再提供独立关键词搜索。 - 筛选控件默认按视图可见列的 Subject 字段类型自动生成;当 Grid View 配置 `settings.filters.fields` 时,仅按该数组顺序展示筛选字段,支持 `metadata.<field>`、裸字段名或 `{ field }` 配置,也可引用视图中的隐藏列。未配置属性时回退到可见列,空数组表示不展示筛选控件;无效字段会被忽略。`select` 选项来自 `settings.options`,日期、数字、布尔、用户和引用字段使用对应控件;提交时按 `field:<path>` 通过 `/record/query` 远程筛选,不再提供独立关键词搜索。
- 引用和用户多选的输入摘要、列表勾选与草稿统一使用归一化 ID;引用写入只保存目标记录 `_id` 或 `_id[]`。 - 引用和用户多选的输入摘要、列表勾选与草稿统一使用归一化 ID;引用写入只保存目标记录 `_id` 或 `_id[]`。
- 表格请求期间 DataGrid 使用居中的 loading 遮罩,空结果与加载中状态分开处理。 - 表格请求期间 DataGrid 使用居中的 loading 遮罩,空结果与加载中状态分开处理。
......
...@@ -778,6 +778,14 @@ function normalizeDynamicFilterField(field) { ...@@ -778,6 +778,14 @@ function normalizeDynamicFilterField(field) {
return `metadata.${normalized}`; return `metadata.${normalized}`;
} }
function normalizeConfiguredFilterField(field) {
if (typeof field !== 'string') {
return '';
}
return normalizeDynamicFilterField(field.trim());
}
function escapeDynamicFilterRegex(value) { function escapeDynamicFilterRegex(value) {
return String(value ?? '').replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); return String(value ?? '').replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
} }
...@@ -859,6 +867,31 @@ export function buildProblemRectificationFilterSchema(columns = []) { ...@@ -859,6 +867,31 @@ export function buildProblemRectificationFilterSchema(columns = []) {
}, []); }, []);
} }
export function resolveProblemRectificationFilterColumns(view, subject, visibleColumns = []) {
const configuredFields = view?.settings?.filters?.fields;
if (!Array.isArray(configuredFields)) {
return visibleColumns;
}
const allViewColumns = buildViewColumns(view, subject, { includeHidden: true });
const columnsByField = new Map(
[...allViewColumns, ...visibleColumns].map((column) => [
normalizeConfiguredFilterField(column?.field),
column,
]),
);
return configuredFields
.map((item) => {
const configuredField =
typeof item === 'string'
? item
: item?.field || item?.path || item?.name;
return columnsByField.get(normalizeConfiguredFilterField(configuredField));
})
.filter(Boolean);
}
function buildInspectionReportMonthFilter(month) { function buildInspectionReportMonthFilter(month) {
const normalizedMonth = normalizeText(month); const normalizedMonth = normalizeText(month);
if (!/^\d{4}-(0[1-9]|1[0-2])$/.test(normalizedMonth)) { if (!/^\d{4}-(0[1-9]|1[0-2])$/.test(normalizedMonth)) {
...@@ -1025,7 +1058,7 @@ function buildCalculatedQualityRatingFilter(rating) { ...@@ -1025,7 +1058,7 @@ function buildCalculatedQualityRatingFilter(rating) {
} }
export function buildProblemRectificationQueryFilter(filters = {}, gridView, subject) { export function buildProblemRectificationQueryFilter(filters = {}, gridView, subject) {
const columns = buildViewColumnsForList(gridView, subject); const columns = buildViewColumns(gridView, subject, { includeHidden: true });
const uiFieldClauses = Object.entries(FILTER_FIELD_PATHS).map(([filterKey, fieldPath]) => { const uiFieldClauses = Object.entries(FILTER_FIELD_PATHS).map(([filterKey, fieldPath]) => {
const value = filters?.[filterKey]; const value = filters?.[filterKey];
if (isEmptyFilterValue(value)) { if (isEmptyFilterValue(value)) {
...@@ -1048,7 +1081,11 @@ export function buildProblemRectificationQueryFilter(filters = {}, gridView, sub ...@@ -1048,7 +1081,11 @@ export function buildProblemRectificationQueryFilter(filters = {}, gridView, sub
.map(([key, value]) => buildDynamicFilterClause( .map(([key, value]) => buildDynamicFilterClause(
key.slice('field:'.length), key.slice('field:'.length),
value, value,
columns.find((column) => column.field === key.slice('field:'.length))?.fieldDef, columns.find(
(column) =>
normalizeConfiguredFilterField(column.field) ===
normalizeConfiguredFilterField(key.slice('field:'.length)),
)?.fieldDef,
)), )),
]); ]);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment