@nocobase/plugin-ai 2.1.0-alpha.10 → 2.1.0-alpha.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (175) hide show
  1. package/dist/{server/ai-employees/built-in/data-modeling/prompt.d.ts → ai/ai-employees/cole.d.ts} +1 -3
  2. package/dist/{server/ai-employees/built-in/nocobase-assistant/prompt.js → ai/ai-employees/cole.js} +15 -7
  3. package/dist/{server/ai-employees/built-in/data-organizer/prompt.d.ts → ai/ai-employees/dara.d.ts} +1 -3
  4. package/dist/{server/ai-employees/built-in/data-visualization/prompt.js → ai/ai-employees/dara.js} +21 -13
  5. package/dist/{server/ai-employees/built-in/data-visualization/prompt.d.ts → ai/ai-employees/dex.d.ts} +1 -3
  6. package/dist/{server/ai-employees/built-in/data-organizer/prompt.js → ai/ai-employees/dex.js} +15 -7
  7. package/dist/ai/ai-employees/ellis.d.ts +10 -0
  8. package/dist/{server/ai-employees/built-in/email-assistant/prompt.js → ai/ai-employees/ellis.js} +19 -11
  9. package/dist/ai/ai-employees/lexi.d.ts +10 -0
  10. package/dist/{server/ai-employees/built-in/translator/prompt.js → ai/ai-employees/lexi.js} +15 -7
  11. package/dist/ai/ai-employees/vera.d.ts +10 -0
  12. package/dist/{server/ai-employees/built-in/research-analyst/prompt.js → ai/ai-employees/vera.js} +15 -7
  13. package/dist/ai/ai-employees/viz.d.ts +10 -0
  14. package/dist/{server/ai-employees/built-in/insights-analyst/prompt.js → ai/ai-employees/viz.js} +15 -7
  15. package/dist/ai/skills/document-search/SKILLS.md +69 -0
  16. package/dist/ai/tools/chartGenerator.js +14 -3
  17. package/dist/ai/tools/formFiller.js +13 -2
  18. package/dist/{server/ai-employees/built-in/ai-coding/prompt.d.ts → ai/tools/getSkill.d.ts} +1 -3
  19. package/dist/{server/ai-employees/built-in/data-modeling/index.js → ai/tools/getSkill.js} +39 -32
  20. package/dist/ai/tools/suggestions.js +13 -2
  21. package/dist/client/{a06081a2b06f1c14.js → 200ac94fc7f6e97b.js} +1 -1
  22. package/dist/client/27539a4356faebb1.js +10 -0
  23. package/dist/client/2db4faf814179140.js +10 -0
  24. package/dist/client/{521c94db45b1e031.js → 4f9117811ffc7ab3.js} +1 -1
  25. package/dist/client/{c49557cc10afc6b2.js → 5af11e24bcb39ac4.js} +1 -1
  26. package/dist/client/62bf6ed27c8de0df.js +10 -0
  27. package/dist/client/6dc8c9b641452067.js +10 -0
  28. package/dist/client/8169eb2b48edf6c7.js +10 -0
  29. package/dist/client/81f6436fd9322dc1.js +10 -0
  30. package/dist/client/{33811690df6f43ba.js → 85af3d6d85eb5b2b.js} +1 -1
  31. package/dist/client/87bc4d3cb55e4006.js +10 -0
  32. package/dist/client/9ac11803370a9625.js +10 -0
  33. package/dist/client/9c00efb8eb0b4d69.js +10 -0
  34. package/dist/client/{f74949b95f9bbb91.js → a4948d5b70172a69.js} +1 -1
  35. package/dist/client/ai-employees/admin/SkillSettings.d.ts +7 -5
  36. package/dist/{server/ai-employees/built-in/ai-coding/document/example/js-column/js_columns_for_accounts_en.d.ts → client/ai-employees/admin/ToolsSettings.d.ts} +8 -4
  37. package/dist/client/ai-employees/admin/mcp/MCPSettings.d.ts +10 -0
  38. package/dist/client/ai-employees/admin/mcp/MCPToolsList.d.ts +19 -0
  39. package/dist/client/ai-employees/admin/mcp/context.d.ts +15 -0
  40. package/dist/client/ai-employees/admin/mcp/schemas.d.ts +1286 -0
  41. package/dist/client/ai-employees/chatbox/utils.d.ts +3 -7
  42. package/dist/client/ai-employees/types.d.ts +5 -4
  43. package/dist/client/c83c2cae956ba914.js +10 -0
  44. package/dist/client/{6fcc98eb80deed47.js → d4e2ed9fa44a82b2.js} +1 -1
  45. package/dist/client/{5be6710cc905ec12.js → f944d487b7ff1f00.js} +1 -1
  46. package/dist/client/index.js +2 -2
  47. package/dist/client/repositories/AIConfigRepository.d.ts +8 -1
  48. package/dist/collections/ai-employees.js +2 -1
  49. package/dist/collections/ai-mcp-clients.d.ts +51 -0
  50. package/dist/collections/ai-mcp-clients.js +111 -0
  51. package/dist/externalVersion.js +14 -14
  52. package/dist/locale/en-US.json +65 -8
  53. package/dist/locale/zh-CN.json +66 -9
  54. package/dist/node_modules/fast-glob/package.json +1 -1
  55. package/dist/node_modules/flexsearch/package.json +1 -1
  56. package/dist/node_modules/fs-extra/package.json +1 -1
  57. package/dist/node_modules/nodejs-snowflake/package.json +1 -1
  58. package/dist/node_modules/openai/package.json +1 -1
  59. package/dist/node_modules/zod/package.json +1 -1
  60. package/dist/server/ai-employees/ai-employee.d.ts +5 -1
  61. package/dist/server/ai-employees/ai-employee.js +90 -13
  62. package/dist/server/ai-employees/middleware/index.d.ts +1 -0
  63. package/dist/server/ai-employees/middleware/index.js +2 -0
  64. package/dist/server/ai-employees/middleware/skill-tools.d.ts +12 -0
  65. package/dist/server/ai-employees/middleware/skill-tools.js +74 -0
  66. package/dist/server/ai-employees/prompts.d.ts +6 -1
  67. package/dist/server/ai-employees/prompts.js +9 -1
  68. package/dist/server/ai-employees/templates/form-assistant.d.ts +2 -2
  69. package/dist/server/ai-employees/templates/form-assistant.js +2 -2
  70. package/dist/server/ai-employees/utils.js +2 -2
  71. package/dist/server/{ai-employees/built-in/ai-coding/document/basic/flow-resource.d.ts → collections/ai-mcp-clients.d.ts} +1 -4
  72. package/dist/server/{ai-employees/built-in/ai-coding/prompt.js → collections/ai-mcp-clients.js} +12 -10
  73. package/dist/server/{ai-employees/built-in/ai-coding/document/example/js-column/js_columns_for_opportunities_en.d.ts → collections/ai-skills.d.ts} +1 -4
  74. package/dist/server/{migrations/20250923221107-setup-build-in.js → collections/ai-skills.js} +46 -13
  75. package/dist/server/manager/ai-coding-manager.d.ts +1 -2
  76. package/dist/server/manager/ai-coding-manager.js +0 -41
  77. package/dist/server/manager/built-in-manager.d.ts +2 -4
  78. package/dist/server/manager/built-in-manager.js +7 -118
  79. package/dist/server/migrations/20260306000001-migrate-skill-settings-tools.js +68 -0
  80. package/dist/server/plugin.d.ts +0 -1
  81. package/dist/server/plugin.js +17 -8
  82. package/dist/server/resource/aiEmployees.js +5 -7
  83. package/dist/server/{ai-employees/built-in/ai-coding/document/example/js-column/js_columns_for_contacts_en.d.ts → resource/aiMcpClients.d.ts} +3 -5
  84. package/dist/server/resource/aiMcpClients.js +78 -0
  85. package/dist/server/{ai-employees/built-in/ai-coding/document/example/js-column/index.d.ts → resource/aiSkills.d.ts} +3 -7
  86. package/dist/server/resource/aiSkills.js +71 -0
  87. package/dist/server/resource/aiTools.js +4 -6
  88. package/dist/server/tools/docs.js +2 -2
  89. package/dist/server/tools/workflow-caller.js +1 -0
  90. package/package.json +2 -2
  91. package/dist/client/16dbe01d9077bb74.js +0 -10
  92. package/dist/client/180c8b1051a4f36e.js +0 -10
  93. package/dist/client/41229e007006e7f6.js +0 -10
  94. package/dist/client/41950da4c64caf73.js +0 -10
  95. package/dist/client/585ba360c7c57caf.js +0 -10
  96. package/dist/client/9f62a4c5136dfe8b.js +0 -10
  97. package/dist/client/b7f721f8dabb54e5.js +0 -10
  98. package/dist/client/bc471dd60174458c.js +0 -10
  99. package/dist/client/c40ed1a900aefb67.js +0 -10
  100. package/dist/server/ai-employees/built-in/ai-coding/document/basic/flow-resource.js +0 -256
  101. package/dist/server/ai-employees/built-in/ai-coding/document/example/js-column/index.js +0 -48
  102. package/dist/server/ai-employees/built-in/ai-coding/document/example/js-column/js_columns_for_accounts_en.js +0 -452
  103. package/dist/server/ai-employees/built-in/ai-coding/document/example/js-column/js_columns_for_contacts_en.js +0 -363
  104. package/dist/server/ai-employees/built-in/ai-coding/document/example/js-column/js_columns_for_opportunities_en.js +0 -270
  105. package/dist/server/ai-employees/built-in/ai-coding/document/example/js-column/js_columns_for_quotations_en.d.ts +0 -13
  106. package/dist/server/ai-employees/built-in/ai-coding/document/example/js-column/js_columns_for_quotations_en.js +0 -219
  107. package/dist/server/ai-employees/built-in/ai-coding/document/example/js-column/js_columns_for_tickets_en.d.ts +0 -13
  108. package/dist/server/ai-employees/built-in/ai-coding/document/example/js-column/js_columns_for_tickets_en.js +0 -409
  109. package/dist/server/ai-employees/built-in/ai-coding/document/example/js-filter/accounts_filter_ant_style.d.ts +0 -13
  110. package/dist/server/ai-employees/built-in/ai-coding/document/example/js-filter/accounts_filter_ant_style.js +0 -324
  111. package/dist/server/ai-employees/built-in/ai-coding/document/example/js-filter/contacts_filter_ant_style.d.ts +0 -13
  112. package/dist/server/ai-employees/built-in/ai-coding/document/example/js-filter/contacts_filter_ant_style.js +0 -309
  113. package/dist/server/ai-employees/built-in/ai-coding/document/example/js-filter/index.d.ts +0 -15
  114. package/dist/server/ai-employees/built-in/ai-coding/document/example/js-filter/index.js +0 -50
  115. package/dist/server/ai-employees/built-in/ai-coding/document/example/js-filter/leads_filter_ant_style.d.ts +0 -13
  116. package/dist/server/ai-employees/built-in/ai-coding/document/example/js-filter/leads_filter_ant_style.js +0 -345
  117. package/dist/server/ai-employees/built-in/ai-coding/document/example/js-filter/opportunities_filter_ant_style.d.ts +0 -13
  118. package/dist/server/ai-employees/built-in/ai-coding/document/example/js-filter/opportunities_filter_ant_style.js +0 -381
  119. package/dist/server/ai-employees/built-in/ai-coding/document/example/js-filter/product_categories_ant_style.d.ts +0 -13
  120. package/dist/server/ai-employees/built-in/ai-coding/document/example/js-filter/product_categories_ant_style.js +0 -545
  121. package/dist/server/ai-employees/built-in/ai-coding/document/example/js-filter/tickets_filter_ant_style.d.ts +0 -13
  122. package/dist/server/ai-employees/built-in/ai-coding/document/example/js-filter/tickets_filter_ant_style.js +0 -346
  123. package/dist/server/ai-employees/built-in/ai-coding/document/js-action.d.ts +0 -13
  124. package/dist/server/ai-employees/built-in/ai-coding/document/js-action.js +0 -102
  125. package/dist/server/ai-employees/built-in/ai-coding/document/js-block.d.ts +0 -13
  126. package/dist/server/ai-employees/built-in/ai-coding/document/js-block.js +0 -314
  127. package/dist/server/ai-employees/built-in/ai-coding/document/js-column.d.ts +0 -13
  128. package/dist/server/ai-employees/built-in/ai-coding/document/js-column.js +0 -113
  129. package/dist/server/ai-employees/built-in/ai-coding/document/js-field.d.ts +0 -13
  130. package/dist/server/ai-employees/built-in/ai-coding/document/js-field.js +0 -498
  131. package/dist/server/ai-employees/built-in/ai-coding/document/js-item.d.ts +0 -13
  132. package/dist/server/ai-employees/built-in/ai-coding/document/js-item.js +0 -184
  133. package/dist/server/ai-employees/built-in/ai-coding/index.d.ts +0 -37
  134. package/dist/server/ai-employees/built-in/ai-coding/index.js +0 -99
  135. package/dist/server/ai-employees/built-in/ai-coding/profile.d.ts +0 -27
  136. package/dist/server/ai-employees/built-in/ai-coding/profile.js +0 -60
  137. package/dist/server/ai-employees/built-in/ai-coding/prompt_en.md +0 -110
  138. package/dist/server/ai-employees/built-in/data-modeling/index.d.ts +0 -37
  139. package/dist/server/ai-employees/built-in/data-modeling/profile.d.ts +0 -27
  140. package/dist/server/ai-employees/built-in/data-modeling/profile.js +0 -60
  141. package/dist/server/ai-employees/built-in/data-modeling/prompt.js +0 -283
  142. package/dist/server/ai-employees/built-in/data-organizer/index.d.ts +0 -37
  143. package/dist/server/ai-employees/built-in/data-organizer/index.js +0 -63
  144. package/dist/server/ai-employees/built-in/data-organizer/profile.d.ts +0 -27
  145. package/dist/server/ai-employees/built-in/data-organizer/profile.js +0 -60
  146. package/dist/server/ai-employees/built-in/data-visualization/index.d.ts +0 -37
  147. package/dist/server/ai-employees/built-in/data-visualization/index.js +0 -58
  148. package/dist/server/ai-employees/built-in/data-visualization/profile.d.ts +0 -27
  149. package/dist/server/ai-employees/built-in/data-visualization/profile.js +0 -60
  150. package/dist/server/ai-employees/built-in/email-assistant/index.d.ts +0 -34
  151. package/dist/server/ai-employees/built-in/email-assistant/index.js +0 -50
  152. package/dist/server/ai-employees/built-in/email-assistant/profile.d.ts +0 -27
  153. package/dist/server/ai-employees/built-in/email-assistant/profile.js +0 -60
  154. package/dist/server/ai-employees/built-in/email-assistant/prompt.d.ts +0 -12
  155. package/dist/server/ai-employees/built-in/insights-analyst/index.d.ts +0 -37
  156. package/dist/server/ai-employees/built-in/insights-analyst/index.js +0 -63
  157. package/dist/server/ai-employees/built-in/insights-analyst/profile.d.ts +0 -27
  158. package/dist/server/ai-employees/built-in/insights-analyst/profile.js +0 -60
  159. package/dist/server/ai-employees/built-in/insights-analyst/prompt.d.ts +0 -12
  160. package/dist/server/ai-employees/built-in/nocobase-assistant/index.d.ts +0 -34
  161. package/dist/server/ai-employees/built-in/nocobase-assistant/index.js +0 -50
  162. package/dist/server/ai-employees/built-in/nocobase-assistant/profile.d.ts +0 -27
  163. package/dist/server/ai-employees/built-in/nocobase-assistant/profile.js +0 -60
  164. package/dist/server/ai-employees/built-in/nocobase-assistant/prompt.d.ts +0 -12
  165. package/dist/server/ai-employees/built-in/research-analyst/index.d.ts +0 -37
  166. package/dist/server/ai-employees/built-in/research-analyst/index.js +0 -63
  167. package/dist/server/ai-employees/built-in/research-analyst/profile.d.ts +0 -27
  168. package/dist/server/ai-employees/built-in/research-analyst/profile.js +0 -60
  169. package/dist/server/ai-employees/built-in/research-analyst/prompt.d.ts +0 -12
  170. package/dist/server/ai-employees/built-in/translator/index.d.ts +0 -37
  171. package/dist/server/ai-employees/built-in/translator/index.js +0 -67
  172. package/dist/server/ai-employees/built-in/translator/profile.d.ts +0 -27
  173. package/dist/server/ai-employees/built-in/translator/profile.js +0 -60
  174. package/dist/server/ai-employees/built-in/translator/prompt.d.ts +0 -12
  175. /package/dist/server/migrations/{20250923221107-setup-build-in.d.ts → 20260306000001-migrate-skill-settings-tools.d.ts} +0 -0
