live_svelte

live_svelte

Phoenix LiveView 与 Svelte 的端到端响应式集成方案

LiveSvelte 是一个将 Svelte 组件集成到 Phoenix LiveView 的工具,实现了端到端的响应式体验。它支持服务器端渲染、Svelte 预处理、Tailwind 和 Dead View 等功能,简化了客户端状态管理和服务器实时通信。LiveSvelte 适用于复杂本地状态管理、JavaScript 生态系统集成、Svelte 动画和作用域 CSS 等场景,有助于提高开发效率和应用性能。

LiveSveltePhoenix LiveViewSvelte服务器端渲染端到端反应性Github开源项目
<div align="center">

LiveSvelte

GitHub Hex.pm

在Phoenix LiveView中使用Svelte,实现无缝端到端响应式

logo

功能特性资源演示安装使用部署

</div>

功能特性

  • ⚡ 与LiveView实现端到端响应式
  • 🔋 服务器端渲染(SSR)Svelte
  • 🪄 Sigil作为替代LiveView DSL
  • ⭐ 支持使用svelte-preprocess进行Svelte预处理
  • 🦄 支持Tailwind
  • 💀 支持Dead View
  • 🤏 支持live_json
  • 🦥 插槽互操作性(实验性)

资源

演示

完整介绍和演示请查看YouTube介绍视频

/examples/advanced_chat

https://user-images.githubusercontent.com/3637265/229902870-29166253-3d18-4b24-bbca-83c4b6648578.webm

<br /> Svelte处理聊天的外观和感觉,而LiveView负责同步。对Svelte组件的端到端响应式意味着我们不需要真正获取任何东西!输入名字的"登录"是一个简单的LiveView表单。混合使用!

/examples/breaking_news

https://user-images.githubusercontent.com/3637265/229902860-f7ada6b4-4a20-4105-9ee9-79c0cbad8d72.webm

<br /> 新闻项目与服务器同步,而速度仅在客户端控制。

为什么选择LiveSvelte

Phoenix LiveView通过服务器渲染的HTML实现丰富的实时用户体验。它通过websocket通信任何状态变化并实时更新DOM。无需编写任何客户端代码就能获得非常好的用户体验。

LiveSvelte在Phoenix LiveView的基础上,允许轻松管理客户端状态,同时仍然允许通过websocket进行通信。

使用LiveSvelte的理由

  • 你有(复杂的)本地状态
  • 你想充分利用JavaScript的生态系统
  • 你想利用Svelte的动画
  • 你想要作用域CSS
  • 你喜欢Svelte及其开发体验 :)

要求

为了使服务器端渲染(SSR)正常工作,你需要在环境中安装node(19版或更高版本)。

确保你在生产环境中也安装了它。你可能在构建步骤中使用node,但实际上它可能没有安装在你的生产环境中。

你可以通过在项目目录中运行node --version来确保安装了node

如果你不想使用SSR,可以通过不在application.ex中设置NodeJS.Supervisor来禁用它。更多相关内容请参阅本文档的SSR部分。

安装

如果你正在从旧版本更新,请确保查看CHANGELOG.md以了解破坏性变更。

  1. mix.exs中将live_svelte添加到Phoenix应用的依赖列表中:
defp deps do [ {:live_svelte, "~> 0.13.3"} ] end
  1. 调整mix.exs中的setupassets.deploy别名:
  • Windows系统
defp aliases do [ setup: ["deps.get", "ecto.setup", "cmd --cd assets npm install"], ..., "assets.deploy": ["tailwind <app_name> --minify", "cmd --cd assets node build.js --deploy", "phx.digest"] ] end
  • Linux/MacOS系统
defp aliases do [ setup: ["deps.get", "ecto.setup", "npm install --prefix assets"], ..., "assets.deploy": ["tailwind <app_name> --minify", "node build.js --deploy --prefix assets", "phx.digest"] ] end

注意:只有在使用Tailwind时,assets.deploy别名中才需要tailwind <app_name> --minify。如果你不使用Tailwind,可以从列表中移除它。

  1. 在终端中运行以下命令
mix deps.get mix live_svelte.setup
  1. /lib/<app_name>_web.ex文件的html_helpers/0中添加import LiveSvelte,如下所示:
