腳本參考
本文件提供了在工作流程規則中編寫腳本的綜合參考。腳本允許您使用 JavaScript 實現進階自動化邏輯。
概述
工作流程規則中的 執行腳本 操作執行 JavaScript 代碼以自動化複雜的工單處理場景。腳本在沙箱環境中執行,可以存取工單資料、訊息上下文和輔助函數。
主要功能:
- 讀取和修改工單屬性
- 存取客戶和擁有者資訊
- 使用自訂欄位
- 使用條件邏輯和循環
- 10 秒執行超時以確保安全
工單物件
ticket 物件是腳本的主要上下文。它提供對工單資料的讀取和寫入存取權限。
唯讀屬性
// 基本工單資訊
ticket.id // UUID 字串
ticket.subject // 工單主旨行
// 當前狀態(物件)
ticket.status.id // 狀態 UUID
ticket.status.code // 狀態代碼(例如,"open"、"closed")
ticket.status.name // 狀態顯示名稱
// 當前優先順序(物件)
ticket.priority.id // 優先順序 UUID
ticket.priority.name // 優先順序顯示名稱
// 當前部門(物件)
ticket.department.id // 部門 UUID
ticket.department.name // 部門顯示名稱
// 分配的擁有者(物件,可能未定義)
ticket.owner.id // 使用者 UUID
ticket.owner.email // 使用者電子郵件
ticket.owner.firstname // 使用者名字
ticket.owner.lastname // 使用者姓氏
// 客戶資訊(物件)
ticket.customer.id // 客戶 UUID
ticket.customer.email // 客戶電子郵件
ticket.customer.firstname // 客戶名字
ticket.customer.lastname // 客戶姓氏
ticket.customer.name // 客戶全名
// 資料夾和標籤
ticket.folder // 當前資料夾:"INBOX"、"ASSIGNED"、"SPAM"、"ARCHIVE"
ticket.tags // 標籤字串陣列
可寫屬性
您可以透過直接分配來修改這些屬性:
// 按代碼或 ID 設定狀態
ticket.status = "closed";
ticket.status = "550e8400-e29b-41d4-a716-446655440000";
// 按名稱或 ID 設定優先順序
ticket.priority = "High";
ticket.priority = "550e8400-e29b-41d4-a716-446655440001";
// 按名稱或 ID 設定部門
ticket.department = "Sales";
ticket.department = "550e8400-e29b-41d4-a716-446655440002";
// 按電子郵件或 ID 設定擁有者
ticket.owner = "[email protected]";
ticket.owner = "550e8400-e29b-41d4-a716-446655440003";
// 設定資料夾
ticket.folder = "ASSIGNED";
ticket.folder = "SPAM";
ticket.folder = "ARCHIVE";
ticket.folder = "INBOX";
// 設定標籤(替換所有現有標籤)
ticket.tags = ["urgent", "vip"];
自訂欄位
可以使用其代碼(而非顯示名稱)讀取和寫入自訂欄位。
讀取自訂欄位
// 直接存取自訂欄位值
var orderId = ticket.order_id; // 文字欄位
var amount = ticket.order_amount; // 數字欄位
var isVip = ticket.is_vip; // 布林欄位
var region = ticket.region; // 選擇欄位
寫入自訂欄位
// 設定文字自訂欄位
ticket.order_id = "ORD-12345";
// 設定數字自訂欄位
ticket.order_amount = 199.99;
// 設定布林自訂欄位
ticket.is_vip = true;
// 設定選擇自訂欄位
ticket.category = "billing";
// 設定日期自訂欄位(ISO 8601 格式)
ticket.due_date = "2024-12-31T23:59:59Z";
ticket.due_date = "2024-12-31";
訊息物件
當規則由訊息事件(新客戶回覆、新員工回覆等)觸發時,message 物件可用。
if (message) {
message.id // 訊息 UUID
message.body_text // 訊息內容(純文字)
message.body_html // 訊息內容(HTML)
message.createdAt // ISO 8601 時間戳記
}
範例:
if (message && message.body_text) {
var bodyLower = message.body_text.toLowerCase();
if (bodyLower.includes("cancel subscription")) {
ticket.department = "Retention";
ticket.priority = "High";
}
}
輔助函數
getStatuses()
返回所有可用狀態的陣列。
var statuses = getStatuses();
// 返回:[{ id: "...", code: "open", name: "Open" }, ...]
// 查找特定狀態
for (var i = 0; i < statuses.length; i++) {
if (statuses[i].code === "pending") {
ticket.status = statuses[i].id;
break;
}
}
getPriorities()
返回所有可用優先順序的陣列。
var priorities = getPriorities();
// 返回:[{ id: "...", name: "Low" }, { id: "...", name: "High" }, ...]
getDepartments()
返回所有可用部門的陣列。
var departments = getDepartments();
// 返回:[{ id: "...", name: "Support" }, { id: "...", name: "Sales" }, ...]
getUsers()
返回所有可用使用者(客服人員)的陣列。
var users = getUsers();
// 返回:[{ id: "...", email: "[email protected]", firstname: "John", lastname: "Doe" }, ...]
fetch()
向外部 API 發出 HTTP 請求。同步 - 直接返回結果。
var response = fetch(url, options);
// response: { ok, status, statusText, text, json }
選項: method(GET/POST/PUT/DELETE)、headers(物件)、body(字串或物件)
範例:從 CRM 獲取並更新自訂欄位
var response = fetch("https://api.example.com/customers/" + ticket.customer.email, {
headers: { "Authorization": "Bearer YOUR_API_KEY" }
});
if (response.ok && response.json) {
ticket.customer_tier = response.json.tier;
ticket.lifetime_value = response.json.lifetime_value;
if (response.json.tier === "enterprise") {
ticket.priority = "High";
}
}
範例:POST 到 webhook
var response = fetch("https://hooks.example.com/helpdesk", {
method: "POST",
body: { ticket_id: ticket.id, customer_email: ticket.customer.email }
});
注意: 僅 HTTPS、5 秒超時、1MB 回應限制、內部網路被阻止。
常見模式
條件分配
// 根據主旨設定優先順序
if (ticket.subject.toLowerCase().includes("urgent")) {
ticket.priority = "High";
} else if (ticket.subject.toLowerCase().includes("question")) {
ticket.priority = "Low";
}
部門路由
var subject = ticket.subject.toLowerCase();
if (subject.includes("billing") || subject.includes("payment") || subject.includes("invoice")) {
ticket.department = "Billing";
} else if (subject.includes("technical") || subject.includes("bug") || subject.includes("error")) {
ticket.department = "Technical Support";
} else if (subject.includes("sales") || subject.includes("pricing") || subject.includes("quote")) {
ticket.department = "Sales";
}
基於客戶域名的邏輯
if (ticket.customer && ticket.customer.email) {
var email = ticket.customer.email;
var domain = email.split("@")[1];
// 企業客戶處理
if (domain === "bigcorp.com" || domain === "enterprise.org") {
ticket.priority = "High";
ticket.department = "Enterprise Support";
ticket.is_enterprise = true;
}
// 教育機構
if (domain.endsWith(".edu")) {
ticket.segment = "education";
}
}
標籤管理
// 新增標籤而不丟失現有標籤
var existingTags = ticket.tags || [];
existingTags.push("processed");
existingTags.push("automated");
ticket.tags = existingTags;
使用訊息
if (message && message.body_text) {
var body = message.body_text.toLowerCase();
// 檢測挫折關鍵字
var frustrationKeywords = ["frustrated", "angry", "terrible", "worst", "unacceptable"];
for (var i = 0; i < frustrationKeywords.length; i++) {
if (body.includes(frustrationKeywords[i])) {
ticket.priority = "High";
ticket.needs_attention = true;
break;
}
}
}
輪流分配
var users = getUsers();
if (users.length > 0) {
// 基於工單 ID 雜湊的簡單輪流
var ticketHash = 0;
for (var i = 0; i < ticket.id.length; i++) {
ticketHash += ticket.id.charCodeAt(i);
}
var assigneeIndex = ticketHash % users.length;
ticket.owner = users[assigneeIndex].email;
}
錯誤處理
腳本在安全環境中執行:
- 語法錯誤會被捕獲並記錄;腳本被跳過。
- 無效欄位值(例如,不存在的狀態名稱)會被忽略。
- 超時(10 秒)防止無限循環。
- 錯誤不會級聯到其他規則或系統組件。
最佳實踐:
// 在存取屬性之前檢查 null/undefined
if (ticket.customer && ticket.customer.email) {
// 安全存取 ticket.customer.email
}
if (message) {
// 安全存取 message 屬性
}
// 對複雜邏輯使用 try-catch
try {
var data = JSON.parse(ticket.custom_json);
ticket.parsed_field = data.value;
} catch (e) {
// 優雅地處理錯誤
}
限制
- 執行超時: 腳本在 10 秒後終止。
- 無檔案系統存取: 檔案操作不可用。
- 無持久狀態: 變數不會在腳本執行之間保持。
- 唯讀欄位:
ticket.id、ticket.subject、ticket.customer無法修改。 - ES5 JavaScript: 現代 JavaScript 功能(箭頭函數、const/let 等)可能不可用。