query.js 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. /* query.js —— 筛选与搜索(纯函数,可单独测试)。
  2. * 维度的取值放在 hash 里,多选维度用逗号连接;结果 = 各维度条件的交集。 */
  3. (function () {
  4. "use strict";
  5. const T = window.KF_TAXONOMY;
  6. function parseList(v) {
  7. return v ? String(v).split(",").map((s) => s.trim()).filter(Boolean) : [];
  8. }
  9. /* 构造"生效中的筛选条件" */
  10. function criteria(q) {
  11. return {
  12. priority: parseList(q.priority),
  13. stage: parseList(q.stage),
  14. category: parseList(q.category),
  15. evidence: parseList(q.evidence),
  16. layer: parseList(q.layer),
  17. member: parseList(q.member),
  18. q: (q.q || "").trim().toLowerCase(),
  19. sort: q.sort || "",
  20. ins: q.ins || "",
  21. focus: q.focus || ""
  22. };
  23. }
  24. function isEmpty(c) {
  25. return !c.priority.length && !c.stage.length && !c.category.length && !c.evidence.length &&
  26. !c.layer.length && !c.member.length && !c.q;
  27. }
  28. /* 多个维度各自"任一命中"即通过,维度之间取交集 */
  29. function test(row, c) {
  30. if (c.priority.length && !c.priority.includes(row.priority)) return false;
  31. if (c.stage.length && !(row.stageObj && c.stage.includes(row.stageObj.code))) return false;
  32. if (c.category.length && !c.category.includes(row.category)) return false;
  33. if (c.evidence.length && !c.evidence.includes(row.evidenceKey || row.evidenceLevel)) return false;
  34. if (c.layer.length && !c.layer.includes(row.layer)) return false;
  35. if (c.member.length && !c.member.includes(row.ownerName)) return false;
  36. if (c.q) {
  37. const hay = [row.title, row.ownerName, row.category, row.projectTitle, row.summary, row.body]
  38. .filter(Boolean).join(" ").toLowerCase();
  39. if (!hay.includes(c.q)) return false;
  40. }
  41. return true;
  42. }
  43. /* 逐维度计数:用于在筛选条上显示"如果只点这一项会有几条",且该计数会受其他维度约束 */
  44. function facetCounts(rows, c, dim, keyFn) {
  45. const rest = { ...c, [dim]: [] };
  46. const m = new Map();
  47. for (const r of rows) {
  48. if (!test(r, rest)) continue;
  49. const k = keyFn(r);
  50. if (k == null) continue;
  51. m.set(k, (m.get(k) || 0) + 1);
  52. }
  53. return m;
  54. }
  55. /* 组内去重成员数(归纳交叉人数用同一口径) */
  56. function distinctOwners(rows) {
  57. return new Set(rows.map((r) => r.ownerKey || r.ownerName).filter(Boolean)).size;
  58. }
  59. window.KF_QUERY = { parseList, criteria, isEmpty, test, facetCounts, distinctOwners };
  60. })();