# /lib/<app_name>_web.ex defp html_helpers do quote do # ... import LiveSvelte # <-- 添加此行 # ... end end
  1. 对于Tailwind支持,在tailwind.config.js文件中将"./svelte/**/*.svelte"添加到content
... content: [ ... "./svelte/**/*.svelte" ], ...
  1. 最后,从config/config.exs中移除esbuild配置,并从mix.exsdeps函数中移除依赖,这样就完成了!

我们做了什么?

Phoenix的esbuild默认配置(通过Elixir包装器)不允许你使用esbuild插件。标准的Elixir esbuild包对于使用Phoenix钩子的简单项目来说效果很好,但要使用LiveSvelte,我们需要一个更复杂的设置。

为了使用插件,Phoenix建议用构建脚本替换默认的构建系统。因此,在设置中,我们从使用标准的esbuild包转向直接使用esbuild作为node_module

因此,你会注意到一些相关的变化:

  • /assets 中创建了一些文件。
  • /lib 中有一些代码更改。
  • 我们不再使用标准的 Elixir esbuild 观察器,而是创建了一个执行相同功能的新观察器。

设置过程注释掉了一些代码行,比如 dev.exs 中的配置。如果您愿意,可以安全地删除被注释掉的代码。

使用方法

Svelte 组件需要放在 assets/svelte 目录中

属性:

  • name:指定 Svelte 组件
  • props(可选):提供您想要使用的应该是响应式的 props,作为 props 字段的映射
  • class(可选):提供 class 来设置 Svelte 根元素的 class 属性
  • ssr(可选):将 ssr 设置为 false 以禁用服务器端渲染

例如,如果您的组件名为 assets/svelte/Example.svelte

def render(assigns) do ~H""" <.svelte name="Example" props={%{number: @number}} socket={@socket} /> """ end

如果您的组件在一个目录中,例如 assets/svelte/some-directory/SomeComponent.svelte,您需要在名称中包含目录:some-directory/SomeComponent

Components 宏

还有一个 Elixir 宏,它会检查您的 assets/svelte 文件夹中的任何 Svelte 组件,并将这些组件的本地函数 def 注入到调用模块中。

这允许在 Liveviews 中使用更类似 JSX 的编写体验。

例如,在下面的示例中,一个名为 Example 的 Svelte 组件可以在 Liveview 模板中调用:

use LiveSvelte.Components def render(assigns) do ~H""" <.Example number={@number} socket={@socket} /> """ end

示例

示例可以在 /examples/example_project 目录中找到。

大多数 /example_project 示例在 YouTube 演示视频 中可见。

我建议克隆 live_svelte 并通过运行以下命令来运行 /example_project 中的示例项目:

git clone https://github.com/woutdp/live_svelte.git
mix assets.build
cd ./live_svelte/example_project
npm install --prefix assets
mix deps.get
mix phx.server

服务器应该在 localhost:4000 上运行

如果您有想要添加的示例,欢迎创建 PR,我很乐意添加它们。

创建 Svelte 组件

<script> // number prop 是响应式的, // 这意味着如果服务器分配了 number,它将在前端更新 export let number = 1 // live 包含所有可供前端使用的导出 LiveView 方法 export let live function increase() { // 这会通过 websocket 推送事件 // 最后一个参数是可选的。它是事件完成时的回调。 // 例如,如果事件需要较长时间,您可以设置一个加载状态,直到事件完成。 live.pushEvent("set_number", {number: number + 1}, () => {}) // 注意,我们实际上从未在前端设置 number! // 我们只是将事件推送到服务器。 // 这就是端到端响应性的作用! // number 将通过 LiveView websocket 自动更新 } function decrease() { live.pushEvent("set_number", {number: number - 1}, () => {}) } </script> <p>数字是 {number}</p> <button on:click={increase}>+</button> <button on:click={decrease}>-</button>

注意:这里我们使用 pushEvent 函数,但如果您愿意,也可以使用 phx-clickphx-value-number

live 上可用的方法有:

  • pushEvent
  • pushEventTo
  • handleEvent
  • removeHandleEvent
  • upload
  • uploadTo

这些需要在客户端运行,不能在 SSR 中运行。确保它们在某个动作(例如点击按钮)上被调用,或者用 onMount 包装它们。

更多信息请参阅 LiveView 文档中关于 js-interop 的部分

创建 LiveView

