Py

Python Script Platform

腳本管理與執行平台

[[ loginError ]]
[[ username.charAt(0).toUpperCase() ]]

[[ username ]]

管理員

[[ pageTitle ]]

[[ pageSubtitle ]]

總腳本數

[[ scripts.length ]]

總變數數

[[ totalVariables ]]

執行次數

[[ totalExecutions ]]

成功率

--

腳本清單
[[ truncateTabName(tab.script.name) ]]

暫無腳本資料

點擊右上角「新增腳本」開始建立

[[ script.name ]]

[[ script.description || '無描述' ]]

[[ formatDate(script.created_at) ]]
[[ activeTab.script.name ]]

腳本變數設定 ([[ (activeTab.script.variables || []).length ]] 個)

尚無變數

敏感 [[ variable.variable_type ]]
引用自全域變數:[[ variable.variable_value || '(未設定)' ]]

✅ 執行成功 ([[ activeTab.testResult.execution_time ]] ms) ❌ 執行失敗 ([[ activeTab.testResult.execution_time ]] ms)

[[ activeTab.testResult.output || '(無輸出)' ]]
[[ activeTab.testResult.error ]]
暫無變數資料

[[ variable.variable_name ]]

[[ variable.variable_type ]] | [[ variable.script_name || '全域' ]]

[[ variable.variable_value && variable.variable_value.length > 30 ? variable.variable_value.substring(0, 30) + '...' : (variable.variable_value || '-') ]]
•••••• [[ variable.variable_value && variable.variable_value.length > 30 ? variable.variable_value.substring(0, 30) + '...' : (variable.variable_value || '-') ]]
🔒
暫無執行記錄
[[ scriptName ]]

[[ formatDate(execution.started_at) ]]

[[ execution.status === 'success' ? '✅ 成功' : '❌ 失敗' ]]
[[ execution.output_log ]]
[[ execution.error_log ]]

執行時間: [[ execution.execution_time ]]s

[[ execution.script_name ]]

[[ formatDate(execution.started_at) ]]

[[ execution.status === 'success' ? '✅ 成功' : '❌ 失敗' ]]
[[ execution.output_log ]]
[[ execution.error_log ]]

執行時間: [[ execution.execution_time ]]s

垃圾桶是空的

已刪除的腳本將會顯示在這裡

[[ script.name ]]

[[ script.description || '無描述' ]]

刪除時間: [[ formatDate(script.deleted_at) ]]

💡 API 金鑰採用加密儲存,您可以隨時查看、複製或重新生成

1 查看 API 金鑰

• 點擊「👁 查看詳情」按鈕開啟詳細資訊頁面

• 點擊眼睛圖標可顯示/隱藏完整的 API 金鑰

• 金鑰格式:sk_xxx...(已加密儲存,安全無虞)

2 複製使用

• 點擊「📋 複製 Key」直接複製到剪貼簿

• 點擊「🔗 複製 URL」複製 API 端點網址

• 在 HTTP 請求中使用 Header:X-API-Key: YOUR_KEY

3 重新生成

• 若 Key 洩露或需要更換,可在詳情頁面點擊「🔄 重新生成」

• 舊 Key 將立即失效,請更新所有使用該 Key 的應用程式

📖 使用範例 (cURL):

暫無 API

[[ apiKey.name ]]

[[ apiKey.script_name ]]

[[ apiKey.is_public ? '公開' : '私密' ]]
速率限制:[[ apiKey.rate_limit ]]/分鐘
建立時間:[[ formatDate(apiKey.created_at) ]]
最後使用:[[ apiKey.last_used_at ? formatDate(apiKey.last_used_at) : '-' ]]

Salesforce 連線狀態

管理您的 Salesforce OAuth 連線

已連接

[[ salesforceStatus.instance_url ]]

Token 過期時間

[[ salesforceStatus.expires_at ? formatDate(salesforceStatus.expires_at) : '無限期' ]]

⚠️ Token 已過期

狀態

[[ salesforceStatus.is_expired ? '需要重新授權' : '正常' ]]

尚未連接到 Salesforce

點擊「連接 Salesforce」按鈕開始 OAuth 認證流程

關於 Salesforce 整合

  • • 連接後,所有腳本都可以使用全域 sf 物件
  • • 支援查詢、建立、更新、刪除 Salesforce 記錄
  • • Token 會自動刷新,無需手動管理
  • • 使用 OAuth 2.0 + PKCE 安全認證

測試結果

✅ 連線測試成功

[[ JSON.stringify(salesforceTestResult.data, null, 2) ]]

❌ 連線測試失敗

