sources.js 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. /* views/sources.js —— 原材料层:品类 / 竞品 / 工艺 / 人群 / 机会 的调研条目。
  2. * 本版只展示框架字段(标题、类型、摘要、出处),具体业务字段等调研回传后再定,
  3. * 因此 payload 不在这里渲染成业务字段,只在详情抽屉里以"待定"说明。 */
  4. (function () {
  5. "use strict";
  6. const U = window.KF_UTIL;
  7. const UI = window.KF_UI;
  8. const esc = U.esc;
  9. const ORDER = ["category", "competitor", "process", "audience", "opportunity", "probe"];
  10. function countByType(list) {
  11. const m = new Map();
  12. for (const s of list) m.set(s.sourceType, (m.get(s.sourceType) || 0) + 1);
  13. return m;
  14. }
  15. function badge(no) {
  16. return `<span class="layer layer-raw">raw</span>`;
  17. }
  18. function row(s) {
  19. return `<tr class="clickable" data-act="open-source" data-id="${esc(s.id)}">
  20. <td class="cell-title"><span class="ttl">${esc(s.title)}</span><span class="sub">${esc(s.summaryText || "—")}</span></td>
  21. <td data-l="类型"><span class="ev ev-supported">${esc(s.sourceTypeLabel)}</span></td>
  22. <td data-l="层">${badge()}</td>
  23. <td data-l="出处">${s.sources.length ? `${s.sources.length} 条` : `<span class="ev ev-none">未附出处</span>`}</td>
  24. <td data-l="阶段">${s.stageObj ? esc(s.stageObj.code) : "—"}</td>
  25. <td data-l="录入时间" class="when">${esc(U.fmtDate(s.createdAt))}</td>
  26. </tr>`;
  27. }
  28. function render(db, c) {
  29. const list = db.sources.slice().sort((a, b) => {
  30. const o = (ORDER.indexOf(a.sourceType) + 1 || 99) - (ORDER.indexOf(b.sourceType) + 1 || 99);
  31. return o || new Date(b.createdAt) - new Date(a.createdAt);
  32. });
  33. const byType = countByType(db.sources);
  34. /* 四类调研库 + 机会,每类一张"位置",没资料时说明这里将来会出现什么 */
  35. const grid = ["category", "competitor", "process", "audience", "opportunity"].map((t) => {
  36. const n = byType.get(t) || 0;
  37. return `<a href="#/sources?type=${t}" class="metric" style="display:block;text-decoration:none;color:inherit">
  38. <div class="k">${esc(window.KF_TAXONOMY.SOURCE_TYPES[t] || t)}</div>
  39. <div class="v" style="font-size:28px">${n}<small>条</small></div>
  40. <div class="foot">${n ? "原材料层 · 字段待定稿" : "调研回传后出现"}</div>
  41. </a>`;
  42. }).join("");
  43. let rowsHtml;
  44. if (!list.length) {
  45. rowsHtml = `<div class="panel">${UI.empty({
  46. title: "原材料层还是空的",
  47. body: "这里会放调研 Agent 回填的品类市场、竞品图谱、工艺和人群资料——事实类内容,每条都带出处。调研成员回传前,本页只保留位置与出处字段,不预设业务字段。",
  48. actions: [{ label: "看看现有成果", href: "#/artifacts" }]
  49. })}</div>`;
  50. } else {
  51. rowsHtml = `<div class="panel tbl-wrap"><table class="tbl"><thead><tr>
  52. <th>资料</th><th>类型</th><th>层</th><th>出处</th><th>阶段</th><th>录入</th>
  53. </tr></thead><tbody>${list.map(row).join("")}</tbody></table></div>`;
  54. }
  55. return `<div class="view-head"><div>
  56. <h1>原材料</h1>
  57. <p class="lede">调研整理出来的事实,必须带出处。与学员成果分开放、分开看,分身查库时能分清"这是事实"还是"这是某人说的"。</p>
  58. </div></div>
  59. <div class="metrics" style="grid-template-columns:repeat(auto-fit,minmax(180px,1fr))">${grid}</div>
  60. <div class="sec"><h2>资料条目</h2><span class="hint">${list.length} 条 · 字段定义待调研回传</span></div>
  61. ${rowsHtml}
  62. <div class="note" style="margin-top:22px">${UI.icons.info}<span>本版只展示「标题 / 类型 / 摘要 / 出处」四个框架字段。品类、竞品、工艺、人群各自的具体字段(市场价格、配料参数、人群画像维度等)等调研成员回传后,在 <code>KfSource.payload</code> 上定稿,不需要改表结构。</span></div>`;
  63. }
  64. window.KF_VIEW_SOURCES = { render };
  65. })();