get_filter_fields() now:
- Copies valueField/textField from alter config to filter field
- Uses custom valueField for empty option check and injection
- Ensures filter form and add/edit form use identical code-type config
1. Default uitype to 'str' when no alter matches (text input)
2. Handle alter.uitype='select' by converting to code with inline data
3. Read browserfields from opts.row_options.browserfields (CRUD-generated
UIs nest it under row_options, not at opts top level)
When CRUD JSON has data_filter in params:
- Toolbar shows a '搜索' button (name:'filter')
- Click opens PopupWindow with Form widget
- Form fields are dynamically generated from data_filter definition
- Extracts all {var, field, op} from AND/OR/NOT nested structure
- Supports dropdown (uitype:'code') via browserfields.alters config
- Customizable labels via filter_labels option
- Form submit collects values → stored in this.filter_values
- merge_search_params() sends data_filter (JSON string) + each var value
to backend API as URL parameters
- Backend .dspy uses sqlor.filter.DBFilter.gen(ns) for SQL WHERE clause
Deleted previous inline DataFilter widget approach; replaced with
popup Form pattern that matches existing CRUD edit/add form UX.
- New bricks.DataFilter widget (bricks/data_filter.js): parses data_filter
JSON definition, renders search input fields for each var parameter,
supports AND/OR/NOT nested structures, and UiCode dropdowns for fields
with browserfields.alters uitype=code configuration.
- Modified DataViewer (bricks/dataviewer.js): added build_datafilter_widget(),
filter_event_handle(), filter_clear_handle() methods; extended
merge_search_params() to send data_filter JSON + collected var values
to the backend API.
- Updated build.sh: added data_filter.js to the JS concatenation list.
Backend integration: DataViewer sends data_filter (JSON string) and
each var's user input value as URL params. Backend .dspy uses
sqlor.filter.DBFilter to convert to SQL WHERE clause.