# `/lib/app_web/live/live_svelte.ex` defmodule AppWeb.SvelteLive do use AppWeb, :live_view def render(assigns) do ~H""" <.svelte name="Example" props={%{number: @number}} socket={@socket} /> """ end def handle_event("set_number", %{"number" => number}, socket) do {:noreply, assign(socket, :number, number)} end def mount(_params, _session, socket) do {:ok, assign(socket, :number, 5)} end end
# `/lib/app_web/router.ex` import Phoenix.LiveView.Router scope "/", AppWeb do ... live "/svelte", SvelteLive ... end

LiveSvelte 作为替代 LiveView DSL

相关的博客文章

我们可以更进一步,使用 LiveSvelte 作为标准 LiveView DSL 的替代品。这个想法受到 Surface UI 的启发。

看看下面的例子:

defmodule ExampleWeb.LiveSigil do use ExampleWeb, :live_view def render(assigns) do ~V""" <script> export let number = 5 let other = 1 $: combined = other + number </script> <p>这是 number:{number}</p> <p>这是 other:{other}</p> <p>这是 other + number:{combined}</p> <button phx-click="increment">增加</button> <button on:click={() => other += 1}>增加</button> """ end def mount(_params, _session, socket) do {:ok, assign(socket, :number, 1)} end def handle_event("increment", _value, socket) do {:noreply, assign(socket, :number, socket.assigns.number + 1)} end end

使用 ~V 符号而不是 ~H,您的 LiveView 将使用 Svelte 而不是 HEEx 模板。

安装

  1. 如果在 html_helpers/0 中尚未导入,请在项目的 live_view 函数中添加 import LiveSvelte,这可以在 /lib/<app_name>_web.ex 中找到:
def live_view do quote do use Phoenix.LiveView, layout: {ExampleWeb.Layouts, :app} import LiveSvelte ```elixir unquote(html_helpers()) end end
  1. 在你的 .gitignore 中忽略构建文件。sigil 会创建 Svelte 文件,这些文件会被 esbuild 拾取,这些文件不需要包含在你的 git 仓库中:
# 忽略由 ~V sigil 自动生成的 Svelte 文件 /assets/svelte/_build/

Neovim Treesitter 配置

要在 Neovim 中启用 Treesitter 的语法高亮,创建以下文件:

~/.config/nvim/after/queries/elixir/injections.scm

; extends

; Svelte
(sigil
  (sigil_name) @_sigil_name
  (quoted_content) @svelte
(#eq? @_sigil_name "V"))

同时确保在 Treesitter 中安装了 Svelte 和 Elixir。

选项

可以通过在 mount 中设置 svelte_opts 来传递选项,请查看以下示例:

def mount(_params, _session, socket) do {:ok, assign(socket, some_value: 1, svelte_opts: %{ssr: false, class: "example-class"})} end

LiveView 实时导航事件

在 Svelte 中你可以定义实时导航链接。这些链接可以在不刷新页面的情况下从一个 LiveView 导航到另一个。

例如,当你有一个 Svelte store 并且想在导航过程中保持这个 store 状态时,这会很有用。Svelte store 使用的示例可以在 /examples/store 中找到。

push_navigate

<a href="/your-liveview-path" data-phx-link="redirect" data-phx-link-state="push">重定向</a>

push_patch

<a href="/your-liveview-path" data-phx-link="patch" data-phx-link-state="push">补丁</a>

LiveView JavaScript 互操作性

LiveView 允许很多互操作性,你可以在这里阅读更多相关内容: https://hexdocs.pm/phoenix_live_view/js-interop.html

预处理器

要使用预处理器,请安装所需的预处理器。

例如 Typescript

cd assets && npm install --save-dev typescript

SSR (服务器端渲染)

如果你不熟悉 SSR (服务器端渲染),它是 Svelte 的一个功能,用于在服务器上渲染 Svelte。这意味着在首次页面加载时,你会看到 HTML 而不是空白页面。紧接着首次页面加载之后,页面会被"水合",这是一个花哨的词,表示为你的组件添加交互性。这个过程在后台进行,你不会注意到这个步骤的发生。

LiveSvelte 通过 LiveView 更新自身的方式是让 Svelte 处理所有的 HTML 编辑。通常 LiveView 会通过 websocket 传递消息来编辑 HTML。在我们的情况下,我们只通过 websocket 将我们在 props 属性中提供的数据传递给 Svelte。LiveView 不会触及任何 HTML,Svelte 负责处理这些。

如前所述,没有 SSR 你会看到未渲染内容的短暂闪烁。有时你可以不在服务器上渲染 Svelte,例如当你的 Svelte 组件在首次页面加载时不做任何渲染,需要用户手动切换可见性时。或者当它是一个没有视觉组件的组件,比如跟踪你的鼠标光标并将其发送回服务器。

在这些情况下,你可以关闭 SSR。

禁用 SSR

当你安装 LiveSvelte 时,SSR 默认是启用的。如果你不想使用 Svelte 的服务器端渲染,你有两个选择:

全局

如果你不想在任何组件上使用 SSR,你可以全局禁用它。 如果你没有在 application.ex 文件中包含 NodeJS 监督者,这将自动成为默认情况。

组件

要在特定组件上禁用 SSR,将 ssr 属性设置为 false。像这样:

<.svelte name="Example" ssr={false} />

live_json

LiveSvelte 支持 live_json

默认情况下,LiveSvelte 通过 LiveView 将整个 json 对象发送到网络上。如果你的 json 对象很大并且经常变化,这可能会很昂贵。

另一方面,live_json 允许你只向 Svelte 发送 json 的差异。随着你的 json 对象越来越大,这非常有用。

与直觉相反,你并不总是想使用 live_json。有时重新发送整个对象更便宜。虽然差异很小,但它们确实会给你的 json 添加一些数据。所以如果你的 json 相对较小,我建议不要使用 live_json,但这是需要根据你的用例进行实验的。

用法

  1. 安装 live_json

  2. 在你的项目中使用 live_json 和 LiveSvelte。例如:

def render(assigns) do ~H""" <.svelte name="Component" live_json_props={%{my_prop: @ljmy_prop}} socket={@socket} /> """ end def mount(_, _, socket) do # 以某种方式获取 `my_big_json_object` {:ok, LiveJson.initialize("my_prop", my_big_json_object)} end def handle_info(%Broadcast{event: "update", payload: my_big_json_object}, socket) do {:noreply, LiveJson.push_patch(socket, "my_prop", my_big_json_object)} end

示例

你可以在这里找到一个示例。

结构体和 Ecto

我们使用 Jason 来序列化你在 props 中传递的任何数据,以便 Javascript 可以处理。 默认情况下 Jason 不知道如何处理结构体,所以你需要自己定义它。

结构体

例如,如果你有一个像这样的常规结构体:

defmodule User do defstruct name: "John", age: 27, address: "Main St" end

你必须定义 @derive

defmodule User do @derive Jason.Encoder defstruct name: "John", age: 27, address: "Main St" end

但要小心,因为你可能会不小心泄露某些你不希望客户端访问的字段,你可以包含要序列化的字段:

defmodule User do @derive {Jason.Encoder, only: [:name, :age]} defstruct name: "John", age: 27, address: "Main St" end

Ecto

在 ecto 的情况下,重要的是也要省略 __meta__ 字段,因为它不可序列化。

请查看以下示例:

defmodule Example.Planets.Planet do use Ecto.Schema import Ecto.Changeset @derive {Jason.Encoder, except: [:__meta__]} ```elixir schema "planets" do field :diameter, :integer field :mass, :integer field :name, :string timestamps() end ... end

文档

更多相关文档:

注意事项

插槽互操作性

插槽互操作性仍处于试验阶段,请谨慎使用!

Svelte 没有官方的方法在挂载 Svelte 对象时设置插槽或在后续更改时更新它,这与属性不同。这使得在 Liveview 中对 Svelte 组件使用插槽变得脆弱。

服务器端渲染的初始 Svelte 渲染确实支持插槽,所以应该能按预期工作。

插槽最终可能会达到稳定状态,任何帮助都将不胜感激。如果你对 Svelte 的内部原理了解很多,你的帮助可能在这里是无价的!

欢迎报告任何相关的错误,特别欢迎提交 PR!

"秘密状态"

使用 LiveView 很容易保密。假设你有一个只在某些条件为 true 时才渲染的条件语句,在 LiveView 中,在显示之前无法知道该条件语句会显示什么,因为 HTML 是通过网络发送的。

