From 7a834b1b6806174bef6f34ba954cd8e03e0187de Mon Sep 17 00:00:00 2001 From: wyc <1104749580@qq.com> Date: Sun, 9 Aug 2026 18:58:48 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8Dbug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Adminive/Backend_Fields.tsx | 83 ++++++++++++++++++++-------- src/Base_Drawer.tsx | 3 +- src/Data_Source/Data_Source_Show.tsx | 3 +- src/Map/Aircraft_List.tsx | 42 +++++++------- 4 files changed, 86 insertions(+), 45 deletions(-) diff --git a/src/Adminive/Backend_Fields.tsx b/src/Adminive/Backend_Fields.tsx index 1b1b0a8..4d72f64 100644 --- a/src/Adminive/Backend_Fields.tsx +++ b/src/Adminive/Backend_Fields.tsx @@ -18,7 +18,15 @@ export type Backend_Form_Section = { title?: string object_path?: string descriptor_path?: string + fields?: string[] + layout?: Backend_Field_Layout[] +} + +export type Backend_Field_Layout = { + kind: "cards" | "horizontal" | "vertical" | "list" | "grid" | string fields: string[] + columns?: number + minimum_width?: number } export type Backend_Disabled_Rule = { @@ -94,36 +102,67 @@ export function Backend_Fields(props: { const object = get_path(props.root, props.section.object_path) as Json_Object | undefined; const descriptor_path = props.section.descriptor_path ?? props.section.object_path; const available_fields = fields_at_path(props.descriptor_fields, descriptor_path); - const selected = props.section.fields - .map(name => available_fields.find(field => field.name === name)) - .filter((field): field is Backend_Field_Descriptor => Boolean(field && field.readable !== false)); + const layout = props.section.layout?.length + ? props.section.layout + : [{kind: "vertical", fields: props.section.fields || []}]; + const arranged_names = layout.flatMap(group => group.fields); + const remaining_names = (props.section.fields || []).filter(name => !arranged_names.includes(name)); + const groups = remaining_names.length > 0 + ? [...layout, {kind: "vertical", fields: remaining_names}] + : layout; + const fields_by_name = new Map(available_fields + .filter(field => field.readable !== false) + .map(field => [field.name, field])); const update = (field: Backend_Field_Descriptor, value: unknown) => { if (!object) return; object[field.name] = value; const path = [props.section.object_path, field.name].filter(Boolean).join("."); props.onChange?.(path, value, field); }; - const booleans = selected.filter(field => (field.presentation?.control || field.value_type) === "boolean"); - const controls = selected.filter(field => !booleans.includes(field)); + const render_control = (field: Backend_Field_Descriptor) => ( + update(field, value)}/> + ); + const render_group = (group: Backend_Field_Layout, index: number) => { + const fields = group.fields.map(name => fields_by_name.get(name)).filter((field): field is Backend_Field_Descriptor => Boolean(field)); + if (fields.length === 0) return null; + if (group.kind === "cards") { + return
+
+ {fields.map(field => { + const active = Boolean(object?.[field.name]); + const disabled = field_disabled(props.root, field, props.rules || []); + return +
{render_control(field)}
+
; + })} +
+
; + } + if (group.kind === "horizontal") { + return
+ {fields.map(render_control)} +
; + } + if (group.kind === "grid") { + const columns = group.columns ? `repeat(${group.columns}, minmax(0, 1fr))` : `repeat(auto-fit, minmax(${group.minimum_width || 280}px, 1fr))`; + return
+ {fields.map(render_control)} +
; + } + return {fields.map(render_control)}; + }; return ( - {booleans.length > 0 &&
- {booleans.map(field => ( - -
- update(field, value)}/> -
-
- ))} -
} - {controls.map(field => update(field, value)}/>) } + {groups.map(render_group)}
); } diff --git a/src/Base_Drawer.tsx b/src/Base_Drawer.tsx index 5ebdef1..1c93fa0 100644 --- a/src/Base_Drawer.tsx +++ b/src/Base_Drawer.tsx @@ -64,7 +64,6 @@ export class Base_Drawer extends enhance.Base { const placement = props.placement || "right"; const header = props.header; const scrollKey = props.scrollKey || "Base_Drawer"; - const width = props.width || "auto"; // 按钮样式自动根据 placement 调整 const switchStyle = this.getSwitchStyle(placement, token); @@ -84,7 +83,7 @@ export class Base_Drawer extends enhance.Base { mask={false} closable={false} getContainer={false} - width={width} + width="auto" styles={header ? {body: {padding: 0}} : undefined} > {header ?
diff --git a/src/Data_Source/Data_Source_Show.tsx b/src/Data_Source/Data_Source_Show.tsx index c938c57..8c51df2 100644 --- a/src/Data_Source/Data_Source_Show.tsx +++ b/src/Data_Source/Data_Source_Show.tsx @@ -453,8 +453,7 @@ export class Data_Source_Show extends enhance.Base { {this.render_header_tabs(mode, enabled_list)}
; const scroll_key = this.active_tab_key === "source" ? `Data_Source_Show:source:${this.active_data_source_key}` : `Data_Source_Show:${mode}:${this.active_tab_key}`; - return + return {this.render_tab_content(mode, active_ds)}
=> ({ }); function render_column_title(label: string) { - return
{label.replaceAll("<", "").replaceAll(">", "")}
; + return
{label}
; } function compare_values(a: unknown, b: unknown): number { @@ -96,6 +100,14 @@ const text_filter = (field: string): TableColumnType => ({ onFilter: (value, record) => String(record[field] ?? "").toLowerCase().includes(String(value).toLowerCase()), }); +const boolean_filter = (field: string): TableColumnType => ({ + filters: [ + {text: "是", value: "true"}, + {text: "否", value: "false"}, + ], + onFilter: (value, record) => Boolean(record[field]) === (value === "true"), +}); + function format_timestamp(row: Record, column: Aircraft_Column_Model): string { const seconds = Number(row[column.secondsKey ?? "uti"]); if (!Number.isFinite(seconds) || seconds <= 0) return ""; @@ -116,7 +128,8 @@ function create_columns(model: readonly Aircraft_Column_Model[]): TableColumnTyp return { title: render_column_title(column.label), key: column.key, - width: 60, + width: column.width, + fixed: column.fixed, align: "center", render: (_value, _record, index) => index + 1, }; @@ -127,33 +140,24 @@ function create_columns(model: readonly Aircraft_Column_Model[]): TableColumnTyp dataIndex: column.key, key: column.key, onHeaderCell, - width: column.type === "timestamp" ? 190 : Math.max(88, column.label.length * 18 + 44), + width: column.width, + fixed: column.fixed, defaultSortOrder: normalized_sort_order(column.defaultSortOrder), - sorter: (a, b) => compare_values(a[column.key], b[column.key]), + sorter: column.sortable ? (a, b) => compare_values(a[column.key], b[column.key]) : undefined, render: value =>
{value == null ? "" : typeof value === "boolean" ? (value ? "是" : "否") : String(value)}
, }; return { ...common, - ...(column.type === "number" ? range_filter(column.key) : text_filter(column.key)), + ...(column.filter === "range" ? range_filter(column.key) + : column.filter === "text" ? text_filter(column.key) + : column.filter === "boolean" ? boolean_filter(column.key) + : {}), }; }); } -function fallback_model(rows: readonly Record[]): Aircraft_Column_Model[] { - const first = rows[0]; - if (!first) return []; - return [ - {key: "index", label: "序号", type: "index"}, - ...Object.keys(first).map(key => ({ - key, - label: key, - type: typeof first[key] === "number" ? "number" : "text", - })), - ]; -} - export class Aircraft_List extends enhance.Base { dataSource: Aircraft_Row[] = []; columns: TableColumnType[] = []; @@ -181,7 +185,7 @@ export class Aircraft_List extends enhance.Base { : Array.isArray(payload) ? payload : []; const model: Aircraft_Column_Model[] = Array.isArray(payload?.model?.columns) ? payload.model.columns - : fallback_model(raw_rows); + : []; this.dataSource = raw_rows.map((item, index) => { const row: Aircraft_Row = {...item, key: `${String(item.hex ?? "aircraft")}:${index}`};