### Start Development Server Source: https://github.com/dingdocs-notable/addon-demo/blob/main/README.md Launches the development server for local development with hot reloading. The application will start at http://localhost:3000 or the next available port. ```bash pnpm start ``` -------------------------------- ### Install Dependencies with pnpm Source: https://github.com/dingdocs-notable/addon-demo/blob/main/CLAUDE.md Use this command to install all project dependencies. Ensure Node.js and pnpm are installed. ```bash pnpm install ``` -------------------------------- ### Start Server for Production Release Source: https://github.com/dingdocs-notable/addon-demo/blob/main/README.md Starts the local server required for plugin public release scenarios, handling DingTalk API requests and signature calculations. ```bash pnpm start:server ``` -------------------------------- ### Server Configuration for Authentication Source: https://github.com/dingdocs-notable/addon-demo/blob/main/README.md The local server requires a `.env.server` file to store DingTalk application credentials (AppKey, AppSecret, AgentId, corpId). Running `pnpm start:server` starts this local server to handle authentication requests. ```text 本地服务端配置要求: - .env.server 文件用于存储插件所属钉钉应用的身份信息(AppKey、AppSecret、AgentId、corpId) - 运行 `pnpm start:server` 启动本地服务端来处理鉴权请求 ``` -------------------------------- ### Example: Get TextField Value Source: https://github.com/dingdocs-notable/addon-demo/blob/main/knowledges/文本字段.md Demonstrates how to get the text value from a '备注' (Notes) TextField for a given record ID and log it to the console. ```typescript // 获取文本字段值 const textField = sheet.getField('备注'); if (textField) { const text = await textField.getValueAsync('rec123456'); console.log(`备注内容: ${text || '无'}`); } ``` -------------------------------- ### Local Backend Server for Permission Signature Source: https://context7.com/dingdocs-notable/addon-demo/llms.txt An Express server to handle OAuth2 token exchange and signature calculation for DingTalk permissions. Configure credentials in `.env.server` and start with `pnpm start:server`. ```bash # local_server/.env.server DINGTALK_APPKEY=your_app_key DINGTALK_APPSECRET=your_app_secret DINGTALK_AGENT_ID=your_agent_id DINGTALK_CORP_ID=your_corp_id ``` ```bash # Get a configPermission payload for a specific page URL curl "http://localhost:3001/api/configPermission?url=http%3A%2F%2Flocalhost%3A3000%2Fui.html" # Expected response: # { # "agentId": "123456789", # "corpId": "ding...", # "timeStamp": 1700000000000, # "nonceStr": "abc123xyz", # "signature": "a3f1b2c4...", # "jsApiList": ["DingdocsScript.base.readWriteAll"], # "url": "http://localhost:3000/ui.html" # } ``` -------------------------------- ### Get Locale and Log Title Source: https://context7.com/dingdocs-notable/addon-demo/llms.txt This example shows how to import and use the `getLocale` function to retrieve locale-specific strings. It demonstrates fallback to 'zh-CN' for unknown locales and logs the 'title' property. ```typescript // src/components/locales.ts import { getLocale, type Locales } from './locales'; // Supported locale keys: 'zh-CN', 'en-US', 'ja-JP' // Falls back to 'zh-CN' for unknown locales const locale: Locales = getLocale('en-US'); console.log(locale.title); // 'Multi-table Management Assistant' console.log(locale.createSheet); // 'Create Sheet' console.log(locale.addRecord); // 'Add Record' console.log(locale.confirmDelete); // 'Confirm Delete' ``` -------------------------------- ### Get All Fields Source: https://github.com/dingdocs-notable/addon-demo/blob/main/knowledges/Sheet模块.md Retrieves a list of all fields within the current data table. ```APIDOC ## getFields ### Description Gets a list of all fields in the current data table. ### Method ```typescript getFields(): Field[] ``` ### Returns - `Field[]` - A list of Field objects. ### Example ```typescript const fields = sheet.getFields(); console.log(`The data table has ${fields.length} fields.`); fields.forEach((field) => { console.log(`- ${field.getName()}: ${field.getType()}`); }); ``` ``` -------------------------------- ### Get All Views Source: https://github.com/dingdocs-notable/addon-demo/blob/main/knowledges/Sheet模块.md Retrieve a list of all available views within the current data sheet. ```typescript const views = sheet.getViews(); console.log(`数据表共有 ${views.length} 个视图`); ``` -------------------------------- ### Get Theme Setting Source: https://github.com/dingdocs-notable/addon-demo/blob/main/knowledges/其它接口.md Retrieves the current theme setting (light or dark) of the environment. Useful for adapting UI. ```typescript getTheme(): Promise; ``` ```typescript type Theme = 'light' | 'dark'; ``` ```typescript const theme = await Dingdocs.base.host.getTheme(); // 'light' ``` -------------------------------- ### Initialize Base Module Source: https://github.com/dingdocs-notable/addon-demo/blob/main/knowledges/Base模块.md Get the main entry point for the AI Table Grid instance. This object provides access to all base module methods. ```typescript const base = DingdocsScript.base; ``` -------------------------------- ### Get All Views Source: https://github.com/dingdocs-notable/addon-demo/blob/main/knowledges/Sheet模块.md Retrieves a list of all views within the current data table. ```APIDOC ## getViews ### Description Gets a list of all views in the current data table. ### Method ```typescript getViews(): View[] ``` ### Returns - `View[]` - A list of View objects. ### Example ```typescript const views = sheet.getViews(); console.log(`The data table has ${views.length} views.`); ``` ``` -------------------------------- ### Get Sheet Description Source: https://github.com/dingdocs-notable/addon-demo/blob/main/knowledges/Sheet模块.md Retrieves the description of the data table. ```APIDOC ## getDesc ### Description Gets the data table description. ### Method ```typescript getDesc(): string | undefined ``` ### Returns - `string | undefined` - The data table description text. Returns `undefined` if there is no description. ### Example ```typescript const description = sheet.getDesc(); if (description) { console.log(`Sheet Description: ${description}`); } else { console.log("This sheet has no description."); } ``` ``` -------------------------------- ### Get Sheet Instance Source: https://github.com/dingdocs-notable/addon-demo/blob/main/knowledges/Sheet模块.md Obtain a Sheet instance using the base object. You can get the currently active sheet or a specific sheet by its name. ```typescript const sheet = DingdocsScript.base.getActiveSheet(); ``` ```typescript const sheet = DingdocsScript.base.getSheet("数据表1"); ``` -------------------------------- ### Get Raw Access Token Source: https://context7.com/dingdocs-notable/addon-demo/llms.txt Use this endpoint to retrieve a raw access token, which is cached and valid for approximately 2 hours. ```bash curl "http://localhost:3001/api/accessToken" ``` -------------------------------- ### Permission Error Handling Source: https://github.com/dingdocs-notable/addon-demo/blob/main/README.md When publishing a plugin for enterprise or third-party use, `configPermission` is required for additional authentication to allow read/write access to AI Table data. This involves setting up a local server with `.env.server` for credentials and running `pnpm start:server`. ```text 获取文档信息失败: PermissionError: Do not have permission to access this document. Using "Dingdocs.base.host.configPermission(agentId, corpId, timeStamp, nonceStr, signature, ['DingdocsScript.base.readWriteAll']). ``` -------------------------------- ### Example: Set TextField Value Source: https://github.com/dingdocs-notable/addon-demo/blob/main/knowledges/文本字段.md Demonstrates how to set a new text value for a '备注' (Notes) TextField for a given record ID and log the success or failure to the console. ```typescript // 设置文本字段值 const textField = sheet.getField('备注'); if (textField) { const success = await textField.setValueAsync('rec123456', '这是一条新的备注内容'); if (success) { console.log('文本更新成功'); } else { console.log('文本更新失败'); } } ``` -------------------------------- ### Get Sheet Name Source: https://github.com/dingdocs-notable/addon-demo/blob/main/knowledges/Sheet模块.md Retrieve the name of the current data sheet. ```typescript const sheetName = sheet.getName(); console.log(`当前数据表名称: ${sheetName}`); ``` -------------------------------- ### Initialize UI Panel and Handle Ready State Source: https://context7.com/dingdocs-notable/addon-demo/llms.txt Call initView in the UI layer to initialize the panel. The onReady callback fires once the DingTalk environment is initialized and all Dingdocs APIs are available. Initial data loading and event listener setup must occur within onReady. ```typescript import { initView } from 'dingtalk-docs-cool-app'; initView({ onReady: async () => { // Get locale from DingTalk host try { const currentLocale = await Dingdocs.base.host.getLocale(); // currentLocale: 'zh-CN' | 'en-US' | 'ja-JP' | ... setLocale(getLocale(currentLocale)); } catch (e) { console.warn('Failed to get locale, using default zh-CN'); } // Load initial data await Promise.all([loadDocumentInfo(), loadSheets(), loadActiveSheet()]); // Set up event listeners setupEvents(); }, }); // Cleanup on unmount return () => { unsubscribers.forEach(fn => fn()); }; ``` -------------------------------- ### Get Sheet Name Source: https://github.com/dingdocs-notable/addon-demo/blob/main/knowledges/Sheet模块.md Retrieves the name of the current data table. ```APIDOC ## getName ### Description Gets the current data table name. ### Method ```typescript getName(): string ``` ### Returns - `string` - The data table name. ### Example ```typescript const sheetName = sheet.getName(); console.log(`Current Sheet Name: ${sheetName}`); ``` ``` -------------------------------- ### Get Locale Setting Source: https://github.com/dingdocs-notable/addon-demo/blob/main/knowledges/其它接口.md Retrieves the current locale setting of the environment. This is useful for internationalization. ```typescript getLocale(): Promise; ``` ```typescript type Locale = "zh-CN" | "zh-HK" | "zh-TW" | "ja-JP" | "en-US" | "ko-KR" | "pt-BR" | "tr-TR" | "th-TH" | "id-ID" | "ms-MY" ``` ```typescript // 注意:⚠️在ui侧调用 const locale = await Dingdocs.base.host.getLocale(); // 'zh-CN' ``` -------------------------------- ### Get All Fields Source: https://github.com/dingdocs-notable/addon-demo/blob/main/knowledges/Sheet模块.md Retrieve a list of all fields present in the current data sheet. Each field object contains its name and type. ```typescript const fields = sheet.getFields(); console.log(`数据表共有 ${fields.length} 个字段`); fields.forEach((field) => { console.log(`- ${field.getName()}: ${field.getType()}`); }); ``` -------------------------------- ### Get Record Creation Time Source: https://github.com/dingdocs-notable/addon-demo/blob/main/knowledges/Record模块.md Returns the creation timestamp of the record in milliseconds. Useful for auditing or chronological sorting. ```typescript getCreatedTime(): number ``` ```typescript // 获取记录创建时间 const createdTime = record.getCreatedTime(); const createdDate = new Date(createdTime); console.log(`记录创建于: ${createdDate.toLocaleString()}`); ``` -------------------------------- ### Get Sheet Description Source: https://github.com/dingdocs-notable/addon-demo/blob/main/knowledges/Sheet模块.md Retrieve the description of the current data sheet. Returns undefined if no description is set. ```typescript const description = sheet.getDesc(); if (description) { console.log(`数据表描述: ${description}`); } else { console.log("该数据表暂无描述"); } ``` -------------------------------- ### Get Sheet by ID or Name Source: https://github.com/dingdocs-notable/addon-demo/blob/main/knowledges/Base模块.md Fetch a specific data sheet using its ID or name. Returns null if the sheet is not found. ```typescript // 通过名称获取数据表 const productSheet = base.getSheet('产品清单'); if (productSheet) { console.log(`成功获取数据表,字段数量: ${productSheet.getFields().length}`); } // 通过ID获取数据表 const sheetById = base.getSheet('sht123456'); ``` -------------------------------- ### Get Record Creator Information Source: https://github.com/dingdocs-notable/addon-demo/blob/main/knowledges/Record模块.md Retrieves information about the user who created the record. Returns null if the creator's information is unavailable. ```typescript getCreatedBy(): OpenApi.UserCellValue | null ``` -------------------------------- ### DingTalk Host Environment APIs Source: https://context7.com/dingdocs-notable/addon-demo/llms.txt Interact with the DingTalk host environment to get user locale, UI theme, upload files, and configure permissions. These APIs should be called in the UI layer only. ```tsx // Get the current user's locale (call in UI layer only) const locale = await Dingdocs.base.host.getLocale(); // Returns: 'zh-CN' | 'zh-HK' | 'zh-TW' | 'ja-JP' | 'en-US' | 'ko-KR' | 'pt-BR' | ... // Get the current UI theme const theme = await Dingdocs.base.host.getTheme(); // Returns: 'light' | 'dark' // Upload files to DingTalk storage (for attachment fields) const inputEl = document.querySelector('input[type=file]') as HTMLInputElement; const files = Array.from(inputEl.files ?? []); const attachments = await Dingdocs.base.batchUploadFiles(files); // attachments: IOpenAttachment[] // Configure enterprise/ISV plugin permissions (required for published plugins) // Obtain agentId, corpId, timeStamp, nonceStr, signature from your backend server const JSAPI_LIST = ['DingdocsScript.base.readWriteAll']; await Dingdocs.base.host.configPermission( configData.agentId, // string configData.corpId, // string configData.timeStamp, // number (ms timestamp) configData.nonceStr, // string (random nonce) configData.signature, // string (SHA-1 HMAC of jsapi_ticket + nonce + timestamp + url) JSAPI_LIST ); ``` -------------------------------- ### Get Raw JSAPI Ticket Source: https://context7.com/dingdocs-notable/addon-demo/llms.txt Use this endpoint to retrieve a raw JSAPI ticket, which is cached and valid for approximately 2 hours. ```bash curl "http://localhost:3001/api/jsapiTicket" ``` -------------------------------- ### Manage Single-Select Field Options and Values Source: https://context7.com/dingdocs-notable/addon-demo/llms.txt Interact with single-select fields to get, add, rename, and delete options. Read and set record values using option IDs. ```typescript const sheet = DingdocsScript.base.getActiveSheet()!; const statusField = sheet.getField('状态'); if (statusField) { // Get all options const options = statusField.getOptions(); // options: Array<{ id: string; name: string; color?: string }> options.forEach(o => console.log(` ${o.name} (${o.id})`)); // Add a single option statusField.addOption('待审核'); // Batch add options statusField.addOptions([{ name: '待处理' }, { name: '进行中' }, { name: '已完成' }, { name: '已取消' }]); // Rename an existing option await statusField.setOptionAsync('进行中', { name: '处理中' }); // Delete an option (async because it affects existing cell values) await statusField.deleteOptionAsync('已取消'); // Read a record's selected option const selected = await statusField.getValueAsync('rec123456'); // selected: { id: string; name: string } | null console.log(`Current status: ${selected?.name ?? 'none'}`); // Set a record's option value by option ID const target = options.find(o => o.name === '已完成'); if (target) { const ok = await statusField.setValueAsync('rec123456', target.id); if (ok) console.log('Status set to 已完成'); } } ``` -------------------------------- ### Get Field Property Configuration Source: https://github.com/dingdocs-notable/addon-demo/blob/main/knowledges/Field模块.md Retrieve the configuration properties of a field. The structure of the returned properties varies depending on the field type (e.g., number, date, select, link fields). ```typescript const property = field.getProperty(); // 对于数字字段,获取格式设置 if (field.getType() === 'number') { console.log(`数字格式: ${property.format}`); console.log(`精度: ${property.precision}`); } ``` -------------------------------- ### Build Production Version Source: https://github.com/dingdocs-notable/addon-demo/blob/main/README.md Compiles the project into a production-ready build. ```bash pnpm run build ``` -------------------------------- ### Authentication Flow Source: https://github.com/dingdocs-notable/addon-demo/blob/main/README.md The frontend initiates authentication in the `initView`'s `ready` callback by requesting `/api/configPermission` from the server. The server generates necessary parameters (timeStamp, nonceStr, signature), which the frontend then uses to call `Dingdocs.base.host.configPermission`. ```text 鉴权流程: 1. 前端在 `initView` 的 `ready` 回调中自动发起鉴权请求 2. 向服务端发送请求 `/api/configPermission` 请求,服务端生成所需的鉴权参数(timeStamp、nonceStr、signature等) 4. 前端使用返回参数调用 `Dingdocs.base.host.configPermission` 完成鉴权 ``` -------------------------------- ### Plugin Initialization: initView Source: https://context7.com/dingdocs-notable/addon-demo/llms.txt Initializes the UI panel and handles the ready state. The `onReady` callback is invoked once the DingTalk environment is initialized and all Dingdocs APIs are available. ```APIDOC ## initView ### Description Initialize the UI panel and handle ready state. Provides the `onReady` callback which fires once the DingTalk environment is initialized and all `Dingdocs` APIs are available. All initial data loading and event listener setup must happen inside `onReady`. ### Usage ```tsx import { initView } from 'dingtalk-docs-cool-app'; initView({ onReady: async () => { // Get locale from DingTalk host try { const currentLocale = await Dingdocs.base.host.getLocale(); // currentLocale: 'zh-CN' | 'en-US' | 'ja-JP' | ... setLocale(getLocale(currentLocale)); } catch (e) { console.warn('Failed to get locale, using default zh-CN'); } // Load initial data await Promise.all([loadDocumentInfo(), loadSheets(), loadActiveSheet()]); // Set up event listeners setupEvents(); }, }); // Cleanup on unmount return () => { unsubscribers.forEach(fn => fn()); }; ``` ``` -------------------------------- ### Project Structure Source: https://github.com/dingdocs-notable/addon-demo/blob/main/README.md Overview of the project's directory structure, separating frontend and backend components. ```text ---------------------前端示例------------------------ ├── src/ │ ├── components/ # React组件 │ │ ├── App.tsx # 主应用组件,包含configPermission初始化逻辑 │ │ ├── locales.ts # 国际化配置 │ │ └── style.css # 样式文件 │ ├── entries/ # 入口文件 │ │ ├── script.tsx # 脚本入口 │ │ └── ui.tsx # UI入口 │ └── script/ # Service Worker (后台服务) │ └── service.ts # 核心业务逻辑 ---------------------服务端示例------------------------ └── local_server/ ├── server.ts # 服务端核心逻辑,处理DingTalk API请求和签名计算 └── .env.server # 服务端环境变量文件,存储钉钉应用凭证 ``` -------------------------------- ### Frontend: Fetch Signature and Configure Permissions Source: https://context7.com/dingdocs-notable/addon-demo/llms.txt This code snippet demonstrates how to fetch signature configuration from the backend and then use it to configure permissions for DingTalk JSAPI. It requires the current URL to be encoded. ```typescript // Frontend: fetch signature and call configPermission const response = await fetch(`/api/configPermission?url=${encodeURIComponent(window.location.href)}`); const configData = await response.json(); await Dingdocs.base.host.configPermission( configData.agentId, configData.corpId, configData.timeStamp, configData.nonceStr, configData.signature, configData.jsApiList ); ``` -------------------------------- ### Plugin Initialization: initScript Source: https://context7.com/dingdocs-notable/addon-demo/llms.txt Initializes the Script Worker entry point by providing the URL to the compiled script bundle. This must be called before any DingdocsScript APIs are available. ```APIDOC ## initScript ### Description Register the Script Worker entry point. Tells the SDK where to find the compiled Script Worker JavaScript bundle. Must be called before any `DingdocsScript` APIs are available. ### Usage ```tsx // src/entries/script.tsx import { initScript } from 'dingtalk-docs-cool-app'; import ReactDOM from 'react-dom/client'; import React, { useEffect } from 'react'; function App() { useEffect(() => { initScript({ scriptUrl: new URL( `${window.location.origin}/static/js/script.code.js`, window.location.href ) }); }, []); return null; } const root = ReactDOM.createRoot(document.getElementById('root_script') as HTMLElement); root.render(); ``` ``` -------------------------------- ### Get Sheet ID Source: https://github.com/dingdocs-notable/addon-demo/blob/main/knowledges/Sheet模块.md Retrieves the unique identifier for the current data table. ```APIDOC ## getId ### Description Gets the current data table ID. ### Method ```typescript getId(): string ``` ### Returns - `string` - The data table ID. ### Example ```typescript const sheetId = sheet.getId(); console.log(`Current Sheet ID: ${sheetId}`); ``` ``` -------------------------------- ### Get Sheet ID Source: https://github.com/dingdocs-notable/addon-demo/blob/main/knowledges/Sheet模块.md Retrieve the unique identifier for the current data sheet. ```typescript const sheetId = sheet.getId(); console.log(`当前数据表ID: ${sheetId}`); ``` -------------------------------- ### Server-Side Functions Source: https://github.com/dingdocs-notable/addon-demo/blob/main/README.md The server handles core logic including fetching access tokens from DingTalk API, generating Jsapi Tickets, calculating signatures for frontend configuration, and providing a `/api/configPermission` endpoint for frontend calls. ```text 服务端(server.ts)功能: - 从钉钉API获取访问令牌(access token) - 生成Jsapi Ticket(jsapiTicket) - 计算签名(signature)用于前端配置 - 提供 `/api/configPermission` 端点供前端调用 ``` -------------------------------- ### batchUploadFiles Source: https://github.com/dingdocs-notable/addon-demo/blob/main/knowledges/其它接口.md Allows for the batch uploading of files. This is useful for scenarios where multiple files need to be uploaded simultaneously, improving efficiency. ```APIDOC ## batchUploadFiles ### Description Batch upload attachments. ### Method ```typescript batchUploadFiles(files: File[]): Promise; ``` ### Type Definition Reference `IOpenAttachment` type definition can be found in ["Attachment Fields"](./附件字段.md) ### Example ```typescript const files = await Dingdocs.base.batchUploadFiles([file]); ``` ``` -------------------------------- ### Get View by ID Source: https://github.com/dingdocs-notable/addon-demo/blob/main/knowledges/Sheet模块.md Retrieves a specific view from the current data table using its ID. ```APIDOC ## getView ### Description Gets a specific view by its ID. ### Method ```typescript getView(id: string): View | null ``` ### Parameters - `id` (`string`) - Required - The ID of the view. ### Returns - `View | null` - The specified View object. Returns `null` if the view is not found. ### Example ```typescript const view = sheet.getView("viewId123"); if (view) { console.log("View found."); } else { console.log("View not found."); } ``` ``` -------------------------------- ### Get Record ID Source: https://github.com/dingdocs-notable/addon-demo/blob/main/knowledges/Record模块.md Fetches the unique identifier for the record. This ID is essential for referencing the record in other operations. ```typescript getId(): string ``` ```typescript const recordId = record.getId(); console.log(`记录ID: ${recordId}`); ``` -------------------------------- ### 设置URL字段值 (TypeScript) Source: https://github.com/dingdocs-notable/addon-demo/blob/main/knowledges/链接字段.md 使用setValueAsync方法为指定记录的URL字段设置值。可以传入一个URL字符串或一个包含link和可选text属性的对象。该方法返回一个Promise,表示操作是否成功。 ```typescript setValueAsync(recordId: string, url: IOpenUrl | string): Promise ``` ```typescript // 使用字符串设置URL字段值 const websiteField = sheet.getField('网站'); if (websiteField) { // 方式1:直接设置链接地址 const success1 = await websiteField.setValueAsync('rec123456', 'https://www.example.com'); // 方式2:设置带显示文本的链接 const success2 = await websiteField.setValueAsync('rec234567', { link: 'https://www.example.org', text: '示例网站' }); console.log('URL设置成功'); } ``` -------------------------------- ### Get Field by ID or Name Source: https://github.com/dingdocs-notable/addon-demo/blob/main/knowledges/Sheet模块.md Retrieves a specific field from the current data table using its ID or name. ```APIDOC ## getField ### Description Gets a specific field by its ID or name. ### Method ```typescript getField(idOrName: string): T | null ``` ### Parameters - `idOrName` (`string`) - Required - The ID or name of the field. ### Returns - `Field | null` - The Field object. Returns `null` if no matching field is found. ### Example ```typescript // Get field by ID const fieldById = sheet.getField("fld123456"); // Get field by name const fieldByName = sheet.getField("Customer Name"); if (fieldByName) { console.log(`Field Type: ${fieldByName.getType()}`); } else { console.log("Specified field not found."); } ``` **Note**: It is recommended to specify the `Field` type (e.g., ``) for better type hinting. ```typescript // getAttachmentUrls is a method specific to AttachmentField const field = sheet.getField(idOrName); const urls = field.getAttachmentUrls("recordId"); ``` ``` -------------------------------- ### Lint Code with pnpm Source: https://github.com/dingdocs-notable/addon-demo/blob/main/CLAUDE.md Execute this command to enforce code style and identify potential issues. It helps maintain code quality. ```bash pnpm lint ``` -------------------------------- ### 获取URL字段值 (TypeScript) Source: https://github.com/dingdocs-notable/addon-demo/blob/main/knowledges/链接字段.md 使用getValueAsync方法获取指定记录的URL字段值。该方法返回一个Promise,解析为包含链接地址和可选显示文本的对象,或在值为空时返回null。 ```typescript getValueAsync(recordId: string): Promise interface IOpenUrl { text?: string, link: string } ``` ```typescript // 获取URL字段值 const websiteField = sheet.getField('网站'); if (websiteField) { const url = await websiteField.getValueAsync('rec123456'); if (url) { console.log(`链接地址: ${url.link}`); if (url.text) { console.log(`显示文本: ${url.text}`); } } else { console.log('未设置网站链接'); } } ``` -------------------------------- ### Get Document UUID Source: https://github.com/dingdocs-notable/addon-demo/blob/main/knowledges/Base模块.md Retrieve the unique identifier (dentryUuid) for the current document. Useful for referencing the document in other operations. ```typescript const uuid = base.getDentryUuid(); console.log(`当前文档UUID: ${uuid}`); ``` -------------------------------- ### Get Active Sheet Source: https://github.com/dingdocs-notable/addon-demo/blob/main/knowledges/Base模块.md Retrieve the currently active data sheet object. Returns null if no sheet is selected. ```typescript const activeSheet = base.getActiveSheet(); if (activeSheet) { console.log(`当前选中的数据表: ${activeSheet.getName()}`); } else { console.log('当前未选中任何数据表'); } ``` -------------------------------- ### Perform Type Checking with pnpm Source: https://github.com/dingdocs-notable/addon-demo/blob/main/CLAUDE.md Run this command to check for type errors in the project. This helps ensure code correctness. ```bash pnpm typecheck ``` -------------------------------- ### Get Field Name Source: https://github.com/dingdocs-notable/addon-demo/blob/main/knowledges/Field模块.md Retrieve the current name of the field. This is useful for display purposes or when referring to the field by its human-readable name. ```typescript const fieldName = field.getName(); console.log(`字段名称: ${fieldName}`); ``` -------------------------------- ### Batch Upload Files Source: https://github.com/dingdocs-notable/addon-demo/blob/main/knowledges/其它接口.md Uploads multiple files in a batch. The return type IOpenAttachment provides details about the uploaded files. ```typescript batchUploadFiles(files: File[]): Promise; ``` ```typescript const files = await Dingdocs.base.batchUploadFiles([file]); ``` -------------------------------- ### Get All Visible Sheets Source: https://github.com/dingdocs-notable/addon-demo/blob/main/knowledges/Base模块.md Retrieve an array of all data sheets currently visible to the user. Useful for iterating through available sheets. ```typescript const allSheets = base.getSheets(); console.log(`可见的数据表数量: ${allSheets.length}`); allSheets.forEach(sheet => { console.log(`- ${sheet.getName()}`); }); ``` -------------------------------- ### Initialize Script Worker Entry Point Source: https://context7.com/dingdocs-notable/addon-demo/llms.txt Call initScript in the script entry point to tell the SDK where to find the compiled Script Worker JavaScript bundle. This must be called before any DingdocsScript APIs are available. ```tsx // src/entries/script.tsx import { initScript } from 'dingtalk-docs-cool-app'; import ReactDOM from 'react-dom/client'; import React, { useEffect } from 'react'; function App() { useEffect(() => { initScript({ scriptUrl: new URL( `${window.location.origin}/static/js/script.code.js`, window.location.href ) }); }, []); return null; } const root = ReactDOM.createRoot(document.getElementById('root_script') as HTMLElement); root.render(); ``` -------------------------------- ### Host APIs — Dingdocs.base.host Source: https://context7.com/dingdocs-notable/addon-demo/llms.txt APIs for interacting with the DingTalk host environment, including retrieving locale and theme, uploading files, and configuring permissions. ```APIDOC ## Host APIs — `Dingdocs.base.host` ### `getLocale` **Description:** Retrieves the current user's locale setting. **Usage:** Call in UI layer only. **Returns:** `string` - The locale code (e.g., 'zh-CN', 'en-US'). ### `getTheme` **Description:** Retrieves the current UI theme setting. **Usage:** Call in UI layer only. **Returns:** `string` - The theme ('light' or 'dark'). ### `batchUploadFiles` **Description:** Uploads files to DingTalk storage, typically for use in attachment fields. **Parameters:** - `files` (Array) - An array of File objects to upload. **Returns:** `Promise` - A promise that resolves with an array of attachment objects. ### `configPermission` **Description:** Configures enterprise or ISV plugin permissions. This is required for published plugins. **Parameters:** - `agentId` (string) - The agent ID. - `corpId` (string) - The corporation ID. - `timeStamp` (number) - The timestamp (in milliseconds). - `nonceStr` (string) - A random nonce string. - `signature` (string) - The signature generated using SHA-1 HMAC of jsapi_ticket, nonce, timestamp, and URL. - `JSAPI_LIST` (Array) - A list of JavaScript API permissions to configure. **Usage:** Obtain `agentId`, `corpId`, `timeStamp`, `nonceStr`, and `signature` from your backend server. ``` -------------------------------- ### Local Backend Server API Source: https://context7.com/dingdocs-notable/addon-demo/llms.txt Provides an API endpoint to generate DingTalk permission signatures for the frontend, facilitating secure access to DingTalk features. ```APIDOC ## Local Backend Server (`local_server/server.ts`) ### `GET /api/configPermission` **Description:** Generates a DingTalk permission signature for the frontend. This Express server handles OAuth2 token exchange and signature calculation. Configure credentials in `local_server/.env.server`. **Usage:** Start the server with `pnpm start:server` (runs on port 3001). **Query Parameters:** - `url` (string) - The URL for which to generate the signature. **Example Request:** ```bash curl "http://localhost:3001/api/configPermission?url=http%3A%2F%2Flocalhost%3A3000%2Fui.html" ``` **Expected Response:** ```json { "agentId": "123456789", "corpId": "ding...", "timeStamp": 1700000000000, "nonceStr": "abc123xyz", "signature": "a3f1b2c4...", "jsApiList": ["DingdocsScript.base.readWriteAll"], "url": "http://localhost:3000/ui.html" } ``` ``` -------------------------------- ### Get Field ID Source: https://github.com/dingdocs-notable/addon-demo/blob/main/knowledges/Field模块.md Retrieve the unique identifier for the current field. This ID is essential for referencing the field in various API calls. ```typescript const fieldId = field.getId(); console.log(`字段ID: ${fieldId}`); ``` -------------------------------- ### Get Record Last Modifier Information Source: https://github.com/dingdocs-notable/addon-demo/blob/main/knowledges/Record模块.md Retrieves information about the user who last modified the record. Returns null if this information is unavailable. ```typescript getLastModifiedBy(): OpenApi.UserCellValue | null ``` -------------------------------- ### getTheme Source: https://github.com/dingdocs-notable/addon-demo/blob/main/knowledges/其它接口.md Retrieves the current theme of the application. This allows developers to adapt UI elements to match the user's selected theme (e.g., light or dark mode). ```APIDOC ## getTheme ### Description Gets the current theme. ### Method ```typescript getTheme(): Promise; ``` ### Type Definition ```typescript type Theme = 'light' | 'dark'; ``` ### Example ```typescript const theme = await Dingdocs.base.host.getTheme(); // 'light' ``` ``` -------------------------------- ### 完整的URL字段使用示例 (TypeScript) Source: https://github.com/dingdocs-notable/addon-demo/blob/main/knowledges/链接字段.md 演示如何在一个应用场景中管理URL字段,包括获取所有记录、统计有效链接、为缺失链接添加搜索URL,以及更新特定记录的链接。 ```typescript // 完整的URL字段使用示例 async function manageWebsiteLinks() { const sheet = base.getSheet('合作伙伴'); const websiteField = sheet.getField('官网链接'); if (websiteField && websiteField.getType() === 'url') { // 获取所有记录 const partners = await sheet.getRecordsAsync({ pageSize: 50 }); // 统计有效的网站链接 let validLinksCount = 0; let missingLinksCount = 0; for (const partner of partners.records) { const website = await websiteField.getValueAsync(partner.getId()); if (website && website.link) { validLinksCount++; console.log(`${partner.getCellValue('公司名称')}: ${website.text || website.link}`); } else { missingLinksCount++; // 为没有网站的合作伙伴自动添加一个搜索链接 const companyName = partner.getCellValue('公司名称'); if (companyName) { const searchUrl = `https://www.google.com/search?q=${encodeURIComponent(companyName)}`; await websiteField.setValueAsync(partner.getId(), { link: searchUrl, text: `搜索 ${companyName}` }); console.log(`为 ${companyName} 添加了搜索链接`); } } } console.log(`统计结果: ${validLinksCount} 个有效链接, ${missingLinksCount} 个缺失链接`); // 更新特定记录的链接 const importantPartnerId = 'rec123456'; await websiteField.setValueAsync(importantPartnerId, { link: 'https://www.important-partner.com', text: '重要合作伙伴官网' }); } } ``` -------------------------------- ### Create New Sheets with Base Module Source: https://context7.com/dingdocs-notable/addon-demo/llms.txt Use `base.insertSheet` to create a new sheet, either with default fields or a custom set of fields. The first custom field defined becomes the primary key. ```typescript const base = DingdocsScript.base; // Create a sheet with default fields const emptySheet = base.insertSheet('新数据表'); ``` ```typescript // Create a sheet with custom fields (first field becomes the primary key) const taskSheet = base.insertSheet('任务管理', [ { name: '标题', type: 'text' }, { name: '状态', type: 'singleSelect' }, { name: '截止日期', type: 'date' }, { name: '优先级', type: 'singleSelect' } ]); console.log(`Created: ${taskSheet.getName()}, ID: ${taskSheet.getId()}`); // Note: Cannot delete the last remaining sheet // Note: First field type must support being a primary field ``` -------------------------------- ### Get Current Locale in UI Source: https://github.com/dingdocs-notable/addon-demo/blob/main/CLAUDE.md Retrieve the current locale setting within the UI components. This is used for internationalization of UI text. ```typescript Dingdocs.base.host.getLocale() ``` -------------------------------- ### Get Sheet ID of Field Source: https://github.com/dingdocs-notable/addon-demo/blob/main/knowledges/Field模块.md Retrieve the ID of the sheet to which the current field belongs. This can be useful for cross-referencing or understanding the field's context. ```typescript const sheetId = field.getSheetId(); console.log(`字段所属数据表ID: ${sheetId}`); ``` -------------------------------- ### getProperty Source: https://github.com/dingdocs-notable/addon-demo/blob/main/knowledges/Field模块.md Retrieves the configuration properties of the field. ```APIDOC ## getProperty ### Description Retrieves the configuration properties of the field. This method is not recommended for direct use. ### Method ```typescript getProperty(): FieldProperty | undefined ``` ### Returns * `FieldProperty` - The configuration properties of the field. The structure varies depending on the field type. ### Example ```typescript const property = field.getProperty(); // For number fields, get format settings if (field.getType() === 'number') { console.log(`Number format: ${property.formatter}`); console.log(`Precision: ${property.precision}`); } ``` ``` -------------------------------- ### Get All Cell Values Source: https://github.com/dingdocs-notable/addon-demo/blob/main/knowledges/Record模块.md Fetches all field values for the record. You can choose to return values keyed by field name (default) or field ID. ```typescript getCellValues(options?: IGetCellValuesOptions): Record; ``` ```typescript // 获取所有字段值(使用字段名称作为键) const allValues = record.getCellValues(); console.log('记录所有字段值:'); Object.entries(allValues).forEach(([fieldName, value]) => { console.log(`- ${fieldName}: ${JSON.stringify(value)}`); }); // 获取所有字段值(使用字段ID作为键) const allValuesById = record.getCellValues({ returnFieldsById: true }); console.log('记录所有字段值(按ID):'); Object.entries(allValuesById).forEach(([fieldId, value]) => { console.log(`- ${fieldId}: ${JSON.stringify(value)}`); }); ``` -------------------------------- ### Get Record Sheet ID Source: https://github.com/dingdocs-notable/addon-demo/blob/main/knowledges/Record模块.md Retrieves the ID of the data table to which the record belongs. Useful for cross-referencing or understanding the record's context. ```typescript getSheetId(): string ``` ```typescript const sheetId = record.getSheetId(); console.log(`记录所属数据表ID: ${sheetId}`); ``` -------------------------------- ### Configure Permission for Script API Source: https://github.com/dingdocs-notable/addon-demo/blob/main/knowledges/其它接口.md Authenticates and configures permissions for using script APIs to read/write AI table data. This involves obtaining an access token, a jsapi ticket, and calculating a signature. ```http POST /v1.0/oauth2/accessToken HTTP/1.1 Host:api.dingtalk.com Content-Type:application/json { "appKey" : "dingeqqpkv3xxxxxx", // 已创建的企业内部应用的 Cilent ID(原企业内部应用AppKey)。 "appSecret" : "GT-lsu-taDAxxxsTsxxxx" // 已创建的企业内部应用的 Cilent Secret (原企业内部应用AppSecret)。 } ``` ```http HTTP/1.1 200 OK Content-Type:application/json { "accessToken" : "fw8ef8we8f76e6f7s8dxxxx", // 生成的accessToken。 "expireIn" : 7200 // accessToken的过期时间,单位秒。 } ``` ```http POST /v1.0/oauth2/jsapiTickets HTTP/1.1 Host:api.dingtalk.com x-acs-dingtalk-access-token:String // 传入accessToken Content-Type:application/json ``` ```http HTTP/1.1 200 OK Content-Type:application/json { "jsapiTicket" : "asjdgxxx", // 返回的jsapi_ticket。 "expireIn" : 7200 } ``` ```typescript const crypto = require('crypto'); /** * 计算dd.config的签名参数 signature * * @param {string} jsticket 通过微应用appKey获取的jsticket * @param {string} nonceStr 自定义固定字符串 * @param {number} timeStamp 当前时间戳 * @param {string} url 调用dd.config的当前页面URL * @returns {string} 签名 */ function sign(jsticket, nonceStr, timeStamp, url) { try { const plain = `jsapi_ticket=${jsticket}&noncestr=${nonceStr}×tamp=${timeStamp}&url=${decodeUrl(url)}`; const sha1 = crypto.createHash('sha256'); sha1.update(plain, 'utf8'); return byteToHex(sha1.digest()); } catch (error) { console.error('Error in sign function:', error); throw error; } } // 字节数组转化成十六进制字符串 function byteToHex(buffer) { return buffer.toString('hex'); } /** * 因为ios端上传递的url是encode过的,android是原始的url。开发者使用的也是原始url, * 所以需要把参数进行一般urlDecode * * @param {string} urlString * @returns {string} 解码后的URL */ function decodeUrl(urlString) { try { const parsedUrl = new URL(urlString); let urlBuffer = `${parsedUrl.protocol}:`; if (parsedUrl.host) { urlBuffer += `//${parsedUrl.host}`; } if (parsedUrl.pathname) { urlBuffer += parsedUrl.pathname; } if (parsedUrl.search) { urlBuffer += `?${decodeURIComponent(parsedUrl.search.substring(1))}`; } return urlBuffer; } catch (error) { console.error('Error in decodeUrl function:', error); throw error; } } module.exports = { sign }; ``` ```typescript const JSAPI_LIST = ["DingdocsScript.base.readWriteAll"]; await Dingdocs.base.host.configPermission( agentId: '应用agentId', corpId: '企业corpId', timeStamp: Number('当前时间戳(number类型)'), nonceStr: '自定义固定字符串', signature: '签名信息', jsApiList: JSAPI_LIST, ); ``` -------------------------------- ### Get TextField Value Async Source: https://github.com/dingdocs-notable/addon-demo/blob/main/knowledges/文本字段.md Retrieves the text value for a specific record in a TextField. Returns null if the record does not exist or the value is empty. ```typescript getValueAsync(recordId: string): Promise ``` -------------------------------- ### getSheets Source: https://github.com/dingdocs-notable/addon-demo/blob/main/knowledges/Base模块.md Retrieves all data tables visible to the current user. ```APIDOC ## getSheets ### Description Gets all data tables visible to the current user. ### Method `getSheets(): Sheet[]` ### Returns * `Sheet[]` - An array of data table objects visible to the current user. ### Example ```typescript const allSheets = base.getSheets(); console.log(`Number of visible sheets: ${allSheets.length}`); allSheets.forEach(sheet => { console.log(`- ${sheet.getName()}`); }); ``` ``` -------------------------------- ### Get Specific View by ID Source: https://github.com/dingdocs-notable/addon-demo/blob/main/knowledges/Sheet模块.md Retrieve a specific view object from the data sheet using its unique ID. Returns null if the view is not found. ```typescript getView(id: string): View | null ``` -------------------------------- ### Real-time event listeners for spreadsheet changes Source: https://context7.com/dingdocs-notable/addon-demo/llms.txt This section describes how to subscribe to real-time events for various spreadsheet changes such as selection changes, sheet modifications, field updates, and record operations. Each listener returns an unsubscribe function to stop listening. ```APIDOC ## Real-time event listeners for spreadsheet changes All event listeners return an unsubscribe function (`OffListener`). Call it to stop listening. Events fire in the UI layer context. ### `Dingdocs.base.event.onSelectionChanged` Fires when the user changes their selection within the spreadsheet, including switching cells or views. **Event Payload:** `{ baseId: string, sheetId: string, viewId: string, fieldId: string, recordId: string }` ### `Dingdocs.base.event.onSheetInserted` Fires when a new sheet is inserted into the spreadsheet. **Event Payload:** `{ baseId: string }` ### `Dingdocs.base.event.onSheetDeleted` Fires when a sheet is deleted from the spreadsheet. **Event Payload:** `{ baseId: string }` ### `Dingdocs.base.event.onFieldInserted` Fires when a new field is inserted into a sheet. **Event Payload:** `{ baseId: string; sheetId: string }` ### `Dingdocs.base.event.onFieldModified` Fires when an existing field in a sheet is modified. **Event Payload:** `{ baseId: string; sheetId: string }` ### `Dingdocs.base.event.onFieldDeleted` Fires when a field is deleted from a sheet. **Event Payload:** `{ baseId: string; sheetId: string }` ### `Dingdocs.base.event.onRecordInserted` Fires when a new record is inserted into a sheet. **Event Payload:** `{ baseId: string; sheetId: string; recordId: string }` ### `Dingdocs.base.event.onRecordModified` Fires when an existing record in a sheet is modified. **Event Payload:** `{ baseId: string; sheetId: string; recordId: string }` ### `Dingdocs.base.event.onRecordDeleted` Fires when a record is deleted from a sheet. **Event Payload:** `{ baseId: string; sheetId: string; recordId: string }` ``` -------------------------------- ### Get Record Last Modification Time Source: https://github.com/dingdocs-notable/addon-demo/blob/main/knowledges/Record模块.md Returns the timestamp of the last modification to the record in milliseconds. Useful for tracking changes or calculating time differences. ```typescript getLastModifiedTime(): number ``` ```typescript // 获取记录最后修改时间 const updatedTime = record.getLastModifiedTime(); const updatedDate = new Date(updatedTime); console.log(`记录最后修改于: ${updatedDate.toLocaleString()}`); // 计算记录最后修改以来的时间 const now = Date.now(); const daysSinceUpdate = Math.floor((now - updatedTime) / (24 * 60 * 60 * 1000)); console.log(`上次更新已过去 ${daysSinceUpdate} 天`); ``` -------------------------------- ### Get Single Cell Value Source: https://github.com/dingdocs-notable/addon-demo/blob/main/knowledges/Record模块.md Retrieves the value of a specific field within the record, identified by its ID or name. Returns null if the field is inaccessible. ```typescript getCellValue(fieldIdOrName: string): OpenApi.CellValue | null ``` ```typescript // 通过字段名称获取值 const title = record.getCellValue('标题'); console.log(`任务标题: ${title}`); // 处理不同类型的字段值 const dueDate = record.getCellValue('截止日期'); if (dueDate) { console.log(`截止日期: ${new Date(dueDate).toLocaleDateString()}`); } ```