diff --git a/docs.json b/docs.json index 50c6250a..71e62a80 100644 --- a/docs.json +++ b/docs.json @@ -326,7 +326,8 @@ "pages": [ "en/basic/record", "en/basic/record/comment", - "en/basic/record/record-history" + "en/basic/record/record-history", + "en/basic/record/archive-trash" ] }, { @@ -405,6 +406,7 @@ "en/basic/admin-panel/computed-outbox", "en/basic/admin-panel/ai-generation-queue", "en/basic/admin-panel/audit-log", + "en/basic/admin-panel/announcements", "en/basic/admin-panel/sandbox-agent" ] }, @@ -693,7 +695,8 @@ "pages": [ "zh/basic/record", "zh/basic/record/comment", - "zh/basic/record/record-history" + "zh/basic/record/record-history", + "zh/basic/record/archive-trash" ] }, { @@ -773,6 +776,7 @@ "zh/basic/admin-panel/computed-outbox", "zh/basic/admin-panel/ai-generation-queue", "zh/basic/admin-panel/audit-log", + "zh/basic/admin-panel/announcements", "zh/basic/admin-panel/sandbox-agent" ] }, diff --git a/en/basic/admin-panel/announcements.mdx b/en/basic/admin-panel/announcements.mdx new file mode 100644 index 00000000..d649f637 --- /dev/null +++ b/en/basic/admin-panel/announcements.mdx @@ -0,0 +1,62 @@ +--- +title: "Announcements" +description: "Publish in-app announcements to everyone, to selected spaces, or to selected users, and withdraw them when they no longer apply." +--- + +Available for self-hosted Business plan and above + +Path: Admin Panel → Announcements + +**Announcements** lets administrators put a message in front of signed-in users without sending email: planned maintenance, an incident and its resolution, a policy change, or a new feature you want people to find. Each announcement runs inside a scheduled window and can be aimed at the whole instance or at a specific group. + +## Publish an Announcement + +Click **Publish announcement** and fill in the form. The preview on the side shows the announcement as users will see it. + +| Setting | What it controls | +| --- | --- | +| **Form** | Where the announcement appears: **Banner** across the top of the app, **Toast** as a transient notification, **Modal** as a dialog that interrupts, or **Sidebar card** in the space and base sidebars. | +| **Level** | The tone users see: **Info**, **Maintenance**, **Critical**, or **Resolved**. | +| Title and **Body** | The announcement text. | +| **Starts at** / **Ends at** | The window during which the announcement is delivered. The end time must be after the start time. | +| **Link text** / **Link URL** | An optional destination. A sidebar card is itself a link, so it always offers the URL field; the other forms show it once the body uses the `{link}` placeholder. | +| **Audience** | **Everyone**, **Specific spaces**, or **Specific users**. | + +Choose the strongest form the message deserves. A banner and a sidebar card sit alongside the user's work; a modal blocks it. Users can dismiss an announcement themselves, and when several are active at once, banners collapse behind a **N more announcements** toggle. + +### Target Specific Spaces or Users + +For **Specific spaces** or **Specific users**, paste identifiers into the audience box (space IDs or names, or user IDs, names, or emails, separated by commas), then click **Match**. Matched entries become chips, and anything Teable could not resolve stays in the box under **Not matched:** so you can correct and retry. + +Space membership is evaluated when the announcement is delivered, so collaborators added later still receive a space-targeted announcement. + +### Insert Live Values + +Use **Insert placeholder** in the body to add values that Teable fills in at display time, so one message stays accurate for every reader: + +| Placeholder | Renders as | +| --- | --- | +| `{startTime}` / `{endTime}` | The window's start or end, in the reader's language and time zone | +| `{time:…}` | A specific instant you choose | +| `{duration}` | How long the window lasts | +| `{countdown}` | A live countdown to the start | +| `{link}` | The link, shown with your **Link text** | + +`{link}` is unavailable for the sidebar card, because the whole card is already the link. + +### Translate the Content + +Write the announcement in one language, then use **AI translate** to fill the other shipped interface languages. Choose **Fill blanks only** to keep translations you already wrote, or **Overwrite all** to re-translate everything. Review each language tab afterwards: the translation is a draft, not a final proofread. Readers see the language that matches their interface, falling back to English. + +## Manage Published Announcements + +The list shows every announcement with its **Status**, **Title**, **Form**, **Level**, **Audience**, **Window**, and **Created by**. Open a row to inspect its full content. + +| Status | Meaning | +| --- | --- | +| **Scheduled** | The start time has not arrived yet. | +| **Active** | Currently being delivered. | +| **Expired** | The end time has passed. | +| **Withdrawn** | Stopped early by an administrator. | + +Click **Withdraw** on an active announcement to stop delivering it immediately. An announcement that has already expired cannot be withdrawn, and its record stays as it was. diff --git a/en/basic/ai/app-builder.mdx b/en/basic/ai/app-builder.mdx index f7c85a0f..b5184f37 100644 --- a/en/basic/ai/app-builder.mdx +++ b/en/basic/ai/app-builder.mdx @@ -122,7 +122,8 @@ When your app is ready, click the **Publish** button (arrow icon) in the top rig - **Custom Domain**: Map your own domain to the app. - **Show branding**: Use **Show branding** in the **Publish** menu to control whether the published app shows the **Build with Teable** badge. If you change this setting after publishing, click **Redeploy** to apply it. - **Unpublish**: For a published app, use **Unpublish** in the publish menu to take the public link offline. -- **App configuration changes**: If the publish menu shows **App configuration changed — redeploy to apply**, click **Redeploy** to apply pending Secret value, AI access, login, or branding changes to the published app. +- **App configuration changes**: When the publish menu shows **Runtime configuration changed. Redeploy to apply it to the live app** or **Branding setting changed. Redeploy to apply it to the live app**, click **Redeploy**. +- **Open published app**: Once an app is published, the icon next to **Publish** opens the live app in a new tab. Hiding the **Build with Teable** badge requires the Business plan or above. diff --git a/en/basic/automation/trigger/records/record-updated.mdx b/en/basic/automation/trigger/records/record-updated.mdx index 0069fb5a..4bd8c368 100644 --- a/en/basic/automation/trigger/records/record-updated.mdx +++ b/en/basic/automation/trigger/records/record-updated.mdx @@ -52,6 +52,12 @@ Choose "All Fields" only when you genuinely need to react to every possible chan It is strongly recommended to select specific watch fields. Selecting "All Fields" can cause the workflow to fire on unrelated edits, waste automation runs, and lead to unexpected behavior. +### Computed fields + +[Formula](/en/basic/field/formula), [Lookup](/en/basic/field/lookup), [Rollup](/en/basic/field/rollup), [Conditional Lookup](/en/basic/field/conditional-lookup), and [Conditional Rollup](/en/basic/field/conditional-rollup) values come from Teable's own calculation rather than from typing, and a recalculation only fires this trigger when you name the computed field in **Watch Fields**. All five behave the same way. + +This lets you react to a derived result instead of to the raw inputs behind it. Watch a `Total amount` Formula field and the workflow runs whenever the total actually changes, no matter which of the underlying fields moved. Watch a Rollup of linked tasks and the workflow runs when the rolled-up value changes, including when the change came from an edit in the linked table. + ## Common pitfall: update loops If your workflow includes an Update Record action that writes to the same table and updates a watched field, the trigger will fire again, creating an infinite loop. diff --git a/en/basic/record.mdx b/en/basic/record.mdx index c11a18dc..aa332400 100644 --- a/en/basic/record.mdx +++ b/en/basic/record.mdx @@ -47,6 +47,8 @@ You can create records in the following ways: Select one or more records, then right-click and choose **Delete record**. For bulk deletion, you can select the checkboxes at the beginning of rows before deleting them. +Deleted records go to the table trash, where you can review and restore them. If you want records out of the table but still available, archive them instead of deleting. See [Archive and Trash](/en/basic/record/archive-trash). + ## Record Details **Archive** or **History** > **Trash**. + +## Archive Records + +Available for Business plan and above + +Archiving takes records out of the table view and out of your space's record count, while keeping their field values, attachments, and creator information. Use it for finished projects, closed deals, or past seasons that you want out of the way but not deleted. + +To archive records, select one or more rows in the grid, right-click, and choose **Archive record** or **Archive all selected records**. The confirmation dialog shows how many records will be archived. If you archive the wrong rows, `Ctrl/Cmd + Z` undoes the action and puts them back. + +### Review the Archive + +The archive opens as a read-only grid with two extra columns, **Archived time** and **Archived by**, in front of the table's own fields. Click the expand icon on a row to open **Record detail** and read the full record. + +Use the toolbar to find the records you need: + +| Control | What it does | +| --- | --- | +| Sort selector | Order by **Sort by archived time**, **Sort by created time**, or **Sort by last modified time** | +| **All creators** | Show only records created by selected collaborators | +| **Archived time** | Limit the list to a date range | +| **Clear filter** | Return to the full archive | +| **Export CSV** | Download the archived records currently listed | + +### Restore or Permanently Delete + +Select rows in the archive, then use **Restore** or **Permanently delete** in the toolbar. Both buttons show the number of selected records. + +Restoring puts the records back into the table with their original values, and they count toward your space record limit again. If the space is already at its record limit, restore fails until you free up rows or raise the limit. + +**Permanently delete** removes the archived records for good. This cannot be undone. + +Owners and creators can archive, restore, and permanently delete. Editors can archive records and open the archive, but cannot restore or delete from it. Commenters and viewers have no access. + +## Table Trash + +The trash lists records, fields, and views that were deleted from the table, along with who deleted them and when. Filter the list by type, by the user who deleted the item, or by deletion time, and use **Clear filter** to go back to the full list. + +To see what a deletion actually contained, click the entry in the **Deleted resource** column of a record row. **Deleted records** lists those rows in a grid, where you can filter by creator or created time and expand a row for its **Record detail**. Check the batch here before you restore it. + +Click **Restore** on a trash entry to put the deleted resource back. As with the archive, restoring records re-occupies row quota, so a space that is already at its record limit must free up rows first. + +### How Long Deleted Records Stay Visible + +How far back the trash lists deletions depends on your plan: + +| Plan | Trash history visible | +| --- | --- | +| Free | 14 days | +| Pro | 1 year | +| Business | 3 years | + +## Related + +- [Record History](/en/basic/record/record-history): trace who changed a value and when +- [Records Overview](/en/basic/record): create, edit, and delete records +- [Billing and Plans](/en/basic/space/billing): compare plan limits and change your subscription diff --git a/en/basic/record/record-history.mdx b/en/basic/record/record-history.mdx index 612a0309..0669da44 100644 --- a/en/basic/record/record-history.mdx +++ b/en/basic/record/record-history.mdx @@ -56,6 +56,7 @@ Users only need editing permission for a specific record to view that record's h ## Notes - Record history stores changes at the cell level. -- Bulk import, bulk paste, and bulk update operations can generate many history entries. +- Bulk paste and bulk update operations can generate many history entries. +- Records added by an import or by duplicating a table do not create history entries. Later changes to those records are recorded as usual. - Button field actions appear as **Clicked button** entries. - If you cannot see the history entry point, first confirm whether you have editing permission for the corresponding record or table. diff --git a/en/deploy/env.mdx b/en/deploy/env.mdx index cab26301..51863bc8 100644 --- a/en/deploy/env.mdx +++ b/en/deploy/env.mdx @@ -4,15 +4,25 @@ description: "Here are all available environment variables in Teable and their e mode: "wide" --- + +Teable no longer ships built-in fallback secrets. If a required secret is not +set, the server refuses to start and the startup log lists exactly which +variables are missing, together with a copy-paste block for each case. See +[Secrets and rotation](#secrets-and-rotation) before upgrading an existing +deployment. + + | Environment Variable | Description | Default Value | Required | Example | | ----------------------------------------- | -------------------------------------------------------------------------- | --------------- | -------- | ------------------------------------------------- | | **Core Configuration** | | | | | | PUBLIC_ORIGIN | Public origin for generating complete URLs, must be set to your app's access address | - | Yes | https://app.teable.ai | -| SECRET_KEY | Key for JWT, sessions, and sharing, use a strong password | defaultSecretKey | Yes | yourStrongSecretKey | -| BACKEND_STORAGE_ENCRYPTION_KEY | Encryption key for storage tokens. The default is a public constant in the source — production deployments must set their own random value (the full-featured assets generate one per host) | public constant | - | 16-char random string | -| BACKEND_STORAGE_ENCRYPTION_IV | Encryption IV paired with BACKEND_STORAGE_ENCRYPTION_KEY | public constant | - | 16-char random string | -| BACKEND_ACCESS_TOKEN_ENCRYPTION_KEY | Encryption key for personal access tokens. Same caveat: the default is public — set your own in production | public constant | - | 16-char random string | -| BACKEND_ACCESS_TOKEN_ENCRYPTION_IV | Encryption IV paired with BACKEND_ACCESS_TOKEN_ENCRYPTION_KEY | public constant | - | 16-char random string | +| SECRET_KEY | Root secret for JWTs, sessions, and sharing. Generate a strong random value | - | Yes | `openssl rand -base64 32` | +| BACKEND_JWT_SECRET | Signs auth, share, and plugin JWTs. Falls back to SECRET_KEY | SECRET_KEY | - | `openssl rand -base64 32` | +| BACKEND_SESSION_SECRET | Signs login session cookies. Falls back to SECRET_KEY | SECRET_KEY | - | `openssl rand -base64 32` | +| BACKEND_STORAGE_ENCRYPTION_KEY | Encrypts attachment access tokens. Required when BACKEND_STORAGE_PROVIDER is `local` | - | Yes | 16-char random string | +| BACKEND_STORAGE_ENCRYPTION_IV | Encryption IV paired with BACKEND_STORAGE_ENCRYPTION_KEY | - | Yes | 16-char random string | +| BACKEND_ACCESS_TOKEN_ENCRYPTION_KEY | Encrypts personal access tokens | - | Yes | 16-char random string | +| BACKEND_ACCESS_TOKEN_ENCRYPTION_IV | Encryption IV paired with BACKEND_ACCESS_TOKEN_ENCRYPTION_KEY | - | Yes | 16-char random string | | PORT | Port on which the application runs | 3000 | - | 3000 | | LOG_LEVEL | Log level, options: fatal, error, warn, info, debug, trace | info | - | debug | | **Storage Configuration** | | | | | @@ -114,7 +124,7 @@ mode: "wide" | SANDBOX_OPENSANDBOX_RUNTIME | Sandbox engine runtime type: `kubernetes` or `docker`. Must be `docker` on Docker deployments | kubernetes | - | docker | | SANDBOX_OPENSANDBOX_USE_SERVER_PROXY | Route sandbox endpoints through the engine's path-based proxy instead of per-port subdomains (used by Docker local mode) | false | - | true | | APP_DEPLOY_PROVIDER | App Builder deployment backend; full-featured self-host uses `docker-runtime` | vercel | - | docker-runtime | -| SANDBOX_JWT_SECRET | Secret signing sandbox sessions — generate a random value per host | - | - | random string | +| SANDBOX_JWT_SECRET | Secret signing sandbox sessions. Generate a random value per host, and use the same value in the sandbox service | - | Yes | random string | | SANDBOX_CPU | vCPUs per sandbox (admin panel settings take precedence) | 2 | - | 2 | | SANDBOX_MEMORY | Memory (GiB) per sandbox (admin panel settings take precedence) | 4 | - | 4 | | SANDBOX_DISK | Ephemeral disk (GiB) per sandbox (admin panel settings take precedence) | 15 | - | 15 | @@ -132,3 +142,31 @@ mode: "wide" | PRISMA_TRANSACTION_TIMEOUT | Maximum time (ms) a transaction can run before timing out. Increase for long-running transactions (e.g., bulk updates with many foreign keys) | 5000 | - | 60000 | | PRISMA_TRANSACTION_MAX_WAIT | Maximum time (ms) to wait to acquire a transaction from the pool | 2000 | - | 5000 | | BIG_TRANSACTION_TIMEOUT | Timeout (ms) for large internal transactions, such as exporting large bases | 600000 | - | 1200000 | + +## Secrets and rotation + +Secrets no longer have defaults compiled into the source. Every value above +marked as a secret must come from your own configuration, and the server checks +them at startup: if any required secret is missing, it stops and prints the +list. + +**Upgrading an existing deployment.** An instance that ran without these +variables was implicitly using the old built-in values. The startup error +prints the exact block to add so current sessions, tokens, and encrypted data +keep working. Copy it as-is, restart, then plan a rotation. If your +configuration format needs it, remember to escape `$` in the values. + +**New deployment.** Generate fresh values instead: + +```bash +openssl rand -base64 32 +``` + +Use `openssl rand -hex 8` for the 16-character `*_ENCRYPTION_KEY` and +`*_ENCRYPTION_IV` slots. + + +If the startup log warns that a secret is still set to a publicly known former +default, the instance keeps running so your data stays reachable, but anyone +can forge tokens or decrypt data protected by that value. Rotate it. + diff --git a/en/deploy/upgrade.mdx b/en/deploy/upgrade.mdx index cd0894c5..1d01bfcc 100644 --- a/en/deploy/upgrade.mdx +++ b/en/deploy/upgrade.mdx @@ -68,6 +68,14 @@ as the upgrade sheet. On each round: running against the platform release manifest (compatible / upgrade the Teable app / unknown combination). +## Required secrets + +Teable no longer falls back to built-in default secrets. If your deployment +relied on those defaults, the first start after upgrading stops with a list of +the environment variables it needs and a copy-paste block that preserves your +existing sessions, tokens, and encrypted data. Add the block, restart, then +plan a rotation. See [Secrets and rotation](/en/deploy/env#secrets-and-rotation). + ## Database migration Teable executes database migrations automatically on startup; no manual step diff --git a/zh/basic/admin-panel/announcements.mdx b/zh/basic/admin-panel/announcements.mdx new file mode 100644 index 00000000..bf4782db --- /dev/null +++ b/zh/basic/admin-panel/announcements.mdx @@ -0,0 +1,62 @@ +--- +title: "站内公告" +description: "向全员、指定空间或指定用户发布站内公告,并在不再适用时撤回。" +--- + +私有化部署商业版及以上适用 + +路径:管理后台 → 站内公告 + +**站内公告** 让管理员不发邮件也能把消息推到已登录用户面前:计划内维护、故障与恢复通知、政策调整,或者想让大家知道的新功能。每条公告都在设定的时间窗内投放,可以面向整个实例,也可以只面向特定人群。 + +## 发布公告 + +点击 **发布公告** 并填写表单,右侧预览会按用户实际看到的样子呈现。 + +| 配置项 | 作用 | +| --- | --- | +| **形态** | 公告出现的位置:**横幅** 显示在应用顶部,**提示** 作为短暂通知出现,**弹窗** 以对话框打断操作,**侧栏卡片** 出现在空间和 Base 侧边栏。 | +| **等级** | 用户看到的语气:**信息**、**维护**、**紧急** 或 **恢复**。 | +| 标题与 **正文** | 公告内容。 | +| **开始时间** / **结束时间** | 投放的时间窗,结束时间必须晚于开始时间。 | +| **链接文本** / **链接地址** | 可选的跳转目标。侧栏卡片本身就是一个链接,因此始终提供链接地址字段;其他形态在正文使用 `{link}` 占位符后才会显示该字段。 | +| **受众** | **全员**、**指定空间** 或 **指定用户**。 | + +按消息的重要程度选择形态:横幅和侧栏卡片不打断用户手上的事,弹窗会。用户可以自行关闭公告;多条公告同时生效时,横幅会折叠到 **还有 N 条公告** 的展开入口后面。 + +### 指定空间或用户 + +选择 **指定空间** 或 **指定用户** 后,把标识粘贴到受众输入框(空间 ID 或名称,用户 ID、姓名或邮箱,用逗号分隔),再点击 **匹配**。匹配成功的会变成标签,未能识别的会留在输入框中并列在 **未匹配:** 后面,方便修正后重试。 + +空间成员关系在公告投放时判定,因此之后加入的协作者同样会收到面向该空间的公告。 + +### 插入动态内容 + +在正文中用 **插入占位符** 加入动态值,Teable 会在展示时按每位读者的语言和时区填充: + +| 占位符 | 展示为 | +| --- | --- | +| `{startTime}` / `{endTime}` | 时间窗的开始或结束时间,按读者的语言和时区呈现 | +| `{time:…}` | 你指定的某个具体时间 | +| `{duration}` | 时间窗的持续时长 | +| `{countdown}` | 距离开始时间的实时倒计时 | +| `{link}` | 链接,使用你填写的 **链接文本** | + +侧栏卡片不支持 `{link}`,因为整张卡片本身就是链接。 + +### 翻译公告内容 + +先用一种语言写好,再用 **AI 翻译** 填充其他界面语言。选择 **仅填充空白** 可以保留你已经写好的译文,选择 **覆盖全部** 会重新翻译所有语言。翻译完成后逐个语言页签检查一遍,它是草稿,不能代替人工校对。读者会看到与自己界面语言匹配的版本,没有对应语言时回退到英文。 + +## 管理已发布的公告 + +列表展示每条公告的 **状态**、**标题**、**形态**、**等级**、**受众**、**生效时间** 和 **创建人**,点击某行可以查看完整内容。 + +| 状态 | 含义 | +| --- | --- | +| **待生效** | 还没到开始时间。 | +| **生效中** | 正在投放。 | +| **已过期** | 已过结束时间。 | +| **已撤回** | 被管理员提前停止。 | + +对生效中的公告点击 **撤回**,可以立即停止投放。已过期的公告不能撤回,记录保持原样。 diff --git a/zh/basic/ai/app-builder.mdx b/zh/basic/ai/app-builder.mdx index 0ef213a6..922009d1 100644 --- a/zh/basic/ai/app-builder.mdx +++ b/zh/basic/ai/app-builder.mdx @@ -132,7 +132,8 @@ Teable 应用构建器 (App Builder) 允许您在不编写代码的情况下, - **自定义域名**:支持绑定您自己的域名。 - **展示品牌标识**:在 **发布** 菜单中控制已发布应用是否显示 **Build with Teable** 标识。发布后修改此设置,需要点击 **重新发布** 才会生效。 - **取消发布**:已发布应用可在发布菜单中点击 **取消发布**,让公开链接暂时下线。 -- **应用配置变更**:如果发布菜单显示 **应用配置已修改,重新发布后生效**,点击 **重新发布**,将待生效的密钥值、AI 访问、登录配置或品牌标识变更应用到已发布应用。 +- **应用配置变更**:发布菜单提示 **运行配置已修改,重新发布后在线上生效** 或 **品牌标识设置已修改,重新发布后在线上生效** 时,点击 **重新发布**。 +- **访问已发布 App**:应用发布后,**发布** 按钮旁的图标会在新标签页中打开线上应用。 关闭 **Build with Teable** 标识需要商业版及以上方案。 diff --git a/zh/basic/automation/trigger/records/record-updated.mdx b/zh/basic/automation/trigger/records/record-updated.mdx index d8ad77d1..ed76ead5 100644 --- a/zh/basic/automation/trigger/records/record-updated.mdx +++ b/zh/basic/automation/trigger/records/record-updated.mdx @@ -44,6 +44,12 @@ AI 会为你处理一切:选择合适的触发器,映射相关字段,自 强烈建议选择特定的监听字段。选择"全部字段"容易导致工作流在不相关的编辑中被频繁触发,浪费运行次数,也可能导致意外行为。 +### 计算字段 + +[公式](/zh/basic/field/formula)、[查找](/zh/basic/field/lookup)、[汇总](/zh/basic/field/rollup)、[条件查找](/zh/basic/field/conditional-lookup)、[条件汇总](/zh/basic/field/conditional-rollup)的值由 Teable 算出,不用手填。这些值重新计算时,只有把该字段列入 **监听字段** 才会触发本触发器,五种字段的行为一致。 + +这样你可以直接响应最终结果,不用盯着背后的每个输入项。监听"总金额"公式字段,不管是哪个基础字段变了,只要总额真的变化工作流就会运行;监听关联任务的汇总字段,汇总值变化时同样会运行,包括变化来自关联表格里的编辑。 + ## 筛选条件说明 筛选条件在记录更新后被评估。只有当更新后的记录满足筛选条件时,后续步骤才会执行。常见用法: diff --git a/zh/basic/record.mdx b/zh/basic/record.mdx index 0c31c323..31d88528 100644 --- a/zh/basic/record.mdx +++ b/zh/basic/record.mdx @@ -47,6 +47,8 @@ description: "记录是表格中存储数据的基本单元。表格视图中, 选中一条或多条记录后,右键点击并选择 **删除记录**。批量删除时,可以先勾选行首复选框,再执行删除操作。 +删除的记录会进入表格回收站,可以在那里查看和恢复。想让记录离开表格但仍然留着,就用归档代替删除。详情请看[归档与回收站](/zh/basic/record/archive-trash)。 + ## 记录详情 **归档区** 或 **历史** > **回收站**。 + +## 归档记录 + +商业版及以上适用 + +归档会把记录移出表格视图,也不再占用空间的记录数配额,但字段值、附件和创建人信息都留着。适合已完结的项目、已成交的订单,或者过往周期的数据:不想再看到,但也不能删掉。 + +在网格中选中一行或多行,右键选择 **归档记录** 或 **归档所有选定的记录**,确认弹窗会显示将要归档的记录数量。如果归档错了,按 `Ctrl/Cmd + Z` 可以撤销并放回原表。 + +### 查看归档区 + +归档区是一个只读网格,在表格自有字段之前会额外显示 **归档时间** 和 **归档人** 两列。点击行首的展开图标,可以打开 **记录详情** 查看完整内容。 + +用顶部工具栏定位需要的记录: + +| 控件 | 作用 | +| --- | --- | +| 排序选择器 | 可选 **按归档时间排序**、**按创建时间排序** 或 **按最后修改时间排序** | +| **全部创建人** | 只看指定协作者创建的记录 | +| **归档时间** | 按时间范围缩小列表 | +| **清除筛选** | 回到完整归档列表 | +| **导出 CSV** | 下载当前列出的归档记录 | + +### 恢复或永久删除 + +在归档区选中记录,使用工具栏的 **恢复** 或 **永久删除**,按钮上会显示已选中的记录数。 + +恢复会把记录按原值放回表格,并重新占用空间的记录数配额。如果空间已经达到记录数上限,恢复会失败,需要先腾出行数或提升上限。 + +**永久删除** 会彻底删除这些归档记录,操作不可撤销。 + +拥有者和创建者可以归档、恢复和永久删除;编辑者可以归档记录、查看归档区,但不能恢复或永久删除;评论者和查看者看不到归档区。 + +## 表格回收站 + +回收站列出该表格中被删除的记录、字段和视图,以及删除人和删除时间。列表可以按类型、操作人和时间筛选,用 **清除筛选** 回到完整列表。 + +想知道一次删除具体包含哪些内容,点击记录行 **资源** 列中的条目,**已删除的记录** 会用网格列出这批行。这里可以按创建人或创建时间筛选,也可以展开某一行查看 **记录详情**。恢复前用它核对一遍,避免还原错批次。 + +点击回收站条目上的 **恢复**,就能把删除的资源放回表格。和归档区一样,恢复记录会重新占用行数配额,空间已达上限时需要先腾出行数。 + +### 已删除记录的可见时长 + +不同套餐可以查看的时间范围不同: + +| 套餐 | 可见范围 | +| --- | --- | +| 免费版 | 14 天 | +| 专业版 | 1 年 | +| 商业版 | 3 年 | + +## 相关内容 + +- [记录历史](/zh/basic/record/record-history):追踪数据被谁在什么时候修改 +- [记录概览](/zh/basic/record):创建、编辑和删除记录 +- [账单与套餐](/zh/basic/space/billing):对比套餐限制、变更订阅 diff --git a/zh/basic/record/record-history.mdx b/zh/basic/record/record-history.mdx index 17379d01..e852148d 100644 --- a/zh/basic/record/record-history.mdx +++ b/zh/basic/record/record-history.mdx @@ -57,6 +57,7 @@ description: "查看表格或单条记录的历史变更,追踪数据被谁在 ## 注意事项 - 记录历史以单元格为最小单位保存变更。 -- 批量导入、批量粘贴或批量更新会产生较多历史记录。 +- 批量粘贴或批量更新会产生较多历史记录。 +- 通过导入或复制表格新增的记录不会生成历史条目,之后对这些记录的修改仍然照常记录。 - 按钮字段的操作会显示为 **点击了按钮**。 - 如果你看不到历史记录入口,先确认自己是否拥有对应记录或表格的编辑权限。 diff --git a/zh/deploy/env.mdx b/zh/deploy/env.mdx index b37c0993..043c777d 100644 --- a/zh/deploy/env.mdx +++ b/zh/deploy/env.mdx @@ -4,15 +4,21 @@ description: "这里列举了Teable 所有可用的环境变量以及相关解 mode: "wide" --- + +Teable 不再内置任何默认密钥。缺少必填密钥时,服务会拒绝启动,并在启动日志中列出缺失的变量以及可直接复制的配置块。升级已有部署前,请先阅读[密钥与轮换](#密钥与轮换)。 + + | 环境变量 | 描述 | 默认值 | 必填 | 示例 | | -------------------------------------------- | ------------------------------------------------------- | ---------------- | ---- | ------------------------------------------------ | | **核心配置** | | | | | | PUBLIC_ORIGIN | 用于生成完整 URL 的公共源,必须设置为您的应用程序访问地址 | - | 是 | https://app.teable.ai | -| SECRET_KEY | 用于 JWT、会话和共享的密钥,请使用强密码 | defaultSecretKey | 是 | yourStrongSecretKey | -| BACKEND_STORAGE_ENCRYPTION_KEY | 存储令牌加密密钥。默认值是源码中的公开常量 —— 生产部署必须自行设置随机值(全功能部署资产会按主机自动生成) | 公开常量 | - | 16 位随机字符串 | -| BACKEND_STORAGE_ENCRYPTION_IV | 与 BACKEND_STORAGE_ENCRYPTION_KEY 配对的加密 IV | 公开常量 | - | 16 位随机字符串 | -| BACKEND_ACCESS_TOKEN_ENCRYPTION_KEY | 个人访问令牌加密密钥。同样注意:默认值公开,生产环境请自行设置 | 公开常量 | - | 16 位随机字符串 | -| BACKEND_ACCESS_TOKEN_ENCRYPTION_IV | 与 BACKEND_ACCESS_TOKEN_ENCRYPTION_KEY 配对的加密 IV | 公开常量 | - | 16 位随机字符串 | +| SECRET_KEY | 用于 JWT、会话和共享的根密钥,请生成强随机值 | - | 是 | `openssl rand -base64 32` | +| BACKEND_JWT_SECRET | 签发登录、分享和插件 JWT 的密钥,未设置时回退到 SECRET_KEY | SECRET_KEY | - | `openssl rand -base64 32` | +| BACKEND_SESSION_SECRET | 签发登录会话 Cookie 的密钥,未设置时回退到 SECRET_KEY | SECRET_KEY | - | `openssl rand -base64 32` | +| BACKEND_STORAGE_ENCRYPTION_KEY | 附件访问令牌的加密密钥。BACKEND_STORAGE_PROVIDER 为 `local` 时必填 | - | 是 | 16 位随机字符串 | +| BACKEND_STORAGE_ENCRYPTION_IV | 与 BACKEND_STORAGE_ENCRYPTION_KEY 配对的加密 IV | - | 是 | 16 位随机字符串 | +| BACKEND_ACCESS_TOKEN_ENCRYPTION_KEY | 个人访问令牌的加密密钥 | - | 是 | 16 位随机字符串 | +| BACKEND_ACCESS_TOKEN_ENCRYPTION_IV | 与 BACKEND_ACCESS_TOKEN_ENCRYPTION_KEY 配对的加密 IV | - | 是 | 16 位随机字符串 | | PORT | 应用程序运行的端口 | 3000 | - | 3000 | | LOG_LEVEL | 日志级别,可选值:fatal、error、warn、info、debug、trace | info | - | debug | | **存储配置** | | | | | @@ -114,7 +120,7 @@ mode: "wide" | SANDBOX_OPENSANDBOX_RUNTIME | 沙箱引擎运行时类型:`kubernetes` 或 `docker`。Docker 部署必须设为 `docker` | kubernetes | - | docker | | SANDBOX_OPENSANDBOX_USE_SERVER_PROXY | 沙箱端点走引擎的路径代理而非按端口子域名(Docker local 模式使用) | false | - | true | | APP_DEPLOY_PROVIDER | App Builder 的部署后端;全功能自部署使用 `docker-runtime` | vercel | - | docker-runtime | -| SANDBOX_JWT_SECRET | 沙箱会话签名密钥 —— 请按主机生成随机值 | - | - | 随机字符串 | +| SANDBOX_JWT_SECRET | 沙箱会话签名密钥 —— 请按主机生成随机值,并在沙箱服务中使用相同的值 | - | 是 | 随机字符串 | | SANDBOX_CPU | 每个沙箱的 vCPU 数(管理面板中的设置优先) | 2 | - | 2 | | SANDBOX_MEMORY | 每个沙箱的内存(GiB,管理面板中的设置优先) | 4 | - | 4 | | SANDBOX_DISK | 每个沙箱的临时磁盘(GiB,管理面板中的设置优先) | 15 | - | 15 | @@ -132,3 +138,21 @@ mode: "wide" | PRISMA_TRANSACTION_TIMEOUT | 事务运行超时时间(毫秒),对于长时间运行的事务(如包含多个外键的批量更新)可以增加此值 | 5000 | - | 60000 | | PRISMA_TRANSACTION_MAX_WAIT | 从连接池获取事务的最大等待时间(毫秒) | 2000 | - | 5000 | | BIG_TRANSACTION_TIMEOUT | 大型内部事务的超时时间(毫秒),例如导出大型数据库 | 600000 | - | 1200000 | + +## 密钥与轮换 + +密钥不再在源码中内置默认值。上表中标注为密钥的每一项都必须来自你自己的配置,服务在启动时会统一校验一次:只要缺少必填密钥就会停止启动,并打印缺失清单。 + +**升级已有部署**:此前没有配置这些变量的实例,一直在用旧的内置值。启动报错会打印需要添加的配置块,照原样复制就能让现有会话、令牌和已加密数据继续可用;重启后再安排一次轮换。如果配置格式有要求,注意对值中的 `$` 做转义。 + +**全新部署**,直接生成新的随机值: + +```bash +openssl rand -base64 32 +``` + +`*_ENCRYPTION_KEY` 和 `*_ENCRYPTION_IV` 这类 16 位的槽位请改用 `openssl rand -hex 8`。 + + +如果启动日志警告某个密钥仍然使用公开的历史默认值,实例会继续运行以保证数据可访问,但任何人都可以伪造令牌或解密受该密钥保护的数据,请尽快轮换。 + diff --git a/zh/deploy/upgrade.mdx b/zh/deploy/upgrade.mdx index e1b56c1f..fba887b3 100644 --- a/zh/deploy/upgrade.mdx +++ b/zh/deploy/upgrade.mdx @@ -60,6 +60,10 @@ Teable 应用以**日期型 release tag** 发布,形如 3. 跑自带的 **doctor** —— 检查健康状态,并把实际运行的组合与平台版本清单 比对(兼容 / 需升级 Teable 应用 / 未知组合)。 +## 必填密钥 + +Teable 不再回退到内置的默认密钥。此前依赖这些默认值的部署,升级后第一次启动会中止,并列出需要配置的环境变量,以及一段可直接复制的配置块,它能让现有会话、令牌和已加密数据继续可用。补齐后重启,再安排一次轮换。详见[密钥与轮换](/zh/deploy/env#密钥与轮换)。 + ## 数据库迁移 Teable 启动时自动执行数据库迁移,无需人工干预。如升级后出现异常,先查日志: