SVN r1104
SVN-Revision: r1104
This commit is contained in:
@@ -282,7 +282,18 @@ namespace Lskj.Control.Model
|
||||
/// 刷新明细的序号(排产模块)
|
||||
/// </summary>
|
||||
public string PlanLetfControl;
|
||||
|
||||
/// <summary>
|
||||
/// 隐藏下方操作按钮
|
||||
/// </summary>
|
||||
public bool HideBottomPanel;
|
||||
/// <summary>
|
||||
/// 隐藏下方操作按钮
|
||||
/// </summary>
|
||||
public string ChartText;
|
||||
/// <summary>
|
||||
/// 隐藏下方操作按钮
|
||||
/// </summary>
|
||||
public string ChartTextColor;
|
||||
|
||||
/// <summary>
|
||||
/// 主模块编号
|
||||
@@ -342,4 +353,7 @@ namespace Lskj.Control.Model
|
||||
this.DBClickEvent = item.Table.Columns.Contains("DBClickEvent") ? "1".Equals(item["DBClickEvent"] + "") : false;
|
||||
this.ProhibitRefresh = item.Table.Columns.Contains("ProhibitRefresh") ? "1".Equals(item["ProhibitRefresh"] + "") : false;
|
||||
this.DragExecuteSql = item.Table.Columns.Contains("DragExecuteSql") ? item["DragExecuteSql"] + "" : "";
|
||||
this.QueryAgain = item.Table.Col
|
||||
this.QueryAgain = item.Table.Columns.Contains("QueryAgain") ? "1".Equals(item["QueryAgain"] + "") : false;
|
||||
this.BottomRefreshMain = item.Table.Columns.Contains("BottomRefreshMain") ? "1".Equals(item["BottomRefreshMain"] + "") : false;
|
||||
this.LoadFilter = item.Table.Columns.Contains("LoadFilter") ? "1".Equals(item["LoadFilter"] + "") : false;
|
||||
this.
|
||||
@@ -42,6 +42,7 @@ public static class LabPicUrlPreview
|
||||
|
||||
// 唯一列名(保持你原逻辑)
|
||||
gridColumn.FieldName = string.Format("{0}{1}", model.FieldName, Guid.NewGuid());
|
||||
//gridColumn.FieldName = model.FieldName;
|
||||
gridColumn.Tag = model; // 事件里取模型
|
||||
|
||||
RepositoryItemPictureEdit pictureEdit = new RepositoryItemPictureEdit();
|
||||
@@ -167,7 +168,7 @@ public static class LabPicUrlPreview
|
||||
int listIndex = view.GetDataSourceRowIndex(rowHandle);
|
||||
try
|
||||
{
|
||||
object val2 = view.GetListSourceRowCellValue(listIndex, m.FieldName);
|
||||
object val2 = view.GetListSourceRowCellValue(listIndex, m.FieldName);// "GM_leb_TuShi_ZS"
|
||||
raw = val2 == null ? null : Convert.ToString(val2);
|
||||
}
|
||||
catch { }
|
||||
|
||||
@@ -0,0 +1,546 @@
|
||||
// ============================================================================
|
||||
// LabPicUrlPreview_TreeList.cs (C# 7.3 / DevExpress 15.2 兼容)
|
||||
// - 适配 TreeList:InitPicColumn / Attach / AttachPreview
|
||||
// - 复用原线程安全缓存:缩略图 & 原图分离缓存、并发限流 + LRU 清理
|
||||
// - 同步阶段写 e.Value,异步完成后刷新 TreeList 单元格或预览窗体
|
||||
// ============================================================================
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
|
||||
using DevExpress.Data;
|
||||
using DevExpress.XtraEditors.Controls;
|
||||
using DevExpress.XtraEditors.Repository;
|
||||
using DevExpress.XtraTreeList;
|
||||
using DevExpress.XtraTreeList.Columns;
|
||||
using DevExpress.XtraTreeList.Nodes;
|
||||
using DevExpress.XtraTreeList.ViewInfo;
|
||||
using Lskj.Control.Model;
|
||||
using Lskj.Control;
|
||||
using Lskj.Business;
|
||||
|
||||
public static class LabPicUrlPreview_TreeList
|
||||
{
|
||||
// ====== 对外:初始化图片列(创建 RepositoryItemPictureEdit、设为 Unbound) ======
|
||||
public static void InitPicColumn(TreeList treeList, TreeListColumn treeListColumn, GridColumnModel model)
|
||||
{
|
||||
if (treeList == null || treeListColumn == null || model == null) return;
|
||||
|
||||
treeListColumn.AppearanceCell.Options.UseTextOptions = true;
|
||||
treeListColumn.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center;
|
||||
treeListColumn.OptionsColumn.AllowEdit = false;
|
||||
|
||||
// 唯一列名(保持原逻辑,避免列名重复)
|
||||
treeListColumn.FieldName = string.Format("{0}{1}", model.FieldName, Guid.NewGuid());
|
||||
treeListColumn.Tag = model; // 事件中获取列模型
|
||||
|
||||
RepositoryItemPictureEdit pictureEdit = new RepositoryItemPictureEdit();
|
||||
pictureEdit.ShowMenu = false;
|
||||
pictureEdit.NullText = " ";
|
||||
pictureEdit.SizeMode = PictureSizeMode.Zoom;
|
||||
|
||||
treeList.RepositoryItems.Add(pictureEdit);
|
||||
treeListColumn.UnboundType = DevExpress.XtraTreeList.Data.UnboundColumnType.Object;
|
||||
treeListColumn.ColumnEdit = pictureEdit;
|
||||
}
|
||||
|
||||
// ====== 对外:绑定“取缩略图”的事件(只需调用一次) ======
|
||||
public static void Attach(TreeList treeList)
|
||||
{
|
||||
if (treeList == null) return;
|
||||
treeList.CustomUnboundColumnData -= OnCustomUnboundColumnData;
|
||||
treeList.CustomUnboundColumnData += OnCustomUnboundColumnData;
|
||||
}
|
||||
|
||||
// ====== 对外:绑定“双击大图预览”的事件(只需调用一次) ======
|
||||
public static void AttachPreview(TreeList treeList)
|
||||
{
|
||||
if (treeList == null) return;
|
||||
treeList.DoubleClick -= OnTreeListDoubleClick;
|
||||
treeList.DoubleClick += OnTreeListDoubleClick;
|
||||
}
|
||||
|
||||
// ===================== 缩略图事件实现(核心改造) =====================
|
||||
private static void OnCustomUnboundColumnData(object sender, TreeListCustomColumnDataEventArgs e)
|
||||
{
|
||||
TreeList treeList = sender as TreeList;
|
||||
if (treeList == null) return;
|
||||
|
||||
GridColumnModel m = e.Column.Tag as GridColumnModel;
|
||||
if (m == null || m.FieldType != ControlType.LabPicUrl || !e.IsGetData) return;
|
||||
|
||||
// 1) TreeList 用 Node 直接定位(替代 Grid 的 RowHandle/ListSourceRowIndex)
|
||||
TreeListNode node = e.Node;
|
||||
if (node == null) return;
|
||||
|
||||
// 2) 读取原始 URL(优先 Node 数据,兜底数据源)
|
||||
string raw = null;
|
||||
try
|
||||
{
|
||||
// TreeList 直接从 Node 获取字段值(兼容绑定 DataTable/自定义对象)
|
||||
object val = node.GetValue(m.FieldName);
|
||||
raw = val == null ? null : Convert.ToString(val);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// 兜底:从数据源(如 DataRow)获取
|
||||
DataRow row = node.Tag as DataRow;
|
||||
if (row != null && row.Table.Columns.Contains(m.FieldName))
|
||||
raw = Convert.ToString(row[m.FieldName]);
|
||||
}
|
||||
if (string.IsNullOrWhiteSpace(raw)) return;
|
||||
|
||||
// 3) 拼接完整 URL(复用原逻辑)
|
||||
string url = ResolveFullUrl(raw);
|
||||
|
||||
// 4) 目标高度(复用原逻辑)
|
||||
int targetHeight = NormalizeHeight(m);
|
||||
|
||||
// 5) 缓存命中:同步赋值 e.Value
|
||||
Image img;
|
||||
if (ImageCache.TryGetThumb(url, targetHeight, out img))
|
||||
{
|
||||
e.Value = img;
|
||||
return;
|
||||
}
|
||||
|
||||
// 6) 未命中:异步下载,完成后刷新当前单元格(TreeList 刷新 API 改造)
|
||||
System.Windows.Forms.Control invoker = treeList; // UI 回调对象
|
||||
ImageCache.GetThumbAsync(url, targetHeight, invoker, delegate ()
|
||||
{
|
||||
RefreshCellCompat(treeList, node, e.Column);
|
||||
});
|
||||
}
|
||||
|
||||
// ===================== 双击预览(原图)(核心改造) =====================
|
||||
private static void OnTreeListDoubleClick(object sender, EventArgs e)
|
||||
{
|
||||
TreeList treeList = sender as TreeList;
|
||||
if (treeList == null) return;
|
||||
|
||||
// 1) TreeList 命中测试(替代 Grid 的 CalcHitInfo)
|
||||
TreeListHitInfo hitInfo = treeList.CalcHitInfo(treeList.PointToClient(Control.MousePosition));
|
||||
//if (hitInfo == null || !hitInfo.InNodeCell || hitInfo.Column == null) return;
|
||||
if (hitInfo == null || hitInfo.HitInfoType != HitInfoType.Cell || hitInfo.Node == null || hitInfo.Column == null) return;
|
||||
TreeListNode hitNode = hitInfo.Node;
|
||||
TreeListColumn hitColumn = hitInfo.Column;
|
||||
|
||||
// 2) 只处理 LabPicUrl 类型列
|
||||
GridColumnModel m = hitColumn.Tag as GridColumnModel;
|
||||
if (m == null || m.FieldType != ControlType.LabPicUrl) return;
|
||||
|
||||
// 3) 读取当前 Node 的 URL(TreeList 专属取值逻辑)
|
||||
string raw = null;
|
||||
try
|
||||
{
|
||||
object val = hitNode.GetValue(m.FieldName);
|
||||
raw = val == null ? null : Convert.ToString(val);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// 兜底:从 Node.Tag(如 DataRow)获取
|
||||
DataRow row = hitNode.Tag as DataRow;
|
||||
if (row != null && row.Table.Columns.Contains(m.FieldName))
|
||||
raw = Convert.ToString(row[m.FieldName]);
|
||||
}
|
||||
if (string.IsNullOrWhiteSpace(raw)) return;
|
||||
|
||||
string url = ResolveFullUrl(raw);
|
||||
|
||||
// 4) 打开预览窗体(复用原逻辑,适配 TreeList 数据)
|
||||
Image thumb = null;
|
||||
ImageCache.TryGetThumb(url, NormalizeHeight(m), out thumb);
|
||||
|
||||
FrmTreePicture frm = new FrmTreePicture();
|
||||
try
|
||||
{
|
||||
// 适配 TreeList 列与节点数据(替换原 Grid 的 Column/Row)
|
||||
frm.PicUrlColumns = treeList.Columns.Where(c => c.Tag is GridColumnModel cm && cm.FieldType == ControlType.LabPicUrl).ToList(); // 兼容原窗体列集合类型
|
||||
frm.FocusedRow = hitNode.Tag as DataRow; // 传递 Node 绑定的 DataRow
|
||||
frm.FocusedColumn = hitColumn;
|
||||
frm.Text = "预览";
|
||||
frm.Picture = thumb;
|
||||
frm.WindowState = FormWindowState.Maximized;
|
||||
frm.StartPosition = FormStartPosition.CenterScreen;
|
||||
|
||||
// 异步拉取原图并更新(复用原缓存逻辑)
|
||||
ImageCache.GetFullAsync(url, frm, delegate (Image full)
|
||||
{
|
||||
if (full == null) return;
|
||||
try
|
||||
{
|
||||
if (!frm.IsDisposed) frm.Picture = full;
|
||||
}
|
||||
catch { }
|
||||
});
|
||||
|
||||
frm.ShowDialog();
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (frm != null && !frm.IsDisposed) frm.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
// ====== TreeList 单元格安全刷新(替代 Grid 的 RefreshRowCell) ======
|
||||
private static void RefreshCellCompat(TreeList treeList, TreeListNode node, TreeListColumn column)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (treeList.IsDisposed || node == null || column == null) return;
|
||||
// 整体刷新节点(避免单个单元格刷新失败)
|
||||
if (!treeList.IsDisposed && node != null)
|
||||
treeList.RefreshNode(node);
|
||||
}
|
||||
catch
|
||||
{
|
||||
try
|
||||
{
|
||||
// 刷新整个 TreeList(极端情况)
|
||||
if (!treeList.IsDisposed)
|
||||
treeList.RefreshDataSource();
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ====== 以下方法完全复用原逻辑(无改造) ======
|
||||
private static int NormalizeHeight(object model)
|
||||
{
|
||||
try
|
||||
{
|
||||
var t = model.GetType();
|
||||
|
||||
// 读取属性
|
||||
var pi = t.GetProperty("LabPicUrlHeight");
|
||||
if (pi != null)
|
||||
{
|
||||
int v = Convert.ToInt32(pi.GetValue(model, null));
|
||||
return v <= 18 ? 30 : v;
|
||||
}
|
||||
|
||||
// 读取无参方法
|
||||
var mi = t.GetMethod("LabPicUrlHeight", Type.EmptyTypes);
|
||||
if (mi != null)
|
||||
{
|
||||
int v = Convert.ToInt32(mi.Invoke(model, null));
|
||||
return v <= 18 ? 30 : v;
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
return 30;
|
||||
}
|
||||
|
||||
private static string ResolveFullUrl(string raw)
|
||||
{
|
||||
if (string.IsNullOrEmpty(raw)) return raw;
|
||||
if (raw.StartsWith("http", StringComparison.OrdinalIgnoreCase)) return raw;
|
||||
|
||||
try
|
||||
{
|
||||
string oa = SystemInfo.Instance.OAUrl;
|
||||
if (string.IsNullOrEmpty(oa)) return raw.TrimStart('/');
|
||||
if (!oa.EndsWith("/")) oa += "/";
|
||||
return oa + raw.TrimStart('/');
|
||||
}
|
||||
catch
|
||||
{
|
||||
return raw.TrimStart('/');
|
||||
}
|
||||
}
|
||||
|
||||
// ====== 图片缓存(完全复用原逻辑,无任何改造) ======
|
||||
private static class ImageCache
|
||||
{
|
||||
// —— 公共接口(缩略图) ——
|
||||
public static bool TryGetThumb(string url, int targetHeight, out Image img)
|
||||
{
|
||||
return ThumbCache.TryGet(url, targetHeight, out img);
|
||||
}
|
||||
public static void GetThumbAsync(string url, int targetHeight, System.Windows.Forms.Control invoker, Action onReady)
|
||||
{
|
||||
ThumbCache.GetOrCreateAsync(url, targetHeight, invoker, onReady);
|
||||
}
|
||||
|
||||
// —— 公共接口(原图) ——
|
||||
public static bool TryGetFull(string url, out Image img)
|
||||
{
|
||||
return FullCache.TryGet(url, out img);
|
||||
}
|
||||
public static void GetFullAsync(string url, System.Windows.Forms.Control invoker, Action<Image> onReady)
|
||||
{
|
||||
FullCache.GetOrCreateAsync(url, invoker, onReady);
|
||||
}
|
||||
|
||||
// ===== 缩略图缓存实现 =====
|
||||
private static class ThumbCache
|
||||
{
|
||||
private class CacheEntry
|
||||
{
|
||||
public Image Image;
|
||||
public DateTime LastHitUtc;
|
||||
}
|
||||
|
||||
private static readonly object _lock = new object();
|
||||
private static readonly Dictionary<string, CacheEntry> _cache =
|
||||
new Dictionary<string, CacheEntry>(StringComparer.OrdinalIgnoreCase);
|
||||
private static readonly Dictionary<string, Task<Image>> _tasks =
|
||||
new Dictionary<string, Task<Image>>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
private static readonly Semaphore _throttle = new Semaphore(4, 4); // 并发 4
|
||||
private const int Capacity = 300;
|
||||
|
||||
static ThumbCache()
|
||||
{
|
||||
EnableTls12();
|
||||
}
|
||||
|
||||
private static string MakeKey(string url, int h)
|
||||
{
|
||||
return url + "#h=" + h.ToString();
|
||||
}
|
||||
|
||||
public static bool TryGet(string url, int targetHeight, out Image image)
|
||||
{
|
||||
string key = MakeKey(url, targetHeight);
|
||||
lock (_lock)
|
||||
{
|
||||
CacheEntry e;
|
||||
if (_cache.TryGetValue(key, out e) && e != null && e.Image != null)
|
||||
{
|
||||
e.LastHitUtc = DateTime.UtcNow;
|
||||
_cache[key] = e;
|
||||
image = e.Image;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
image = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void GetOrCreateAsync(string url, int targetHeight, System.Windows.Forms.Control uiInvoker, Action onReady)
|
||||
{
|
||||
string key = MakeKey(url, targetHeight);
|
||||
|
||||
lock (_lock)
|
||||
{
|
||||
if (_cache.ContainsKey(key))
|
||||
{
|
||||
BeginInvokeSafe(uiInvoker, onReady);
|
||||
return;
|
||||
}
|
||||
|
||||
Task<Image> exist;
|
||||
if (_tasks.TryGetValue(key, out exist))
|
||||
{
|
||||
exist.ContinueWith(delegate { BeginInvokeSafe(uiInvoker, onReady); }, TaskScheduler.Default);
|
||||
return;
|
||||
}
|
||||
|
||||
Task<Image> task = Task.Factory.StartNew<Image>(delegate
|
||||
{
|
||||
_throttle.WaitOne();
|
||||
try
|
||||
{
|
||||
byte[] bytes = DownloadBytes(url);
|
||||
if (bytes == null) return null;
|
||||
using (Bitmap src = BytesToBitmap(bytes))
|
||||
{
|
||||
return ScaleBitmap(src, targetHeight);
|
||||
}
|
||||
}
|
||||
catch { return null; }
|
||||
finally { try { _throttle.Release(); } catch { } }
|
||||
}, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default).ContinueWith<Image>(delegate (Task<Image> t)
|
||||
{
|
||||
Image result = t.Result;
|
||||
lock (_lock)
|
||||
{
|
||||
_tasks.Remove(key);
|
||||
if (result != null)
|
||||
{
|
||||
_cache[key] = new CacheEntry { Image = result, LastHitUtc = DateTime.UtcNow };
|
||||
TrimIfNeededUnsafe();
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}, TaskScheduler.Default);
|
||||
|
||||
_tasks[key] = task;
|
||||
task.ContinueWith(delegate { BeginInvokeSafe(uiInvoker, onReady); }, TaskScheduler.Default);
|
||||
}
|
||||
}
|
||||
|
||||
private static void TrimIfNeededUnsafe()
|
||||
{
|
||||
if (_cache.Count <= Capacity) return;
|
||||
List<KeyValuePair<string, CacheEntry>> list = _cache.ToList();
|
||||
list.Sort(delegate (KeyValuePair<string, CacheEntry> a, KeyValuePair<string, CacheEntry> b)
|
||||
{
|
||||
return a.Value.LastHitUtc.CompareTo(b.Value.LastHitUtc);
|
||||
});
|
||||
int removeCount = Math.Max(1, Capacity / 10);
|
||||
for (int i = 0; i < removeCount && i < list.Count; i++)
|
||||
{
|
||||
string k = list[i].Key;
|
||||
CacheEntry e;
|
||||
if (_cache.TryGetValue(k, out e))
|
||||
{
|
||||
_cache.Remove(k);
|
||||
try { if (e.Image != null) e.Image.Dispose(); } catch { }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ===== 原图缓存实现(容量更小) =====
|
||||
private static class FullCache
|
||||
{
|
||||
private class CacheEntry
|
||||
{
|
||||
public Image Image;
|
||||
public DateTime LastHitUtc;
|
||||
}
|
||||
|
||||
private static readonly object _lock = new object();
|
||||
private static readonly Dictionary<string, CacheEntry> _cache =
|
||||
new Dictionary<string, CacheEntry>(StringComparer.OrdinalIgnoreCase);
|
||||
private static readonly Dictionary<string, Task<Image>> _tasks =
|
||||
new Dictionary<string, Task<Image>>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
private static readonly Semaphore _throttle = new Semaphore(2, 2); // 原图并发更小
|
||||
private const int Capacity = 50;
|
||||
|
||||
static FullCache()
|
||||
{
|
||||
EnableTls12();
|
||||
}
|
||||
|
||||
public static bool TryGet(string url, out Image image)
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
CacheEntry e;
|
||||
if (_cache.TryGetValue(url, out e) && e != null && e.Image != null)
|
||||
{
|
||||
e.LastHitUtc = DateTime.UtcNow;
|
||||
_cache[url] = e;
|
||||
image = e.Image;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
image = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void GetOrCreateAsync(string url, System.Windows.Forms.Control uiInvoker, Action<Image> onReady)
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
Image cached;
|
||||
if (TryGet(url, out cached))
|
||||
{
|
||||
BeginInvokeSafe(uiInvoker, delegate { onReady(cached); });
|
||||
return;
|
||||
}
|
||||
|
||||
Task<Image> exist;
|
||||
if (_tasks.TryGetValue(url, out exist))
|
||||
{
|
||||
exist.ContinueWith(t => BeginInvokeSafe(uiInvoker, delegate { onReady(t.Result); }), TaskScheduler.Default);
|
||||
return;
|
||||
}
|
||||
|
||||
Task<Image> task = Task.Factory.StartNew<Image>(delegate
|
||||
{
|
||||
_throttle.WaitOne();
|
||||
try
|
||||
{
|
||||
byte[] bytes = DownloadBytes(url);
|
||||
if (bytes == null) return null;
|
||||
using (Bitmap bmp = BytesToBitmap(bytes))
|
||||
{
|
||||
return CopyBitmap(bmp);
|
||||
}
|
||||
}
|
||||
catch { return null; }
|
||||
finally { try { _throttle.Release(); } catch { } }
|
||||
}, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default).ContinueWith<Image>(delegate (Task<Image> t)
|
||||
{
|
||||
Image result = t.Result;
|
||||
lock (_lock)
|
||||
{
|
||||
_tasks.Remove(url);
|
||||
if (result != null)
|
||||
{
|
||||
_cache[url] = new CacheEntry { Image = result, LastHitUtc = DateTime.UtcNow };
|
||||
TrimIfNeededUnsafe();
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}, TaskScheduler.Default);
|
||||
|
||||
_tasks[url] = task;
|
||||
task.ContinueWith(t => BeginInvokeSafe(uiInvoker, delegate { onReady(t.Result); }), TaskScheduler.Default);
|
||||
}
|
||||
}
|
||||
|
||||
private static void TrimIfNeededUnsafe()
|
||||
{
|
||||
if (_cache.Count <= Capacity) return;
|
||||
List<KeyValuePair<string, CacheEntry>> list = _cache.ToList();
|
||||
list.Sort(delegate (KeyValuePair<string, CacheEntry> a, KeyValuePair<string, CacheEntry> b)
|
||||
{
|
||||
return a.Value.LastHitUtc.CompareTo(b.Value.LastHitUtc);
|
||||
});
|
||||
int removeCount = Math.Max(1, Capacity / 10);
|
||||
for (int i = 0; i < removeCount && i < list.Count; i++)
|
||||
{
|
||||
string k = list[i].Key;
|
||||
CacheEntry e;
|
||||
if (_cache.TryGetValue(k, out e))
|
||||
{
|
||||
_cache.Remove(k);
|
||||
try { if (e.Image != null) e.Image.Dispose(); } catch { }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ===== 共享底层工具 =====
|
||||
private static void EnableTls12()
|
||||
{
|
||||
try
|
||||
{
|
||||
const System.Security.Authentication.SslProtocols _Tls12 =
|
||||
(System.Security.Authentication.SslProtocols)0x00000C00;
|
||||
ServicePointManager.SecurityProtocol |= (SecurityProtocolType)_Tls12;
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
private static byte[] DownloadBytes(string url)
|
||||
{
|
||||
using (WebClient wc = new WebClient())
|
||||
{
|
||||
return wc.DownloadData(url);
|
||||
}
|
||||
}
|
||||
|
||||
private static Bitmap BytesToBitmap(byte[] bytes)
|
||||
{
|
||||
using (MemoryStream ms = new MemoryStream(bytes))
|
||||
{
|
||||
using (Image img = Image.FromStream(ms))
|
||||
{
|
||||
return new
|
||||
@@ -34,6 +34,8 @@ using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading;
|
||||
using System.Web;
|
||||
using System.Windows.Forms;
|
||||
|
||||
@@ -100,22 +102,22 @@ namespace Lskj.Control.Model
|
||||
|
||||
//判断是否存在网址框(需要绑定右键打开事件判断是否生成 网址框右键)
|
||||
bool existLabWWW = false;
|
||||
if (view is GridControlEx)
|
||||
if (view is GridControlEx)
|
||||
{
|
||||
GridControlEx grid= view as GridControlEx;
|
||||
foreach (GridColumn item in grid.GridView.Columns)
|
||||
GridControlEx grid = view as GridControlEx;
|
||||
foreach (GridColumn item in grid.GridView.Columns)
|
||||
{
|
||||
if (item.Tag is GridColumnModel)
|
||||
if (item.Tag is GridColumnModel)
|
||||
{
|
||||
GridColumnModel gridColumnModel = item.Tag as GridColumnModel;
|
||||
if (gridColumnModel.FieldType == ControlType.LabWWW) existLabWWW = true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (((table == null || table.Rows.Count == 0) && menu == null)&& !existLabWWW) return;
|
||||
if (((table == null || table.Rows.Count == 0) && menu == null) && !existLabWWW) return;
|
||||
|
||||
ContextMenuStrip cmsMenu = new ContextMenuStrip();
|
||||
cmsMenu.Opening += new CancelEventHandler(MenuStripOpening);
|
||||
@@ -274,17 +276,20 @@ namespace Lskj.Control.Model
|
||||
|
||||
ToolStripMenuItem item = sender as ToolStripMenuItem;
|
||||
DXMenuItem items = sender as DXMenuItem;
|
||||
|
||||
|
||||
|
||||
DataRow[] rowArray = GetSelectedRows();
|
||||
GridRightMenuModel model = item == null ? items.Tag as GridRightMenuModel : item.Tag as GridRightMenuModel;
|
||||
|
||||
|
||||
if (!model.Mergeexec && !model.MoreClick && rowArray.Length > 1)
|
||||
{
|
||||
MessageUtil.Show(string.Format(ResourceKeys.ExecRightMenuOnlyOne, model.MenuName));
|
||||
return;
|
||||
}
|
||||
|
||||
if (model.AllowNullExec && rowArray.Length == 0)
|
||||
{
|
||||
rowArray = new DataRow[] { new DataTable().NewRow() };
|
||||
}
|
||||
if (rowArray.Length == 0 && model.IsMustSelectRow())
|
||||
{
|
||||
MessageUtil.Show(ResourceKeys.SelectRowIsNull);
|
||||
@@ -341,9 +346,9 @@ namespace Lskj.Control.Model
|
||||
MessageUtil.Show(Message, ex.Message);
|
||||
LogHelper.Instance.WriteError(ex);
|
||||
}
|
||||
finally
|
||||
finally
|
||||
{
|
||||
if(!string.IsNullOrEmpty(model.UnionZTid))ToDBatching(AccountItem, AccountItem);
|
||||
if (!string.IsNullOrEmpty(model.UnionZTid)) ToDBatching(AccountItem, AccountItem);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
@@ -449,7 +454,7 @@ namespace Lskj.Control.Model
|
||||
|
||||
string actionSql = string.Empty;
|
||||
bool execOnlyOne = IsExecOnlyOne(model, paramListEx, rows, out actionSql);
|
||||
|
||||
|
||||
bool tipOnlyOne = true; // 执行是否提示一次
|
||||
bool allowBefore = ApiHelper.IsExecEventApi(Interface.Api.OperateEvent.BeforeModuleContextMenu, Model.ModuleCode, model.Id);
|
||||
bool allowAfter = ApiHelper.IsExecEventApi(Interface.Api.OperateEvent.AfterModuleContextMenu, Model.ModuleCode, model.Id);
|
||||
@@ -531,25 +536,74 @@ namespace Lskj.Control.Model
|
||||
// 特殊处理程序
|
||||
else if (dllName.Contains(".exe") && !model.WipeExes.Contains(dllName.ToString()) && (dllName.ToLower() != "lstest.exe"))
|
||||
{
|
||||
//删除选中行的json信息
|
||||
if(!string.IsNullOrWhiteSpace(maintabFocusedRowJson))paramList.Remove(maintabFocusedRowJson);
|
||||
// 创建进程启动信息对象
|
||||
ProcessStartInfo startInfo = new ProcessStartInfo();
|
||||
startInfo.FileName = File.Exists(dllName) ? dllName : PubUtil.AbsolutelyLibPath + dllName; // 指定要启动的 EXE 路径
|
||||
// 将参数数组拼接为命令行字符串(注意空格处理)
|
||||
// 若参数包含空格,需要用双引号包裹,避免被解析为多个参数
|
||||
startInfo.Arguments = string.Join(" ", paramList.Select(arg =>
|
||||
arg.Contains(" ") ? $"\"{arg}\"" : arg
|
||||
));
|
||||
// 可选:设置进程启动选项
|
||||
startInfo.UseShellExecute = false; // 不使用系统外壳程序(建议为 false,便于重定向输入输出)
|
||||
startInfo.CreateNoWindow = false; // 是否在新窗口中启动(false 为显示窗口)
|
||||
// 启动进程
|
||||
Process process = Process.Start(startInfo);
|
||||
|
||||
// 执行exe程序
|
||||
//WinHelper.WinExec(File.Exists(dllName) ? dllName : PubUtil.AbsolutelyLibPath + dllName, 1);
|
||||
// WinHelper.WinExec(dllName);
|
||||
string[] dllNameSplit = Regex.Split(dllName, ":args=");
|
||||
string[] pmsSplit = dllNameSplit.Length > 1 ? (dllNameSplit[1] + "").Split(',') : null;
|
||||
if (dllNameSplit.Length > 1 && pmsSplit != null && pmsSplit.Length > 0)//嵌入exe模块
|
||||
{
|
||||
string[] pmsArgs = pmsSplit.Select(pms => ReplaceHelper.ReplaceUserInfo(pms)).ToArray();
|
||||
string guid = Guid.NewGuid().ToString();
|
||||
Panel mainPanel = new Panel();
|
||||
ProcessStartInfo processStartInfo = new ProcessStartInfo()
|
||||
{
|
||||
FileName = dllNameSplit[0],
|
||||
Arguments = HandleHelper.CombineArgs(pmsArgs),
|
||||
UseShellExecute = false,
|
||||
RedirectStandardOutput = false,
|
||||
RedirectStandardError = false,
|
||||
CreateNoWindow = false
|
||||
};
|
||||
Process startedProcess = Process.Start(processStartInfo);
|
||||
if (startedProcess == null)
|
||||
{
|
||||
MessageUtil.Show("进程启动失败");
|
||||
return false;
|
||||
}
|
||||
startedProcess.WaitForInputIdle();
|
||||
int retry = 0;
|
||||
while (startedProcess.MainWindowHandle == IntPtr.Zero && retry < 500)
|
||||
{
|
||||
Thread.Sleep(100);
|
||||
startedProcess.Refresh();
|
||||
retry++;
|
||||
}
|
||||
IntPtr exeMainHandle = startedProcess.MainWindowHandle;
|
||||
if (exeMainHandle == IntPtr.Zero)
|
||||
{
|
||||
MessageBox.Show("无法获取启动程序的主窗口句柄");
|
||||
return false;
|
||||
}
|
||||
HandleHelper.SetFormNoneStyle(exeMainHandle, mainPanel);
|
||||
mainPanel.Dock = DockStyle.Fill;
|
||||
using (BaseForm baseForm = new BaseForm())
|
||||
{
|
||||
baseForm.WindowState = FormWindowState.Maximized;
|
||||
baseForm.Controls.Add(mainPanel);
|
||||
baseForm.ShowDialog();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//删除选中行的json信息
|
||||
if (!string.IsNullOrWhiteSpace(maintabFocusedRowJson)) paramList.Remove(maintabFocusedRowJson);
|
||||
// 创建进程启动信息对象
|
||||
ProcessStartInfo startInfo = new ProcessStartInfo();
|
||||
startInfo.FileName = File.Exists(dllName) ? dllName : PubUtil.AbsolutelyLibPath + dllName; // 指定要启动的 EXE 路径
|
||||
// 将参数数组拼接为命令行字符串(注意空格处理)
|
||||
// 若参数包含空格,需要用双引号包裹,避免被解析为多个参数
|
||||
startInfo.Arguments = string.Join(" ", paramList.Select(arg =>
|
||||
arg.Contains(" ") ? $"\"{arg}\"" : arg
|
||||
));
|
||||
// 可选:设置进程启动选项
|
||||
startInfo.UseShellExecute = false; // 不使用系统外壳程序(建议为 false,便于重定向输入输出)
|
||||
startInfo.CreateNoWindow = false; // 是否在新窗口中启动(false 为显示窗口)
|
||||
// 启动进程
|
||||
Process process = Process.Start(startInfo);
|
||||
|
||||
// 执行exe程序
|
||||
//WinHelper.WinExec(File.Exists(dllName) ? dllName : PubUtil.AbsolutelyLibPath + dllName, 1);
|
||||
}
|
||||
}
|
||||
else if (dllName.StartsWith("www.") ||
|
||||
dllName.StartsWith("http://") ||
|
||||
@@ -580,7 +634,7 @@ namespace Lskj.Control.Model
|
||||
switch (model.ActionType)
|
||||
{
|
||||
case 1: // 执行存储过程
|
||||
if (i == rows.Length - 1 || execOnlyOne )
|
||||
if (i == rows.Length - 1 || execOnlyOne)
|
||||
{
|
||||
//执行最后一条
|
||||
FinallySucceeded = true;
|
||||
@@ -633,8 +687,13 @@ namespace Lskj.Control.Model
|
||||
return resultValue;
|
||||
}
|
||||
|
||||
|
||||
public bool OpenFrmcCover(GridRightMenuModel model, List<string> paramList)
|
||||
/// <summary>
|
||||
/// 导入数据或者反写到界面
|
||||
/// </summary>
|
||||
/// <param name="model"></param>
|
||||
/// <param name="paramList"></param>
|
||||
/// <returns></returns>
|
||||
public bool OpenFrmcCover(GridRightMenuModel model, List<string> paramList)
|
||||
{
|
||||
|
||||
bool importIntoDatabase = false;
|
||||
@@ -647,32 +706,58 @@ namespace Lskj.Control.Model
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
//模式2,保存到数据库中,在执行保存后sql
|
||||
importIntoDatabase = true;
|
||||
if (string.IsNullOrWhiteSpace(paramList[1]) )
|
||||
if (string.IsNullOrWhiteSpace(paramList[1]))
|
||||
{
|
||||
MessageUtil.Show("模块编号未配置");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
string primaryKey = paramList[2];
|
||||
FrmCover frmCover = new FrmCover(importIntoDatabase,paramList[1], paramList[2], paramList[3]);
|
||||
if (frmCover.ShowDialog() == DialogResult.OK&& !importIntoDatabase)
|
||||
FrmCover frmCover = new FrmCover(importIntoDatabase, paramList[1], paramList[2], paramList[3]);
|
||||
if (frmCover.ShowDialog() == DialogResult.OK && !importIntoDatabase)
|
||||
{
|
||||
//反写数据源
|
||||
DataTable ReverseData = frmCover.ReverseData;
|
||||
//外部数据
|
||||
DataTable table = GetDataTable();
|
||||
|
||||
// 2. 筛选出 ReverseData 和 table 中名称和数据类型都相同的列(排除主键列,避免重复赋值)
|
||||
|
||||
// 提取 ReverseData 中所有的主键值
|
||||
HashSet<object> reversePrimaryKeys = new HashSet<object>(
|
||||
ReverseData.AsEnumerable()
|
||||
.Select(dr => dr[primaryKey])
|
||||
.Where(val => val != DBNull.Value && val != null)
|
||||
);
|
||||
// 获取table中,没有更新的行(在ReverseData中没有对应主键)
|
||||
IEnumerable<DataRow> noUpdateRows = table.AsEnumerable()
|
||||
.Where(dr => dr[primaryKey] != DBNull.Value && dr[primaryKey] != null
|
||||
&& !reversePrimaryKeys.Contains(dr[primaryKey]));
|
||||
//提示存在没有更新的行
|
||||
if (noUpdateRows.Any())
|
||||
{
|
||||
// 提示没有反写的数据
|
||||
string noUpdateIds = string.Join("、", noUpdateRows.Select(dr => dr[primaryKey].ToString()));
|
||||
string text = string.Format("有 {0} 条数据未更新,主键为:{1} \r\n请确认是否要继续", noUpdateRows.Count(), noUpdateIds);
|
||||
DialogResult result = MessageUtil.Show(text, MessageBoxButtons.YesNo);
|
||||
if (result != DialogResult.Yes)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
//筛选出 ReverseData 和 table 中名称和数据类型都相同的列(排除主键列,避免重复赋值)
|
||||
var commonColumns = ReverseData.Columns.Cast<DataColumn>()
|
||||
.Where(col1 => col1.ColumnName != primaryKey // 跳过 id 列(无需更新)
|
||||
&& table.Columns.Contains(col1.ColumnName) // 列名存在于 table2
|
||||
)
|
||||
)
|
||||
.Select(col => col.ColumnName)
|
||||
.ToList();
|
||||
|
||||
@@ -691,7 +776,7 @@ namespace Lskj.Control.Model
|
||||
continue; // 跳过 id 为空的行
|
||||
|
||||
// 在 table2 中查找 id 匹配的行(使用 Select 方法快速定位)
|
||||
DataRow[] matchedRows = table.Select($""+ primaryKey + " = '"+ idValue + "'");
|
||||
DataRow[] matchedRows = table.Select($"" + primaryKey + " = '" + idValue + "'");
|
||||
|
||||
// 只处理找到唯一匹配行的情况
|
||||
if (matchedRows.Length == 1)
|
||||
@@ -855,9 +940,9 @@ namespace Lskj.Control.Model
|
||||
catch (Exception)
|
||||
{
|
||||
result = 0;
|
||||
if (result==0 )
|
||||
if (result == 0)
|
||||
{
|
||||
SqlStoredProcedurepPrompt.GenerateProcedureExecutionScript(procName, paramList, isFirstFlag, comfirmFlag );
|
||||
SqlStoredProcedurepPrompt.GenerateProcedureExecutionScript(procName, paramList, isFirstFlag, comfirmFlag);
|
||||
}
|
||||
}
|
||||
finally
|
||||
@@ -1011,7 +1096,7 @@ namespace Lskj.Control.Model
|
||||
/// <para>版本:1.0</para>
|
||||
/// </summary>
|
||||
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>
|
||||
private bool ExecDynamicLinkLibary(GridRightMenuModel model, List<string> paramList, string dllName, bool isAddPage = false,DataRow rowData = null)
|
||||
private bool ExecDynamicLinkLibary(GridRightMenuModel model, List<string> paramList, string dllName, bool isAddPage = false, DataRow rowData = null)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(dllName))
|
||||
{
|
||||
@@ -1214,7 +1299,8 @@ namespace Lskj.Control.Model
|
||||
{
|
||||
form.SubForm.Show();
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
form.SubForm.ShowDialog();
|
||||
StaticControl.DogVerifyNoPageForms.Remove(form);
|
||||
form.SubForm.Dispose();
|
||||
@@ -1227,7 +1313,7 @@ namespace Lskj.Control.Model
|
||||
XtraTabPage tp = new XtraTabPage();
|
||||
tp.Text = model.MenuName;
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(model.PageName))
|
||||
if (!string.IsNullOrWhiteSpace(model.PageName))
|
||||
{
|
||||
tp.Text = ReplaceHelper.ReplaceRowParam(rowData, model.PageName).Trim();
|
||||
}
|
||||
@@ -1288,8 +1374,8 @@ namespace Lskj.Control.Model
|
||||
int filequency = 0;
|
||||
bool isOpenvisble = rows.Count() > 0;
|
||||
string parmaryKey = BaseImpl.GetBasePrimaryKey(this.Model.ModuleCode);//获取主键
|
||||
//string detailparmaryKey = parmaryKey;
|
||||
List <GridDetailModel> details = GetDetails(Model.ModuleCode);//捕获所有明细 // 2. 筛选出 “关联下载” 的明细
|
||||
//string detailparmaryKey = parmaryKey;
|
||||
List<GridDetailModel> details = GetDetails(Model.ModuleCode);//捕获所有明细 // 2. 筛选出 “关联下载” 的明细
|
||||
List<GridDetailModel> downloadRelated = details
|
||||
.Where(d => d.IsDownloadRelated) // 只保留 IsDownloadRelated 为 true 的项
|
||||
.ToList();
|
||||
@@ -1308,7 +1394,7 @@ namespace Lskj.Control.Model
|
||||
{
|
||||
foreach (DataRow row in dataTable.Rows)
|
||||
{
|
||||
|
||||
|
||||
string url = row["webpath"] + "";
|
||||
if (!string.IsNullOrEmpty(url))
|
||||
{
|
||||
@@ -1423,7 +1509,8 @@ namespace Lskj.Control.Model
|
||||
MessageUtil.Show("未配置关联明细数据");
|
||||
}
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
|
||||
MessageUtil.Show("没有需要下载的数据");
|
||||
}
|
||||
@@ -1446,7 +1533,7 @@ namespace Lskj.Control.Model
|
||||
List<SqlParameter> sqlParamList = new List<SqlParameter>();
|
||||
SqlParameter pMsg = new SqlParameter("@msg", SqlDbType.VarChar, 2000);
|
||||
SqlParameter pComfirmFlag = new SqlParameter("@comfirmFlag", SqlDbType.Int);
|
||||
paramList = model.Mergeexec? paramList:this.HandleRightMenuParams(model.ParamList,dataRow, null, model.ActionType);
|
||||
paramList = model.Mergeexec ? paramList : this.HandleRightMenuParams(model.ParamList, dataRow, null, model.ActionType);
|
||||
for (int i = 0; i < paramStr.Length; i++)
|
||||
{
|
||||
string item = paramStr[i];
|
||||
@@ -1588,7 +1675,7 @@ namespace Lskj.Control.Model
|
||||
/// <param name="model">The model.</param>
|
||||
/// <param name="rowItem">The row item.</param>
|
||||
/// <returns>System.String.</returns>
|
||||
protected string GetSearchSql(GridDetailModel model, DataRow rowItem,string ParmaryKey)
|
||||
protected string GetSearchSql(GridDetailModel model, DataRow rowItem, string ParmaryKey)
|
||||
{
|
||||
string fieldName = !string.IsNullOrEmpty(model.UnionParentField) && rowItem.Table.Columns.Contains(model.UnionParentField) ? model.UnionParentField : ParmaryKey;
|
||||
string sqlValue = model.IsReadOnly || model.IsChart ? model.DetailSql : model.SystemModel.MenuSql;
|
||||
@@ -1778,10 +1865,10 @@ namespace Lskj.Control.Model
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取外面的数据源
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
/// <summary>
|
||||
/// 获取外面的数据源
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
protected virtual DataTable GetDataTable()
|
||||
{
|
||||
return null;
|
||||
@@ -1972,28 +2059,4 @@ namespace Lskj.Control.Model
|
||||
DataRow[] dataRows = columnsTab.Select().Where(n => (n["name"] + "").Equals(colunmField.Key)).ToArray();
|
||||
if (dataRows.Length == 0)
|
||||
{
|
||||
string addColSql = string.Format("alter table P_PrivateDllTab add {0} {1}", colunmField.Key, colunmField.Value);
|
||||
SqlHelper.ExecuteNonQuery(addColSql);//添加列
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
string createTabSql = "create table P_PrivateDllTab(id int IDENTITY(1,1) NOT NULL,{0})";
|
||||
string createCol = string.Empty;
|
||||
foreach (KeyValuePair<string, string> colunmField in colDic)
|
||||
{
|
||||
createCol += string.Format("{0} {1},", colunmField.Key, colunmField.Value);
|
||||
}
|
||||
createTabSql = string.Format(createTabSql, createCol.TrimEnd(','));
|
||||
SqlHelper.ExecuteNonQuery(createTabSql);//创建表
|
||||
}
|
||||
return true;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
string a
|
||||
@@ -327,6 +327,12 @@ namespace Lskj.Control.Model
|
||||
/// 页签名称(审核模块以页签形式打开,可以配置单据id)
|
||||
/// </summary>
|
||||
public string PageName;
|
||||
/// <summary>
|
||||
/// 右键菜单是否可用条件2(单据模块中使用。点击时实时判断主键控件是否满足条件,MenuCond之前写成了重置按钮时根据主表判断是否可以交互。)
|
||||
/// </summary>
|
||||
/// <value>The menu cond.</value>
|
||||
public string ClickCond;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 需要单独处理的exe程序
|
||||
@@ -451,4 +457,5 @@ namespace Lskj.Control.Model
|
||||
if (item.Table.Columns.Contains("DuringExecutionMinimize"))
|
||||
this.DuringExecutionMinimize = string.IsNullOrWhiteSpace(item["DuringExecutionMinimize"] + "") ? false : "1".Equals(item["DuringExecutionMinimize"] + "");
|
||||
if (item.Table.Columns.Contains("SqlDirectExecution"))
|
||||
this.SqlDirectExecution = string.IsNullOrWhi
|
||||
this.SqlDirectExecution = string.IsNullOrWhiteSpace(item["SqlDirectExecution"] + "") ? false : "1".Equals(item["SqlDirectExecution"] + "");
|
||||
if (item
|
||||
@@ -156,7 +156,10 @@ namespace Lskj.Control.Model
|
||||
///单据特殊模块id(单据来源控件)
|
||||
/// </summary>
|
||||
public string BillSourceControlId = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
///特殊左侧表
|
||||
/// </summary>
|
||||
public GridControlEx SpecialLeftTable;
|
||||
|
||||
/// <summary>
|
||||
/// 执行查询之前验证
|
||||
@@ -859,6 +862,10 @@ namespace Lskj.Control.Model
|
||||
{
|
||||
return BaseImpl.GetDefaultValue(item["defaultValue"] + "", ParentKey, OtherParams);
|
||||
}));
|
||||
Task<string> LookupSqlTask = cachesDic.AddTask(item, "LookupSql", new Task<string>(() =>
|
||||
{
|
||||
return BaseImpl.SpecialReplacement(item["lookupSql"] + "", OtherParams);
|
||||
}));
|
||||
Task<ControlModel> controlModelTask = cachesDic.AddTask(item, "ControlModel", new Task<ControlModel>(() =>
|
||||
{
|
||||
ControlModel controlModel = GetControlModel(item);//获取控件对象
|
||||
@@ -1255,6 +1262,10 @@ namespace Lskj.Control.Model
|
||||
{
|
||||
return BaseImpl.GetDefaultValue(item["defaultValue"] + "", ParentKey, OtherParams);
|
||||
}));
|
||||
Task<string> LookupSqlTask = cachesDic.AddTask(item, "LookupSql", new Task<string>(() =>
|
||||
{
|
||||
return BaseImpl.SpecialReplacement(item["lookupSql"] + "", OtherParams);
|
||||
}));
|
||||
Task<ControlModel> controlModelTask = cachesDic.AddTask(item, "ControlModel", new Task<ControlModel>(() =>
|
||||
{
|
||||
ControlModel controlModel = GetControlModel(item);//获取控件对象
|
||||
@@ -1693,7 +1704,7 @@ namespace Lskj.Control.Model
|
||||
/// </summary>
|
||||
/// <param name="rowItem">The row item.</param>
|
||||
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>
|
||||
public void CopyControlValue(bool refreshSearchSource = false)
|
||||
public void CopyControlValue(bool Association = true,bool refreshSearchSource = false)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -1759,15 +1770,19 @@ namespace Lskj.Control.Model
|
||||
}
|
||||
}
|
||||
|
||||
foreach (ControlModel model in this.ControlModels)
|
||||
if (Association)
|
||||
{
|
||||
BaseUserControl control = FindControl(model);
|
||||
// 树结构节点不清空数据
|
||||
if (control != null && model.FieldType != ControlType.LabTreeType)
|
||||
foreach (ControlModel model in this.ControlModels)
|
||||
{
|
||||
this.SetUnionAncCalcControl(control);
|
||||
BaseUserControl control = FindControl(model);
|
||||
// 树结构节点不清空数据
|
||||
if (control != null && model.FieldType != ControlType.LabTreeType)
|
||||
{
|
||||
this.SetUnionAncCalcControl(control);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -4018,7 +4033,14 @@ namespace Lskj.Control.Model
|
||||
model.Sign = item.Table.Columns.Contains("TM_tagID") && !string.IsNullOrEmpty(item["TM_tagID"] + "") ? Convert.ToInt32(item["TM_tagID"] + "") : 0;
|
||||
model.TextMember = item["lookupResult"] + "";
|
||||
model.ValueMember = item["lookupKeyField"] + "";
|
||||
model.SourceSql = item["lookupSql"] + "";
|
||||
|
||||
|
||||
if (!dataCaches.GetValue(item, "LookupSql", out string lookupSql))
|
||||
{
|
||||
lookupSql=BaseImpl.SpecialReplacement(item["lookupSql"] + "",OtherParams);
|
||||
}
|
||||
//model.SourceSql = item["lookupSql"] + "";
|
||||
model.SourceSql = lookupSql;
|
||||
model.NullText = item.Table.Columns.Contains("InputHintText") ? item["InputHintText"] + "" : string.Empty;
|
||||
model.TabOrder = item.Table.Columns.Contains("TabOrder") && !string.IsNullOrEmpty(item["TabOrder"] + "") ? Convert.ToInt32(item["TabOrder"] + "") : 0;
|
||||
model.CalcExpr = item.Table.Columns.Contains("CalcExpr") ? item["CalcExpr"] + "" : string.Empty;
|
||||
@@ -4186,6 +4208,7 @@ namespace Lskj.Control.Model
|
||||
{
|
||||
dateEdit.TextEdit.Properties.VistaCalendarViewStyle = DevExpress.XtraEditors.VistaCalendarViewStyle.YearView;
|
||||
}
|
||||
|
||||
baseControl = dateEdit;
|
||||
break;
|
||||
case ControlType.LabComboxValue:
|
||||
@@ -5459,6 +5482,24 @@ namespace Lskj.Control.Model
|
||||
}
|
||||
|
||||
}
|
||||
if (SpecialLeftTable != null)
|
||||
{
|
||||
GridView gridview = SpecialLeftTable.GridControl.DefaultView as GridView;
|
||||
DataRow rowItem = gridview.GetFocusedDataRow();
|
||||
if (rowItem != null)
|
||||
{
|
||||
sqlValue = ReplaceHelper.ReplaceRowParam(rowItem, sqlValue);
|
||||
}
|
||||
if (SpecialLeftTable is TreeGridControlEx)
|
||||
{
|
||||
rowItem = SpecialLeftTable.GetViewFocusedDataRow();
|
||||
if (rowItem != null)
|
||||
{
|
||||
sqlValue = ReplaceHelper.ReplaceRowParam(rowItem, sqlValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ReplaceHelper.ReplaceWhereCond(sqlValue) + WhereCond;
|
||||
}
|
||||
/// <summary>
|
||||
|
||||
@@ -49,4 +49,5 @@ namespace Lskj.Control.Model
|
||||
public static KeyValuePair<string, GridControlEx> AddParentGrid = new KeyValuePair<string, GridControlEx>();
|
||||
/// <summary>
|
||||
/// 当前右键点击时的表格
|
||||
/// </summa
|
||||
/// </summary>
|
||||
public static GridView _
|
||||
Reference in New Issue
Block a user