对于 LiveSvelte,我们处理的是发送到 Svelte 的 JSON,Svelte 接收 JSON 数据并有条件地渲染内容。即使我们没有将条件设置为 true,Svelte 代码也会包含在条件变为 true 时显示的内容。

在很多情况下这不是问题,但可能会出现问题,你应该注意这一点。

LiveSvelte 开发

本地设置

示例项目

你可以使用 /example_project 来本地测试 live_svelte

自定义项目

你也可以使用自己的项目。

live_svelte 克隆到要测试的项目的父目录中。

mix.exs 中:

{:live_svelte, path: "../live_svelte"},

assets/package.json 中:

"live_svelte": "file:../../live_svelte",

构建静态文件

/assets/js 中进行更改,然后运行:

mix assets.build

或运行监视器:

mix assets.build --watch

发布

  • 确保你已构建最新的资源
  • 更新 README.md 中的版本
  • 更新 package.json 中的版本
  • 更新 mix.exs 中的版本
  • 更新更新日志

运行:

mix hex.publish
  • 为最新版本发布一个标签

部署

部署 LiveSvelte 应用与部署常规 Phoenix 应用相同,只是你需要确保在生产环境中安装了 nodejs(19 版或更高版本)。

以下指南展示了如何将 LiveSvelte 应用部署到 Fly.io,但也可以采取类似的步骤部署到其他托管提供商。 你可以在这里找到有关如何部署 Phoenix 应用的更多信息。

在 Fly.io 上部署

以下步骤用于部署到 Fly.io。本指南假设你将使用 Fly Postgres 作为数据库。有关如何部署到 Fly.io 的更多指导可以在这里找到。

  1. 生成 Dockerfile:
mix phx.gen.release --docker
  1. 修改生成的 Dockerfile 以安装 curl(用于安装 nodejs 19 版或更高版本),并添加一个步骤来安装我们的 npm 依赖:
# ./Dockerfile ... # 安装构建依赖 - RUN apt-get update -y && apt-get install -y build-essential git \ + RUN apt-get update -y && apt-get install -y build-essential git curl \ && apt-get clean && rm -f /var/lib/apt/lists/*_* + # 为构建阶段安装 nodejs + RUN curl -fsSL https://deb.nodesource.com/setup_19.x | bash - && apt-get install -y nodejs ... COPY assets assets + # 在 assets 目录中安装所有 npm 包 + WORKDIR /app/assets + RUN npm install + # 切回构建目录 + WORKDIR /app ... # 开始一个新的构建阶段,以便最终镜像只包含 # 编译后的发布版本和其他运行时必需品 FROM ${RUNNER_IMAGE} RUN apt-get update -y && \ - apt-get install -y libstdc++6 openssl libncurses5 locales ca-certificates \ + apt-get install -y libstdc++6 openssl libncurses5 locales ca-certificates curl \ && apt-get clean && rm -f /var/lib/apt/lists/*_* + # 为生产环境安装 nodejs + RUN curl -fsSL https://deb.nodesource.com/setup_19.x | bash - && apt-get install -y nodejs ...

注意: nodejs 同时安装在构建阶段和最终镜像中。这是因为我们需要 nodejs 来安装 npm 依赖,同时在运行应用时也需要它。

  1. 使用 Fly.io CLI 启动你的应用:
fly launch
  1. 当提示调整设置时,选择 y:
? Do you want to tweak these settings before proceeding? (y/N) y

这将打开一个新窗口,你可以在其中调整启动设置。在数据库部分,选择 Fly Postgres 并为数据库输入一个名称。你可能还想将数据库更改为开发配置以避免额外费用。除非你想更改其他设置,否则可以保留其余设置不变。

确认后部署将继续。

  1. 部署完成后,运行以下命令查看已部署的应用!
fly apps open

致谢

Vue 替代方案

更喜欢 Vue? 有 LiveVue,它的功能与 LiveSvelte 完全相同,但使用 Vue。

LiveSvelte 项目

在公开项目中使用 LiveSvelte? 告诉我,我会将其添加到此列表中!

编辑推荐精选

Trae

Trae

字节跳动发布的AI编程神器IDE

Trae是一种自适应的集成开发环境(IDE),通过自动化和多元协作改变开发流程。利用Trae,团队能够更快速、精确地编写和部署代码,从而提高编程效率和项目交付速度。Trae具备上下文感知和代码自动完成功能,是提升开发效率的理想工具。

