@nokecy/qc-ui 1.1.22 → 1.1.23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -4,7 +4,7 @@ function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" ==
4
4
  Object.defineProperty(exports, "__esModule", {
5
5
  value: true
6
6
  });
7
- exports.toTree = exports.flattenTreeDeep = exports.flatten = exports.dateValueFormatter = exports.dateTimeValueFormatter = exports.convertSortModel = exports.convertFilterModel = void 0;
7
+ exports.toTree = exports.flattenTreeDeep = exports.flatten = exports.dateValueFormatter = exports.dateTimeValueFormatter = exports.convertSortModel = exports.convertRulesToFilterString = exports.convertFilterModel = void 0;
8
8
  var _cloneDeep2 = _interopRequireDefault(require("lodash/cloneDeep"));
9
9
  var _dayjs = _interopRequireDefault(require("dayjs"));
10
10
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
@@ -22,6 +22,91 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
22
22
  var esc = function esc(v) {
23
23
  return v.replace(/([(),|,\\]|\/i)/g, '\\$1');
24
24
  };
25
+
26
+ // --- Query Builder Logic Helpers (P0) ---
27
+
28
+ /**
29
+ * 将高级查询规则转换为后端 Filter 字符串
30
+ * 注意: 目前为了保持兼容性,只能尽量将 OR 转换为后端支持的格式(如 A=1|A=2),
31
+ * 复杂的嵌套 OR 可能需要后端升级支持。当前策略是尽力转换。
32
+ */
33
+ var convertRulesToFilterString = exports.convertRulesToFilterString = function convertRulesToFilterString(ruleGroup, colDefs) {
34
+ if (!ruleGroup || !ruleGroup.children || ruleGroup.children.length === 0) {
35
+ return "";
36
+ }
37
+ var processGroup = function processGroup(group) {
38
+ var results = [];
39
+ var isAnd = group.logic === 'AND';
40
+ group.children.forEach(function (child) {
41
+ if (child.logic) {
42
+ // Nested Group
43
+ var childFilters = processGroup(child);
44
+ if (childFilters.length > 0) {
45
+ // 简单的嵌套处理,如果顶层是 AND,子组也是 AND,则展开
46
+ // 如果逻辑不一致,目前简单的 Filter String 可能无法完美表达 ((A=1) AND (B=2)) OR (C=3)
47
+ // 现在的降级策略:如果是 OR 组,尝试用逗号分隔(但标准是 AND 用逗号)
48
+ // TODO: 确认后端是否支持 SQL-like filter string。
49
+ // 假设目前只处理最简单的:平铺的 AND
50
+ results.push.apply(results, _toConsumableArray(childFilters)); // 暂时打平
51
+ }
52
+ } else {
53
+ // Rule
54
+ var colDef = colDefs.find(function (c) {
55
+ return c.field === child.field;
56
+ });
57
+ var filter = getRuleFilter(child, colDef);
58
+ if (filter) {
59
+ results.push(filter);
60
+ }
61
+ }
62
+ });
63
+ return results;
64
+ };
65
+
66
+ // 目前为了兼容性,强制打平输出。高级功能的完整支持依赖后端。
67
+ // 这里我们把所有规则都视为可以通过 convertFilterModel 处理的单元
68
+ var filters = processGroup(ruleGroup);
69
+ return filters.join(",");
70
+ };
71
+ var getRuleFilter = function getRuleFilter(rule, colDef) {
72
+ var field = rule.field,
73
+ operator = rule.operator,
74
+ value = rule.value;
75
+ if (value === undefined || value === null || value === "") return "";
76
+ var objectKey = field;
77
+
78
+ // 根据操作符构造查询串
79
+ switch (operator) {
80
+ case '=':
81
+ return "".concat(objectKey, " = ").concat(value);
82
+ case '!=':
83
+ return "".concat(objectKey, " != ").concat(value);
84
+ case '>':
85
+ return "".concat(objectKey, " > ").concat(value);
86
+ case '>=':
87
+ return "".concat(objectKey, " >= ").concat(value);
88
+ case '<':
89
+ return "".concat(objectKey, " < ").concat(value);
90
+ case '<=':
91
+ return "".concat(objectKey, " <= ").concat(value);
92
+ case 'contains':
93
+ return "".concat(objectKey, " =* ").concat(esc(value));
94
+ case 'startsWith':
95
+ return "".concat(objectKey, " ^ ").concat(esc(value));
96
+ case 'endsWith':
97
+ // 后端可能不支持 endWith 语法,暂用 =*
98
+ return "".concat(objectKey, " =* ").concat(esc(value));
99
+ case 'between':
100
+ if (Array.isArray(value)) {
101
+ // 复用现有的 range 逻辑
102
+ return getFilter(objectKey, value, colDef);
103
+ }
104
+ return "";
105
+ default:
106
+ // 默认回退到标准处理
107
+ return getFilter(objectKey, value, colDef);
108
+ }
109
+ };
25
110
  var getFilter = function getFilter(objectKey, value, colDef) {
26
111
  if (typeof value === 'string') {
27
112
  return value && value != "" ? "".concat(objectKey, " ").concat(colDef !== null && colDef !== void 0 && colDef.exactQuery ? '^' : "=*", " ").concat(esc(value)) : "";
@@ -23,7 +23,7 @@ function _objectWithoutProperties(source, excluded) { if (source == null) return
23
23
  function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }
24
24
  import { ModuleRegistry } from 'ag-grid-community';
25
25
  import { AgGridReact } from 'ag-grid-react';
26
- import { Spin, Pagination, Card, Tag, Typography } from 'antd';
26
+ import { Spin, Pagination, Card, Tag, Typography, Popover, Badge, Button } from 'antd';
27
27
  import React, { useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState } from 'react';
28
28
  import { AllEnterpriseModule } from "ag-grid-enterprise";
29
29
 
@@ -36,8 +36,10 @@ import "./index.less";
36
36
  import FormRender from "./queryForm";
37
37
  import ToolBar from "./toolBar";
38
38
  import SettingItem from "./settingItem";
39
- import { RedoOutlined } from '@ant-design/icons';
40
- import { convertFilterModel, dateTimeValueFormatter, dateValueFormatter, flatten, toTree } from "./utils";
39
+ import { RedoOutlined, FilterOutlined } from '@ant-design/icons';
40
+ import { convertFilterModel, convertRulesToFilterString, dateTimeValueFormatter, dateValueFormatter, flatten, toTree } from "./utils";
41
+ import AdvancedQueryBuilder from "./queryForm/AdvancedQueryBuilder";
42
+ import { v4 as uuidv4 } from 'uuid';
41
43
  import Setting from "./setting";
42
44
  import { useGridPlusColumnState } from '.';
43
45
  import CustomGroupCellRenderer from "./_utils/customGroupCellRenderer";
@@ -218,6 +220,23 @@ function AgGridPlus(props) {
218
220
  queryItemsOrder = _useState18[0],
219
221
  setQueryItemsOrder = _useState18[1];
220
222
 
223
+ // 高级查询状态
224
+ var _useState19 = useState(false),
225
+ _useState20 = _slicedToArray(_useState19, 2),
226
+ advancedPopoverOpen = _useState20[0],
227
+ setAdvancedPopoverOpen = _useState20[1];
228
+ var createEmptyRuleGroup = function createEmptyRuleGroup() {
229
+ return {
230
+ id: uuidv4(),
231
+ logic: 'AND',
232
+ children: []
233
+ };
234
+ };
235
+ var _useState21 = useState(createEmptyRuleGroup),
236
+ _useState22 = _slicedToArray(_useState21, 2),
237
+ advancedQueryRules = _useState22[0],
238
+ setAdvancedQueryRules = _useState22[1];
239
+
221
240
  /**
222
241
  * 【P1 架构优化】使用单向数据流架构
223
242
  *
@@ -676,7 +695,19 @@ function AgGridPlus(props) {
676
695
  pagination: pagination
677
696
  });
678
697
  try {
679
- var filter = convertFilterModel(queryFilter, allColDefsRef.current);
698
+ // 处理高级查询模式
699
+ var filter;
700
+ if (queryFilter.__advancedMode__ && queryFilter.__rules__) {
701
+ // 高级模式:使用规则转换
702
+ filter = convertRulesToFilterString(queryFilter.__rules__, allColDefsRef.current);
703
+ logger.debug('高级模式 Filter', {
704
+ rules: queryFilter.__rules__,
705
+ filter: filter
706
+ });
707
+ } else {
708
+ // 简单模式:使用原有的转换逻辑
709
+ filter = convertFilterModel(queryFilter, allColDefsRef.current);
710
+ }
680
711
  var params = _objectSpread(_objectSpread({
681
712
  filter: filter
682
713
  }, stableGridParams), {}, {
@@ -1181,16 +1212,33 @@ function AgGridPlus(props) {
1181
1212
  defaultExpand: defaultSearchExpand,
1182
1213
  gridApi: apiRef.current,
1183
1214
  onQuery: function onQuery(formValues) {
1215
+ // 优先使用高级搜索:如果存在高级搜索条件,忽略简单查询
1216
+ if (advancedQueryRules.children.length > 0) {
1217
+ var filter = {
1218
+ __advancedMode__: true,
1219
+ __rules__: advancedQueryRules
1220
+ };
1221
+ setQueryFilter(filter);
1222
+ if (pagination.current !== 1) {
1223
+ setPagination(function (prev) {
1224
+ return _objectSpread(_objectSpread({}, prev), {}, {
1225
+ current: 1
1226
+ });
1227
+ });
1228
+ }
1229
+ onRequest && onRequest(filter);
1230
+ return;
1231
+ }
1184
1232
  setQueryFilter(_objectSpread({}, formValues));
1185
- setPagination(function (prev) {
1186
- if (prev.current !== 1) {
1233
+ // 始终使用传入的 formValues 发起请求
1234
+ if (pagination.current !== 1) {
1235
+ setPagination(function (prev) {
1187
1236
  return _objectSpread(_objectSpread({}, prev), {}, {
1188
1237
  current: 1
1189
1238
  });
1190
- }
1191
- onRequest && onRequest(formValues);
1192
- return prev;
1193
- });
1239
+ });
1240
+ }
1241
+ onRequest && onRequest(formValues);
1194
1242
  },
1195
1243
  onInit: function onInit(defaultValues) {
1196
1244
  setQueryFilter(defaultValues);
@@ -1228,7 +1276,79 @@ function AgGridPlus(props) {
1228
1276
  gridKey: gridKey,
1229
1277
  gridApi: apiRef.current,
1230
1278
  onSaveColumnState: onColumnStateChanged
1231
- })]
1279
+ }),
1280
+ /*#__PURE__*/
1281
+ // 高级搜索(图标风格,位于设置右边)
1282
+ React.createElement(Popover, {
1283
+ key: "advanced-search-setting",
1284
+ content: /*#__PURE__*/React.createElement("div", {
1285
+ style: {
1286
+ width: 600,
1287
+ maxHeight: 400,
1288
+ overflow: 'auto'
1289
+ }
1290
+ }, /*#__PURE__*/React.createElement(AdvancedQueryBuilder, {
1291
+ rootGroup: advancedQueryRules,
1292
+ onChange: setAdvancedQueryRules,
1293
+ colDefs: allColDefs
1294
+ }), /*#__PURE__*/React.createElement("div", {
1295
+ style: {
1296
+ marginTop: 12,
1297
+ textAlign: 'right',
1298
+ borderTop: '1px solid #f0f0f0',
1299
+ paddingTop: 12
1300
+ }
1301
+ }, /*#__PURE__*/React.createElement(Button, {
1302
+ size: "small",
1303
+ onClick: function onClick() {
1304
+ setAdvancedQueryRules(createEmptyRuleGroup());
1305
+ setQueryFilter({});
1306
+ onRequest && onRequest({});
1307
+ setAdvancedPopoverOpen(false);
1308
+ },
1309
+ style: {
1310
+ marginRight: 8
1311
+ }
1312
+ }, "\u91CD\u7F6E"), /*#__PURE__*/React.createElement(Button, {
1313
+ size: "small",
1314
+ type: "primary",
1315
+ onClick: function onClick() {
1316
+ var filter = {
1317
+ __advancedMode__: true,
1318
+ __rules__: advancedQueryRules
1319
+ };
1320
+ setQueryFilter(filter);
1321
+ if (pagination.current !== 1) {
1322
+ setPagination(function (prev) {
1323
+ return _objectSpread(_objectSpread({}, prev), {}, {
1324
+ current: 1
1325
+ });
1326
+ });
1327
+ }
1328
+ onRequest && onRequest(filter);
1329
+ setAdvancedPopoverOpen(false);
1330
+ }
1331
+ }, "\u67E5\u8BE2"))),
1332
+ title: "\u9AD8\u7EA7\u641C\u7D22",
1333
+ trigger: "click",
1334
+ open: advancedPopoverOpen,
1335
+ onOpenChange: setAdvancedPopoverOpen,
1336
+ placement: "bottomRight",
1337
+ overlayStyle: {
1338
+ maxWidth: 'none'
1339
+ }
1340
+ }, /*#__PURE__*/React.createElement(Badge, {
1341
+ count: advancedQueryRules.children.length,
1342
+ size: "small",
1343
+ offset: [-2, 2]
1344
+ }, /*#__PURE__*/React.createElement("div", {
1345
+ style: {
1346
+ margin: "0 4px",
1347
+ color: advancedQueryRules.children.length > 0 ? '#1890ff' : '#000',
1348
+ fontSize: 16,
1349
+ cursor: "pointer"
1350
+ }
1351
+ }, /*#__PURE__*/React.createElement(FilterOutlined, null))))]
1232
1352
  }), /*#__PURE__*/React.createElement(AgGridReact, _extends({
1233
1353
  theme: agGridTheme
1234
1354
  }, rest, {
@@ -0,0 +1,10 @@
1
+ import React from 'react';
2
+ import { QueryRuleGroup } from '../shared/storage/schemeStorageAdapter';
3
+ import { ExtendedColDef } from '../types';
4
+ interface AdvancedQueryBuilderProps {
5
+ rootGroup: QueryRuleGroup;
6
+ onChange: (group: QueryRuleGroup) => void;
7
+ colDefs: ExtendedColDef[];
8
+ }
9
+ declare const AdvancedQueryBuilder: React.FC<AdvancedQueryBuilderProps>;
10
+ export default AdvancedQueryBuilder;