feat(control): add grid extended lookup column search

This commit is contained in:
2026-07-31 10:38:40 +08:00
parent e06a67f002
commit 004778f2a8
@@ -38,6 +38,8 @@ namespace Lskj.Control
new Dictionary<string, ExtendedReturnPopupContext>(StringComparer.OrdinalIgnoreCase); new Dictionary<string, ExtendedReturnPopupContext>(StringComparer.OrdinalIgnoreCase);
private readonly Dictionary<string, DataTable> mExtendedReturnSchemas = private readonly Dictionary<string, DataTable> mExtendedReturnSchemas =
new Dictionary<string, DataTable>(StringComparer.OrdinalIgnoreCase); new Dictionary<string, DataTable>(StringComparer.OrdinalIgnoreCase);
private readonly Dictionary<string, string> mExtendedReturnSchemaSqls =
new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
private readonly Dictionary<string, string> mExtendedReturnDisplayFields = private readonly Dictionary<string, string> mExtendedReturnDisplayFields =
new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
private readonly Dictionary<string, ExtendedLookupRequestState> mExtendedReturnQueryStates = private readonly Dictionary<string, ExtendedLookupRequestState> mExtendedReturnQueryStates =
@@ -70,8 +72,10 @@ namespace Lskj.Control
public DateTime DueTime; public DateTime DueTime;
public string FieldName; public string FieldName;
public string Keyword; public string Keyword;
public string SearchField;
public string SourceSql; public string SourceSql;
public string ConnectionString; public string ConnectionString;
public bool SchemaOnly;
public GridColumnModel Model; public GridColumnModel Model;
public PopupContainerEdit Editor; public PopupContainerEdit Editor;
public ExtendedReturnPopupContext PopupContext; public ExtendedReturnPopupContext PopupContext;
@@ -80,6 +84,7 @@ namespace Lskj.Control
private sealed class ExtendedLookupQueryResult private sealed class ExtendedLookupQueryResult
{ {
public DataTable Schema;
public DataTable Table; public DataTable Table;
public Exception Error; public Exception Error;
} }
@@ -340,9 +345,31 @@ namespace Lskj.Control
string actualValueText = GetExtendedReturnBusinessValueText(context); string actualValueText = GetExtendedReturnBusinessValueText(context);
context.Popup.PrepareForOpen(); context.Popup.PrepareForOpen();
string sourceSql = ResolveExtendedReturnSourceSql(model, context.BusinessRow);
DataTable cachedSchema = TryGetExtendedReturnSchema(model.FieldName, sourceSql);
if (cachedSchema != null)
{
ConfigureExtendedReturnSearchColumns(context, cachedSchema);
}
if (actualValueText.Length > 0) if (actualValueText.Length > 0)
{ {
StartExtendedReturnSearch(context, actualValueText); QueueExtendedReturnSearch(
context.OwnerEdit,
context,
sourceSql,
actualValueText,
string.Empty,
false);
}
else if (cachedSchema == null)
{
QueueExtendedReturnSearch(
context.OwnerEdit,
context,
sourceSql,
string.Empty,
string.Empty,
true);
} }
else else
{ {
@@ -426,7 +453,7 @@ namespace Lskj.Control
try try
{ {
StartExtendedReturnSearch(context, popup.SearchText); StartExtendedReturnSearch(context, popup.SearchText, popup.SelectedSearchField);
} }
catch (Exception ex) catch (Exception ex)
{ {
@@ -434,18 +461,27 @@ namespace Lskj.Control
} }
} }
private void StartExtendedReturnSearch(ExtendedReturnPopupContext context, string keyword) private void StartExtendedReturnSearch(
ExtendedReturnPopupContext context,
string keyword,
string searchField)
{ {
if (context == null || context.Model == null || context.OwnerEdit == null) return; if (context == null || context.Model == null || context.OwnerEdit == null) return;
keyword = (keyword ?? string.Empty).Trim(); keyword = (keyword ?? string.Empty).Trim();
CancelExtendedReturnSearch(context.Model.FieldName); CancelExtendedReturnSearch(context.Model.FieldName);
context.Popup.ResultGrid.DataSource = null; context.Popup.ClearResultAndFilter();
if (keyword.Length == 0) return; if (keyword.Length == 0) return;
ValidateExtendedReturnBusinessConfiguration(context.Model, context.BusinessRow); ValidateExtendedReturnBusinessConfiguration(context.Model, context.BusinessRow);
string sourceSql = ResolveExtendedReturnSourceSql(context.Model, context.BusinessRow); string sourceSql = ResolveExtendedReturnSourceSql(context.Model, context.BusinessRow);
QueueExtendedReturnSearch(context.OwnerEdit, context, sourceSql, keyword); QueueExtendedReturnSearch(
context.OwnerEdit,
context,
sourceSql,
keyword,
searchField,
false);
} }
private void ExtendedReturnSearch_ClearRequested(object sender, EventArgs e) private void ExtendedReturnSearch_ClearRequested(object sender, EventArgs e)
@@ -622,7 +658,9 @@ namespace Lskj.Control
PopupContainerEdit edit, PopupContainerEdit edit,
ExtendedReturnPopupContext context, ExtendedReturnPopupContext context,
string sourceSql, string sourceSql,
string keyword) string keyword,
string searchField,
bool schemaOnly)
{ {
GridColumnModel model = context.Model; GridColumnModel model = context.Model;
ExtendedLookupRequest request; ExtendedLookupRequest request;
@@ -636,8 +674,10 @@ namespace Lskj.Control
DueTime = DateTime.UtcNow, DueTime = DateTime.UtcNow,
FieldName = model.FieldName, FieldName = model.FieldName,
Keyword = keyword, Keyword = keyword,
SearchField = searchField,
SourceSql = sourceSql, SourceSql = sourceSql,
ConnectionString = SqlHelper._connection.ConnectionString, ConnectionString = SqlHelper._connection.ConnectionString,
SchemaOnly = schemaOnly,
Model = model, Model = model,
Editor = edit, Editor = edit,
PopupContext = context, PopupContext = context,
@@ -781,13 +821,18 @@ namespace Lskj.Control
try try
{ {
DataTable schema = GetExtendedReturnSchema(request.FieldName, request.SourceSql, request.ConnectionString); DataTable schema = GetExtendedReturnSchema(request.FieldName, request.SourceSql, request.ConnectionString);
result.Schema = schema;
IList<ExtendedReturnFieldMapping> mappings = ExtendedReturnSupport.ParseResultFields(request.Model.ResultFields); IList<ExtendedReturnFieldMapping> mappings = ExtendedReturnSupport.ParseResultFields(request.Model.ResultFields);
ValidateExtendedReturnSourceColumns(schema.Columns, request.Model, mappings); ValidateExtendedReturnSourceColumns(schema.Columns, request.Model, mappings);
string searchSql = ExtendedReturnSupport.BuildSearchSql(request.SourceSql, schema.Columns, ExtendedLookupMaxRows); if (!request.SchemaOnly)
result.Table = ExecuteExtendedReturnQuery( {
searchSql, string searchSql = ExtendedReturnSupport.BuildSearchSql(
ExtendedReturnSupport.BuildLikeParameterValue(request.Keyword), request.SourceSql, schema.Columns, ExtendedLookupMaxRows, request.SearchField);
request.ConnectionString); result.Table = ExecuteExtendedReturnQuery(
searchSql,
ExtendedReturnSupport.BuildLikeParameterValue(request.Keyword),
request.ConnectionString);
}
} }
catch (Exception ex) catch (Exception ex)
{ {
@@ -802,7 +847,13 @@ namespace Lskj.Control
lock (mExtendedReturnSyncRoot) lock (mExtendedReturnSyncRoot)
{ {
DataTable cachedSchema; DataTable cachedSchema;
if (mExtendedReturnSchemas.TryGetValue(fieldName, out cachedSchema)) return cachedSchema; string cachedSql;
if (mExtendedReturnSchemas.TryGetValue(fieldName, out cachedSchema) &&
mExtendedReturnSchemaSqls.TryGetValue(fieldName, out cachedSql) &&
string.Equals(cachedSql, sourceSql, StringComparison.Ordinal))
{
return cachedSchema;
}
schemaGeneration = mExtendedReturnSchemaGeneration; schemaGeneration = mExtendedReturnSchemaGeneration;
} }
@@ -810,15 +861,38 @@ namespace Lskj.Control
lock (mExtendedReturnSyncRoot) lock (mExtendedReturnSyncRoot)
{ {
DataTable cachedSchema; DataTable cachedSchema;
if (mExtendedReturnSchemas.TryGetValue(fieldName, out cachedSchema)) return cachedSchema; string cachedSql;
if (mExtendedReturnSchemas.TryGetValue(fieldName, out cachedSchema) &&
mExtendedReturnSchemaSqls.TryGetValue(fieldName, out cachedSql) &&
string.Equals(cachedSql, sourceSql, StringComparison.Ordinal))
{
return cachedSchema;
}
if (schemaGeneration == mExtendedReturnSchemaGeneration) if (schemaGeneration == mExtendedReturnSchemaGeneration)
{ {
mExtendedReturnSchemas[fieldName] = schema; mExtendedReturnSchemas[fieldName] = schema;
mExtendedReturnSchemaSqls[fieldName] = sourceSql;
} }
} }
return schema; return schema;
} }
private DataTable TryGetExtendedReturnSchema(string fieldName, string sourceSql)
{
lock (mExtendedReturnSyncRoot)
{
DataTable cachedSchema;
string cachedSql;
if (mExtendedReturnSchemas.TryGetValue(fieldName, out cachedSchema) &&
mExtendedReturnSchemaSqls.TryGetValue(fieldName, out cachedSql) &&
string.Equals(cachedSql, sourceSql, StringComparison.Ordinal))
{
return cachedSchema;
}
return null;
}
}
private static DataTable ExecuteExtendedReturnQuery( private static DataTable ExecuteExtendedReturnQuery(
string commandText, string commandText,
string keywordParameterValue, string keywordParameterValue,
@@ -870,11 +944,13 @@ namespace Lskj.Control
if (state.Version != request.Version) return; if (state.Version != request.Version) return;
} }
ConfigureExtendedReturnSearchColumns(request.PopupContext, result.Schema);
if (result.Error != null) if (result.Error != null)
{ {
MessageUtil.Show("扩展搜索查询失败:" + result.Error.Message); MessageUtil.Show("扩展搜索查询失败:" + result.Error.Message);
return; return;
} }
if (request.SchemaOnly) return;
lock (mExtendedReturnSyncRoot) lock (mExtendedReturnSyncRoot)
{ {
@@ -904,6 +980,27 @@ namespace Lskj.Control
} }
} }
private void ConfigureExtendedReturnSearchColumns(
ExtendedReturnPopupContext context,
DataTable sourceSchema)
{
if (context == null || context.Popup == null || context.Model == null || sourceSchema == null) return;
ExtendedReturnSearchPopup popup = context.Popup;
List<KeyValuePair<string, string>> options = new List<KeyValuePair<string, string>>();
IList<ExtendedReturnFieldMapping> mappings =
ExtendedReturnSupport.ParseResultFields(context.Model.ResultFields);
foreach (DataColumn column in sourceSchema.Columns)
{
if (!ExtendedReturnSupport.IsSearchableColumn(column.ColumnName)) continue;
options.Add(new KeyValuePair<string, string>(
column.ColumnName,
GetExtendedReturnColumnCaption(column.ColumnName, mappings)));
}
popup.SetSearchColumns(options);
}
private void ConfigureExtendedReturnViewColumns(ExtendedReturnPopupContext context, DataTable table) private void ConfigureExtendedReturnViewColumns(ExtendedReturnPopupContext context, DataTable table)
{ {
if (context == null || context.Popup == null || table == null || context.Model == null) return; if (context == null || context.Popup == null || table == null || context.Model == null) return;
@@ -972,7 +1069,7 @@ namespace Lskj.Control
} }
context.OwnerEdit.EditValue = null; context.OwnerEdit.EditValue = null;
context.Popup.ResultGrid.DataSource = null; context.Popup.ClearResultAndFilter();
if (context.OwnerEdit.IsPopupOpen) context.OwnerEdit.ClosePopup(); if (context.OwnerEdit.IsPopupOpen) context.OwnerEdit.ClosePopup();
this.GridView.PostEditor(); this.GridView.PostEditor();
this.GridView.UpdateCurrentRow(); this.GridView.UpdateCurrentRow();
@@ -1002,7 +1099,7 @@ namespace Lskj.Control
ExtendedReturnPopupContext context = GetExtendedReturnPopupContext(model.FieldName); ExtendedReturnPopupContext context = GetExtendedReturnPopupContext(model.FieldName);
CancelExtendedReturnSearch(model.FieldName); CancelExtendedReturnSearch(model.FieldName);
SetExtendedReturnEditorBusinessValue(context); SetExtendedReturnEditorBusinessValue(context);
context.Popup.ResultGrid.DataSource = null; context.Popup.ClearResultAndFilter();
this.GridView.RefreshRow(this.GridView.FocusedRowHandle); this.GridView.RefreshRow(this.GridView.FocusedRowHandle);
} }
catch (Exception ex) catch (Exception ex)
@@ -1192,12 +1289,13 @@ namespace Lskj.Control
lock (mExtendedReturnSyncRoot) lock (mExtendedReturnSyncRoot)
{ {
mExtendedReturnSchemas.Clear(); mExtendedReturnSchemas.Clear();
mExtendedReturnSchemaSqls.Clear();
mExtendedReturnSchemaGeneration++; mExtendedReturnSchemaGeneration++;
} }
foreach (ExtendedReturnPopupContext context in mExtendedReturnPopupContexts.Values) foreach (ExtendedReturnPopupContext context in mExtendedReturnPopupContexts.Values)
{ {
context.Popup.ResultGrid.DataSource = null; context.Popup.ClearResultAndFilter();
} }
} }