@@ -1,452 +0,0 @@
1
- /**
2
- * This file is part of the NocoBase (R) project.
3
- * Copyright (c) 2020-2024 NocoBase Co., Ltd.
4
- * Authors: NocoBase Team.
5
- *
6
- * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
7
- * For more information, please refer to: https://www.nocobase.com/agreement.
8
- */
9
-
10
- var __defProp = Object.defineProperty;
11
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
12
- var __getOwnPropNames = Object.getOwnPropertyNames;
13
- var __hasOwnProp = Object.prototype.hasOwnProperty;
14
- var __export = (target, all) => {
15
- for (var name in all)
16
- __defProp(target, name, { get: all[name], enumerable: true });
17
- };
18
- var __copyProps = (to, from, except, desc) => {
19
- if (from && typeof from === "object" || typeof from === "function") {
20
- for (let key of __getOwnPropNames(from))
21
- if (!__hasOwnProp.call(to, key) && key !== except)
22
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
23
- }
24
- return to;
25
- };
26
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
27
- var js_columns_for_accounts_en_exports = {};
28
- __export(js_columns_for_accounts_en_exports, {
29
- default: () => js_columns_for_accounts_en_default
30
- });
31
- module.exports = __toCommonJS(js_columns_for_accounts_en_exports);
32
- var js_columns_for_accounts_en_default = {
33
- name: "js_columns_for_accounts",
34
- content: String.raw`# NocoBase JS Column Examples - Accounts Table
35
-
36
- ## Overview
37
- Practical JavaScript column examples for the accounts table in CRM systems. These aggregated columns combine multiple fields, calculate derived metrics, and provide visual representations to enhance data readability and business insights.
38
-
39
- ## Selected JS Column Examples
40
-
41
- ## 1. Account Comprehensive Information Column
42
-
43
- Displays core account information including name, number, type, and industry labels. Account name is clickable to open detail dialog.
44
-
45
- \`\`\`javascript
46
- // Account info card - Name, number, industry tags with clickable name
47
- const name = ctx.record?.name || 'Unknown';
48
- const accountNumber = ctx.record?.account_number || 'N/A';
49
- const industry = ctx.record?.industry || '';
50
- const type = ctx.record?.type || '';
51
- const account_id = ctx.record?.id;
52
-
53
- // Industry mapping and colors
54
- const industryMap = {
55
- 'Technology': { label: 'Tech', color: '#1677ff' },
56
- 'Healthcare': { label: 'Health', color: '#52c41a' },
57
- 'Finance': { label: 'Finance', color: '#faad14' },
58
- 'Retail': { label: 'Retail', color: '#fa8c16' },
59
- 'Education': { label: 'Edu', color: '#2563eb' },
60
- 'Manufacturing': { label: 'Mfg', color: '#eb2f96' },
61
- 'Real estate': { label: 'Real Estate', color: '#fa541c' },
62
- 'Energy': { label: 'Energy', color: '#fadb14' },
63
- 'Government': { label: 'Gov', color: '#73d13d' }
64
- };
65
-
66
- const typeMap = {
67
- 'Customer': 'Customer',
68
- 'Partner': 'Partner',
69
- 'Competitor': 'Competitor',
70
- 'Vendor': 'Vendor',
71
- 'Prospect': 'Prospect',
72
- 'Other': 'Other'
73
- };
74
-
75
- const industryInfo = industryMap[industry] || { label: industry, color: '#8c8c8c' };
76
- const typeLabel = typeMap[type] || type;
77
-
78
- ctx.element.innerHTML = \`
79
- <div style="display:flex;flex-direction:column;gap:4px;">
80
- <div style="display:flex;align-items:center;gap:8px;">
81
- <strong
82
- class="account-name-link"
83
- style="color:#000;font-size:14px;cursor:pointer;text-decoration:none;"
84
- onmouseover="this.style.color='#1677ff';this.style.textDecoration='underline'"
85
- onmouseout="this.style.color='#000';this.style.textDecoration='none'"
86
- >\${name}</strong>
87
- \${type ? \`<span style="padding:2px 6px;background:#f0f5ff;color:#1677ff;border-radius:2px;font-size:11px;">\${typeLabel}</span>\` : ''}
88
- </div>
89
- <div style="display:flex;align-items:center;gap:6px;">
90
- <span style="color:#8c8c8c;font-size:12px;">\${accountNumber}</span>
91
- \${industry ? \`<span style="padding:2px 6px;background:\${industryInfo.color}15;color:\${industryInfo.color};border-radius:2px;font-size:11px;">\${industryInfo.label}</span>\` : ''}
92
- </div>
93
- </div>
94
- \`;
95
-
96
- // Add click handler for account name
97
- if (account_id) {
98
- const nameLink = ctx.element.querySelector('.account-name-link');
99
- if (nameLink && !nameLink._eventBound) {
100
- nameLink._eventBound = true;
101
- nameLink.addEventListener('click', async () => {
102
- await ctx.openView('c91bba4e338', {
103
- collectionName: 'accounts',
104
- dataSourceKey: 'main',
105
- filterByTk: account_id
106
- }); // Account dialog UID
107
- });
108
- }
109
- }
110
- \`\`\`
111
-
112
- ## 2. Health Score Column
113
-
114
- Calculates account health score based on multiple dimensions including owner assignment, contacts, opportunities, recent activities, and revenue data.
115
-
116
- \`\`\`javascript
117
- // Account health score - Based on multiple indicators
118
- const hasOwner = ctx.record?.owner_id ? 20 : 0;
119
- const hasContacts = ctx.record?.contacts?.length > 0 ? 20 : 0;
120
- const hasOpportunities = ctx.record?.opportunities?.length > 0 ? 20 : 0;
121
- const hasRecentActivity = ctx.record?.updatedAt &&
122
- (new Date() - new Date(ctx.record.updatedAt)) < 30 * 24 * 60 * 60 * 1000 ? 20 : 0;
123
- const hasRevenue = ctx.record?.annual_revenue > 0 ? 20 : 0;
124
-
125
- const score = hasOwner + hasContacts + hasOpportunities + hasRecentActivity + hasRevenue;
126
- const level = score >= 80 ? 'Excellent' : score >= 60 ? 'Good' : score >= 40 ? 'Fair' : 'Poor';
127
- const color = score >= 80 ? '#52c41a' : score >= 60 ? '#1677ff' : score >= 40 ? '#faad14' : '#ff4d4f';
128
-
129
- ctx.element.innerHTML = \`
130
- <div style="display:flex;align-items:center;gap:8px;">
131
- <div style="position:relative;width:120px;height:8px;background:#f0f0f0;border-radius:4px;overflow:hidden;">
132
- <div style="position:absolute;left:0;top:0;height:100%;width:\${score}%;background:\${color};border-radius:4px;transition:width 0.3s;"></div>
133
- </div>
134
- <span style="font-size:12px;color:\${color};font-weight:600;">\${score}% \${level}</span>
135
- </div>
136
- \`;
137
- \`\`\`
138
-
139
- ## 3. Business Scale Indicator
140
-
141
- Shows company scale level and annual revenue with different visual elements for different sizes.
142
-
143
- \`\`\`javascript
144
- // Business scale - Employee count and annual revenue combination
145
- const employees = ctx.record?.employees || '';
146
- const revenue = ctx.record?.annual_revenue || 0;
147
-
148
- const formatRevenue = (val) => {
149
- if (val >= 1000000) return \`$\${(val/1000000).toFixed(1)}M\`;
150
- if (val >= 1000) return \`$\${(val/1000).toFixed(0)}K\`;
151
- return \`$\${val}\`;
152
- };
153
-
154
- const sizeMap = {
155
- '1-49': { label: 'Small', icon: '●', color: '#1677ff' },
156
- '50-199': { label: 'Medium', icon: '●●', color: '#faad14' },
157
- '200-999': { label: 'Large', icon: '●●●', color: '#52c41a' },
158
- '1000+': { label: 'Enterprise', icon: '●●●●', color: '#eb2f96' }
159
- };
160
-
161
- const size = sizeMap[employees] || { label: 'Unknown', icon: '○', color: '#8c8c8c' };
162
-
163
- ctx.element.innerHTML = \`
164
- <div style="display:flex;flex-direction:column;gap:4px;">
165
- <div style="display:flex;align-items:center;gap:6px;">
166
- <span style="color:\${size.color};font-size:10px;">\${size.icon}</span>
167
- <span style="color:#000;font-size:13px;font-weight:500;">\${size.label}</span>
168
- </div>
169
- \${revenue > 0 ? \`
170
- <div style="color:#52c41a;font-size:14px;font-weight:600;">
171
- \${formatRevenue(revenue)}
172
- </div>
173
- \` : '<span style="color:#bfbfbf;font-size:12px;">No revenue data</span>'}
174
- </div>
175
- \`;
176
- \`\`\`
177
-
178
- ## 4. Relationship Network Badges
179
-
180
- Displays counts of related leads, contacts, and opportunities. Click to show list where titles are clickable to open detail dialogs.
181
-
182
- \`\`\`javascript
183
- // Relationship network badges - Using ctx.viewer.drawer, list items clickable
184
- const leads = ctx.record?.leads || [];
185
- const contacts = ctx.record?.contacts || [];
186
- const opportunities = ctx.record?.opportunities || [];
187
-
188
- const badges = [
189
- {
190
- label: 'Leads',
191
- type: 'leads',
192
- count: leads.length,
193
- color: '#722ed1',
194
- icon: '👤',
195
- items: leads,
196
- dialogUID: 'c4f1bf0165c' // Contact dialog UID
197
- },
198
- {
199
- label: 'Contacts',
200
- type: 'contacts',
201
- count: contacts.length,
202
- color: '#1677ff',
203
- icon: '📇',
204
- items: contacts,
205
- dialogUID: 'c4f1bf0165c' // Contact dialog UID
206
- },
207
- {
208
- label: 'Opportunities',
209
- type: 'opportunities',
210
- count: opportunities.length,
211
- color: '#52c41a',
212
- icon: '💼',
213
- items: opportunities,
214
- dialogUID: '44be52bf4bb' // Opportunity dialog UID
215
- }
216
- ].filter(b => b.count > 0);
217
-
218
- ctx.element.innerHTML = \`
219
- <div style="display:flex;gap:8px;flex-wrap:wrap;">
220
- \${badges.length > 0 ? badges.map((badge, index) => \`
221
- <a
222
- href="javascript:void(0)"
223
- class="badge-link"
224
- data-index="\${index}"
225
- style="
226
- display:inline-flex;
227
- align-items:center;
228
- gap:4px;
229
- padding:4px 8px;
230
- background:\${badge.color}15;
231
- border-radius:12px;
232
- text-decoration:none;
233
- transition:all 0.2s;
234
- border:1px solid \${badge.color}30;
235
- cursor:pointer;
236
- "
237
- onmouseover="this.style.background='\${badge.color}25';this.style.transform='scale(1.05)'"
238
- onmouseout="this.style.background='\${badge.color}15';this.style.transform='scale(1)'"
239
- >
240
- <span style="font-size:12px;">\${badge.icon}</span>
241
- <span style="color:\${badge.color};font-size:12px;font-weight:600;">\${badge.count}</span>
242
- <span style="color:#595959;font-size:11px;">\${badge.label}</span>
243
- </a>
244
- \`).join('') : '<span style="color:#bfbfbf;font-size:12px;">No related data</span>'}
245
- </div>
246
- \`;
247
-
248
- // Bind click events
249
- ctx.element.querySelectorAll('.badge-link').forEach((link) => {
250
- const badgeIndex = parseInt(link.dataset.index);
251
- const badge = badges[badgeIndex];
252
-
253
- link.addEventListener('click', (e) => {
254
- e.preventDefault();
255
-
256
- // Prepare detail content
257
- let detailContent = '';
258
- const formatValue = (val) => {
259
- if (val >= 1000000) return \`$\${(val/1000000).toFixed(1)}M\`;
260
- if (val >= 1000) return \`$\${(val/1000).toFixed(0)}K\`;
261
- return \`$\${val}\`;
262
- };
263
-
264
- if (badge.type === 'opportunities') {
265
- const totalValue = badge.items.reduce((sum, opp) => sum + (opp.amount || 0), 0);
266
-
267
- detailContent = \`
268
- <div style="padding:16px;">
269
- <h4 style="margin:0 0 12px;color:#333;">Opportunities List</h4>
270
- <div style="padding:8px;background:#e6f7ff;border-radius:4px;margin-bottom:12px;">
271
- <strong>Total Pipeline Value: <span style="color:#52c41a;">\${formatValue(totalValue)}</span></strong>
272
- </div>
273
- <div style="max-height:400px;overflow-y:auto;">
274
- \${badge.items.slice(0, 10).map(opp => \`
275
- <div style="padding:8px;margin-bottom:8px;background:#f5f5f5;border-radius:4px;">
276
- <div
277
- class="item-title"
278
- style="font-weight:500;margin-bottom:4px;color:#1677ff;cursor:pointer;"
279
- onmouseover="this.style.textDecoration='underline'"
280
- onmouseout="this.style.textDecoration='none'"
281
- data-dialog="\${badge.dialogUID}"
282
- >\${opp.name || 'Unnamed Opportunity'}</div>
283
- <div style="font-size:12px;color:#8c8c8c;">
284
- Amount: <strong style="color:#52c41a;">\${formatValue(opp.amount || 0)}</strong> |
285
- Stage: \${opp.stage || 'Unknown'}
286
- </div>
287
- </div>
288
- \`).join('')}
289
- \${badge.items.length > 10 ? \`
290
- <div style="padding:8px;text-align:center;color:#8c8c8c;font-size:12px;">
291
- ...and \${badge.items.length - 10} more opportunities
292
- </div>
293
- \` : ''}
294
- </div>
295
- </div>
296
- \`;
297
- } else {
298
- // Similar implementation for leads and contacts
299
- detailContent = \`
300
- <div style="padding:16px;">
301
- <h4 style="margin:0 0 12px;color:#333;">\${badge.label} List</h4>
302
- <div style="max-height:400px;overflow-y:auto;">
303
- \${badge.items.slice(0, 10).map(item => \`
304
- <div style="padding:8px;margin-bottom:8px;background:#f5f5f5;border-radius:4px;">
305
- <div
306
- class="item-title"
307
- style="font-weight:500;margin-bottom:4px;color:#1677ff;cursor:pointer;"
308
- >\${item.name || 'Unnamed'}</div>
309
- <div style="font-size:12px;color:#8c8c8c;">
310
- \${item.email || 'No email'} | \${item.phone || 'No phone'}
311
- </div>
312
- </div>
313
- \`).join('')}
314
- </div>
315
- </div>
316
- \`;
317
- }
318
-
319
- // Use ctx.viewer.drawer to show content
320
- const drawer = ctx.viewer.drawer({
321
- title: \`\${badge.icon} \${badge.label} (\${badge.count})\`,
322
- content: detailContent,
323
- width: 500
324
- });
325
- });
326
- });
327
- \`\`\`
328
-
329
- ## 5. Activity Status Indicator
330
-
331
- Shows account activity status based on last update time with visual indicators.
332
-
333
- \`\`\`javascript
334
- // Activity indicator - Based on last update time
335
- const updatedAt = ctx.record?.updatedAt;
336
- const createdAt = ctx.record?.createdAt;
337
-
338
- const getTimeDiff = (date) => {
339
- const diff = new Date() - new Date(date);
340
- const days = Math.floor(diff / (1000 * 60 * 60 * 24));
341
- const hours = Math.floor(diff / (1000 * 60 * 60));
342
- const minutes = Math.floor(diff / (1000 * 60));
343
-
344
- if (days > 30) return { text: \`\${Math.floor(days/30)} months ago\`, status: 'inactive' };
345
- if (days > 0) return { text: \`\${days} days ago\`, status: days > 7 ? 'warning' : 'active' };
346
- if (hours > 0) return { text: \`\${hours} hours ago\`, status: 'active' };
347
- return { text: \`\${minutes} minutes ago\`, status: 'active' };
348
- };
349
-
350
- const timeInfo = updatedAt ? getTimeDiff(updatedAt) : null;
351
- const statusColors = {
352
- active: '#52c41a',
353
- warning: '#faad14',
354
- inactive: '#ff4d4f'
355
- };
356
-
357
- ctx.element.innerHTML = timeInfo ? \`
358
- <div style="display:flex;align-items:center;gap:6px;">
359
- <div style="width:8px;height:8px;border-radius:50%;background:\${statusColors[timeInfo.status]};
360
- \${timeInfo.status === 'active' ? 'animation: pulse 2s infinite;' : ''}"></div>
361
- <span style="color:#595959;font-size:12px;">Updated \${timeInfo.text}</span>
362
- </div>
363
- <style>
364
- @keyframes pulse {
365
- 0% { opacity: 1; }
366
- 50% { opacity: 0.5; }
367
- 100% { opacity: 1; }
368
- }
369
- </style>
370
- \` : '<span style="color:#bfbfbf;font-size:12px;">Never updated</span>';
371
- \`\`\`
372
-
373
- ## 6. Revenue Potential Progress Bar
374
-
375
- Displays annual revenue and potential opportunity value, calculates growth potential. Pipeline value is clickable to open opportunities dialog.
376
-
377
- \`\`\`javascript
378
- // Revenue potential - Annual revenue + opportunity value with clickable pipeline
379
- const annualRevenue = ctx.record?.annual_revenue || 0;
380
- const opportunities = ctx.record?.opportunities || [];
381
- const potentialValue = opportunities.reduce((sum, opp) => sum + (opp.amount || 0), 0);
382
- const totalPotential = annualRevenue + potentialValue;
383
- const hasOpportunities = opportunities.length > 0;
384
-
385
- const formatCurrency = (val) => {
386
- if (val >= 1000000) return \`$\${(val/1000000).toFixed(2)}M\`;
387
- if (val >= 1000) return \`$\${(val/1000).toFixed(1)}K\`;
388
- return \`$\${val.toFixed(0)}\`;
389
- };
390
-
391
- const percentage = annualRevenue > 0 ? Math.min((potentialValue / annualRevenue) * 100, 100) : 0;
392
- const growthColor = percentage > 50 ? '#52c41a' : percentage > 20 ? '#1677ff' : '#faad14';
393
-
394
- ctx.element.innerHTML = \`
395
- <div style="display:flex;flex-direction:column;gap:6px;min-width:150px;">
396
- <div style="display:flex;justify-content:space-between;align-items:center;">
397
- <span style="font-size:11px;color:#8c8c8c;">Annual Revenue</span>
398
- <span style="font-size:13px;color:#000;font-weight:600;">\${formatCurrency(annualRevenue)}</span>
399
- </div>
400
- \${potentialValue > 0 ? \`
401
- <div
402
- class="pipeline-link"
403
- style="display:flex;justify-content:space-between;align-items:center;cursor:pointer;padding:2px;border-radius:2px;transition:background 0.2s;"
404
- onmouseover="this.style.background='#f0f5ff'"
405
- onmouseout="this.style.background='transparent'"
406
- >
407
- <span style="font-size:11px;color:#8c8c8c;">Pipeline (\${opportunities.length})</span>
408
- <span style="font-size:13px;color:\${growthColor};font-weight:600;">+\${formatCurrency(potentialValue)}</span>
409
- </div>
410
- <div style="position:relative;width:100%;height:4px;background:#f0f0f0;border-radius:2px;overflow:hidden;">
411
- <div style="position:absolute;left:0;top:0;height:100%;width:\${percentage}%;background:\${growthColor};border-radius:2px;"></div>
412
- </div>
413
- \` : ''}
414
- </div>
415
- \`;
416
-
417
- // Add click handler for pipeline link
418
- if (hasOpportunities) {
419
- const pipelineLink = ctx.element.querySelector('.pipeline-link');
420
- if (pipelineLink && !pipelineLink._eventBound) {
421
- pipelineLink._eventBound = true;
422
- pipelineLink.addEventListener('click', async () => {
423
- // Open opportunities related to this account
424
- await ctx.openView('44be52bf4bb', {
425
- collectionName: 'opportunities',
426
- dataSourceKey: 'main',
427
- filterByTk: ctx.record?.id // Filter opportunities by account_id
428
- });
429
- });
430
- }
431
- }
432
- \`\`\`
433
-
434
- ## Usage Instructions
435
-
436
- ### Configuration in NocoBase
437
- 1. Navigate to the table configuration interface
438
- 2. Add a new column and select "JavaScript" type
439
- 3. Paste the corresponding code into the code editor
440
- 4. Save and refresh the table to see the effects
441
-
442
- ### Performance Optimization
443
- - For columns with complex calculations, limit the number of rows displayed per page
444
- - Ensure proper query optimization for columns that need to count related data
445
- - Consider caching results for complex calculations
446
-
447
- ### Customization Tips
448
- - **Color schemes**: Modify color values to match brand colors
449
- - **Thresholds**: Adjust health score and activity thresholds based on business needs
450
- - **Display formats**: Adjust currency and date formats based on regional preferences
451
- - **Icons**: Replace with other emojis or icon fonts as needed`
452
- };