20260511214503
This commit is contained in:
1 parent
364d29dbaa
commit
e98740192d
9 files changed
+2451
-875
No files matched your search
@@ -0,0 +1,225 @@
|
||||
# 搜索场景下本地数据处理方案
|
||||
|
||||
## 场景分析
|
||||
|
||||
### 场景一:新增数据后的搜索
|
||||
|
||||
**问题**:用户新增了10条数据(仅在本地,未保存到数据库),执行 LIKE 搜索时,这些本地数据无法被搜索到。
|
||||
|
||||
**期望**:搜索结果应包含本地新增的行,且支持 LIKE 模糊匹配。
|
||||
|
||||
### 场景二:更新数据后的搜索
|
||||
|
||||
**问题**:用户更新了10条数据(本地已修改),执行搜索时,远程返回的是旧数据,本地修改的数据可能不符合搜索条件。
|
||||
|
||||
**期望**:搜索结果应使用本地更新后的数据进行匹配,而不是远程的旧数据。
|
||||
|
||||
***
|
||||
|
||||
## 解决方案
|
||||
|
||||
### 方案核心思路
|
||||
|
||||
1. **本地数据也参与搜索过滤**:在搜索时,对本地的 `insertRows` 和 `updateRows` 也应用搜索条件过滤
|
||||
2. **合并展示**:将远程搜索结果与本地过滤后的结果合并展示
|
||||
3. **保持状态**:保留本地数据的 `_rowState` 标记
|
||||
|
||||
### 修改内容
|
||||
|
||||
#### 1. JS 文件修改 (`js/feegrid-manager.js`)
|
||||
|
||||
**新增方法:**
|
||||
|
||||
* `_filterLocalRows(condition)` - 根据搜索条件过滤本地数据
|
||||
|
||||
* 修改 `loadPage()` - 在加载远程数据后,合并本地过滤后的数据
|
||||
|
||||
**搜索条件解析**:
|
||||
|
||||
* 支持 `LIKE '%xxx%'` 模糊匹配
|
||||
|
||||
* 支持 `=`, `!=`, `<`, `>`, `<=`, `>=` 比较
|
||||
|
||||
* 支持 `AND`, `OR` 逻辑(简化版)
|
||||
|
||||
#### 2. 修改 `loadPage()` 方法
|
||||
|
||||
```js
|
||||
function loadPage(pageNumber) {
|
||||
_setLoading();
|
||||
|
||||
var pagination = state.draftManager.getPagination();
|
||||
var pageSize = pagination.pageSize;
|
||||
var remoteTotal = pagination.remoteTotal;
|
||||
var insertRows = state.draftManager.getInsertRows();
|
||||
var updateRows = state.draftManager.getUpdateRows();
|
||||
|
||||
// 获取搜索条件
|
||||
var searchCondition = options.searchCondition ||
|
||||
options.keyField.replace('subid', 'mx_') + "='" + state.masterId + "'";
|
||||
|
||||
// 过滤本地数据
|
||||
var filteredInserts = _filterLocalRows(insertRows, searchCondition);
|
||||
var filteredUpdates = _filterLocalRows(updateRows, searchCondition);
|
||||
|
||||
// ... 原有远程加载逻辑 ...
|
||||
|
||||
// 合并结果时,使用本地过滤后的数据
|
||||
}
|
||||
```
|
||||
|
||||
#### 3. 新增条件解析工具函数
|
||||
|
||||
```js
|
||||
function _filterLocalRows(rows, condition) {
|
||||
if (!condition || condition.trim() === '') {
|
||||
return rows;
|
||||
}
|
||||
|
||||
var filtered = [];
|
||||
var conditions = _parseCondition(condition);
|
||||
|
||||
for (var i = 0; i < rows.length; i++) {
|
||||
var row = rows[i];
|
||||
if (_matchesConditions(row, conditions)) {
|
||||
filtered.push(row);
|
||||
}
|
||||
}
|
||||
|
||||
return filtered;
|
||||
}
|
||||
|
||||
function _parseCondition(condition) {
|
||||
var result = [];
|
||||
|
||||
var parts = condition.split(/\s+(AND|OR)\s+/i);
|
||||
for (var i = 0; i < parts.length; i += 2) {
|
||||
var expr = parts[i].trim();
|
||||
var operator = parts[i + 1] ? parts[i + 1].toUpperCase() : 'AND';
|
||||
|
||||
var match;
|
||||
|
||||
// LIKE 匹配
|
||||
if ((match = expr.match(/^\s*(\w+)\s+LIKE\s+['"](.*)['"]\s*$/i))) {
|
||||
result.push({
|
||||
field: match[1],
|
||||
operator: 'LIKE',
|
||||
value: match[2],
|
||||
logic: operator
|
||||
});
|
||||
}
|
||||
// 等于匹配
|
||||
else if ((match = expr.match(/^\s*(\w+)\s*=\s*['"](.*)['"]\s*$/))) {
|
||||
result.push({
|
||||
field: match[1],
|
||||
operator: '=',
|
||||
value: match[2],
|
||||
logic: operator
|
||||
});
|
||||
}
|
||||
// 不等于匹配
|
||||
else if ((match = expr.match(/^\s*(\w+)\s*(!=|<>)=\s*['"](.*)['"]\s*$/))) {
|
||||
result.push({
|
||||
field: match[1],
|
||||
operator: '!=',
|
||||
value: match[2],
|
||||
logic: operator
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function _matchesConditions(row, conditions) {
|
||||
if (conditions.length === 0) return true;
|
||||
|
||||
var result = true;
|
||||
|
||||
for (var i = 0; i < conditions.length; i++) {
|
||||
var cond = conditions[i];
|
||||
var fieldValue = row[cond.field];
|
||||
|
||||
if (fieldValue === undefined || fieldValue === null) {
|
||||
fieldValue = '';
|
||||
}
|
||||
|
||||
var fieldStr = String(fieldValue).toLowerCase();
|
||||
var valueStr = String(cond.value).toLowerCase();
|
||||
var matches = false;
|
||||
|
||||
switch (cond.operator) {
|
||||
case 'LIKE':
|
||||
var pattern = valueStr
|
||||
.replace(/%/g, '.*')
|
||||
.replace(/_/g, '.');
|
||||
matches = new RegExp('^' + pattern + '$').test(fieldStr);
|
||||
break;
|
||||
|
||||
case '=':
|
||||
matches = fieldStr === valueStr;
|
||||
break;
|
||||
|
||||
case '!=':
|
||||
matches = fieldStr !== valueStr;
|
||||
break;
|
||||
}
|
||||
|
||||
if (cond.logic === 'AND') {
|
||||
result = result && matches;
|
||||
} else {
|
||||
result = result || matches;
|
||||
}
|
||||
|
||||
if (!result && cond.logic === 'AND') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
```
|
||||
|
||||
***
|
||||
|
||||
## 实施步骤
|
||||
|
||||
1. **修改** **`js/feegrid-manager.js`**:
|
||||
|
||||
* 新增 `_filterLocalRows()` 函数
|
||||
|
||||
* 新增 `_parseCondition()` 函数
|
||||
|
||||
* 新增 `_matchesConditions()` 函数
|
||||
|
||||
* 修改 `loadPage()` 方法,在加载时过滤本地数据
|
||||
|
||||
2. **修改** **`reload()`** **方法**:
|
||||
|
||||
* 确保 `reload()` 时也应用本地数据过滤
|
||||
|
||||
3. **测试验证**:
|
||||
|
||||
* 测试新增数据后的 LIKE 搜索
|
||||
|
||||
* 测试更新数据后的搜索匹配
|
||||
|
||||
***
|
||||
|
||||
## 预期效果
|
||||
|
||||
| 场景 | 操作 | 预期结果 |
|
||||
| --- | ------------------------- | -------------------------------- |
|
||||
| 场景一 | 新增10条数据 → 搜索 LIKE '%xxx%' | 本地新增且匹配的行会显示在搜索结果中 |
|
||||
| 场景二 | 更新10条数据 → 搜索更新后的字段 | 使用本地更新后的数据进行匹配 |
|
||||
| 场景三 | 删除数据后搜索 | 已标记删除的行仍然出现在搜索结果中,但是status显示删除即可 |
|
||||
|
||||
***
|
||||
|
||||
## 风险与注意事项
|
||||
|
||||
1. **条件解析复杂度**:只支持简单的 LIKE、=、!= 操作符,复杂条件可能解析失败
|
||||
2. **性能考虑**:本地数据量大时,过滤可能有性能问题(建议限制本地数据量)
|
||||
3. **日期格式**:日期字段的比较需要注意格式统一
|
||||
4. **多表关联**:不支持跨表字段的搜索条件
|
||||
|
||||
Reference in new issue
Block a user