diff --git a/docs/developers/concepts/2-auth-models.md b/docs/developers/concepts/2-auth-models.md index e215ada7c..5143c8eba 100644 --- a/docs/developers/concepts/2-auth-models.md +++ b/docs/developers/concepts/2-auth-models.md @@ -23,6 +23,7 @@ coScene 根据上述的权限体系和原则,在系统内为所有的资源预 1. 组织管理员:可以管理组织内的所有资源和权限 2. 成员:可以管理所有组织内成员有权限的数据 3. 只读成员:可以读取所有组织内成员有权限的数据 +4. 外部人员:不是组织内的实际用户,可以通过邀请加入组织,访问被添加的项目 ### 项目 @@ -30,4 +31,8 @@ coScene 根据上述的权限体系和原则,在系统内为所有的资源预 2. 成员:可以管理项目内所有的数据 3. 只读成员:可以读取项目内所有的数据 -当一个用户拥有项目的角色时,该用户项目内的角色会被优先使用。唯一的例外是组织管理员,组织管理员目前拥有最高的系统权限,能访问所有的项目,并且会忽略项目内的角色设置(如果有)。 +当一个用户拥有项目的角色时,该用户项目内的角色会被优先使用。唯一的例外是组织管理员,组织管理员目前拥有最高的系统权限,能访问所有的项目。 + +各角色的操作权限如下: + +![auth.png](./img/auth.png) diff --git a/docs/developers/concepts/img/auth.png b/docs/developers/concepts/img/auth.png new file mode 100644 index 000000000..b34acfb97 Binary files /dev/null and b/docs/developers/concepts/img/auth.png differ diff --git a/docs/developers/s3/1-s3-authentication.md b/docs/developers/s3/1-s3-authentication.md new file mode 100644 index 000000000..a963fad6b --- /dev/null +++ b/docs/developers/s3/1-s3-authentication.md @@ -0,0 +1,27 @@ +--- +sidebar_position: 1 +--- + +# S3 身份验证 + +了解如何使用 S3 进行身份验证,从而对组织内有权限的项目执行 S3 操作。 + +1. 进入项目概览-S3 连接页面,获取 Endpoint、Region、Bucket 等信息。 + + ![pro-s3_1](./img/pro-s3_1.png) + +2. 点击【我的访问秘钥】,前往个人设置-安全页面,管理个人的 S3 访问秘钥。 + + ![pro-s3_2](./img/pro-s3_2.png) + +3. 点击【创建访问秘钥】,输入备注信息后,创建 S3 访问秘钥。 + + ![pro-s3_3](./img/pro-s3_3.png) + +4. 复制访问秘钥 ID 和访问秘钥,用于后续 S3 操作。例如,使用 [AIStor Client(mc)](https://docs.min.io/enterprise/aistor-object-store/reference/cli/) 工具进行 S3 身份验证: + + ```bash + mc alias set coscene + ``` + +注意:**个人的 S3 访问秘钥可对组织内有权限的所有项目执行操作,仅用于个人使用,不建议分享给他人。** \ No newline at end of file diff --git a/docs/developers/s3/2-s3-operations.md b/docs/developers/s3/2-s3-operations.md new file mode 100644 index 000000000..8b7d000cc --- /dev/null +++ b/docs/developers/s3/2-s3-operations.md @@ -0,0 +1,70 @@ +--- +sidebar_position: 2 +--- + +# S3 操作 + +在项目中,通过 S3 可对记录、资源进行上传、下载等操作。 + +## 存储路径 + +1. **记录** + + 记录中的文件在 S3 对应 Bucket 中的路径为 `records//files/`。 + + 例如,记录的 ID 为 `123456`,文件名为 `example.txt`,则文件的路径为 `records/123456/files/example.txt`。 + + ![s3-record](./img/s3-record.png) + +2. **资源** + + 资源中的文件在 S3 对应 Bucket 中的路径为 `files/`。 + + 例如,资源中文件名为 `example.txt`,则文件的路径为 `files/example.txt`。 + + ![s3-resource](./img/s3-resource.png) + +## 操作示例 +以 [AIStor Client(mc)](https://docs.min.io/enterprise/aistor-object-store/reference/cli/) 工具为例。假设项目 Bucket 为 `coscene.01`,记录的 ID 为 `123456`,文件名为 `example.txt`,S3 配置的别名为 `coscene`。 + +### 列出文件 + +1. 列出记录中的文件 + + ```bash + mc ls coscene/coscene.01/records/123456/files/ + ``` + +2. 列出资源中的文件 + + ```bash + mc ls coscene/coscene.01/files/ + ``` + +### 上传文件 + +1. 上传文件到记录中: + + ```bash + mc put example.txt coscene/coscene.01/records/123456/files/ + ``` + +2. 上传文件到资源中: + + ```bash + mc put example.txt coscene/coscene.01/files/ + ``` + +### 下载文件 + +1. 从记录中下载文件 + + ```bash + mc get coscene/coscene.01/records/123456/files/example.txt . + ``` + +2. 从资源中下载文件 + + ```bash + mc get coscene/coscene.01/files/example.txt . + ``` \ No newline at end of file diff --git a/docs/developers/s3/_category_.json b/docs/developers/s3/_category_.json new file mode 100644 index 000000000..ac2e069ce --- /dev/null +++ b/docs/developers/s3/_category_.json @@ -0,0 +1,9 @@ +{ + "label": "S3 存储", + "position": 4, + "collapsible": true, + "link": { + "type": "generated-index", + "slug": "/category/s3" + } +} diff --git a/docs/developers/s3/img/pro-s3_1.png b/docs/developers/s3/img/pro-s3_1.png new file mode 100644 index 000000000..f757694a1 Binary files /dev/null and b/docs/developers/s3/img/pro-s3_1.png differ diff --git a/docs/developers/s3/img/pro-s3_2.png b/docs/developers/s3/img/pro-s3_2.png new file mode 100644 index 000000000..961ec2ff3 Binary files /dev/null and b/docs/developers/s3/img/pro-s3_2.png differ diff --git a/docs/developers/s3/img/pro-s3_3.png b/docs/developers/s3/img/pro-s3_3.png new file mode 100644 index 000000000..575ee5c21 Binary files /dev/null and b/docs/developers/s3/img/pro-s3_3.png differ diff --git a/docs/developers/s3/img/s3-record.png b/docs/developers/s3/img/s3-record.png new file mode 100644 index 000000000..cbea31815 Binary files /dev/null and b/docs/developers/s3/img/s3-record.png differ diff --git a/docs/developers/s3/img/s3-resource.png b/docs/developers/s3/img/s3-resource.png new file mode 100644 index 000000000..4524cc5bb Binary files /dev/null and b/docs/developers/s3/img/s3-resource.png differ diff --git a/docs/viz/1-about-viz.md b/docs/viz/1-about-viz.md index 7abce8f17..a9d676d82 100644 --- a/docs/viz/1-about-viz.md +++ b/docs/viz/1-about-viz.md @@ -8,7 +8,7 @@ sidebar_position: 1 ## 如何进行进入可视化界面 -在记录中,点击【播放记录】或直接点击文件进入可视化界面 +在记录中,点击【播放记录】进入可视化界面 ![viz-1-1.png](./img/viz-1-1.png) @@ -96,14 +96,15 @@ sidebar_position: 1 ![viz-1-12.png](./img/viz-1-12.png) 以下是该区域的功能介绍: -1. 【创建一刻】按钮,用于选择「一刻」的起止点 +1. 创建一刻:在关键时间段创建「一刻」,用于快速定位和回放该时间段的内容 2. 显示文件播放的开始时间、结束时间和持续时间 -3. 当前进度时间戳 +3. 当前播放的时间点 4. 暂停及前进后退按钮 -5. 循环播放按钮 -6. 倍速播放按钮 -7. 播放画质选项按钮 -8. 绝对相对时间切换按钮 +5. 播放步长:调整暂停时的前进/后退时长 +6. 循环播放按钮 +7. 倍速播放按钮 +8. 一刻:一刻在时间轴上以蓝色矩形表示 +9. 可播时间段:可播时间段是指在时间轴上可以播放的时间段,以浅蓝色矩形表示 --- diff --git a/docs/viz/4-panel/10-user-scripts.md b/docs/viz/4-panel/10-user-scripts.md new file mode 100644 index 000000000..b21226463 --- /dev/null +++ b/docs/viz/4-panel/10-user-scripts.md @@ -0,0 +1,262 @@ +--- +sidebar_position: 10 +--- + +# 用户脚本面板 + +用户脚本面板支持用户编写自定义脚本(使用 TypeScript),对输入消息进行转换并输出到新的主题(topic)。该功能支持对回放数据和范围加载数据进行处理,适用于快速数据转换与调试。 + +- 回放数据:逐帧流式传入的消息,例如[原始消息面板](./9-raw-messages.md)或 [三维面板](./2-3d-panel.md)的数据。 +- 范围加载数据:一次性加载整个回放范围内的消息,例如[图表面板](./4-plot-panel.md)或状态转换面板的数据。 + +注意:用户脚本仅作用于当前布局。若需要在所有布局中统一转换消息,请使用[消息转换器](../8-extensions/1-introduction.md#message-converters)。 + +## 快速开始 +用户脚本使用 TypeScript 编写。 +> **提示** +> +> TypeScript 是 JavaScript 的超集,因此可通过 JavaScript 术语搜索语法问题(如操作数组或访问对象属性),通过 TypeScript 术语搜索语义问题(如设置可选对象属性)。 + +### 编写第一个脚本 +每个脚本必须声明以下 3 个导出项: + +- `inputs` - 待转换的输入 topic 数组 +- `output` - 转换后的输出 topic 名称 +- `script` - 处理输入消息并发布到输出 topic 的函数(必须是[默认导出](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/export#description)) + +示例脚本(将 `/rosout` 消息原样输出到 `/coscene_script/echo`): + +```typescript +import { Input, Message } from "./types"; + + +export const inputs = ["/rosout"]; +export const output = "/coscene_script/echo"; + + +export default function script(event: Input<"/rosout">): Message<"rosgraph_msgs/Log"> { + return event.message; +} +``` + +若可视化中包含 `/rosout` topic,则可在[原始消息面板](./9-raw-messages.md)中查看 `/studio_script/echo` topic。 + +当创建一个新脚本时,系统会自动生成示例模板代码: + +```typescript +import { Input, Message } from "./types"; + +type Output = { hello: string }; + +export const inputs = ["/input/topic"]; +export const output = "/studio_script/output_topic"; + +export default function script(event: Input<"/input/topic">): Output { + return { hello: "world!" }; +} +``` + +其中: + +- `Input` 和 `Message` 类型是从 `./types` 模块中导入的,该模块为输入事件和消息提供了辅助类型。 +- `Output` 类型包含一些默认属性,脚本函数的输出必须符合这些属性要求。 +- `Input` 是一个泛型类型,需要传入参数才能使用。这里故意留空,你需要填入输入 topic 的名称,例如:`Input<"/rosout">`。 +- 输入 `event` 为只读。请勿修改该 `event` 对象。 + +关于 **Output** 类型,你有两种方式: + +* 手动定义你关心的输出属性(即模板代码里提供的那些属性); +* 或者使用上面引入的 **Message** 类型中动态生成的类型。例如,如果你想发布一个 marker 数组,可以返回 `Message<"visualization_msgs/MarkerArray">` 类型。 + +需要注意的是,消息属性对可视化结果的影响并不总是直观可见。通过严格类型约束,你可以在编译时发现问题,而不是等到运行时才暴露。 + +当然,在写脚本草稿时,如果你不想被 Typescript 校验打断,可以在想忽略的那行代码前加上 `// @ts-expect-error` 来关闭类型检查。 + +### 使用多输入 topic +通过联合类型处理多个输入 topic 的消息: + +```typescript +import { Input, Message } from "./types"; + +export const inputs = ["/rosout", "/tf"]; +export const output = "/coscene_script/echo"; + +export default function script(event: Input<"/rosout"> | Input<"/tf">): { data: number[] } { + if (event.topic === "/rosout") { + // read event.message fields expected for /rosout messages + } else { + // read event.message fields expected for /tf messages + } + + return { data: [] }; +} +``` + +这段代码片段使用了联合类型(union types),用来声明脚本函数中的消息既可以来自 `/rosout` topic,也可以来自 `/tf` topic。处理消息时,可以通过 `if/else` 判断不同的 schema 名称,从而区分具体是哪个 topic 的消息。 + +如果你需要合并多个 topic 的消息,可以在脚本的全局作用域中创建一个变量,并在每次脚本函数被调用时引用它。同时要检查时间戳,确保不会发布不同步的数据。 + +```typescript +import { Input, Message, Time } from "./types"; + +export const inputs = ["/rosout", "/tf"]; +export const output = "/coscene_script/echo"; + +let lastReceiveTime: Time = { sec: 0, nsec: 0 }; +const myScope: { tf?: Message<"tf2_msgs/TFMessage">; rosout?: Message<"rosgraph_msgs/Log"> } = {}; + +export default function script( + event: Input<"/rosout"> | Input<"/tf">, +): { data: number[] } | undefined { + const { receiveTime } = message; + let inSync = true; + + if (receiveTime.sec !== lastReceiveTime.sec || receiveTime.nsec !== lastReceiveTime.nsec) { + lastReceiveTime = receiveTime; + inSync = false; + } + + if (message.topic === "/rosout") { + myScope.rosout = event.message; + } else { + myScope.tf = event.message; + } + + if (!inSync) { + return { data: [] }; + } +} +``` + +### 使用全局变量 +脚本函数在每次执行时,都会以对象的形式接收所有变量。每当有新消息到来,脚本函数都会用最新的变量值重新运行。 + +> **注意** +> +> 用户脚本中的全局变量是只读的,请勿修改 `globalVars` 参数。 + + +```typescript +import { Input, Message } from "./types"; + +type Output = {}; +type GlobalVariables = { someNumericaVar: number }; + +export const inputs = []; +export const output = "/coscene_script/"; + +export default function script(event: Input<"/foo_marker">, globalVars: GlobalVariables): Output { + if (event.message.id === globalVars.someNumericaVar) { + // Message's id matches $someNumericaVar + } + + return { data: [] }; +} +``` + +### 调试 +用户脚本只有在布局中有使用其输出 topic 时才会被执行。 + +要调试脚本,先在布局中添加一个订阅输出 topic 的原始消息面板。然后,你可以直接查看输入 topic 的消息,或者在脚本中使用 `log(someValue)` 将值打印到面板底部的 Logs 区域。 + +唯一不能使用 `log()` 打印的值是函数本身,或者包含函数定义的值。你也可以一次打印多个值,例如:`log(someValue, anotherValue, yetAnotherValue)`。 + +以下 log 语句不会产生任何错误: + +```typescript +const addNums = (a: number, b: number): number => a + b; +log(50, "ABC", null, undefined, { abc: 2, def: false }); +log(1 + 2, addNums(1, 2)); +``` + +但包含函数定义的值会报错: + +```typescript +log(() => {}); +log(addNums); +log({ subtractNums: (a: number, b: number): number => a - b }); +``` + +在脚本函数外调用 `log()` 会在脚本注册时执行一次;在脚本函数内部调用 `log()`,则会在每次脚本函数被调用时打印该值。 + +> **注意** +> +> 对于高频发布的 topic,使用 `log()` 可能会降低用户脚本的执行效率。 +> +> 此外,由于图表面板会对渲染时间范围内的所有消息调用用户脚本,当在图表面板中查看用户脚本输出时,`log()` 的内容不会显示。这种情况下,可以使用原始消息面板来查看输出消息。 + +### 跳过输出 +当你不希望发布消息时,可以在函数体内提前(或延迟)返回。例如,假设你只想在输入中的某个常量不等于 3 时才发布消息: + +```typescript +import { Input } from "./types"; + +export const inputs = ["/state"]; +export const output = "/coscene_script/manual_metrics"; + +export default function script(event: Input<"/state">): { metrics: number } | undefined { + if (event.message.constant === 3) { + // Do not publish any message + return; + } + return { + // Your data here + }; +} +``` + +在 TypeScript 中,如果你直接 `return` 而不带返回值,函数会隐式返回 `undefined`。请注意脚本函数的联合返回类型——我们已经告诉 TypeScript,该函数可能返回 `undefined`。 + +### 使用 @foxglove/schemas +在用户脚本中,可以从 [@foxglove/schemas](https://github.com/foxglove/foxglove-sdk) 包导入并使用类型: + +```typescript +import { Input } from "./types"; +import { Color } from "@foxglove/schemas"; + +export const inputs = ["/imu"]; +export const output = "/s_script/json_data"; + +export default function script(event: Input<"/imu">): Color { + return { + r: 1, + g: 1, + b: 1, + a: 1, + }; +} +``` + +## 工具与模板 + +- **Utilities 标签页**:包含可在任意脚本中导入使用的函数(例如:`import { compare } from "./time.ts"`)。`types.ts` 工具文件会根据当前加载的数据源生成,包含所有已发现 schema 的类型定义。 +- **Templates 标签页**:包含常见脚本模板,如发布 `MarkerArray` 的脚本 + +## 设置 + +| 通用 | | +| --- | --- | +| 保存时自动格式化 | 保存时自动格式化脚本中的代码 | + +## 快捷键 +输入 `Cmd` + `S` 保存脚本 + +## TypeScript 资源 + +- [Basic Types](https://www.typescriptlang.org/docs/handbook/2/basic-types.html) +- [Gitbook](https://basarat.gitbook.io/typescript/getting-started/why-typescript) + +## 用户脚本 vs Topic Converter 扩展 +用户脚本和 [topic converter 扩展](../8-extensions/1-introduction.md#message-converters)功能相似,但在编写方式、共享方式以及对第三方包的支持上存在关键区别。 + +| 功能 | 用户脚本 | Topic Converter 扩展 | +| --- | --- | --- | +| 数据转换 | ✅ | ✅ | +| 创建新 topic | ✅ | ✅ | +| 直接编辑 | ✅ | ❌ | +| 作用于一个布局 | ✅ | ❌ | +| 跨布局复用 | ❌ | ✅ | +| 团队共享 | ❌ | ✅ | +| 在你的 IDE 中编辑 | ❌ | ✅ | +| 你代码库的一部分 | ❌ | ✅ | +| 使用第三方包 | ❌ | ✅ | diff --git a/docs/viz/4-panel/9-raw-messages.md b/docs/viz/4-panel/9-raw-messages.md new file mode 100644 index 000000000..9c435c2b4 --- /dev/null +++ b/docs/viz/4-panel/9-raw-messages.md @@ -0,0 +1,46 @@ +--- +sidebar_position: 9 +--- + +# 原始消息面板 + +在数据源中查看指定的消息路径。 + +当该路径有新消息进入时,折叠树会自动更新并只显示最新消息。您可以根据需要展开或收起各个键,展开/收起的状态在回放时也会被保留。 + +![raw-messages_1.png](../img/raw-messages_1.png) + +## 设置 + +| 字段 | 说明 | +| --- | --- | +| 字体大小 | 文本显示的字体大小 | + +## 快捷方式 + +### 对比模式 +通过显示字段的新增(绿色)、删除(红色)和修改(黄色)来对比消息,分为两类: + +- `上一条消息` – 对比指定消息路径的连续消息 +- `自定义` – 对比指定时间点不同 topic 的消息 + +![raw-messages_2.png](../img/raw-messages_2.png) +![raw-messages_3.png](../img/raw-messages_3.png) + +### 展开全部 +单击消息路径旁边的图标可展开或折叠显示消息中的所有嵌套字段。 + +| 展开全部 | 收起全部 | +| --- | --- | +| ![raw-messages_5.png](../img/raw-messages_5.png) | ![raw-messages_4.png](../img/raw-messages_4.png) | + +### 逐帧查看 +当消息数量较多时,可使用该功能逐条查看消息。 +通过点击按钮,或选中面板后使用快捷键 `上箭头` 和 `下箭头` 查看。 + +![raw-messages_6.png](../img/raw-messages_6.png) + +### 复制消息 +点击【复制消息】按钮,将当前主题消息复制到剪贴板 + +![raw-messages_7.png](../img/raw-messages_7.png) \ No newline at end of file diff --git a/docs/viz/8-extensions/1-introduction.md b/docs/viz/8-extensions/1-introduction.md index 821c17235..30b69917b 100644 --- a/docs/viz/8-extensions/1-introduction.md +++ b/docs/viz/8-extensions/1-introduction.md @@ -21,7 +21,7 @@ sidebar_position: 1 * 指南:创建自定义面板 * 构建自定义面板扩展(React) -## 消息转换器 +## 消息转换器 {#message-converters} 消息转换器扩展允许您将消息从一种架构转换为另一种架构。通过将消息转换为符合可视化支持的架构,您可以使用可视化的内置可视化功能检查它们。例如,您可以使用消息转换器将自定义 GPS 消息转换为 foxglove.LocationFix 消息,以便在地图面板中可视化。 diff --git a/docs/viz/img/raw-messages_1.png b/docs/viz/img/raw-messages_1.png new file mode 100644 index 000000000..19690e176 Binary files /dev/null and b/docs/viz/img/raw-messages_1.png differ diff --git a/docs/viz/img/raw-messages_2.png b/docs/viz/img/raw-messages_2.png new file mode 100644 index 000000000..94f00f41d Binary files /dev/null and b/docs/viz/img/raw-messages_2.png differ diff --git a/docs/viz/img/raw-messages_3.png b/docs/viz/img/raw-messages_3.png new file mode 100644 index 000000000..0c6425d5f Binary files /dev/null and b/docs/viz/img/raw-messages_3.png differ diff --git a/docs/viz/img/raw-messages_4.png b/docs/viz/img/raw-messages_4.png new file mode 100644 index 000000000..3c051fac6 Binary files /dev/null and b/docs/viz/img/raw-messages_4.png differ diff --git a/docs/viz/img/raw-messages_5.png b/docs/viz/img/raw-messages_5.png new file mode 100644 index 000000000..503c5a0a7 Binary files /dev/null and b/docs/viz/img/raw-messages_5.png differ diff --git a/docs/viz/img/raw-messages_6.png b/docs/viz/img/raw-messages_6.png new file mode 100644 index 000000000..6ccfca769 Binary files /dev/null and b/docs/viz/img/raw-messages_6.png differ diff --git a/docs/viz/img/raw-messages_7.png b/docs/viz/img/raw-messages_7.png new file mode 100644 index 000000000..8bb4561a3 Binary files /dev/null and b/docs/viz/img/raw-messages_7.png differ diff --git a/docs/viz/img/viz-1-12.png b/docs/viz/img/viz-1-12.png index 50f6b4a54..e6b66e1a9 100644 Binary files a/docs/viz/img/viz-1-12.png and b/docs/viz/img/viz-1-12.png differ diff --git a/i18n/en/code.json b/i18n/en/code.json index a7d1c13a0..0e890d82b 100644 --- a/i18n/en/code.json +++ b/i18n/en/code.json @@ -575,6 +575,9 @@ "home.catalogue.openapi": { "message": "OpenAPI Platform" }, + "home.catalogue.s3": { + "message": "S3 Storage" + }, "home.catalogue.use-case": { "message": "Use Cases" }, diff --git a/i18n/en/docusaurus-plugin-content-docs/current.json b/i18n/en/docusaurus-plugin-content-docs/current.json index 9bb92bb83..ba9b7b345 100644 --- a/i18n/en/docusaurus-plugin-content-docs/current.json +++ b/i18n/en/docusaurus-plugin-content-docs/current.json @@ -83,6 +83,10 @@ "message": "OpenAPI", "description": "The label for category 开放平台 OpenAPI in sidebar tutorialSidebar" }, + "sidebar.tutorialSidebar.category.S3 存储": { + "message": "S3 Storage", + "description": "The label for category S3 存储 in sidebar tutorialSidebar" + }, "sidebar.tutorialSidebar.category.组织和团队": { "message": "Organization and Team", "description": "The label for category 组织和团队 in sidebar tutorialSidebar" diff --git a/i18n/en/docusaurus-plugin-content-docs/current/developers/concepts/2-auth-models.md b/i18n/en/docusaurus-plugin-content-docs/current/developers/concepts/2-auth-models.md index 248e609f8..188105ff4 100644 --- a/i18n/en/docusaurus-plugin-content-docs/current/developers/concepts/2-auth-models.md +++ b/i18n/en/docusaurus-plugin-content-docs/current/developers/concepts/2-auth-models.md @@ -23,6 +23,7 @@ Based on the above permission system and principles, the coScene platform predef 1. Organization Administrator: Can manage all resources and permissions within the organization 2. Member: Can manage all data within the organization that members have permission to 3. Read-only Member: Can read all data within the organization that members have permission to +4. External User: Not an actual user within the organization, can join the organization by invitation and access the projects added by the organization ### Project @@ -30,4 +31,8 @@ Based on the above permission system and principles, the coScene platform predef 2. Member: Can manage all data within the project 3. Read-only Member: Can read all data within the project -When a user has a role in a project, the user's role within the project will be prioritized. The only exception is the organizational administrator, who currently has the highest system permission, can access all projects, and will ignore the role settings within the project (if any). +When a user has a role in a project, the user's role within the project will be prioritized. The only exception is the organizational administrator, who currently has the highest system permission, can access all projects. + +The operation permissions for each role are as follows: + +![auth.png](./img/auth.png) \ No newline at end of file diff --git a/i18n/en/docusaurus-plugin-content-docs/current/developers/concepts/img/auth.png b/i18n/en/docusaurus-plugin-content-docs/current/developers/concepts/img/auth.png new file mode 100644 index 000000000..30356edc0 Binary files /dev/null and b/i18n/en/docusaurus-plugin-content-docs/current/developers/concepts/img/auth.png differ diff --git a/i18n/en/docusaurus-plugin-content-docs/current/developers/s3/1-s3-authentication.md b/i18n/en/docusaurus-plugin-content-docs/current/developers/s3/1-s3-authentication.md new file mode 100644 index 000000000..8d18d9834 --- /dev/null +++ b/i18n/en/docusaurus-plugin-content-docs/current/developers/s3/1-s3-authentication.md @@ -0,0 +1,27 @@ +--- +sidebar_position: 1 +--- + +# S3 Authentication + +Learn how to use S3 authentication to perform S3 operations on projects within your organization that you have permissions for. + +1. Go to the Project Overview - S3 connection page to obtain information such as Endpoint, Region, and Bucket. + + ![pro-s3_1](./img/pro-s3_1.png) + +2. Click on [My access key] to navigate to the Personal settings - Security page and manage your personal S3 access keys. + + ![pro-s3_2](./img/pro-s3_2.png) + +3. Click on [Create access key], enter a description, and create your S3 access key. + + ![pro-s3_3](./img/pro-s3_3.png) + +4. Copy the Access Key ID and Secret Access Key for subsequent S3 operations. For example, use the [AIStor Client(mc)](https://docs.min.io/enterprise/aistor-object-store/reference/cli/) tool for S3 authentication: + + ```bash + mc alias set coscene + ``` + +Note: **Your personal S3 access keys can perform operations on all projects within the organization that you have permissions for. These keys are for personal use only and should not be shared with others.** \ No newline at end of file diff --git a/i18n/en/docusaurus-plugin-content-docs/current/developers/s3/2-s3-operations.md b/i18n/en/docusaurus-plugin-content-docs/current/developers/s3/2-s3-operations.md new file mode 100644 index 000000000..5cfe14a58 --- /dev/null +++ b/i18n/en/docusaurus-plugin-content-docs/current/developers/s3/2-s3-operations.md @@ -0,0 +1,70 @@ +--- +sidebar_position: 2 +--- + +# S3 Operations + +In a project, you can perform operations such as uploading and downloading records and resources through S3. + +## Storage Paths + +1. **Records** + + The path of files in records within the corresponding S3 bucket is `records//files/`. + + For example, if the record ID is `123456` and the file name is `example.txt`, the file path would be `records/123456/files/example.txt`. + + ![s3-record](./img/s3-record.png) + +2. **Resources** + + The path of files in resources within the corresponding S3 bucket is `files/`. + + For example, if the file name in resources is `example.txt`, the file path would be `files/example.txt`. + + ![s3-resource](./img/s3-resource.png) + +## Operation Examples +Using the [AIStor Client(mc)](https://docs.min.io/enterprise/aistor-object-store/reference/cli/) tool as an example. Assume the project bucket is `coscene.01`, the record ID is `123456`, the file name is `example.txt`, and the S3 configuration alias is `coscene`. + +### List Files + +1. List files in a record + + ```bash + mc ls coscene/coscene.01/records/123456/files/ + ``` + +2. List files in resources + + ```bash + mc ls coscene/coscene.01/files/ + ``` + +### Upload Files + +1. Upload a file to a record: + + ```bash + mc put example.txt coscene/coscene.01/records/123456/files/ + ``` + +2. Upload a file to resources: + + ```bash + mc put example.txt coscene/coscene.01/files/ + ``` + +### Download Files + +1. Download a file from a record + + ```bash + mc get coscene/coscene.01/records/123456/files/example.txt . + ``` + +2. Download a file from resources + + ```bash + mc get coscene/coscene.01/files/example.txt . + ``` \ No newline at end of file diff --git a/i18n/en/docusaurus-plugin-content-docs/current/developers/s3/img/pro-s3_1.png b/i18n/en/docusaurus-plugin-content-docs/current/developers/s3/img/pro-s3_1.png new file mode 100644 index 000000000..014d0a87f Binary files /dev/null and b/i18n/en/docusaurus-plugin-content-docs/current/developers/s3/img/pro-s3_1.png differ diff --git a/i18n/en/docusaurus-plugin-content-docs/current/developers/s3/img/pro-s3_2.png b/i18n/en/docusaurus-plugin-content-docs/current/developers/s3/img/pro-s3_2.png new file mode 100644 index 000000000..6c08d9e01 Binary files /dev/null and b/i18n/en/docusaurus-plugin-content-docs/current/developers/s3/img/pro-s3_2.png differ diff --git a/i18n/en/docusaurus-plugin-content-docs/current/developers/s3/img/pro-s3_3.png b/i18n/en/docusaurus-plugin-content-docs/current/developers/s3/img/pro-s3_3.png new file mode 100644 index 000000000..57403afb9 Binary files /dev/null and b/i18n/en/docusaurus-plugin-content-docs/current/developers/s3/img/pro-s3_3.png differ diff --git a/i18n/en/docusaurus-plugin-content-docs/current/developers/s3/img/s3-record.png b/i18n/en/docusaurus-plugin-content-docs/current/developers/s3/img/s3-record.png new file mode 100644 index 000000000..fce85fc45 Binary files /dev/null and b/i18n/en/docusaurus-plugin-content-docs/current/developers/s3/img/s3-record.png differ diff --git a/i18n/en/docusaurus-plugin-content-docs/current/developers/s3/img/s3-resource.png b/i18n/en/docusaurus-plugin-content-docs/current/developers/s3/img/s3-resource.png new file mode 100644 index 000000000..6cb80a2ee Binary files /dev/null and b/i18n/en/docusaurus-plugin-content-docs/current/developers/s3/img/s3-resource.png differ diff --git a/i18n/en/docusaurus-plugin-content-docs/current/viz/1-about-viz.md b/i18n/en/docusaurus-plugin-content-docs/current/viz/1-about-viz.md index 2eadf5255..69ef4819f 100644 --- a/i18n/en/docusaurus-plugin-content-docs/current/viz/1-about-viz.md +++ b/i18n/en/docusaurus-plugin-content-docs/current/viz/1-about-viz.md @@ -8,7 +8,7 @@ The data visualization interface presents device data in an intuitive visual man ## How to Enter the Visualization Interface -In a Record, click **Play** or directly click the file to enter the visualization interface. +In a Record, click **Play** to enter the visualization interface. ![viz-1-1-Eng](./img/viz-1-1-Eng.png) @@ -99,9 +99,10 @@ The functions in this area include: 2. Display of the start time, end time, and duration of file playback 3. Current progress timestamp 4. **Pause** and **forward**/**backward** buttons -5. **Loop playback** button -6. **Playback speed** button -7. **Playback quality** button -8. **Absolute**/**Relative** time toggle button +5. **Playback Step**:Adjust the forward/backward duration when paused +6. **Loop playback** button +7. **Playback speed** button +8. **Moment**:A moment is represented by a blue rectangle on the timeline +9. **Playable Time Range**:The playable time range is represented by a light blue rectangle on the timeline --- diff --git a/i18n/en/docusaurus-plugin-content-docs/current/viz/4-panel/10-user-scripts.md b/i18n/en/docusaurus-plugin-content-docs/current/viz/4-panel/10-user-scripts.md new file mode 100644 index 000000000..f815ff0f7 --- /dev/null +++ b/i18n/en/docusaurus-plugin-content-docs/current/viz/4-panel/10-user-scripts.md @@ -0,0 +1,267 @@ +--- +sidebar_position: 10 +--- + +# User Scripts panel + +User scripts are custom in-app scripts (written in TypeScript) that transform messages. A user script can transform both playback and range-loaded. The result is output to a new topic. + +- Playback data – Messages streaming frame-by-frame into Foxglove; e.g. data for the [Raw Messages](./9-raw-messages.md) or [3D panel](./2-3d-panel.md) +- Range-loaded data – Messages for the entire data range being played back; e.g. data for the [Plot](./4-plot-panel.md) or State Transitions panels + +When transforming range-loaded data, Foxglove creates two instances of the running user script – one handles the full data range, while the other handles just the current playback frame of messages. Each instance of the user script receives the messages in log time order. + +> **Tip** +> +> User scripts are local to a layout. Use a [message converter](../8-extensions/1-introduction.md#message-converters) to transform messages in a way that will apply to all layouts. + +## Getting started +User Scripts are written in TypeScript. + +> **Info** +> +> TypeScript is a superset of JavaScript, so you can Google syntactic questions (e.g. how to manipulate arrays, or access object properties) using JavaScript terms, and semantic questions (e.g. how to make an object property optional) using TypeScript terms. + +### Writing your first script +Every script must declare 3 exports: + +- `inputs` – An array of input topics to transform +- `output` – Name of the transformed output topic +- `script` – A function that takes messages from input topics, transforms them, and then publishes messages on the output topic; must be the [default export](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/export#description) + +Here is a basic script that echoes its input on a new output topic, `/coscene_script/echo`: + +```typescript +import { Input, Message } from "./types"; + + +export const inputs = ["/rosout"]; +export const output = "/coscene_script/echo"; + + +export default function script(event: Input<"/rosout">): Message<"rosgraph_msgs/Log"> { + return event.message; +} +``` + +If you open a recording with a `/rosout` topic, you can now inspect the `/studio_script/echo` topic in the [Raw Messages panel](./9-raw-messages.md). + +When you create a new script, you’ll be presented with some boilerplate: + +```typescript +import { Input, Message } from "./types"; + +type Output = { hello: string }; + +export const inputs = ["/input/topic"]; +export const output = "/studio_script/output_topic"; + +export default function script(event: Input<"/input/topic">): Output { + return { hello: "world!" }; +} +``` + +You’ll notice a few things: + +- The `Input` and `Message` types are imported from the `./types` module, which provides helper types for your Input events and messages +- The `Output` type has some default properties that the `script` function's output must adhere to + +`Input` is a generic type, meaning that it takes a parameter in order to be used. It is left empty on purpose as you'll need to populate it with the name of your input topic, e.g. `Input<"/rosout">`. + +> **Note** +> +> The input event is read-only. Do not modify the event object. + +As for the `Output` type, you can either manually type out your output with the properties you care about (i.e. what is available in the boilerplate) or use one of the dynamically generated types from the `Message` type imported above. For instance, if you want to publish an array of markers, you can return the type `Message<"visualization_msgs/MarkerArray">`. + +It's not always obvious how message properties affect the visualized output – strictly typing your scripts helps you debug issues at compile time rather than at runtime. With that said, you can disable Typescript checks when working on a rough draft of your script by adding `// @ts-expect-error` on the line above the one you want to ignore. + +### Using multiple input topics +In some cases, you will want to define multiple input topics: + +```typescript +import { Input, Message } from "./types"; + +export const inputs = ["/rosout", "/tf"]; +export const output = "/coscene_script/echo"; + +export default function script(event: Input<"/rosout"> | Input<"/tf">): { data: number[] } { + if (event.topic === "/rosout") { + // read event.message fields expected for /rosout messages + } else { + // read event.message fields expected for /tf messages + } + + return { data: [] }; +} +``` + +This snippet uses union types to assert that the message in the `script` function can take either a `/rosout` or `/tf` topic. Use an if/else clause to differentiate between incoming topics' schema names when manipulating messages. + +To combine messages from multiple topics, create a variable in your script's global scope to reference every time your `script` function is invoked. Check timestamps to make sure you are not publishing out-of-sync data. + +```typescript +import { Input, Message, Time } from "./types"; + +export const inputs = ["/rosout", "/tf"]; +export const output = "/coscene_script/echo"; + +let lastReceiveTime: Time = { sec: 0, nsec: 0 }; +const myScope: { tf?: Message<"tf2_msgs/TFMessage">; rosout?: Message<"rosgraph_msgs/Log"> } = {}; + +export default function script( + event: Input<"/rosout"> | Input<"/tf">, +): { data: number[] } | undefined { + const { receiveTime } = message; + let inSync = true; + + if (receiveTime.sec !== lastReceiveTime.sec || receiveTime.nsec !== lastReceiveTime.nsec) { + lastReceiveTime = receiveTime; + inSync = false; + } + + if (message.topic === "/rosout") { + myScope.rosout = event.message; + } else { + myScope.tf = event.message; + } + + if (!inSync) { + return { data: [] }; + } +} +``` + +### Using global variables +The `script` function will receive all of the variables as an object every time it is called. Each time a new message is received, the `script` function will be re-run with the latest variable values: + +> **Note** +> +> Global variables are read-only on user-scripts. Do not modify the globalVars parameter. + +```typescript +import { Input, Message } from "./types"; + +type Output = {}; +type GlobalVariables = { someNumericaVar: number }; + +export const inputs = []; +export const output = "/coscene_script/"; + +export default function script(event: Input<"/foo_marker">, globalVars: GlobalVariables): Output { + if (event.message.id === globalVars.someNumericaVar) { + // Message's id matches $someNumericaVar + } + + return { data: [] }; +} +``` + +### Debugging +User scripts are not executed unless the output topic is being used somewhere within your layout. + +To debug your script, first add a Raw Messages panel subscribing to the output topic to your layout. From there, you can either inspect the incoming topic directly, or invoke `log(someValue)` throughout the user script to print values to the Logs section at the bottom of the panel. + +The only value you cannot `log()` is one that is, or contains, a function definition. You can also log multiple values at once, e.g. `log(someValue, anotherValue, yetAnotherValue)`. + +The following log statements will not produce any errors: + +```typescript +const addNums = (a: number, b: number): number => a + b; +log(50, "ABC", null, undefined, { abc: 2, def: false }); +log(1 + 2, addNums(1, 2)); +``` + +But these containing function definitions will: + +```typescript +log(() => {}); +log(addNums); +log({ subtractNums: (a: number, b: number): number => a - b }); +``` + +Invoking `log()` outside your `script` function will invoke it once, when your script is registered. Invoking `log()` inside your `script` function will log that value every time your `script` function is called. + +> **Tip** +> +> For topics publishing at a high rate, using `log()` can slow down the user script. +> +> Because a Plot panel will invoke the user script across all messages in the rendered time-range, `log()` output is not shown when plotting the output of a user script. In this case, use a Raw Messages panel to view the output message instead. + +### Skipping output +Do an early (or late) `return` in your function body when you don't want to publish. For example, let's say you only wanted to publish messages when a constant in the input is not 3: + +```typescript +import { Input } from "./types"; + +export const inputs = ["/state"]; +export const output = "/coscene_script/manual_metrics"; + +export default function script(event: Input<"/state">): { metrics: number } | undefined { + if (event.message.constant === 3) { + // Do not publish any message + return; + } + return { + // Your data here + }; +} +``` + +In Typescript, if you return without a value, it will implicitly return `undefined`. Note the union return type for the `script` function – we've indicated to Typescript that this function can return `undefined`. + +### Using @foxglove/schemas +Import and use types from the [@foxglove/schemas](https://github.com/foxglove/foxglove-sdk) package in user scripts: + +```typescript +import { Input } from "./types"; +import { Color } from "@foxglove/schemas"; + +export const inputs = ["/imu"]; +export const output = "/s_script/json_data"; + +export default function script(event: Input<"/imu">): Color { + return { + r: 1, + g: 1, + b: 1, + a: 1, + }; +} +``` + +## Utilities and templates +The sidebar's "Utilities" tab includes functions that can be imported for use in any script (e.g. `import { compare } from "./time.ts"`). The `types.ts` utility file is generated from the currently loaded data source, and contains type definitions for all found schemas. + +We currently do not allow importing 3rd-party packages, but let us know if there are packages that would be useful to you! + +The Templates tab includes boilerplate for writing common scripts, like one that publishes a `MarkerArray`. If you have any other use cases that would work well as a template, please let us know. + +## Settings + +| General | | +| --- | --- | +| Auto-format on save | Auto-format the code in your script on save | + +## Controls and shortcuts +Press `Cmd` + `s` to save script changes. + +## TypeScript Resources + +- [Basic Types](https://www.typescriptlang.org/docs/handbook/2/basic-types.html) +- [Gitbook](https://basarat.gitbook.io/typescript/getting-started/why-typescript) + +## When to use a user script or a topic converter extension +User scripts and [topic converter extensions](../8-extensions/1-introduction.md#message-converters) have similar capabilities, but there are key differences in how they are authored, shared, and how they support third-party packages. + +| | User scripts | Topic converters | +| --- | --- | --- | +| Data transformation | ✅ | ✅ | +| Create new topics | ✅ | ✅ | +| Edit directly | ✅ | ❌ | +| Scoped to a layout | ✅ | ❌ | +| Reusable across layouts | ❌ | ✅ | +| Shareable with your team | ❌ | ✅ | +| Written in your IDE | ❌ | ✅ | +| Part of your codebase | ❌ | ✅ | +| Use third-party packages | ❌ | ✅ | \ No newline at end of file diff --git a/i18n/en/docusaurus-plugin-content-docs/current/viz/4-panel/9-raw-messages.md b/i18n/en/docusaurus-plugin-content-docs/current/viz/4-panel/9-raw-messages.md new file mode 100644 index 000000000..998f3c510 --- /dev/null +++ b/i18n/en/docusaurus-plugin-content-docs/current/viz/4-panel/9-raw-messages.md @@ -0,0 +1,47 @@ +--- +sidebar_position: 9 +--- + +# Raw Messages + +Inspect a particular message path in your data source. + +As new messages are received for a given path, the collapsible tree will show just the latest message. You will be able to expand and collapse keys, and have those changes persist across playback. + +![raw-messages_1.png](../img/raw-messages_1.png) + +## Settings + +| Field | Description | +| --- | --- | +| Font Size | Font size for text display | + +## Shortcuts + +### Diff mode +Compare messages by showing additions (green), deletions (red), and changes (yellow) to their fields across 2 categories: + +- "previous message" – Compare consecutive messages for a given message path +- "custom" – Compare different topic messages for a given timestamp + +![raw-messages_2.png](../img/raw-messages_2.png) +![raw-messages_3.png](../img/raw-messages_3.png) + +### Expand all +Click the icon next to the message path to expand or collapse all nested fields in the displayed message. + +| Expand all | Collapse all | +| --- | --- | +| ![raw-messages_5.png](../img/raw-messages_5.png) | ![raw-messages_4.png](../img/raw-messages_4.png) | + +### Frame by frame +When there are many messages, you can view them one by one using this feature. + +By clicking the buttons or using the keyboard shortcuts `Up Arrow` and `Down Arrow`, you can navigate through the messages. + +![raw-messages_6.png](../img/raw-messages_6.png) + +### Copy message +Click "Copy msg" to copy the current topic message to your clipboard. + +![raw-messages_7.png](../img/raw-messages_7.png) \ No newline at end of file diff --git a/i18n/en/docusaurus-plugin-content-docs/current/viz/8-extensions/1-introduction.md b/i18n/en/docusaurus-plugin-content-docs/current/viz/8-extensions/1-introduction.md index e03aa003f..3b3623f30 100644 --- a/i18n/en/docusaurus-plugin-content-docs/current/viz/8-extensions/1-introduction.md +++ b/i18n/en/docusaurus-plugin-content-docs/current/viz/8-extensions/1-introduction.md @@ -21,7 +21,7 @@ Custom panels are ideal when your visualization or interaction requirements are - Guide: Creating Custom Panels - Building Custom Panel Extensions (React) -## Message Converters +## Message Converters {#message-converters} Message converter extensions allow you to transform messages from one schema to another. By converting messages to schemas supported by visualization, you can inspect them using visualization's built-in visualization features. For example, you can use a message converter to transform custom GPS messages into foxglove.LocationFix messages for visualization in the map panel. diff --git a/i18n/en/docusaurus-plugin-content-docs/current/viz/img/raw-messages_1.png b/i18n/en/docusaurus-plugin-content-docs/current/viz/img/raw-messages_1.png new file mode 100644 index 000000000..19690e176 Binary files /dev/null and b/i18n/en/docusaurus-plugin-content-docs/current/viz/img/raw-messages_1.png differ diff --git a/i18n/en/docusaurus-plugin-content-docs/current/viz/img/raw-messages_2.png b/i18n/en/docusaurus-plugin-content-docs/current/viz/img/raw-messages_2.png new file mode 100644 index 000000000..a15c14c59 Binary files /dev/null and b/i18n/en/docusaurus-plugin-content-docs/current/viz/img/raw-messages_2.png differ diff --git a/i18n/en/docusaurus-plugin-content-docs/current/viz/img/raw-messages_3.png b/i18n/en/docusaurus-plugin-content-docs/current/viz/img/raw-messages_3.png new file mode 100644 index 000000000..0f2ef6090 Binary files /dev/null and b/i18n/en/docusaurus-plugin-content-docs/current/viz/img/raw-messages_3.png differ diff --git a/i18n/en/docusaurus-plugin-content-docs/current/viz/img/raw-messages_4.png b/i18n/en/docusaurus-plugin-content-docs/current/viz/img/raw-messages_4.png new file mode 100644 index 000000000..3c051fac6 Binary files /dev/null and b/i18n/en/docusaurus-plugin-content-docs/current/viz/img/raw-messages_4.png differ diff --git a/i18n/en/docusaurus-plugin-content-docs/current/viz/img/raw-messages_5.png b/i18n/en/docusaurus-plugin-content-docs/current/viz/img/raw-messages_5.png new file mode 100644 index 000000000..503c5a0a7 Binary files /dev/null and b/i18n/en/docusaurus-plugin-content-docs/current/viz/img/raw-messages_5.png differ diff --git a/i18n/en/docusaurus-plugin-content-docs/current/viz/img/raw-messages_6.png b/i18n/en/docusaurus-plugin-content-docs/current/viz/img/raw-messages_6.png new file mode 100644 index 000000000..6ccfca769 Binary files /dev/null and b/i18n/en/docusaurus-plugin-content-docs/current/viz/img/raw-messages_6.png differ diff --git a/i18n/en/docusaurus-plugin-content-docs/current/viz/img/raw-messages_7.png b/i18n/en/docusaurus-plugin-content-docs/current/viz/img/raw-messages_7.png new file mode 100644 index 000000000..8bb4561a3 Binary files /dev/null and b/i18n/en/docusaurus-plugin-content-docs/current/viz/img/raw-messages_7.png differ diff --git a/i18n/en/docusaurus-plugin-content-docs/current/viz/img/viz-1-12-Eng.png b/i18n/en/docusaurus-plugin-content-docs/current/viz/img/viz-1-12-Eng.png index 6ffa3e863..e263ba10e 100644 Binary files a/i18n/en/docusaurus-plugin-content-docs/current/viz/img/viz-1-12-Eng.png and b/i18n/en/docusaurus-plugin-content-docs/current/viz/img/viz-1-12-Eng.png differ diff --git a/i18n/en/docusaurus-plugin-content-pages/changelog.md b/i18n/en/docusaurus-plugin-content-pages/changelog.md index 9f662a377..980d62e70 100644 --- a/i18n/en/docusaurus-plugin-content-pages/changelog.md +++ b/i18n/en/docusaurus-plugin-content-pages/changelog.md @@ -5,6 +5,28 @@ id: changelog # Release History +## [25.37.0] - 2025-9-12 + +### [Added] + +- Added message-by-message playback feature: + - Support viewing messages one by one in the raw message and table panels + - Support custom playback step size: On the right side of the visualization timeline, you can adjust the forward/backward duration when paused +- Added S3 storage functionality: Support connecting to projects within the organization via the S3 protocol to perform read/write operations. See [S3 Documentation](/docs/developers/s3/s3-authentication) +- Added device ID anomaly detection: Real-time detection of duplicate IDs and inconsistencies between device-side and web-side IDs +- Added file search functionality: Support keyword search when previewing text files +- Added Data Collection Client v1.1.10: + - Added IP reporting functionality: View device IP addresses on the device details page + - Fixed issue with delayed upload resumption on devices under weak network conditions + - Fixed issue where linked files could not be uploaded after changes in symbolic link mode + +### [Improved] + +- Improved device real-time operation entry permissions, closed organization-level real-time visualization and web SSH entry, only supporting real-time operation of devices within projects +- Improved visualization playback loading logic, supporting parallel loading of multi-tab data + +--- + ## [25.34.0] - 2025-8-20 ### 【Added】 diff --git a/src/components/homeCatalogue/catalogue.ts b/src/components/homeCatalogue/catalogue.ts index 42585dbbf..62d25bdcc 100644 --- a/src/components/homeCatalogue/catalogue.ts +++ b/src/components/homeCatalogue/catalogue.ts @@ -127,6 +127,7 @@ export const CATALOGUE = (locale: string) => [ { docLink: '/category/core-concepts', title: translate({ id: 'home.catalogue.core-concepts', message: '概念' }) }, { docLink: '/category/cocli', title: translate({ id: 'home.catalogue.cocli', message: '命令行工具 coCLI' }), }, { docLink: '/category/openapi', title: translate({ id: 'home.catalogue.openapi', message: '开放平台 OpenAPI' }) }, + { docLink: '/category/s3', title: translate({ id: 'home.catalogue.s3', message: 'S3 存储' }) }, ], }, { diff --git a/src/pages/changelog.md b/src/pages/changelog.md index be41f41e7..c75b624f8 100644 --- a/src/pages/changelog.md +++ b/src/pages/changelog.md @@ -5,6 +5,28 @@ id: changelog # 发布历史 +## [25.37.0] - 2025-9-12 + +### 【新增】 + +- 新增消息逐条播放功能: + - 在原始消息与表格面板中,支持逐条查看消息 + - 支持自定义播放步长:在可视化时间轴右侧,可调整暂停时的前进/后退时长 +- 新增 S3 存储功能:支持通过 S3 协议连接组织内的项目,执行读/写操作。详见[S3 文档](/docs/developers/s3/s3-authentication) +- 新增设备 ID 异常检测功能:实时检测重复 ID 及设备端与网页端 ID 不一致的问题 +- 新增文件搜索功能:文本文件预览时支持关键词搜索 +- 新增数采客户端 v1.1.10: + - 新增 IP 上报功能:在设备详情页,可查看设备 IP 地址 + - 修复设备在弱网情况下,恢复上传延时的问题 + - 修复软链接模式下,指向文件变更后无法上传的问题 + +### 【改进】 + +- 改进设备实时操作入口权限,关闭组织层级实时可视化与网页 SSH 入口,仅支持项目内设备实时操作 +- 改进可视化播放加载逻辑,支持多选项卡数据并行加载 + +--- + ## [25.34.0] - 2025-8-20 ### 【新增】