[[ salesforceTestResult.message ]]

用戶管理

ID 用戶名 角色 建立時間 操作

暫無用戶

[[ user.id ]]
[[ user.username ]]
[[ user.role_name || '未分配' ]] [[ formatDate(user.created_at) ]]

角色管理

暫無角色

[[ role.name ]]

[[ role.description || '無描述' ]]

[[ role.user_count || 0 ]] 用戶
權限數量: [[ (role.permissions || []).length ]]
[[ perm.name ]]

[[ editingScript ? '編輯腳本' : '新增腳本' ]]

腳本變數設定 ([[ (currentModalScript.variables || []).length ]] 個)

💡 變數使用:使用 在程式碼中引用變數
🚀 API 返回:使用 __api_response__ 變數返回 API 響應,點擊上方「📖 API Response 指南」查看完整說明

尚無變數

點擊「新增變數」手動添加,或在程式碼中使用變數後自動檢測

[[ variable.variable_type ]] 敏感 只讀

執行結果

[[ editorExecutionResult.status === 'success' ? '✅ 成功' : editorExecutionResult.status === 'failed' ? '❌ 失敗' : '⏳ 執行中' ]]
[[ editorExecutionResult.output_log ]]
[[ editorExecutionResult.error_log ]]
執行時間: [[ editorExecutionResult.execution_time ]]秒

[[ editingVariable ? '編輯變數' : '新增變數' ]]

💡 請輸入有效的 JSON 格式,例如:{"Content-Type": "application/pdf"}

🌐 引用全域變數

選擇要在此腳本中使用的全域變數

💡 提示:引用全域變數後,該變數的值會在所有使用它的腳本中保持同步

尚無可用的全域變數

請先到「變數管理」頁面建立全域變數

[[ globalVar.variable_type ]] 敏感

分類: [[ globalVar.category ]]

值: [[ globalVar.variable_value.substring(0, 50) ]][[ globalVar.variable_value.length > 50 ? '...' : '' ]]

已選擇 [[ selectedGlobalVariableIds.length ]] 個變數

新增腳本變數

📝 編輯變數

[[ selectedScriptForVariables?.name ]]

此腳本尚無變數

變數會在程式碼中使用 格式時自動檢測

💡 使用提示:在腳本中使用 來引用變數
[[ variable.variable_type ]] 敏感 只讀
分類:[[ variable.category ]]

執行結果

[[ executionResult.script_name ]]

[[ executionResult.status === 'success' ? '✅ 成功' : executionResult.status === 'failed' ? '❌ 失敗' : '⏳ 執行中' ]]
[[ executionResult.output_log ]]
[[ executionResult.error_log ]]
開始時間: [[ formatDate(executionResult.started_at) ]]
執行時間: [[ executionResult.execution_time ]]秒

[[ editingApiKey ? '編輯 API' : '新增 API' ]]

設定後可使用 /api/run/[別名] 代替 script_id。僅允許小寫字母、數字、連字號

公開:無需金鑰即可調用 | 私密:必須在 Header 中提供 X-API-Key 驗證

選擇此 API 端點允許的 HTTP 請求方法

API 建立成功!

您可以隨時查看或重新生成此 Key

使用範例

Body 參數方式(POST):

curl -X POST [[ apiDomain ]]/api/run/[[ newApiKeyIdentifier || newApiKeyScriptId ]] \
  -H "X-API-Key: [[ newApiKeyValue ]]" \
  -H "Content-Type: application/json" \
  -d '[[ generateVariableExample(newApiKeyScriptId) ]]'

Query 參數方式(GET):

curl -X GET "[[ apiDomain ]]/api/run/[[ newApiKeyIdentifier || newApiKeyScriptId ]]?[[ generateQueryStringExample(newApiKeyScriptId) ]]" \
  -H "X-API-Key: [[ newApiKeyValue ]]"

連線成功!

Salesforce OAuth 認證完成

[[ salesforceSuccessMessage ]]

提示:您現在可以關閉此視窗,繼續使用系統。所有腳本都能自動使用 Salesforce API 功能。

API 使用統計

[[ selectedApiKeyForUsage?.name ]]

載入中...

總請求次數

[[ apiKeyUsage.total_requests || 0 ]]

成功次數

[[ apiKeyUsage.successful_requests || 0 ]]

失敗次數

[[ apiKeyUsage.failed_requests || 0 ]]

平均響應時間

[[ apiKeyUsage.avg_response_time || 0 ]]s

最後請求時間:[[ formatDate(apiKeyUsage.last_request_at) ]]

API 詳細資訊

[[ selectedApiKeyForDetail ? selectedApiKeyForDetail.name : '' ]]

[[ selectedApiKeyForDetail.script_name ]]

[[ selectedApiKeyForDetail.alias || '-' ]]

[[ selectedApiKeyForDetail.is_public ? '公開' : '私密' ]]

[[ selectedApiKeyForDetail.allowed_methods ]]

[[ selectedApiKeyForDetail.rate_limit_per_minute ]] 次/分鐘

[[ selectedApiKeyForDetail.rate_limit_window_seconds ]] 秒

[[ selectedApiKeyForDetail.expires_at ? formatDate(selectedApiKeyForDetail.expires_at) : '永不過期' ]]

[[ formatDate(selectedApiKeyForDetail.created_at) ]]

📖 API 使用說明

Body 參數方式(POST):

curl -X POST [[ apiDomain ]]/api/run/[[ selectedApiKeyForDetail.alias || selectedApiKeyForDetail.script_id ]] \
  -H "X-API-Key: [[ newApiKeyValue ]]" \
  -H "Content-Type: application/json" \
  -d '[[ generateVariableExample(selectedApiKeyForDetail.script_id) ]]'

Query 參數方式(GET):

curl -X GET "[[ apiDomain ]]/api/run/[[ selectedApiKeyForDetail.alias || selectedApiKeyForDetail.script_id ]]?[[ generateQueryStringExample(selectedApiKeyForDetail.script_id) ]]" \
  -H "X-API-Key: [[ newApiKeyValue ]]"

使用資訊

最後使用:[[ formatDate(selectedApiKeyForDetail.last_used_at) ]]

[[ editingUser ? '編輯用戶' : '新增用戶' ]]

[[ editingRole ? '編輯角色' : '新增角色' ]]

管理角色權限 - [[ editingRole?.name ]]

選擇此角色擁有的權限

[[ getCategoryName(category) ]]

__api_response__ 特殊應用設計指南

完整的 API 響應設計規範與應用場景

什麼是 __api_response__?

__api_response__ 是平台提供的特殊變數,用於控制腳本透過 API 執行時的返回內容。 當您的腳本需要被外部系統調用(如 Salesforce、Power Automate、Zapier 等)時,此變數讓您能精確控制返回的數據格式、HTTP 狀態碼、Headers,甚至實現自動重定向功能。

重要觀念:print() 僅用於調試日誌,不會成為 API 響應。 若要返回數據給調用方,必須設定 __api_response__

基本使用格式

📋 格式 1:純數據返回(默認 200 狀態碼)
# 最簡單的格式:直接返回字典
__api_response__ = {
    "success": True,
    "message": "操作成功",
    "data": {"id": 123, "name": "測試"}
}

# 系統會自動轉換為 HTTP 200 響應
📋 格式 2:自定義狀態碼
# 使用元組格式:(數據, 狀態碼)
__api_response__ = (
    {"id": 456, "created": True},
    201  # HTTP 201 Created
)

# 常用狀態碼:
# 200 - OK(成功)
# 201 - Created(已創建)
# 204 - No Content(無內容)
# 400 - Bad Request(請求錯誤)
# 404 - Not Found(找不到)
# 500 - Internal Server Error(伺服器錯誤)
📋 格式 3:完整格式(數據 + 狀態碼 + Headers)
# 完整控制:(數據, 狀態碼, 自定義 Headers)
custom_headers = {
    "X-Custom-Header": "MyValue",
    "X-Request-ID": "abc-123",
    "Cache-Control": "no-cache"
}

__api_response__ = (
    {"result": "success"},
    200,
    custom_headers
)
📋 格式 4:二進制文件(PDF、Excel、圖片等)
import base64

# 讀取或生成文件
with open("report.pdf", "rb") as f:
    pdf_bytes = f.read()

# 轉換為 Base64 編碼
pdf_base64 = base64.b64encode(pdf_bytes).decode('utf-8')

# 返回文件
__api_response__ = {
    "data": pdf_base64,
    "content_type": "application/pdf",
    "filename": "report.pdf"
}

# 支持的文件類型:
# • application/pdf - PDF 文件
# • application/vnd.ms-excel - Excel (.xls)
# • application/vnd.openxmlformats-officedocument.spreadsheetml.sheet - Excel (.xlsx)
# • image/png、image/jpeg - 圖片
# • text/csv - CSV 文件
# • application/zip - ZIP 壓縮文件

🚀 進階功能:SharePoint 自動重定向

當您的腳本透過 公開 API 執行並返回 SharePoint 或 OneDrive 連結時,系統會自動執行 HTTP 302 重定向, 讓瀏覽器直接跳轉到 SharePoint 資料夾或文件頁面。

✨ 自動重定向條件:
  • 腳本執行成功(狀態碼 200)
  • __api_response__ 包含 web_urlsharepoint_link
  • URL 必須是安全的 Microsoft 域名(sharepoint.com、onedrive.com、office.com、microsoft.com)
# 示例:建立 SharePoint 資料夾後自動跳轉
folder_result = onedrive.create_folder(
    folder_path=f"/Opportunities/{opportunity_name}"
)

# 返回包含 web_url 的響應
__api_response__ = {
    "success": True,
    "message": "資料夾建立成功",
    "folder_id": folder_result.get("id"),
    "web_url": folder_result.get("webUrl"),  # 自動重定向
    "folder_path": folder_path
}

# 系統檢測到 web_url 後,會:
# 1. 驗證 URL 安全性(防止開放重定向攻擊)
# 2. 返回 HTTP 302 重定向
# 3. 瀏覽器自動跳轉到 SharePoint 頁面
安全提醒: 系統會驗證 URL 是否來自 Microsoft 官方域名。如果 URL 不安全,系統會返回 400 錯誤而非執行重定向,保護您免受開放重定向攻擊(Open Redirect Attack)。

實際應用場景

🔷 場景 1:Salesforce 整合(建立資料夾並跳轉)
# Salesforce 按鈕調用 API,建立 SharePoint 資料夾後自動開啟
opportunity = sf.query(f"SELECT Id, Name FROM Opportunity WHERE Id = ''")[0]
folder = onedrive.create_folder(f"/Opportunities/{opportunity['Name']}")

__api_response__ = {
    "success": True,
    "message": f"已為 {opportunity['Name']} 建立資料夾",
    "web_url": folder.get("webUrl")  # 自動重定向到 SharePoint
}
🔷 場景 2:數據同步與狀態回報
# 同步數據並返回詳細狀態
records = sf.query("SELECT Id, Name FROM Account WHERE CreatedDate = TODAY")
sync_results = []

for record in records:
    result = external_api.sync(record)
    sync_results.append({
        "account_id": record["Id"],
        "status": "success" if result else "failed"
    })

__api_response__ = (
    {
        "total": len(records),
        "synced": len([r for r in sync_results if r["status"] == "success"]),
        "details": sync_results
    },
    200 if all(r["status"] == "success" for r in sync_results) else 207  # 207 = Multi-Status
)
🔷 場景 3:生成並返回 PDF 報表
# 生成 PDF 報表並返回文件
from reportlab.pdfgen import canvas
import io, base64

buffer = io.BytesIO()
pdf = canvas.Canvas(buffer)
pdf.drawString(100, 750, f"Report for: {opportunity_name}")
pdf.save()

pdf_bytes = buffer.getvalue()
pdf_base64 = base64.b64encode(pdf_bytes).decode()

__api_response__ = {
    "data": pdf_base64,
    "content_type": "application/pdf",
    "filename": f"Report_{opportunity_id}.pdf"
}
# 前端收到後會自動下載文件
🔷 場景 4:錯誤處理與狀態碼
# 根據不同情況返回適當的狀態碼
try:
    opportunity = sf.query(f"SELECT Id FROM Opportunity WHERE Id = ''")
    
    if not opportunity:
        __api_response__ = (
            {"success": False, "message": "找不到指定的商機"},
            404  # Not Found
        )
    else:
        # 處理邏輯...
        __api_response__ = {"success": True, "data": opportunity[0]}
        
except Exception as e:
    __api_response__ = (
        {"success": False, "error": str(e)},
        500  # Internal Server Error
    )

⚠️ 重要注意事項

  • 1. print() 輸出僅用於調試日誌,不會成為 API 響應。若要返回數據,必須設定 __api_response__
  • 2. 未設定 __api_response__ 時,系統會返回錯誤響應,提示「腳本未設定 API 響應」。
  • 3. 二進制文件必須使用 Base64 編碼並指定正確的 content_type
  • 4. SharePoint 自動重定向僅在成功狀態(200)且 URL 為安全域名時觸發。
  • 5. 在編輯器中測試執行時,系統會顯示 __api_response__ 內容供您檢視,但不會觸發重定向。

⚡ 快速參考

純數據
__api_response__ = {...}
含狀態碼
__api_response__ = ({...}, 201)
完整格式
__api_response__ = ({...}, 200, headers)
SharePoint 跳轉
{"web_url": "https://..."}

[[ toast.message ]]