@nocobase/plugin-ai 2.1.0-alpha.10 → 2.1.0-alpha.12
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.
- package/dist/{server/ai-employees/built-in/data-modeling/prompt.d.ts → ai/ai-employees/cole.d.ts} +1 -3
- package/dist/{server/ai-employees/built-in/nocobase-assistant/prompt.js → ai/ai-employees/cole.js} +15 -7
- package/dist/{server/ai-employees/built-in/data-organizer/prompt.d.ts → ai/ai-employees/dara.d.ts} +1 -3
- package/dist/{server/ai-employees/built-in/data-visualization/prompt.js → ai/ai-employees/dara.js} +21 -13
- package/dist/{server/ai-employees/built-in/data-visualization/prompt.d.ts → ai/ai-employees/dex.d.ts} +1 -3
- package/dist/{server/ai-employees/built-in/data-organizer/prompt.js → ai/ai-employees/dex.js} +15 -7
- package/dist/ai/ai-employees/ellis.d.ts +10 -0
- package/dist/{server/ai-employees/built-in/email-assistant/prompt.js → ai/ai-employees/ellis.js} +19 -11
- package/dist/ai/ai-employees/lexi.d.ts +10 -0
- package/dist/{server/ai-employees/built-in/translator/prompt.js → ai/ai-employees/lexi.js} +15 -7
- package/dist/ai/ai-employees/vera.d.ts +10 -0
- package/dist/{server/ai-employees/built-in/research-analyst/prompt.js → ai/ai-employees/vera.js} +15 -7
- package/dist/ai/ai-employees/viz.d.ts +10 -0
- package/dist/{server/ai-employees/built-in/insights-analyst/prompt.js → ai/ai-employees/viz.js} +15 -7
- package/dist/ai/skills/document-search/SKILLS.md +69 -0
- package/dist/ai/tools/chartGenerator.js +14 -3
- package/dist/ai/tools/formFiller.js +13 -2
- package/dist/{server/ai-employees/built-in/ai-coding/prompt.d.ts → ai/tools/getSkill.d.ts} +1 -3
- package/dist/{server/ai-employees/built-in/data-modeling/index.js → ai/tools/getSkill.js} +39 -32
- package/dist/ai/tools/suggestions.js +13 -2
- package/dist/client/{a06081a2b06f1c14.js → 200ac94fc7f6e97b.js} +1 -1
- package/dist/client/27539a4356faebb1.js +10 -0
- package/dist/client/2db4faf814179140.js +10 -0
- package/dist/client/{521c94db45b1e031.js → 4f9117811ffc7ab3.js} +1 -1
- package/dist/client/{c49557cc10afc6b2.js → 5af11e24bcb39ac4.js} +1 -1
- package/dist/client/62bf6ed27c8de0df.js +10 -0
- package/dist/client/6dc8c9b641452067.js +10 -0
- package/dist/client/8169eb2b48edf6c7.js +10 -0
- package/dist/client/81f6436fd9322dc1.js +10 -0
- package/dist/client/{33811690df6f43ba.js → 85af3d6d85eb5b2b.js} +1 -1
- package/dist/client/87bc4d3cb55e4006.js +10 -0
- package/dist/client/9ac11803370a9625.js +10 -0
- package/dist/client/9c00efb8eb0b4d69.js +10 -0
- package/dist/client/{f74949b95f9bbb91.js → a4948d5b70172a69.js} +1 -1
- package/dist/client/ai-employees/admin/SkillSettings.d.ts +7 -5
- 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
- package/dist/client/ai-employees/admin/mcp/MCPSettings.d.ts +10 -0
- package/dist/client/ai-employees/admin/mcp/MCPToolsList.d.ts +19 -0
- package/dist/client/ai-employees/admin/mcp/context.d.ts +15 -0
- package/dist/client/ai-employees/admin/mcp/schemas.d.ts +1286 -0
- package/dist/client/ai-employees/chatbox/utils.d.ts +3 -7
- package/dist/client/ai-employees/types.d.ts +5 -4
- package/dist/client/c83c2cae956ba914.js +10 -0
- package/dist/client/{6fcc98eb80deed47.js → d4e2ed9fa44a82b2.js} +1 -1
- package/dist/client/{5be6710cc905ec12.js → f944d487b7ff1f00.js} +1 -1
- package/dist/client/index.js +2 -2
- package/dist/client/repositories/AIConfigRepository.d.ts +8 -1
- package/dist/collections/ai-employees.js +2 -1
- package/dist/collections/ai-mcp-clients.d.ts +51 -0
- package/dist/collections/ai-mcp-clients.js +111 -0
- package/dist/externalVersion.js +14 -14
- package/dist/locale/en-US.json +65 -8
- package/dist/locale/zh-CN.json +66 -9
- package/dist/node_modules/fast-glob/package.json +1 -1
- package/dist/node_modules/flexsearch/package.json +1 -1
- package/dist/node_modules/fs-extra/package.json +1 -1
- package/dist/node_modules/nodejs-snowflake/package.json +1 -1
- package/dist/node_modules/openai/package.json +1 -1
- package/dist/node_modules/zod/package.json +1 -1
- package/dist/server/ai-employees/ai-employee.d.ts +5 -1
- package/dist/server/ai-employees/ai-employee.js +90 -13
- package/dist/server/ai-employees/middleware/index.d.ts +1 -0
- package/dist/server/ai-employees/middleware/index.js +2 -0
- package/dist/server/ai-employees/middleware/skill-tools.d.ts +12 -0
- package/dist/server/ai-employees/middleware/skill-tools.js +74 -0
- package/dist/server/ai-employees/prompts.d.ts +6 -1
- package/dist/server/ai-employees/prompts.js +9 -1
- package/dist/server/ai-employees/templates/form-assistant.d.ts +2 -2
- package/dist/server/ai-employees/templates/form-assistant.js +2 -2
- package/dist/server/ai-employees/utils.js +2 -2
- package/dist/server/{ai-employees/built-in/ai-coding/document/basic/flow-resource.d.ts → collections/ai-mcp-clients.d.ts} +1 -4
- package/dist/server/{ai-employees/built-in/ai-coding/prompt.js → collections/ai-mcp-clients.js} +12 -10
- 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
- package/dist/server/{migrations/20250923221107-setup-build-in.js → collections/ai-skills.js} +46 -13
- package/dist/server/manager/ai-coding-manager.d.ts +1 -2
- package/dist/server/manager/ai-coding-manager.js +0 -41
- package/dist/server/manager/built-in-manager.d.ts +2 -4
- package/dist/server/manager/built-in-manager.js +7 -118
- package/dist/server/migrations/20260306000001-migrate-skill-settings-tools.js +68 -0
- package/dist/server/plugin.d.ts +0 -1
- package/dist/server/plugin.js +17 -8
- package/dist/server/resource/aiEmployees.js +5 -7
- 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
- package/dist/server/resource/aiMcpClients.js +78 -0
- package/dist/server/{ai-employees/built-in/ai-coding/document/example/js-column/index.d.ts → resource/aiSkills.d.ts} +3 -7
- package/dist/server/resource/aiSkills.js +71 -0
- package/dist/server/resource/aiTools.js +4 -6
- package/dist/server/tools/docs.js +2 -2
- package/dist/server/tools/workflow-caller.js +1 -0
- package/package.json +2 -2
- package/dist/client/16dbe01d9077bb74.js +0 -10
- package/dist/client/180c8b1051a4f36e.js +0 -10
- package/dist/client/41229e007006e7f6.js +0 -10
- package/dist/client/41950da4c64caf73.js +0 -10
- package/dist/client/585ba360c7c57caf.js +0 -10
- package/dist/client/9f62a4c5136dfe8b.js +0 -10
- package/dist/client/b7f721f8dabb54e5.js +0 -10
- package/dist/client/bc471dd60174458c.js +0 -10
- package/dist/client/c40ed1a900aefb67.js +0 -10
- package/dist/server/ai-employees/built-in/ai-coding/document/basic/flow-resource.js +0 -256
- package/dist/server/ai-employees/built-in/ai-coding/document/example/js-column/index.js +0 -48
- package/dist/server/ai-employees/built-in/ai-coding/document/example/js-column/js_columns_for_accounts_en.js +0 -452
- package/dist/server/ai-employees/built-in/ai-coding/document/example/js-column/js_columns_for_contacts_en.js +0 -363
- package/dist/server/ai-employees/built-in/ai-coding/document/example/js-column/js_columns_for_opportunities_en.js +0 -270
- package/dist/server/ai-employees/built-in/ai-coding/document/example/js-column/js_columns_for_quotations_en.d.ts +0 -13
- package/dist/server/ai-employees/built-in/ai-coding/document/example/js-column/js_columns_for_quotations_en.js +0 -219
- package/dist/server/ai-employees/built-in/ai-coding/document/example/js-column/js_columns_for_tickets_en.d.ts +0 -13
- package/dist/server/ai-employees/built-in/ai-coding/document/example/js-column/js_columns_for_tickets_en.js +0 -409
- package/dist/server/ai-employees/built-in/ai-coding/document/example/js-filter/accounts_filter_ant_style.d.ts +0 -13
- package/dist/server/ai-employees/built-in/ai-coding/document/example/js-filter/accounts_filter_ant_style.js +0 -324
- package/dist/server/ai-employees/built-in/ai-coding/document/example/js-filter/contacts_filter_ant_style.d.ts +0 -13
- package/dist/server/ai-employees/built-in/ai-coding/document/example/js-filter/contacts_filter_ant_style.js +0 -309
- package/dist/server/ai-employees/built-in/ai-coding/document/example/js-filter/index.d.ts +0 -15
- package/dist/server/ai-employees/built-in/ai-coding/document/example/js-filter/index.js +0 -50
- package/dist/server/ai-employees/built-in/ai-coding/document/example/js-filter/leads_filter_ant_style.d.ts +0 -13
- package/dist/server/ai-employees/built-in/ai-coding/document/example/js-filter/leads_filter_ant_style.js +0 -345
- package/dist/server/ai-employees/built-in/ai-coding/document/example/js-filter/opportunities_filter_ant_style.d.ts +0 -13
- package/dist/server/ai-employees/built-in/ai-coding/document/example/js-filter/opportunities_filter_ant_style.js +0 -381
- package/dist/server/ai-employees/built-in/ai-coding/document/example/js-filter/product_categories_ant_style.d.ts +0 -13
- package/dist/server/ai-employees/built-in/ai-coding/document/example/js-filter/product_categories_ant_style.js +0 -545
- package/dist/server/ai-employees/built-in/ai-coding/document/example/js-filter/tickets_filter_ant_style.d.ts +0 -13
- package/dist/server/ai-employees/built-in/ai-coding/document/example/js-filter/tickets_filter_ant_style.js +0 -346
- package/dist/server/ai-employees/built-in/ai-coding/document/js-action.d.ts +0 -13
- package/dist/server/ai-employees/built-in/ai-coding/document/js-action.js +0 -102
- package/dist/server/ai-employees/built-in/ai-coding/document/js-block.d.ts +0 -13
- package/dist/server/ai-employees/built-in/ai-coding/document/js-block.js +0 -314
- package/dist/server/ai-employees/built-in/ai-coding/document/js-column.d.ts +0 -13
- package/dist/server/ai-employees/built-in/ai-coding/document/js-column.js +0 -113
- package/dist/server/ai-employees/built-in/ai-coding/document/js-field.d.ts +0 -13
- package/dist/server/ai-employees/built-in/ai-coding/document/js-field.js +0 -498
- package/dist/server/ai-employees/built-in/ai-coding/document/js-item.d.ts +0 -13
- package/dist/server/ai-employees/built-in/ai-coding/document/js-item.js +0 -184
- package/dist/server/ai-employees/built-in/ai-coding/index.d.ts +0 -37
- package/dist/server/ai-employees/built-in/ai-coding/index.js +0 -99
- package/dist/server/ai-employees/built-in/ai-coding/profile.d.ts +0 -27
- package/dist/server/ai-employees/built-in/ai-coding/profile.js +0 -60
- package/dist/server/ai-employees/built-in/ai-coding/prompt_en.md +0 -110
- package/dist/server/ai-employees/built-in/data-modeling/index.d.ts +0 -37
- package/dist/server/ai-employees/built-in/data-modeling/profile.d.ts +0 -27
- package/dist/server/ai-employees/built-in/data-modeling/profile.js +0 -60
- package/dist/server/ai-employees/built-in/data-modeling/prompt.js +0 -283
- package/dist/server/ai-employees/built-in/data-organizer/index.d.ts +0 -37
- package/dist/server/ai-employees/built-in/data-organizer/index.js +0 -63
- package/dist/server/ai-employees/built-in/data-organizer/profile.d.ts +0 -27
- package/dist/server/ai-employees/built-in/data-organizer/profile.js +0 -60
- package/dist/server/ai-employees/built-in/data-visualization/index.d.ts +0 -37
- package/dist/server/ai-employees/built-in/data-visualization/index.js +0 -58
- package/dist/server/ai-employees/built-in/data-visualization/profile.d.ts +0 -27
- package/dist/server/ai-employees/built-in/data-visualization/profile.js +0 -60
- package/dist/server/ai-employees/built-in/email-assistant/index.d.ts +0 -34
- package/dist/server/ai-employees/built-in/email-assistant/index.js +0 -50
- package/dist/server/ai-employees/built-in/email-assistant/profile.d.ts +0 -27
- package/dist/server/ai-employees/built-in/email-assistant/profile.js +0 -60
- package/dist/server/ai-employees/built-in/email-assistant/prompt.d.ts +0 -12
- package/dist/server/ai-employees/built-in/insights-analyst/index.d.ts +0 -37
- package/dist/server/ai-employees/built-in/insights-analyst/index.js +0 -63
- package/dist/server/ai-employees/built-in/insights-analyst/profile.d.ts +0 -27
- package/dist/server/ai-employees/built-in/insights-analyst/profile.js +0 -60
- package/dist/server/ai-employees/built-in/insights-analyst/prompt.d.ts +0 -12
- package/dist/server/ai-employees/built-in/nocobase-assistant/index.d.ts +0 -34
- package/dist/server/ai-employees/built-in/nocobase-assistant/index.js +0 -50
- package/dist/server/ai-employees/built-in/nocobase-assistant/profile.d.ts +0 -27
- package/dist/server/ai-employees/built-in/nocobase-assistant/profile.js +0 -60
- package/dist/server/ai-employees/built-in/nocobase-assistant/prompt.d.ts +0 -12
- package/dist/server/ai-employees/built-in/research-analyst/index.d.ts +0 -37
- package/dist/server/ai-employees/built-in/research-analyst/index.js +0 -63
- package/dist/server/ai-employees/built-in/research-analyst/profile.d.ts +0 -27
- package/dist/server/ai-employees/built-in/research-analyst/profile.js +0 -60
- package/dist/server/ai-employees/built-in/research-analyst/prompt.d.ts +0 -12
- package/dist/server/ai-employees/built-in/translator/index.d.ts +0 -37
- package/dist/server/ai-employees/built-in/translator/index.js +0 -67
- package/dist/server/ai-employees/built-in/translator/profile.d.ts +0 -27
- package/dist/server/ai-employees/built-in/translator/profile.js +0 -60
- package/dist/server/ai-employees/built-in/translator/prompt.d.ts +0 -12
- /package/dist/server/migrations/{20250923221107-setup-build-in.d.ts → 20260306000001-migrate-skill-settings-tools.d.ts} +0 -0
|
@@ -1,363 +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_contacts_en_exports = {};
|
|
28
|
-
__export(js_columns_for_contacts_en_exports, {
|
|
29
|
-
default: () => js_columns_for_contacts_en_default
|
|
30
|
-
});
|
|
31
|
-
module.exports = __toCommonJS(js_columns_for_contacts_en_exports);
|
|
32
|
-
var js_columns_for_contacts_en_default = {
|
|
33
|
-
name: "js_columns_for_contacts",
|
|
34
|
-
content: String.raw`# NocoBase JS Column Examples - Contacts Table
|
|
35
|
-
|
|
36
|
-
## Overview
|
|
37
|
-
Practical JavaScript column examples for the contacts table in CRM systems. These aggregated columns integrate multiple fields, display relationship networks, and visualize communication history to enhance contact data readability and business value.
|
|
38
|
-
|
|
39
|
-
## Selected JS Column Examples
|
|
40
|
-
|
|
41
|
-
## 1. Contact Business Card
|
|
42
|
-
|
|
43
|
-
Display contact's core information including name, title, department, and company affiliation.
|
|
44
|
-
|
|
45
|
-
\`\`\`javascript
|
|
46
|
-
// Contact business card - Name, title, company, department
|
|
47
|
-
const name = ctx.record?.name || 'Unknown';
|
|
48
|
-
const title = ctx.record?.title || '';
|
|
49
|
-
const department = ctx.record?.department || '';
|
|
50
|
-
const account = ctx.record?.account;
|
|
51
|
-
const accountName = account?.name || '';
|
|
52
|
-
const salutation = ctx.record?.salutation || '';
|
|
53
|
-
const email = ctx.record?.email || '';
|
|
54
|
-
|
|
55
|
-
// Get initials for avatar
|
|
56
|
-
const getInitials = (name) => {
|
|
57
|
-
return name.split(' ').map(n => n[0]).join('').toUpperCase().slice(0, 2);
|
|
58
|
-
};
|
|
59
|
-
|
|
60
|
-
// Generate color based on department
|
|
61
|
-
const departmentColors = {
|
|
62
|
-
'Sales': '#52c41a',
|
|
63
|
-
'Marketing': '#1677ff',
|
|
64
|
-
'Engineering': '#722ed1',
|
|
65
|
-
'Support': '#faad14',
|
|
66
|
-
'Finance': '#eb2f96',
|
|
67
|
-
'Human Resources': '#13c2c2',
|
|
68
|
-
'Operations': '#fa8c16'
|
|
69
|
-
};
|
|
70
|
-
|
|
71
|
-
const getDeptColor = (dept) => {
|
|
72
|
-
for (let key in departmentColors) {
|
|
73
|
-
if (dept?.toLowerCase().includes(key.toLowerCase())) {
|
|
74
|
-
return departmentColors[key];
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
return '#8c8c8c';
|
|
78
|
-
};
|
|
79
|
-
|
|
80
|
-
const avatarColor = getDeptColor(department);
|
|
81
|
-
|
|
82
|
-
ctx.element.innerHTML = \`
|
|
83
|
-
<div style="display:flex;align-items:center;gap:12px;">
|
|
84
|
-
<div style="
|
|
85
|
-
width:40px;
|
|
86
|
-
height:40px;
|
|
87
|
-
border-radius:50%;
|
|
88
|
-
background:\${avatarColor};
|
|
89
|
-
color:white;
|
|
90
|
-
display:flex;
|
|
91
|
-
align-items:center;
|
|
92
|
-
justify-content:center;
|
|
93
|
-
font-weight:600;
|
|
94
|
-
font-size:14px;
|
|
95
|
-
flex-shrink:0;
|
|
96
|
-
">
|
|
97
|
-
\${getInitials(name)}
|
|
98
|
-
</div>
|
|
99
|
-
<div style="display:flex;flex-direction:column;min-width:0;">
|
|
100
|
-
<div style="display:flex;align-items:center;gap:6px;">
|
|
101
|
-
\${salutation ? \`<span style="color:#8c8c8c;font-size:12px;">\${salutation}</span>\` : ''}
|
|
102
|
-
<strong style="color:#000;font-size:14px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;">\${name}</strong>
|
|
103
|
-
</div>
|
|
104
|
-
\${title || department ? \`
|
|
105
|
-
<div style="color:#595959;font-size:12px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;">
|
|
106
|
-
\${title}\${title && department ? ' · ' : ''}\${department}
|
|
107
|
-
</div>
|
|
108
|
-
\` : ''}
|
|
109
|
-
\${accountName ? \`
|
|
110
|
-
<div style="display:flex;align-items:center;gap:4px;">
|
|
111
|
-
<span style="color:#8c8c8c;font-size:11px;">@</span>
|
|
112
|
-
<a class="account-link" style="
|
|
113
|
-
color:#1677ff;
|
|
114
|
-
font-size:11px;
|
|
115
|
-
overflow:hidden;
|
|
116
|
-
text-overflow:ellipsis;
|
|
117
|
-
white-space:nowrap;
|
|
118
|
-
cursor:pointer;
|
|
119
|
-
text-decoration:none;
|
|
120
|
-
transition:all 0.2s;
|
|
121
|
-
"
|
|
122
|
-
onmouseover="this.style.textDecoration='underline'"
|
|
123
|
-
onmouseout="this.style.textDecoration='none'"
|
|
124
|
-
>\${accountName}</a>
|
|
125
|
-
</div>
|
|
126
|
-
\` : ''}
|
|
127
|
-
</div>
|
|
128
|
-
</div>
|
|
129
|
-
\`;
|
|
130
|
-
|
|
131
|
-
// Click company name to open account info dialog
|
|
132
|
-
if (accountName) {
|
|
133
|
-
ctx.element.querySelector('.account-link')?.addEventListener('click', async () => {
|
|
134
|
-
await ctx.openView('c91bba4e338', {
|
|
135
|
-
title: 'Account Info',
|
|
136
|
-
navigation: false,
|
|
137
|
-
});
|
|
138
|
-
});
|
|
139
|
-
}
|
|
140
|
-
\`\`\`
|
|
141
|
-
|
|
142
|
-
## 2. Contact Information Display
|
|
143
|
-
|
|
144
|
-
Shows all contact methods with quick copy functionality.
|
|
145
|
-
|
|
146
|
-
\`\`\`javascript
|
|
147
|
-
// Contact methods - Email, phone, mobile with quick actions
|
|
148
|
-
const email = ctx.record?.email || '';
|
|
149
|
-
const phone = ctx.record?.phone || '';
|
|
150
|
-
const mobile = ctx.record?.mobile || '';
|
|
151
|
-
|
|
152
|
-
const contacts = [
|
|
153
|
-
{ type: 'email', value: email, icon: '✉️', color: '#1677ff' },
|
|
154
|
-
{ type: 'phone', value: phone, icon: '☎️', color: '#52c41a' },
|
|
155
|
-
{ type: 'mobile', value: mobile, icon: '📱', color: '#fa8c16' }
|
|
156
|
-
].filter(c => c.value);
|
|
157
|
-
|
|
158
|
-
// Format display text while preserving content
|
|
159
|
-
const formatContactDisplay = (type, value) => {
|
|
160
|
-
if (type === 'email') {
|
|
161
|
-
// Show more characters for email
|
|
162
|
-
if (value.length > 25) {
|
|
163
|
-
const [username, domain] = value.split('@');
|
|
164
|
-
if (username.length > 15) {
|
|
165
|
-
return username.substring(0, 15) + '...@' + domain;
|
|
166
|
-
}
|
|
167
|
-
return value;
|
|
168
|
-
}
|
|
169
|
-
return value;
|
|
170
|
-
}
|
|
171
|
-
// Display full phone number
|
|
172
|
-
return value;
|
|
173
|
-
};
|
|
174
|
-
|
|
175
|
-
ctx.element.innerHTML = \`
|
|
176
|
-
<div style="display:flex;gap:6px;flex-wrap:wrap;min-width:200px;">
|
|
177
|
-
\${contacts.length > 0 ? contacts.map(contact => \`
|
|
178
|
-
<a
|
|
179
|
-
href="javascript:void(0)"
|
|
180
|
-
class="contact-btn"
|
|
181
|
-
data-type="\${contact.type}"
|
|
182
|
-
data-value="\${contact.value}"
|
|
183
|
-
title="\${contact.value}"
|
|
184
|
-
style="
|
|
185
|
-
display:inline-flex;
|
|
186
|
-
align-items:center;
|
|
187
|
-
gap:4px;
|
|
188
|
-
padding:4px 10px;
|
|
189
|
-
background:\${contact.color}10;
|
|
190
|
-
border:1px solid \${contact.color}30;
|
|
191
|
-
border-radius:4px;
|
|
192
|
-
text-decoration:none;
|
|
193
|
-
transition:all 0.2s;
|
|
194
|
-
cursor:pointer;
|
|
195
|
-
max-width:250px;
|
|
196
|
-
"
|
|
197
|
-
>
|
|
198
|
-
<span style="font-size:12px;flex-shrink:0;">\${contact.icon}</span>
|
|
199
|
-
<span style="
|
|
200
|
-
color:\${contact.color};
|
|
201
|
-
font-size:11px;
|
|
202
|
-
font-weight:500;
|
|
203
|
-
overflow:hidden;
|
|
204
|
-
text-overflow:ellipsis;
|
|
205
|
-
white-space:nowrap;
|
|
206
|
-
">
|
|
207
|
-
\${formatContactDisplay(contact.type, contact.value)}
|
|
208
|
-
</span>
|
|
209
|
-
</a>
|
|
210
|
-
\`).join('') : '<span style="color:#bfbfbf;font-size:12px;">No contact info</span>'}
|
|
211
|
-
</div>
|
|
212
|
-
\`;
|
|
213
|
-
|
|
214
|
-
// Bind click to copy functionality
|
|
215
|
-
ctx.element.querySelectorAll('.contact-btn').forEach(btn => {
|
|
216
|
-
btn.addEventListener('click', (e) => {
|
|
217
|
-
e.preventDefault();
|
|
218
|
-
const value = btn.dataset.value;
|
|
219
|
-
const type = btn.dataset.type;
|
|
220
|
-
|
|
221
|
-
// Copy to clipboard
|
|
222
|
-
navigator.clipboard.writeText(value).then(() => {
|
|
223
|
-
ctx.message.success(\`\${type === 'email' ? 'Email' : type === 'phone' ? 'Phone' : 'Mobile'} copied!\`);
|
|
224
|
-
}).catch(() => {
|
|
225
|
-
ctx.message.error('Failed to copy');
|
|
226
|
-
});
|
|
227
|
-
});
|
|
228
|
-
|
|
229
|
-
// Hover effect
|
|
230
|
-
btn.addEventListener('mouseenter', () => {
|
|
231
|
-
btn.style.transform = 'translateY(-1px)';
|
|
232
|
-
btn.style.boxShadow = '0 2px 4px rgba(0,0,0,0.1)';
|
|
233
|
-
});
|
|
234
|
-
btn.addEventListener('mouseleave', () => {
|
|
235
|
-
btn.style.transform = 'translateY(0)';
|
|
236
|
-
btn.style.boxShadow = 'none';
|
|
237
|
-
});
|
|
238
|
-
});
|
|
239
|
-
\`\`\`
|
|
240
|
-
|
|
241
|
-
## 3. Activity Metrics Dashboard
|
|
242
|
-
|
|
243
|
-
Calculates interaction frequency based on tasks, events, and last update time.
|
|
244
|
-
|
|
245
|
-
\`\`\`javascript
|
|
246
|
-
// Activity metrics - Activity frequency and last interaction
|
|
247
|
-
// Note: Include tasks, events and contact_comments relations in query
|
|
248
|
-
const tasks = ctx.record?.tasks || ctx.record?.campaign_tasks || [];
|
|
249
|
-
const events = ctx.record?.events || [];
|
|
250
|
-
const comments = ctx.record?.contact_comments || [];
|
|
251
|
-
const updatedAt = ctx.record?.updatedAt;
|
|
252
|
-
|
|
253
|
-
// Show all data without time filtering
|
|
254
|
-
const totalTasks = tasks.length;
|
|
255
|
-
const totalEvents = events.length;
|
|
256
|
-
const totalComments = comments.length;
|
|
257
|
-
const totalActivities = totalTasks + totalEvents + totalComments;
|
|
258
|
-
|
|
259
|
-
// Calculate activity level
|
|
260
|
-
const activityLevel = totalActivities >= 10 ? 'Very Active' :
|
|
261
|
-
totalActivities >= 5 ? 'Active' :
|
|
262
|
-
totalActivities >= 1 ? 'Low Activity' :
|
|
263
|
-
'Inactive';
|
|
264
|
-
|
|
265
|
-
const levelColors = {
|
|
266
|
-
'Very Active': '#52c41a',
|
|
267
|
-
'Active': '#1677ff',
|
|
268
|
-
'Low Activity': '#faad14',
|
|
269
|
-
'Inactive': '#ff4d4f'
|
|
270
|
-
};
|
|
271
|
-
|
|
272
|
-
// Calculate last interaction
|
|
273
|
-
const getLastInteraction = () => {
|
|
274
|
-
if (!updatedAt) return 'Never contacted';
|
|
275
|
-
const diff = new Date() - new Date(updatedAt);
|
|
276
|
-
const days = Math.floor(diff / (1000 * 60 * 60 * 24));
|
|
277
|
-
const hours = Math.floor(diff / (1000 * 60 * 60));
|
|
278
|
-
|
|
279
|
-
if (days > 30) return \`\${Math.floor(days/30)} months ago\`;
|
|
280
|
-
if (days > 0) return \`\${days} days ago\`;
|
|
281
|
-
if (hours > 0) return \`\${hours} hours ago\`;
|
|
282
|
-
return 'Just now';
|
|
283
|
-
};
|
|
284
|
-
|
|
285
|
-
const levelColor = levelColors[activityLevel];
|
|
286
|
-
|
|
287
|
-
ctx.element.innerHTML = \`
|
|
288
|
-
<div style="display:flex;flex-direction:column;gap:6px;">
|
|
289
|
-
<div style="display:flex;align-items:center;justify-content:space-between;gap:16px;">
|
|
290
|
-
<div style="display:flex;align-items:center;gap:8px;">
|
|
291
|
-
<div style="
|
|
292
|
-
width:8px;
|
|
293
|
-
height:8px;
|
|
294
|
-
border-radius:50%;
|
|
295
|
-
background:\${levelColor};
|
|
296
|
-
\${activityLevel === 'Very Active' ? 'animation: pulse 2s infinite;' : ''}
|
|
297
|
-
"></div>
|
|
298
|
-
<span style="color:\${levelColor};font-size:12px;font-weight:600;">\${activityLevel}</span>
|
|
299
|
-
</div>
|
|
300
|
-
<div style="display:flex;align-items:center;gap:4px;margin-left:auto;">
|
|
301
|
-
<span style="color:#bfbfbf;font-size:10px;">Last update:</span>
|
|
302
|
-
<span style="color:#8c8c8c;font-size:11px;">\${getLastInteraction()}</span>
|
|
303
|
-
</div>
|
|
304
|
-
</div>
|
|
305
|
-
|
|
306
|
-
<div style="display:flex;gap:4px;">
|
|
307
|
-
<div style="flex:1;text-align:center;padding:4px 0;border-right:1px solid #f0f0f0;">
|
|
308
|
-
<div style="color:#595959;font-size:16px;font-weight:600;">\${totalTasks}</div>
|
|
309
|
-
<div style="color:#8c8c8c;font-size:10px;">Tasks</div>
|
|
310
|
-
</div>
|
|
311
|
-
<div style="flex:1;text-align:center;padding:4px 0;border-right:1px solid #f0f0f0;">
|
|
312
|
-
<div style="color:#595959;font-size:16px;font-weight:600;">\${totalEvents}</div>
|
|
313
|
-
<div style="color:#8c8c8c;font-size:10px;">Events</div>
|
|
314
|
-
</div>
|
|
315
|
-
<div style="flex:1;text-align:center;padding:4px 0;">
|
|
316
|
-
<div style="color:#595959;font-size:16px;font-weight:600;">\${totalComments}</div>
|
|
317
|
-
<div style="color:#8c8c8c;font-size:10px;">Comments</div>
|
|
318
|
-
</div>
|
|
319
|
-
</div>
|
|
320
|
-
|
|
321
|
-
<div style="position:relative;height:4px;background:#f0f0f0;border-radius:2px;overflow:hidden;">
|
|
322
|
-
<div style="
|
|
323
|
-
position:absolute;
|
|
324
|
-
left:0;
|
|
325
|
-
top:0;
|
|
326
|
-
height:100%;
|
|
327
|
-
width:\${Math.min(totalActivities * 10, 100)}%;
|
|
328
|
-
background:\${levelColor};
|
|
329
|
-
border-radius:2px;
|
|
330
|
-
transition:width 0.3s;
|
|
331
|
-
"></div>
|
|
332
|
-
</div>
|
|
333
|
-
</div>
|
|
334
|
-
|
|
335
|
-
<style>
|
|
336
|
-
@keyframes pulse {
|
|
337
|
-
0% { opacity: 1; }
|
|
338
|
-
50% { opacity: 0.5; }
|
|
339
|
-
100% { opacity: 1; }
|
|
340
|
-
}
|
|
341
|
-
</style>
|
|
342
|
-
\`;
|
|
343
|
-
\`\`\`
|
|
344
|
-
|
|
345
|
-
## Usage Instructions
|
|
346
|
-
|
|
347
|
-
### Configuration in NocoBase
|
|
348
|
-
1. Navigate to the contacts table configuration interface
|
|
349
|
-
2. Add a new column and select "JavaScript" type
|
|
350
|
-
3. Paste the corresponding code into the code editor
|
|
351
|
-
4. Save and refresh the table to see the effects
|
|
352
|
-
|
|
353
|
-
### Data Dependencies
|
|
354
|
-
- **Related data**: Properly configure account, owner, reports_to, opportunities, tasks, events, tags relations
|
|
355
|
-
- **Null handling**: All code includes null checks to prevent errors with missing data
|
|
356
|
-
- **Performance**: For columns with many related data, limit rows per page
|
|
357
|
-
|
|
358
|
-
### Customization Tips
|
|
359
|
-
- **Color theme**: Adjust to match brand color #1677ff
|
|
360
|
-
- **Display limits**: Adjust the number of tags, tasks, events shown
|
|
361
|
-
- **Time format**: Adjust date/time display based on regional preferences
|
|
362
|
-
- **Icon style**: Replace with other emojis or icon fonts as needed`
|
|
363
|
-
};
|
|
@@ -1,270 +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_opportunities_en_exports = {};
|
|
28
|
-
__export(js_columns_for_opportunities_en_exports, {
|
|
29
|
-
default: () => js_columns_for_opportunities_en_default
|
|
30
|
-
});
|
|
31
|
-
module.exports = __toCommonJS(js_columns_for_opportunities_en_exports);
|
|
32
|
-
var js_columns_for_opportunities_en_default = {
|
|
33
|
-
name: "js_columns_for_opportunities",
|
|
34
|
-
content: String.raw`# NocoBase JS Column Examples - Opportunities Table
|
|
35
|
-
|
|
36
|
-
## Overview
|
|
37
|
-
Practical JavaScript column examples for the opportunities table in CRM systems. These aggregated columns integrate sales stages, amount forecasting, and close probability to enhance opportunity management efficiency.
|
|
38
|
-
|
|
39
|
-
## Selected JS Column Examples
|
|
40
|
-
|
|
41
|
-
## 1. Opportunity Overview Card
|
|
42
|
-
|
|
43
|
-
Displays opportunity name, amount, and current stage with highlighted key information.
|
|
44
|
-
|
|
45
|
-
\`\`\`javascript
|
|
46
|
-
// Opportunity overview card - Name, amount, stage
|
|
47
|
-
const name = ctx.record?.name || 'Unnamed Opportunity';
|
|
48
|
-
const amount = ctx.record?.amount || 0;
|
|
49
|
-
const stage = ctx.record?.stage || 'Initial Contact';
|
|
50
|
-
const probability = (ctx.record?.probability || 0) * 100; // Database stores as decimal, multiply by 100 for display
|
|
51
|
-
|
|
52
|
-
// Stage color configuration
|
|
53
|
-
const stageColors = {
|
|
54
|
-
'Initial Contact': '#1677ff',
|
|
55
|
-
'Needs Analysis': '#722ed1',
|
|
56
|
-
'Solution Development': '#13c2c2',
|
|
57
|
-
'Proposal & Negotiation': '#faad14',
|
|
58
|
-
'Contract Review': '#fa8c16',
|
|
59
|
-
'New Order': '#eb2f96',
|
|
60
|
-
'Win': '#52c41a',
|
|
61
|
-
'Lost': '#ff4d4f'
|
|
62
|
-
};
|
|
63
|
-
|
|
64
|
-
const stageColor = stageColors[stage] || '#8c8c8c';
|
|
65
|
-
const isWon = stage === 'Win';
|
|
66
|
-
const isLost = stage === 'Lost';
|
|
67
|
-
|
|
68
|
-
// Simple formatting function
|
|
69
|
-
const formatCurrency = (value) => {
|
|
70
|
-
if (value >= 1000000) return \`$\${(value/1000000).toFixed(1)}M\`;
|
|
71
|
-
if (value >= 1000) return \`$\${(value/1000).toFixed(0)}K\`;
|
|
72
|
-
return \`$\${value.toFixed(0)}\`;
|
|
73
|
-
};
|
|
74
|
-
|
|
75
|
-
ctx.element.innerHTML = \`
|
|
76
|
-
<div style="
|
|
77
|
-
display: flex;
|
|
78
|
-
flex-direction: column;
|
|
79
|
-
gap: 3px;
|
|
80
|
-
padding: 0;
|
|
81
|
-
">
|
|
82
|
-
<div style="
|
|
83
|
-
font-size: 12px;
|
|
84
|
-
font-weight: 500;
|
|
85
|
-
color: #000;
|
|
86
|
-
overflow: hidden;
|
|
87
|
-
text-overflow: ellipsis;
|
|
88
|
-
white-space: nowrap;
|
|
89
|
-
" title="\${name}">
|
|
90
|
-
\${name}
|
|
91
|
-
</div>
|
|
92
|
-
<div style="
|
|
93
|
-
display: flex;
|
|
94
|
-
align-items: center;
|
|
95
|
-
gap: 8px;
|
|
96
|
-
">
|
|
97
|
-
<span style="
|
|
98
|
-
font-size: 14px;
|
|
99
|
-
font-weight: 600;
|
|
100
|
-
color: \${isLost ? '#999' : '#000'};
|
|
101
|
-
\${isLost ? 'text-decoration: line-through;' : ''}
|
|
102
|
-
">
|
|
103
|
-
\${formatCurrency(amount)}
|
|
104
|
-
</span>
|
|
105
|
-
\${probability > 0 && !isWon && !isLost ? \`
|
|
106
|
-
<span style="
|
|
107
|
-
color: #666;
|
|
108
|
-
font-size: 10px;
|
|
109
|
-
">
|
|
110
|
-
\${Math.round(probability)}%
|
|
111
|
-
</span>
|
|
112
|
-
\` : ''}
|
|
113
|
-
</div>
|
|
114
|
-
<div style="
|
|
115
|
-
display: inline-flex;
|
|
116
|
-
align-items: center;
|
|
117
|
-
padding: 2px 6px;
|
|
118
|
-
background: \${stageColor}15;
|
|
119
|
-
color: \${stageColor};
|
|
120
|
-
border-radius: 3px;
|
|
121
|
-
font-size: 10px;
|
|
122
|
-
font-weight: 500;
|
|
123
|
-
align-self: flex-start;
|
|
124
|
-
">
|
|
125
|
-
\${stage}
|
|
126
|
-
</div>
|
|
127
|
-
</div>
|
|
128
|
-
\`;
|
|
129
|
-
\`\`\`
|
|
130
|
-
|
|
131
|
-
## 2. Close Date Tracker
|
|
132
|
-
|
|
133
|
-
Monitors opportunity's expected close date and urgency level.
|
|
134
|
-
|
|
135
|
-
\`\`\`javascript
|
|
136
|
-
// Close date tracker
|
|
137
|
-
const closeDate = ctx.record?.close_date;
|
|
138
|
-
const stage = ctx.record?.stage || 'Initial Contact';
|
|
139
|
-
const createdAt = ctx.record?.createdAt;
|
|
140
|
-
const amount = ctx.record?.amount || 0;
|
|
141
|
-
|
|
142
|
-
// Calculate opportunity age
|
|
143
|
-
const getOpportunityAge = () => {
|
|
144
|
-
if (!createdAt) return null;
|
|
145
|
-
const age = Math.floor((new Date() - new Date(createdAt)) / (1000 * 60 * 60 * 24));
|
|
146
|
-
return age;
|
|
147
|
-
};
|
|
148
|
-
|
|
149
|
-
// Calculate days to close
|
|
150
|
-
const getDaysToClose = () => {
|
|
151
|
-
if (!closeDate) return null;
|
|
152
|
-
const days = Math.ceil((new Date(closeDate) - new Date()) / (1000 * 60 * 60 * 24));
|
|
153
|
-
return days;
|
|
154
|
-
};
|
|
155
|
-
|
|
156
|
-
// Get urgency status
|
|
157
|
-
const getUrgencyStatus = () => {
|
|
158
|
-
const daysToClose = getDaysToClose();
|
|
159
|
-
const age = getOpportunityAge();
|
|
160
|
-
|
|
161
|
-
if (stage === 'Win' || stage === 'Lost') {
|
|
162
|
-
return {
|
|
163
|
-
status: stage === 'Win' ? 'Closed Won' : 'Closed Lost',
|
|
164
|
-
color: stage === 'Win' ? '#52c41a' : '#8c8c8c'
|
|
165
|
-
};
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
if (!closeDate) {
|
|
169
|
-
if (age > 90) return { status: 'Stalled', color: '#ff4d4f' };
|
|
170
|
-
if (age > 60) return { status: 'Slow Progress', color: '#faad14' };
|
|
171
|
-
return { status: 'Active', color: '#1677ff' };
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
if (daysToClose < 0) return { status: 'Overdue', color: '#ff4d4f' };
|
|
175
|
-
if (daysToClose <= 7) return { status: 'This Week', color: '#fa8c16' };
|
|
176
|
-
if (daysToClose <= 30) return { status: 'This Month', color: '#faad14' };
|
|
177
|
-
if (daysToClose <= 90) return { status: 'This Quarter', color: '#1677ff' };
|
|
178
|
-
return { status: 'Future', color: '#52c41a' };
|
|
179
|
-
};
|
|
180
|
-
|
|
181
|
-
const urgency = getUrgencyStatus();
|
|
182
|
-
const daysToClose = getDaysToClose();
|
|
183
|
-
const age = getOpportunityAge();
|
|
184
|
-
|
|
185
|
-
// Simple formatting function
|
|
186
|
-
const formatCurrency = (value) => {
|
|
187
|
-
if (value >= 1000000) return \`$\${(value/1000000).toFixed(1)}M\`;
|
|
188
|
-
if (value >= 1000) return \`$\${(value/1000).toFixed(0)}K\`;
|
|
189
|
-
return \`$\${value.toFixed(0)}\`;
|
|
190
|
-
};
|
|
191
|
-
|
|
192
|
-
ctx.element.innerHTML = \`
|
|
193
|
-
<div style="
|
|
194
|
-
display: flex;
|
|
195
|
-
flex-direction: column;
|
|
196
|
-
gap: 3px;
|
|
197
|
-
padding: 0;
|
|
198
|
-
">
|
|
199
|
-
<div style="
|
|
200
|
-
display: flex;
|
|
201
|
-
align-items: center;
|
|
202
|
-
gap: 6px;
|
|
203
|
-
">
|
|
204
|
-
<span style="
|
|
205
|
-
color: \${urgency.color};
|
|
206
|
-
font-size: 12px;
|
|
207
|
-
font-weight: 500;
|
|
208
|
-
">
|
|
209
|
-
\${urgency.status}
|
|
210
|
-
</span>
|
|
211
|
-
\${daysToClose !== null && daysToClose > 0 ? \`
|
|
212
|
-
<span style="color: #666; font-size: 11px;">
|
|
213
|
-
(\${daysToClose}d)
|
|
214
|
-
</span>
|
|
215
|
-
\` : ''}
|
|
216
|
-
</div>
|
|
217
|
-
|
|
218
|
-
\${closeDate && stage !== 'Win' && stage !== 'Lost' ? \`
|
|
219
|
-
<div style="
|
|
220
|
-
color: #666;
|
|
221
|
-
font-size: 11px;
|
|
222
|
-
">
|
|
223
|
-
Close: \${new Date(closeDate).toLocaleDateString()}
|
|
224
|
-
</div>
|
|
225
|
-
\` : ''}
|
|
226
|
-
|
|
227
|
-
\${age !== null ? \`
|
|
228
|
-
<div style="
|
|
229
|
-
color: #999;
|
|
230
|
-
font-size: 10px;
|
|
231
|
-
">
|
|
232
|
-
Age: \${
|
|
233
|
-
age === 0 ? 'New' :
|
|
234
|
-
age < 30 ? \`\${age}d\` :
|
|
235
|
-
age < 90 ? \`\${Math.floor(age/30)}mo\` :
|
|
236
|
-
\`\${Math.floor(age/30)}mo\`
|
|
237
|
-
}
|
|
238
|
-
\${amount > 0 ? \` • \${formatCurrency(amount)}\` : ''}
|
|
239
|
-
</div>
|
|
240
|
-
\` : ''}
|
|
241
|
-
</div>
|
|
242
|
-
\`;
|
|
243
|
-
\`\`\`
|
|
244
|
-
|
|
245
|
-
## Usage Instructions
|
|
246
|
-
|
|
247
|
-
### Configuration in NocoBase
|
|
248
|
-
1. Navigate to the opportunities table configuration interface
|
|
249
|
-
2. Add a new column and select "JavaScript" type
|
|
250
|
-
3. Paste the corresponding code into the code editor
|
|
251
|
-
4. Save and refresh the table to see the effects
|
|
252
|
-
|
|
253
|
-
### Data Dependencies
|
|
254
|
-
- **Base fields**: name, amount, stage, probability
|
|
255
|
-
- **Date fields**: close_date, createdAt
|
|
256
|
-
- **Related fields**: account, contact, owner
|
|
257
|
-
- **Extended fields**: expected_revenue, lead_source, stage_sort
|
|
258
|
-
|
|
259
|
-
### Performance Optimization
|
|
260
|
-
- Cache results for complex calculations like scoring
|
|
261
|
-
- Query only necessary fields for related data
|
|
262
|
-
- Consider pagination or virtual scrolling for large datasets
|
|
263
|
-
|
|
264
|
-
### Customization Tips
|
|
265
|
-
- **Stage management**: Ensure sales stages are clearly defined with proper flow rules
|
|
266
|
-
- **Probability settings**: Establish default stage-to-probability mappings
|
|
267
|
-
- **Amount accuracy**: Update opportunity amounts promptly for accurate forecasting
|
|
268
|
-
- **Close dates**: Set reasonable expected close dates for priority management
|
|
269
|
-
- **Scoring system**: Adjust score weights based on business characteristics`
|
|
270
|
-
};
|
|
@@ -1,13 +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
|
-
declare const _default: {
|
|
10
|
-
name: string;
|
|
11
|
-
content: string;
|
|
12
|
-
};
|
|
13
|
-
export default _default;
|