AI工具TraeAI IDE协作生产力转型热门
问小白

问小白

全能AI智能助手,随时解答生活与工作的多样问题

问小白,由元石科技研发的AI智能助手,快速准确地解答各种生活和工作问题,包括但不限于搜索、规划和社交互动,帮助用户在日常生活中提高效率,轻松管理个人事务。

热门AI助手AI对话AI工具聊天机器人
Transly

Transly

实时语音翻译/同声传译工具

Transly是一个多场景的AI大语言模型驱动的同声传译、专业翻译助手,它拥有超精准的音频识别翻译能力,几乎零延迟的使用体验和支持多国语言可以让你带它走遍全球,无论你是留学生、商务人士、韩剧美剧爱好者,还是出国游玩、多国会议、跨国追星等等,都可以满足你所有需要同传的场景需求,线上线下通用,扫除语言障碍,让全世界的语言交流不再有国界。

讯飞智文

讯飞智文

一键生成PPT和Word,让学习生活更轻松

讯飞智文是一个利用 AI 技术的项目,能够帮助用户生成 PPT 以及各类文档。无论是商业领域的市场分析报告、年度目标制定,还是学生群体的职业生涯规划、实习避坑指南,亦或是活动策划、旅游攻略等内容,它都能提供支持,帮助用户精准表达,轻松呈现各种信息。

AI办公办公工具AI工具讯飞智文AI在线生成PPTAI撰写助手多语种文档生成AI自动配图热门
讯飞星火

讯飞星火

深度推理能力全新升级,全面对标OpenAI o1

科大讯飞的星火大模型,支持语言理解、知识问答和文本创作等多功能,适用于多种文件和业务场景,提升办公和日常生活的效率。讯飞星火是一个提供丰富智能服务的平台,涵盖科技资讯、图像创作、写作辅助、编程解答、科研文献解读等功能,能为不同需求的用户提供便捷高效的帮助,助力用户轻松获取信息、解决问题,满足多样化使用场景。

热门AI开发模型训练AI工具讯飞星火大模型智能问答内容创作多语种支持智慧生活
Spark-TTS

Spark-TTS

一种基于大语言模型的高效单流解耦语音令牌文本到语音合成模型

Spark-TTS 是一个基于 PyTorch 的开源文本到语音合成项目,由多个知名机构联合参与。该项目提供了高效的 LLM(大语言模型)驱动的语音合成方案,支持语音克隆和语音创建功能,可通过命令行界面(CLI)和 Web UI 两种方式使用。用户可以根据需求调整语音的性别、音高、速度等参数,生成高质量的语音。该项目适用于多种场景,如有声读物制作、智能语音助手开发等。

咔片PPT

咔片PPT

AI助力,做PPT更简单!

咔片是一款轻量化在线演示设计工具,借助 AI 技术,实现从内容生成到智能设计的一站式 PPT 制作服务。支持多种文档格式导入生成 PPT,提供海量模板、智能美化、素材替换等功能,适用于销售、教师、学生等各类人群,能高效制作出高品质 PPT,满足不同场景演示需求。

讯飞绘文

讯飞绘文

选题、配图、成文,一站式创作,让内容运营更高效

讯飞绘文,一个AI集成平台,支持写作、选题、配图、排版和发布。高效生成适用于各类媒体的定制内容,加速品牌传播,提升内容营销效果。

热门AI辅助写作AI工具讯飞绘文内容运营AI创作个性化文章多平台分发AI助手
材料星

材料星

专业的AI公文写作平台,公文写作神器

AI 材料星,专业的 AI 公文写作辅助平台,为体制内工作人员提供高效的公文写作解决方案。拥有海量公文文库、9 大核心 AI 功能,支持 30 + 文稿类型生成,助力快速完成领导讲话、工作总结、述职报告等材料,提升办公效率,是体制打工人的得力写作神器。

openai-agents-python

openai-agents-python

OpenAI Agents SDK,助力开发者便捷使用 OpenAI 相关功能。

openai-agents-python 是 OpenAI 推出的一款强大 Python SDK,它为开发者提供了与 OpenAI 模型交互的高效工具,支持工具调用、结果处理、追踪等功能,涵盖多种应用场景,如研究助手、财务研究等,能显著提升开发效率,让开发者更轻松地利用 OpenAI 的技术优势。

下拉加载更多