CommonHelper.cs 45 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108
  1. using DirectService.Tools;
  2. using JLHHJSvr.BLL;
  3. using JLHHJSvr.Com;
  4. using JLHHJSvr.LJException;
  5. using JLHHJSvr.Tools;
  6. using LJLib.DAL.SQL;
  7. using LJLib.SQLEX;
  8. using Newtonsoft.Json;
  9. using Newtonsoft.Json.Linq;
  10. using PhoneUI.BLL.L1BLL;
  11. using System;
  12. using System.Collections.Generic;
  13. using System.Data;
  14. using System.Data.SqlClient;
  15. using System.Diagnostics;
  16. using System.IO;
  17. using System.Linq;
  18. using System.Text;
  19. using System.Text.RegularExpressions;
  20. using System.Xml;
  21. using static LJLib.DAL.SQL.SqlStrHelper;
  22. namespace JLHHJSvr.Helper
  23. {
  24. /// <summary>
  25. /// 通用助手类,提供常用的业务操作方法
  26. /// </summary>
  27. internal class CommonHelper : HelperBase
  28. {
  29. #region 常量和正则表达式
  30. private const string _mapperAppend = "_Mapper_";
  31. private readonly Regex _staticParmReg = new Regex("[\\$]+[\\w]+[\\$]*");
  32. private readonly Regex _listParmReg = new Regex("@@[\\w]+@@");
  33. private readonly Dictionary<string, string> _xmlEscapeMap = new Dictionary<string, string>
  34. {
  35. {"&", "&amp;"},
  36. {"'", "&apos;"},
  37. {"\"", "&quot;"},
  38. {">", "&gt;"},
  39. {"<", "&lt;"},
  40. };
  41. private readonly Regex _computeRefReg = new Regex("([A-Za-z_][\\w]+)([\\s]*)([(]*)");
  42. #endregion
  43. #region 数据结构
  44. /// <summary>
  45. /// 查询结果数据结构
  46. /// </summary>
  47. private class QueryResult
  48. {
  49. public JArray datatable { get; set; }
  50. public JObject tableinfo { get; set; }
  51. public int totalcnt { get; set; }
  52. public int pageindex { get; set; }
  53. public int pagesize { get; set; }
  54. }
  55. /// <summary>
  56. /// 请求参数数据结构
  57. /// </summary>
  58. private class DynamicSelectRequest
  59. {
  60. public string token { get; set; }
  61. public string clienttype { get; set; }
  62. public string dsname { get; set; }
  63. public JObject queryparams { get; set; }
  64. public string orderstr { get; set; }
  65. public int pageindex { get; set; }
  66. public int pagesize { get; set; }
  67. public string dwname { get; set; }
  68. public string itemname { get; set; }
  69. public byte ifcompress { get; set; }
  70. }
  71. /// <summary>
  72. /// 响应结果数据结构
  73. /// </summary>
  74. public class DynamicSelectResponse
  75. {
  76. public string ErrMsg { get; set; }
  77. public JArray datatable { get; set; }
  78. public JObject tableinfo { get; set; }
  79. public int totalcnt { get; set; }
  80. public int pageindex { get; set; }
  81. public int pagesize { get; set; }
  82. }
  83. #endregion
  84. #region 主要公共方法
  85. /// <summary>
  86. /// 通用动态查询方法
  87. /// </summary>
  88. /// <param name="token">用户令牌</param>
  89. /// <param name="dsname">数据源XML名称</param>
  90. /// <param name="queryParams">查询参数</param>
  91. /// <param name="pageIndex">页码,默认为1</param>
  92. /// <param name="pageSize">页大小,默认为50</param>
  93. /// <param name="orderStr">排序字符串,可选</param>
  94. /// <param name="dwName">用户习惯数据窗口名称,可选</param>
  95. /// <param name="itemName">用户习惯项目名称,可选</param>
  96. /// <param name="ifCompress">是否压缩用户习惯数据,默认为0</param>
  97. /// <returns>查询结果</returns>
  98. public DynamicSelectResponse ExecuteDynamicSelect(
  99. string dsname,
  100. JObject queryParams,
  101. int pageIndex = 1,
  102. int pageSize = 50,
  103. string orderStr = null,
  104. string dwName = null,
  105. string itemName = null,
  106. byte ifCompress = 0)
  107. {
  108. if (string.IsNullOrEmpty(dsname))
  109. {
  110. throw new ArgumentException("dsname不能为空", nameof(dsname));
  111. }
  112. if (queryParams == null)
  113. {
  114. throw new ArgumentNullException(nameof(queryParams));
  115. }
  116. var request = new DynamicSelectRequest
  117. {
  118. dsname = dsname,
  119. queryparams = queryParams,
  120. orderstr = orderStr,
  121. pageindex = pageIndex,
  122. pagesize = pageSize,
  123. dwname = dwName,
  124. itemname = itemName,
  125. ifcompress = ifCompress
  126. };
  127. return ExecuteDynamicSelectInternal(request);
  128. }
  129. /// <summary>
  130. /// 通用动态查询方法(简化版,使用当前用户上下文)
  131. /// </summary>
  132. /// <param name="dsname">数据源XML名称</param>
  133. /// <param name="queryParams">查询参数</param>
  134. /// <param name="pageIndex">页码,默认为1</param>
  135. /// <param name="pageSize">页大小,默认为50</param>
  136. /// <param name="orderStr">排序字符串,可选</param>
  137. /// <param name="dwName">用户习惯数据窗口名称,可选</param>
  138. /// <param name="itemName">用户习惯项目名称,可选</param>
  139. /// <param name="ifCompress">是否压缩用户习惯数据,默认为0</param>
  140. /// <returns>查询结果</returns>
  141. public DynamicSelectResponse ExecuteDynamicSelectWithContext(
  142. string dsname,
  143. JObject queryParams,
  144. int pageIndex = 1,
  145. int pageSize = 50,
  146. string orderStr = null,
  147. string dwName = null,
  148. string itemName = null,
  149. byte ifCompress = 0)
  150. {
  151. if (context?.tokendata == null)
  152. {
  153. throw new InvalidOperationException("用户上下文或token为空");
  154. }
  155. return ExecuteDynamicSelect(
  156. dsname,
  157. queryParams,
  158. pageIndex,
  159. pageSize,
  160. orderStr,
  161. dwName,
  162. itemName,
  163. ifCompress
  164. );
  165. }
  166. /// <summary>
  167. /// 执行动态查询并返回指定类型的列表
  168. /// </summary>
  169. /// <typeparam name="T">返回数据类型</typeparam>
  170. /// <param name="token">用户令牌</param>
  171. /// <param name="dsname">数据源XML名称</param>
  172. /// <param name="queryParams">查询参数</param>
  173. /// <param name="pageIndex">页码,默认为1</param>
  174. /// <param name="pageSize">页大小,默认为50</param>
  175. /// <param name="orderStr">排序字符串,可选</param>
  176. /// <param name="dwName">用户习惯数据窗口名称,可选</param>
  177. /// <param name="itemName">用户习惯项目名称,可选</param>
  178. /// <param name="ifCompress">是否压缩用户习惯数据,默认为0</param>
  179. /// <returns>查询结果列表</returns>
  180. public List<T> ExecuteDynamicSelectToList<T>(
  181. string dsname,
  182. JObject queryParams,
  183. int pageIndex = 1,
  184. int pageSize = 50,
  185. string orderStr = null,
  186. string dwName = null,
  187. string itemName = null,
  188. byte ifCompress = 0)
  189. {
  190. var response = ExecuteDynamicSelect(dsname, queryParams, pageIndex, pageSize, orderStr, dwName, itemName, ifCompress);
  191. if (!string.IsNullOrEmpty(response.ErrMsg)) { throw new Exception(response.ErrMsg); }
  192. if (response?.datatable != null)
  193. {
  194. return response.datatable.ToObject<List<T>>();
  195. }
  196. return new List<T>();
  197. }
  198. /// <summary>
  199. /// 执行动态查询并返回指定类型的列表(简化版,使用当前用户上下文)
  200. /// </summary>
  201. /// <typeparam name="T">返回数据类型</typeparam>
  202. /// <param name="dsname">数据源XML名称</param>
  203. /// <param name="queryParams">查询参数</param>
  204. /// <param name="pageIndex">页码,默认为1</param>
  205. /// <param name="pageSize">页大小,默认为50</param>
  206. /// <param name="orderStr">排序字符串,可选</param>
  207. /// <param name="dwName">用户习惯数据窗口名称,可选</param>
  208. /// <param name="itemName">用户习惯项目名称,可选</param>
  209. /// <param name="ifCompress">是否压缩用户习惯数据,默认为0</param>
  210. /// <returns>查询结果列表</returns>
  211. public List<T> ExecuteDynamicSelectToListWithContext<T>(
  212. string dsname,
  213. JObject queryParams,
  214. int pageIndex = 1,
  215. int pageSize = 50,
  216. string orderStr = null,
  217. string dwName = null,
  218. string itemName = null,
  219. byte ifCompress = 0)
  220. {
  221. var response = ExecuteDynamicSelectWithContext(dsname, queryParams, pageIndex, pageSize, orderStr, dwName, itemName, ifCompress);
  222. if (response?.datatable != null)
  223. {
  224. return response.datatable.ToObject<List<T>>();
  225. }
  226. return new List<T>();
  227. }
  228. /// <summary>
  229. /// 执行分页查询获取数据字典(用于下拉框等控件)
  230. /// </summary>
  231. /// <param name="dsname">数据源XML名称</param>
  232. /// <param name="queryParams">查询参数</param>
  233. /// <param name="valueField">值字段名,默认为"value"</param>
  234. /// <param name="labelField">显示字段名,默认为"label"</param>
  235. /// <param name="pageSize">最大返回条数,默认为1000</param>
  236. /// <returns>数据字典列表</returns>
  237. public List<KeyValuePair<string, string>> GetDictionaryData(
  238. string dsname,
  239. JObject queryParams = null,
  240. string valueField = "value",
  241. string labelField = "label",
  242. int pageSize = 1000)
  243. {
  244. queryParams = queryParams ?? new JObject();
  245. var response = ExecuteDynamicSelectWithContext(dsname, queryParams, 1, pageSize);
  246. var result = new List<KeyValuePair<string, string>>();
  247. if (response?.datatable != null)
  248. {
  249. foreach (var item in response.datatable)
  250. {
  251. var value = item[valueField]?.ToString() ?? string.Empty;
  252. var label = item[labelField]?.ToString() ?? string.Empty;
  253. if (!string.IsNullOrEmpty(value))
  254. {
  255. result.Add(new KeyValuePair<string, string>(value, label));
  256. }
  257. }
  258. }
  259. return result;
  260. }
  261. /// <summary>
  262. /// 检查指定数据是否存在
  263. /// </summary>
  264. /// <param name="dsname">数据源XML名称</param>
  265. /// <param name="queryParams">查询参数</param>
  266. /// <returns>是否存在数据</returns>
  267. public bool CheckDataExists(string dsname, JObject queryParams)
  268. {
  269. var response = ExecuteDynamicSelectWithContext(dsname, queryParams, 1, 1);
  270. return response?.datatable != null && response.datatable.Count > 0;
  271. }
  272. /// <summary>
  273. /// 获取数据总数
  274. /// </summary>
  275. /// <param name="dsname">数据源XML名称</param>
  276. /// <param name="queryParams">查询参数</param>
  277. /// <returns>数据总数</returns>
  278. public int GetDataCount(string dsname, JObject queryParams)
  279. {
  280. var response = ExecuteDynamicSelectWithContext(dsname, queryParams, 1, 1);
  281. return response?.totalcnt ?? 0;
  282. }
  283. #endregion
  284. #region 核心实现逻辑
  285. /// <summary>
  286. /// 执行动态查询的核心逻辑
  287. /// </summary>
  288. /// <param name="request">请求参数</param>
  289. /// <returns>响应结果</returns>
  290. private DynamicSelectResponse ExecuteDynamicSelectInternal(DynamicSelectRequest request)
  291. {
  292. var response = new DynamicSelectResponse();
  293. try
  294. {
  295. if (request.queryparams == null)
  296. {
  297. throw new ArgumentNullException("queryparams");
  298. }
  299. if (string.IsNullOrEmpty(request.dsname))
  300. {
  301. throw new ArgumentNullException("dsname");
  302. }
  303. var rsltGroup = GetXmlResult(request.dsname, request, false);
  304. response.datatable = rsltGroup.datatable;
  305. response.tableinfo = rsltGroup.tableinfo;
  306. response.totalcnt = rsltGroup.totalcnt;
  307. response.pageindex = rsltGroup.pageindex;
  308. response.pagesize = rsltGroup.pagesize;
  309. }
  310. catch (Exception ex)
  311. {
  312. response.ErrMsg = ex.Message;
  313. }
  314. return response;
  315. }
  316. /// <summary>
  317. /// 解析XML并执行查询
  318. /// </summary>
  319. /// <param name="cmd">SQL命令对象</param>
  320. /// <param name="dsname">数据源名称</param>
  321. /// <param name="request">请求参数</param>
  322. /// <param name="tokendata">用户令牌数据</param>
  323. /// <param name="ifmapper">是否为mapper模式</param>
  324. /// <returns>查询结果</returns>
  325. private QueryResult GetXmlResult(string dsname, DynamicSelectRequest request, bool ifmapper)
  326. {
  327. var rslt = new QueryResult();
  328. var rootPath = GlobalVar.App_Data + "\\DataStore\\";
  329. #if DEBUG
  330. rootPath = rootPath.Substring(0, rootPath.IndexOf("\\bin\\")) + "\\DataStore\\";
  331. #endif
  332. var filePath = rootPath + dsname + ".xml";
  333. if (!File.Exists(filePath))
  334. {
  335. throw new LJCommonException("缺失接口文件:" + dsname + ".xml");
  336. }
  337. var queryParams = request.queryparams;
  338. var wholexml = File.ReadAllText(filePath);
  339. var treatedsb = new StringBuilder();
  340. // 逐行扫描,检查全局变量与转义符
  341. var staticParmDic = new Dictionary<string, string>();
  342. using (StringReader reader = new StringReader(wholexml))
  343. {
  344. var incomment = false;
  345. string line;
  346. while ((line = reader.ReadLine()) != null)
  347. {
  348. var lineTrim = line.Trim();
  349. if (line.Contains("<!--"))
  350. {
  351. incomment = true;
  352. var commentStartIndex = line.IndexOf("<!--");
  353. if (commentStartIndex > 0)
  354. {
  355. treatedsb.AppendLine(line.Substring(0, commentStartIndex));
  356. }
  357. }
  358. if (incomment)
  359. {
  360. if (line.Contains("-->"))
  361. {
  362. incomment = false;
  363. var commenttail = line.Substring(line.IndexOf("-->") + 3);
  364. if (!string.IsNullOrEmpty(commenttail))
  365. {
  366. treatedsb.AppendLine(commenttail);
  367. }
  368. }
  369. continue;
  370. }
  371. // 处理$标记的全局变量
  372. var staticMatches = _staticParmReg.Matches(line);
  373. var staticMatchesStr = new HashSet<string>();
  374. foreach (Match match in staticMatches)
  375. {
  376. var matchstr = match.ToString();
  377. staticMatchesStr.Add(matchstr);
  378. }
  379. // $$开头$$结束为全局数组变量,直接作字符串替换
  380. foreach (var item in staticMatchesStr.Where(x => x.StartsWith("$$")))
  381. {
  382. if (!staticParmDic.ContainsKey(item))
  383. {
  384. var staticParm = item.Trim('$');
  385. var staticVal = string.Empty;
  386. if (staticParm == "user_deptstr")
  387. {
  388. // 用户部门权限 - 需要根据实际业务实现
  389. staticVal = "1"; // 简化处理
  390. }
  391. else if (staticParm == "user_outrepstr")
  392. {
  393. // 用户外勤权限 - 需要根据实际业务实现
  394. staticVal = ""; // 简化处理
  395. }
  396. staticVal = staticVal ?? string.Empty;
  397. staticParmDic[item] = staticVal.Trim(new[] { '(', ')' });
  398. }
  399. if (lineTrim.StartsWith("<") && lineTrim.EndsWith(">"))
  400. {
  401. // xml标签
  402. }
  403. else
  404. {
  405. var staticVal = staticParmDic[item];
  406. line = line.Replace(item, staticVal);
  407. }
  408. }
  409. // $开头的全局变量转换为@开头的变量
  410. foreach (var item in staticMatchesStr.Where(x => x.StartsWith("$") && !x.StartsWith("$$")))
  411. {
  412. var staticParm = item.Trim('$');
  413. if (!queryParams.ContainsKey(staticParm))
  414. {
  415. if (staticParm.StartsWith("user_"))
  416. {
  417. // 查询用户权限值
  418. var keyStr = staticParm.Substring("user_".Length);
  419. var userKeyStr = "0";
  420. cmd.CommandText = @"select " + keyStr + " from u_user_jlhprice where empid = @empid";
  421. cmd.Parameters.Clear();
  422. cmd.Parameters.AddWithValue("@empid", context.tokendata.userid);
  423. using (var UserReader = cmd.ExecuteReader())
  424. {
  425. if (UserReader.Read())
  426. {
  427. userKeyStr = Convert.ToString(UserReader[keyStr]).Trim();
  428. }
  429. }
  430. queryParams[staticParm] = userKeyStr;
  431. }
  432. else
  433. {
  434. throw new NotImplementedException(staticParm);
  435. }
  436. }
  437. line = line.Replace(item, "@" + item.Substring(1));
  438. }
  439. if (lineTrim.StartsWith("<") && lineTrim.EndsWith(">"))
  440. {
  441. // xml标签
  442. line = line.Replace(" $", " ");
  443. line = line.Replace(" @", " ");
  444. line = line.Replace("!=\"", "_notequals=\"");
  445. }
  446. else
  447. {
  448. // 处理@@标记的数组变量
  449. var listParmMatches = _listParmReg.Matches(line);
  450. foreach (Match match in listParmMatches)
  451. {
  452. var matchstr = match.ToString();
  453. var pname = matchstr.Trim('@');
  454. if (!queryParams.ContainsKey(pname))
  455. {
  456. continue;
  457. }
  458. if (queryParams.GetValue(pname).Type != JTokenType.Array)
  459. {
  460. continue;
  461. }
  462. var listval = queryParams.Value<JArray>(pname).Select(x => "'" + x + "'");
  463. var pval = string.Join(",", listval);
  464. line = line.Replace(matchstr, pval);
  465. }
  466. // 处理转义字符
  467. foreach (var escapeItem in _xmlEscapeMap)
  468. {
  469. line = line.Replace(escapeItem.Key, escapeItem.Value);
  470. }
  471. }
  472. treatedsb.AppendLine(line);
  473. }
  474. }
  475. var treatedxml = treatedsb.ToString();
  476. var xmlDoc = new XmlDocument();
  477. xmlDoc.LoadXml(treatedxml);
  478. XmlNode selectNode = null;
  479. XmlNode rootNode = null;
  480. foreach (XmlNode rchild in xmlDoc.ChildNodes)
  481. {
  482. if (rchild.Name != "xml")
  483. {
  484. rootNode = rchild;
  485. break;
  486. }
  487. }
  488. if (rootNode == null)
  489. {
  490. throw new LJCommonException("格式错误,不存在根节点");
  491. }
  492. if (rootNode.Name == "data")
  493. {
  494. var dataChild = rootNode.FirstChild;
  495. if (dataChild == null)
  496. {
  497. throw new LJCommonException("格式错误,data不存在根节点");
  498. }
  499. if (dataChild.Name == "json")
  500. {
  501. var dataJson = dataChild.InnerText;
  502. rslt.datatable = JsonConvert.DeserializeObject<JArray>(dataJson);
  503. return rslt;
  504. }
  505. else
  506. {
  507. throw new LJCommonException("未支持的data节点:" + dataChild.Name);
  508. }
  509. }
  510. else if (rootNode.Name == "select")
  511. {
  512. selectNode = rootNode;
  513. }
  514. else
  515. {
  516. throw new LJCommonException("未支持的根节点:" + rootNode.Name);
  517. }
  518. // 处理select节点
  519. var selectbase = string.Empty;
  520. var selectstr = selectNode.SelectSingleNode("selectstr")?.InnerText;
  521. var orderstr = selectNode.SelectSingleNode("orderstr")?.InnerText;
  522. var whereList = new List<string>();
  523. var whereNode = selectNode.SelectSingleNode("where");
  524. if (whereNode != null)
  525. {
  526. foreach (XmlNode whereChild in whereNode.ChildNodes)
  527. {
  528. if (whereChild.Name == "when")
  529. {
  530. var match = true;
  531. foreach (XmlAttribute attr in whereChild.Attributes)
  532. {
  533. var attrname = attr.Name;
  534. var attrval = attr.Value;
  535. JToken valjtoken = null;
  536. if (attrval.StartsWith("@"))
  537. {
  538. var pname = attrval.Replace("@", "");
  539. attrval = null;
  540. if (queryParams.ContainsKey(pname))
  541. {
  542. valjtoken = queryParams[pname];
  543. switch (valjtoken.Type)
  544. {
  545. case JTokenType.Null:
  546. case JTokenType.None:
  547. case JTokenType.Undefined:
  548. attrval = null;
  549. break;
  550. case JTokenType.Object:
  551. case JTokenType.Array:
  552. attrval = valjtoken.ToString();
  553. break;
  554. default:
  555. attrval = valjtoken.ToString();
  556. break;
  557. }
  558. }
  559. }
  560. if (attrname == "notnull")
  561. {
  562. if (attrval == null)
  563. {
  564. match = false;
  565. break;
  566. }
  567. }
  568. else if (attrname == "notempty")
  569. {
  570. if (valjtoken == null || string.IsNullOrEmpty(valjtoken.ToString()))
  571. {
  572. match = false;
  573. break;
  574. }
  575. if (valjtoken.Type == JTokenType.Array)
  576. {
  577. if ((valjtoken as JArray).Count == 0)
  578. {
  579. match = false;
  580. break;
  581. }
  582. }
  583. }
  584. else
  585. {
  586. var ifnot = false;
  587. var attrnameVal = attrname.TrimStart('@');
  588. if (attrnameVal.EndsWith("_notequals"))
  589. {
  590. ifnot = true;
  591. attrnameVal = attrnameVal.Substring(0, attrnameVal.IndexOf("_notequals"));
  592. }
  593. if (!queryParams.ContainsKey(attrnameVal))
  594. {
  595. throw new ArgumentException("queryparams." + attrnameVal);
  596. }
  597. attrnameVal = queryParams[attrnameVal].ToString();
  598. if (string.Equals(attrnameVal, attrval) != !ifnot)
  599. {
  600. match = false;
  601. break;
  602. }
  603. }
  604. }
  605. if (match)
  606. {
  607. whereList.Add(whereChild.InnerText.Trim());
  608. }
  609. }
  610. else
  611. {
  612. throw new NotImplementedException();
  613. }
  614. }
  615. }
  616. var wherestr = ListEx.GetWhereStr(whereList);
  617. var parmDic = new Dictionary<string, object>();
  618. foreach (var item in queryParams)
  619. {
  620. if (item.Value is JArray)
  621. {
  622. continue;
  623. }
  624. else
  625. {
  626. parmDic[item.Key] = item.Value.ToString();
  627. }
  628. }
  629. var displayfields = selectNode.SelectSingleNode("displayfields");
  630. var uncomputefields = new Dictionary<string, string>();
  631. string rownumfield = null;
  632. if (displayfields != null)
  633. {
  634. foreach (XmlNode fieldNode in displayfields.ChildNodes)
  635. {
  636. string field = null;
  637. XmlAttribute computeAttr = null;
  638. foreach (XmlAttribute attr in fieldNode.Attributes)
  639. {
  640. if (string.Equals(attr.Name, "field", StringComparison.OrdinalIgnoreCase))
  641. {
  642. field = attr.Value;
  643. }
  644. else if (string.Equals(attr.Name, "compute", StringComparison.OrdinalIgnoreCase))
  645. {
  646. computeAttr = attr;
  647. }
  648. }
  649. if (computeAttr != null)
  650. {
  651. var computeexpr = computeAttr.Value;
  652. if (!string.IsNullOrEmpty(computeexpr))
  653. {
  654. if (computeexpr.IndexOf("getrow(", StringComparison.OrdinalIgnoreCase) >= 0)
  655. {
  656. rownumfield = field;
  657. }
  658. else
  659. {
  660. uncomputefields[field] = computeexpr;
  661. }
  662. fieldNode.Attributes.Remove(computeAttr);
  663. }
  664. }
  665. }
  666. }
  667. // 处理计算字段
  668. var parseResult = SqlStrHelper.ParseSelectStr(selectstr);
  669. if (parseResult.selectStr.ToUpper().Contains("DISTINCT"))
  670. {
  671. throw new NotImplementedException("未支持DISTINCT");
  672. }
  673. if (uncomputefields.Count > 0)
  674. {
  675. // 多次循环,防止因嵌套解析失败
  676. var checkcnt = uncomputefields.Count;
  677. for (var i = 0; i < checkcnt; i++)
  678. {
  679. if (uncomputefields.Count == 0)
  680. {
  681. break;
  682. }
  683. var flist = uncomputefields.Keys.ToList();
  684. foreach (var compf in flist)
  685. {
  686. if (!uncomputefields.ContainsKey(compf))
  687. {
  688. continue;
  689. }
  690. var waitnext = false;
  691. var computeexpr = uncomputefields[compf];
  692. var refMatches = _computeRefReg.Matches(computeexpr);
  693. var refFields = new HashSet<string>();
  694. foreach (Match refmatch in refMatches)
  695. {
  696. if (string.IsNullOrEmpty(refmatch.Groups[3].ToString()))
  697. {
  698. var refField = refmatch.Groups[1].ToString();
  699. if (!parseResult.selectFieldsDic.ContainsKey(refField))
  700. {
  701. waitnext = true;
  702. break;
  703. }
  704. refFields.Add(refField);
  705. }
  706. }
  707. if (waitnext)
  708. {
  709. continue;
  710. }
  711. var refSorts = refFields.OrderByDescending(x => x.Length).ToList();
  712. var holderid = -1;
  713. foreach (var reff in refSorts)
  714. {
  715. holderid++;
  716. computeexpr = computeexpr.Replace(reff, "{" + holderid.ToString("000") + "}");
  717. }
  718. for (var hindex = 0; hindex <= holderid; hindex++)
  719. {
  720. var reff = refSorts[hindex];
  721. var refselect = parseResult.selectFieldsDic[reff];
  722. var asIndex = refselect.LastIndexOf(" as ", StringComparison.OrdinalIgnoreCase);
  723. if (asIndex > 0)
  724. {
  725. var asname = refselect.Substring(asIndex + " as ".Length).Trim();
  726. if (string.Equals(asname, reff, StringComparison.OrdinalIgnoreCase))
  727. {
  728. refselect = refselect.Substring(0, asIndex).Trim();
  729. }
  730. }
  731. computeexpr = computeexpr.Replace("{" + hindex.ToString("000") + "}", "(" + refselect + ")");
  732. }
  733. parseResult.selectFieldsDic[compf] = computeexpr + " AS " + compf;
  734. uncomputefields.Remove(compf);
  735. }
  736. }
  737. if (uncomputefields.Count > 0)
  738. {
  739. throw new LJCommonException($"解析计算列失败:[{string.Join(",", uncomputefields.Keys)}]");
  740. }
  741. }
  742. // 构建SQL并执行
  743. var mergesql = SqlStrHelper.BuildSelectStrL1(parseResult, string.Join(",", parseResult.selectFieldsDic.Keys), wherestr, orderstr, request.pageindex, request.pagesize);
  744. cmd.CommandText = mergesql;
  745. cmd.CommandType = CommandType.Text;
  746. cmd.Parameters.Clear();
  747. if (queryParams != null)
  748. {
  749. foreach (var item in queryParams)
  750. {
  751. if (item.Value == null)
  752. {
  753. cmd.Parameters.AddWithValue("@" + item.Key, DBNull.Value);
  754. }
  755. else
  756. {
  757. object pval = null;
  758. switch (item.Value.Type)
  759. {
  760. case JTokenType.Array:
  761. continue;
  762. case JTokenType.Integer:
  763. pval = Convert.ToInt64(item.Value);
  764. break;
  765. case JTokenType.Float:
  766. pval = Convert.ToDecimal(item.Value);
  767. break;
  768. case JTokenType.Boolean:
  769. pval = Convert.ToBoolean(item.Value);
  770. break;
  771. default:
  772. pval = item.Value.ToString();
  773. break;
  774. }
  775. cmd.Parameters.AddWithValue("@" + item.Key, pval);
  776. }
  777. }
  778. }
  779. rslt.datatable = new JArray();
  780. var rownum = (request.pageindex - 1) * request.pagesize;
  781. if (rownum < 0)
  782. {
  783. rownum = 0;
  784. }
  785. using (var reader = cmd.ExecuteReader())
  786. {
  787. while (reader.Read())
  788. {
  789. rownum++;
  790. var row = new JObject();
  791. if (rownumfield != null)
  792. {
  793. row.Add(rownumfield, rownum);
  794. }
  795. for (var i = 0; i < reader.FieldCount; i++)
  796. {
  797. var fieldName = reader.GetName(i);
  798. var dbval = reader[fieldName];
  799. if (ifmapper)
  800. {
  801. if (i == 0)
  802. {
  803. fieldName = "value";
  804. }
  805. else if (i == 1)
  806. {
  807. fieldName = "label";
  808. }
  809. }
  810. if (dbval == DBNull.Value)
  811. {
  812. row.Add(fieldName, null);
  813. }
  814. else if (dbval is string)
  815. {
  816. row.Add(fieldName, (dbval as string).TrimEnd());
  817. }
  818. else if (dbval is DateTime)
  819. {
  820. row.Add(fieldName, (DateTime)dbval);
  821. }
  822. else
  823. {
  824. row.Add(fieldName, JToken.FromObject(dbval));
  825. }
  826. }
  827. rslt.datatable.Add(row);
  828. }
  829. }
  830. // 处理总行数
  831. if (!ifmapper)
  832. {
  833. string countstr = parseResult.selectStr + " COUNT(0) " + parseResult.fromStr;
  834. if (!string.IsNullOrEmpty(wherestr))
  835. {
  836. countstr += " WHERE " + wherestr;
  837. }
  838. cmd.CommandText = countstr;
  839. try
  840. {
  841. var totalcnt = Convert.ToInt32(cmd.ExecuteScalar());
  842. rslt.totalcnt = totalcnt;
  843. rslt.pageindex = request.pageindex;
  844. rslt.pagesize = request.pagesize;
  845. }
  846. catch (Exception ex)
  847. {
  848. throw new Exception(string.Format("ex:{0}\r\ncmd:{1}", ex, cmd.CommandText));
  849. }
  850. }
  851. // 处理用户习惯配置
  852. if (request.pageindex <= 1 && !ifmapper)
  853. {
  854. try
  855. {
  856. var ufs = HelperBase.GetHelper<SysUserFileString>(cmd, context);
  857. var preferenceobj = new JObject();
  858. var preferencejson = BllHelper.GetValue(cmd, context.tokendata.userid, request.dwname, request.itemname, string.Empty, request.ifcompress == 1);
  859. if (string.IsNullOrEmpty(preferencejson))//如果没有自己的布局方案,尝试获取系统的布局方案
  860. {
  861. preferencejson = ufs.getSystemLayout(request.dwname, request.itemname, request.ifcompress);
  862. }
  863. if (!string.IsNullOrEmpty(preferencejson))
  864. {
  865. try
  866. {
  867. preferenceobj = JsonConvert.DeserializeObject<JObject>(preferencejson);
  868. }
  869. catch (Exception e)
  870. {
  871. Trace.Write("解析json失败" + preferencejson);
  872. }
  873. }
  874. var oldcolDic = new Dictionary<string, JObject>(StringComparer.OrdinalIgnoreCase);
  875. var colSortDic = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
  876. var sortid = 0;
  877. if (preferenceobj.ContainsKey("columns"))
  878. {
  879. var oldcols = preferenceobj.GetValue("columns") as JArray;
  880. foreach (JObject col in oldcols)
  881. {
  882. var field = col["field"].ToString();
  883. oldcolDic[field] = col;
  884. sortid++;
  885. colSortDic[field] = sortid;
  886. }
  887. }
  888. var cols = new List<JObject>();
  889. var colSortDicDefault = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
  890. sortid = 0;
  891. foreach (XmlNode fieldNode in selectNode.SelectSingleNode("displayfields").ChildNodes)
  892. {
  893. var col = new JObject();
  894. string field = null;
  895. string mapper = null;
  896. foreach (XmlAttribute attr in fieldNode.Attributes)
  897. {
  898. if (string.Equals(attr.Name, "mapper", StringComparison.OrdinalIgnoreCase))
  899. {
  900. mapper = attr.Value;
  901. continue;
  902. }
  903. col.Add(attr.Name, attr.Value);
  904. if (string.Equals(attr.Name, "field", StringComparison.OrdinalIgnoreCase))
  905. {
  906. field = attr.Value;
  907. }
  908. }
  909. string dbField = null;
  910. var title = fieldNode.InnerText.Trim();
  911. if (field == "getrow(")
  912. {
  913. dbField = string.Empty;
  914. }
  915. else
  916. {
  917. dbField = parseResult.selectFieldsDic[field];
  918. }
  919. col.Add("title", title);
  920. //handleCustomTitle(cmd, tokendata, col, dbField);
  921. if (!string.IsNullOrEmpty(field) && oldcolDic.ContainsKey(field))
  922. {
  923. var oldInfo = oldcolDic[field];
  924. foreach (var prop in oldInfo.Properties())
  925. {
  926. if (string.Equals(prop.Name, "field", StringComparison.OrdinalIgnoreCase))
  927. {
  928. continue;
  929. }
  930. if (string.Equals(prop.Name, "title", StringComparison.OrdinalIgnoreCase))
  931. {
  932. continue;
  933. }
  934. //col.Add(prop.Name, prop.Value);
  935. col[prop.Name] = prop.Value;
  936. }
  937. }
  938. if (mapper != null)
  939. {
  940. if (string.IsNullOrEmpty(mapper))
  941. {
  942. mapper = RemoveAS(dbField);
  943. if (mapper.StartsWith("'") || !Regex.IsMatch(mapper, "[a-zA-Z]"))
  944. {
  945. throw new LJCommonException($"列{col["field"]}对于常量字段,无法自动匹配Mapper,请直接指定具体Mapper");
  946. }
  947. }
  948. var mappername = mapper;
  949. if (mappername.Contains("."))
  950. {
  951. mappername = mappername.Substring(mappername.IndexOf(".") + 1);
  952. }
  953. var mapperMatched = false;
  954. mapperMatched = File.Exists(rootPath + _mapperAppend + mappername + ".xml");
  955. if (!mapperMatched)
  956. {
  957. mappername = mapper.Replace(".", "_");
  958. mapperMatched = File.Exists(rootPath + _mapperAppend + mappername + ".xml");
  959. }
  960. if (!mapperMatched && col.ContainsKey("table"))
  961. {
  962. mappername = mapper;
  963. if (mappername.Contains("."))
  964. {
  965. mappername = mappername.Substring(mappername.IndexOf(".") + 1);
  966. }
  967. mappername = col["table"] + "_" + mappername;
  968. mapperMatched = File.Exists(rootPath + _mapperAppend + mappername + ".xml");
  969. }
  970. if (!mapperMatched)
  971. {
  972. throw new LJCommonException($"列{col["field"]}未匹配到mapper对应的xml:{mapper}");
  973. }
  974. var mapperreq = new DynamicSelectRequest
  975. {
  976. queryparams = queryParams
  977. };
  978. var mapperrslt = GetXmlResult(_mapperAppend + mappername, mapperreq, true);
  979. col.Add("enum", mapperrslt.datatable);
  980. }
  981. cols.Add(col);
  982. sortid++;
  983. colSortDicDefault[field] = sortid;
  984. }
  985. var colSort = cols.OrderBy(x =>
  986. {
  987. var field = x.GetValue("field")?.ToString();
  988. if (colSortDic.ContainsKey(field))
  989. {
  990. return colSortDic[field];
  991. }
  992. else
  993. {
  994. return int.MaxValue;
  995. }
  996. }).ThenBy(x =>
  997. {
  998. var field = x.GetValue("field")?.ToString();
  999. if (colSortDicDefault.ContainsKey(field))
  1000. {
  1001. return colSortDicDefault[field];
  1002. }
  1003. else
  1004. {
  1005. return int.MaxValue;
  1006. }
  1007. });
  1008. var colSortJArr = new JArray();
  1009. foreach (var col in colSort)
  1010. {
  1011. colSortJArr.Add(col);
  1012. }
  1013. preferenceobj["columns"] = colSortJArr;
  1014. rslt.tableinfo = preferenceobj;
  1015. }
  1016. catch (Exception ex)
  1017. {
  1018. Trace.Write("处理用户习惯配置失败: " + ex.Message);
  1019. rslt.tableinfo = new JObject();
  1020. }
  1021. }
  1022. return rslt;
  1023. }
  1024. /// <summary>
  1025. /// 移除AS关键字
  1026. /// </summary>
  1027. /// <param name="oristr">原始字符串</param>
  1028. /// <returns>处理后的字符串</returns>
  1029. private string RemoveAS(string oristr)
  1030. {
  1031. var asindex = oristr.IndexOf(" as ", StringComparison.OrdinalIgnoreCase);
  1032. if (asindex > 0)
  1033. {
  1034. return oristr.Substring(0, asindex);
  1035. }
  1036. return oristr;
  1037. }
  1038. #endregion
  1039. }
  1040. }