介绍 网络正在不断发展,Web3 技术正在彻底改变传统行业,包括视频流。Odysee 等平台引领潮流,为 YouTube 和 Rumble 提供 中心化的替代方案。同样,与 Google Drive 和 Dropbox 等传统提供商不同, 正在改变数据存储,提供注重隐私和以用户为中心的方法。 去 Sia 。本教程系列将指导您创建一个利用 Sia 的区块链技术来确保用户数据所有权和隐私的去中心化应用程序。 加入我们,使用 NextJs、TypeScript、Tailwind CSS 和 Sia Renterd 构建尖端的 Web3 电影流媒体 dApp 在本教程结束时,您将获得以下专业知识: 构建功能齐全的电影流媒体平台,与朋友分享或用作学校项目 启动您自己的 SaaS(软件即服务)应用程序 释放 Web3 技术在视频流行业的潜力 来了解项目的实际运行,并 以获取更多类似的创新内容! 观看下面的演示视频 订阅我们的频道 https://www.youtube.com/watch?v=Hgfdesry8Ss&embedable=true 先决条件 为了继续进行,请确保您已安装以下工具,并且熟悉堆栈也将增强您的理解: Node.js 库 NextJs Tailwind CSS TypeScript Docker (必需) 本系列由三部分组成,涵盖: - Renterd Zen 测试网、包安装和环境变量。 第 1 部分:项目设置 - 构建后端服务 第 2 部分:后端开发 - 将前端与后端服务集成。 第 3 部分:前端开发 如果您更喜欢观看整个开发过程, ,在播放列表中,这里写的所有内容以及更多内容都包含在视频中。 我建议您观看这个播放列表 话虽如此,让我们开始建立这个项目。 项目设置 - 第 1 部分 我们首先克隆一个包含 Sia Renterd docker compose 脚本以及后端和前端服务的准备好的存储库。运行以下命令: $ git clone https://github.com/Daltonic/sia_vid_tv $ cd sia_vid_tv 现在,我们必须切换到这个新克隆的 GitHub 项目的启动分支并运行以下命令来完成该操作。 $ git checkout 01_starter_branch 接下来,让我们为这个 Renterd 服务设置相关的环境变量。在此项目的根目录下创建一个 文件并应用以下键: .env RENTERD_SEED=<RENTERD_SEED_PHRASE> RENTERD_API_PASSWORD=<YOUR_PREFERED_PASSWORD> RENTERD_LOG_LEVEL=debug RENTERD_LOG_DATABASE_LEVEL=error 要获取这些 API 密钥,您需要在您的机器上安装 Sia Renterd;请观看下面的简短视频,它几乎总结了所有内容。 https://www.youtube.com/watch?v=78XCHGWZwhA&embedable=true 使用 Renterd 应用程序生成种子短语,如上视频所示,并按照上视频中的说明将其包含在环境变量中。将密码替换为您容易记住的内容。 接下来,如果您还没有安装 Docker,我们需要 来安装。或者,如果可能的话,使用免费的在线平台(如 或 VPS 来运行 Docker 实例。否则,请将其安装在本地计算机上。 从官方网站下载它 Gitpod) 最后,我们可以通过在该项目的根目录下运行以下 docker 命令来启动 docker 容器。确保终端与此 文件位于同一目录位置。 docker-compose.yml $ docker compose -f "docker-compose.yml" up -d --build 请注意拉下容器的命令: 。当您想要关闭 Docker 实例时运行此命令(但不是现在)。 $ docker compose -f "docker-compose.yml" down 如果您正确执行了上述说明,当您在浏览器上访问 时,您应该会看到下面的界面。 http://localhost:9880 输入您的密码(来自您的环境变量)登录。然后,按照下面视频中的配置步骤设置您的 Sia Renterd 实例以进行文件上传、下载和流式传输。 https://www.youtube.com/watch?v=ZJ8YWdVTWUA&t=401s&embedable=true 上述视频从 分钟开始,请在 处停止,此部分将直观地指导您完成 Renterd 配置过程。 6:41 20:01 请注意,区块链同步过程以及主机匹配最多需要 才能准备好,因此您必须耐心等待整个过程。 25 min 请在 Renterd 上创建一个名为 的新存储桶,我们将在此存储此项目的所有文件。如果您已成功执行上述说明,您的 Renterd 节点应已准备好进行上传和下载。参见下图。 vidtv 太棒了。此时,我们的 Renterd 服务已准备好开始接收文件,但我们需要通过编程与其进行通信。 让我们通过为后端和前端设置包和环境变量来完成本教程的第一部分。 执行以下说明以安装后端服务包并准备进一步开发。 后端项目设置 使用以下命令从新的终端实例导航到后端目录: $ cd backend $ yarn install #you can also use npm install $ touch .env #or mannually create it at the root of the backend directory 接下来,将以下信息提供给环境变量。 SIA_API_BUCKET=vidtv SIA_API_PASSWORD=<YOUR_PREFERED_PASSWORD> SIA_API_BASE_URL=http://localhost:9880 ORIGIN=http://localhost:9000 PORT=9000 现在,运行 来启动后端并确认它没有任何错误。 $ yarn build && yarn start 最后,运行以下命令来安装与前端相关的包。之后,我们将运行它。 前端项目设置 使用以下命令从新的终端实例导航到后端目录: $ cd frontend $ yarn install #you can also use npm install $ touch .env #or mannually create it at the root of the backend directory 接下来,将以下信息提供给环境变量。 NEXT_PUBLIC_PROJECT_ID=<YOUR_WALLET_CONNECT_ID> NEXT_PUBLIC_FILE_SERVICE_URL=http://localhost:9000 使用 注册并创建项目以获取您的项目 ID。将项目 ID 提供给环境变量后,运行 以启动后端并确认它没有任何错误。 Walletconnect $ yarn build && yarn start 此时,当你在浏览器访问 时,你将看到下面的界面。 http://localhost:3000 恭喜您达到这一里程碑! 以完成后端服务开发。 下一步 继续第 2 部分 后端服务 - 第 2 部分 如果您还没有读过第 1 部分,请通读一下。现在,让我们深入了解第 2 部分:为我们的 web3 电影流媒体平台构建后端服务。 欢迎回来! 我们提供了后端的起始代码,当您启动服务器并在浏览器中访问 它会显示“欢迎”消息。让我们在此基础上进行构建。 http://localhost:9000 目前我们在后端的源码目录中有这些代码。我先简单给大家解释一下。 该文件夹可以完全寻址到 其中包含两个基本文件:一个 HTTP 异常处理函数和一个用于处理文件上传信息的接口。 实用程序文件 backend/src/utils 此代码定义了一个自定义的 类,该类扩展了内置的 JavaScript 类,允许创建具有特定 HTTP 状态代码和消息的错误实例。 HttpException Error https://gist.github.com/Daltonic/bb37e1d4c5f84bc9c10fcbb8c3e19621 此代码定义了一个代表上传文件的接口 ,指定其属性,如名称、数据、大小、编码等,提供了一种结构化的方式来处理此后端应用程序中的文件上传。 FileUpload https://gist.github.com/Daltonic/64fb31bf3b19668a17d14f59e087a77e 然后在 根文件夹中,我们有这个 文件,它设置了一个具有 CORS 和文件上传支持的 Express.js 服务器,定义了一个返回“欢迎”消息的单个 GET 路由,并通过捕获并重新抛出错误来处理错误作为自定义 HttpExceptions,然后按照环境变量中指定的端口 9000 上启动服务器。 backend/src index.ts https://gist.github.com/Daltonic/8d76c3a212681d7bfe89b0792b0e707f 现在我们已经介绍了关键文件,让我们在 文件夹中创建两个新文件,每个文件在我们的应用程序中都有不同的用途。 services 服务文件 在 文件夹中,在此位置创建一个名为 新文件夹,我们将在此处创建两个服务: backend/src services :处理文件上传、下载、流式传输和缓存,并与 Renterd 服务通信。 Sia 服务 :管理缓存文件,7 天后每天午夜自动删除它们。 后台服务 Sia 服务 让我们在 文件夹创建一个名为 的文件,并按照以下步骤制定该服务。 backend/src/services sia.service.ts https://gist.github.com/Daltonic/a82a0c1cf8d3e7b31702b66eeead3718?embedable=true 此代码定义了一个 类,该类使用 Sia API 设置的环境变量和源 URL 进行初始化,为管理与 Sia 服务的交互提供了基础。现在,让我们提供此服务的其余代码。 SiaService 要将文件上传到 Sia 网络,我们需要将这三种方法添加到类中,其中两种是私有的,一种是公共的。 将文件上传到 Sia Renterd https://gist.github.com/Daltonic/ddf74dffc5ac1005585f7ae3ad55c286?embedable=true 此代码定义了一个私有方法 ,该方法使用循环从预定义字符串中随机选择字符,生成指定长度的随机字符串,由大写字母、小写字母和数字组成。在将文件发送到Renterd之前,我们将使用它来唯一地重命名每个文件。 generateRandomString https://gist.github.com/Daltonic/e6a82ac4af9eca9c881f4e0bdd1d682b?embedable=true 上述代码定义了一个私有方法 ,该方法使用 Axios 上传文件到 Sia Renterd,处理上传进度和错误,并在上传失败时返回 Axios 响应或抛出错误。 uploadToSiaService Renterd 端点写在 API 文档中,您可以查看或观看下面的视频,我在其中解释了 Sia Renterd API 文档。 https://www.youtube.com/watch?v=zOmUMz0DBQM&embedable=true 现在让我们包含公共方法,稍后我们将在我们的应用程序中将其作为端点公开。 https://gist.github.com/Daltonic/ce565350160a39c4d9f0abc0b7e7dc26?embedable=true 这段代码定义了一个公共方法 ,通过生成唯一标识来上传文件,将文件保存到本地缓存,然后上传到Sia Renterd,返回文件的URL和成功信息,如果上传失败则抛出错误。 uploadFile 要将文件下载到 Sia 网络,我们需要将这两种方法添加到类中,一种是私有的,另一种是公共的。 将文件下载到 Sia Renterd https://gist.github.com/Daltonic/b401e92d510ffddc8a0b7301d526f702?embedable=true 这段代码定义了一个私有方法 ,从 Sia 服务中获取一个文件,在本地缓存,并返回该文件的可读流,如果找不到该文件则处理错误并返回 404 图像。 downloadFromSiaService 让我们在后端目录中使用这些 response_files,否则我们将在调用 文件时遇到错误。在 目录中创建另一个名为 文件夹,并将以下图像复制到其中。 404.png backend response_files 完美,现在我们来完成这个文件下载服务。同样在 类中添加下面的方法。 SiaService https://gist.github.com/Daltonic/1f1a99c82d5b15693eaa2d8d2482f6c2?embedable=true 这段代码定义了一个公共方法 ,它调用私有方法 从 Sia Renterd 中检索文件并返回检索到的文件的可读流。 downloadFile downloadFromSiaService 服务端点 现在是时候将这些不同的方法与它们各自的端点结合起来了,目前我们只有一个端点,但我们需要另外两个用于上传和下载文件。文件流也将利用下载端点。 前往 文件并使用这些代码更新其内容。 backend/src/index.ts https://gist.github.com/Daltonic/c8dec40acbc47b2582c651e04fae432f?embedable=true 此代码设置了一个具有 CORS 和文件上传支持的 Express.js 服务器,定义了三个端点:欢迎消息、将文件上传到 Sia 网络和从 Sia 网络下载文件,使用 SiaService 类处理文件操作和 HttpException 进行错误处理。 如果您需要一些视觉帮助,请观看下面这部分视频,确保您在 时间戳处停止。 01:50:44 https://www.youtube.com/watch?v=ZJ8YWdVTWUA&t=3795&si=A6fF8n8Pd92i6weM&embedable=true 我们需要创建一个缓存管理服务,通过控制文件在缓存中停留的时间,确保我们的服务器不会被未使用的文件填满。重要的是要知道,我们需要这项服务的唯一原因是减少 。 数据延迟 后台服务 前往 文件夹并创建一个名为 的文件并将这些代码序列添加到其中。 backend/src/services background.service.ts https://gist.github.com/Daltonic/bc62ccefd72cec85772dedd311afbffd?embedable=true 此代码定义了一个 类,该类设置缓存目录并使用 库安排每日作业,初始化后台作业并记录确认消息。让我们创建一个方法,负责删除缓存中超过 7 天的文件。 BackgroundService node-cron 将此方法添加到 类。 删除旧文件 BackgroundService https://gist.github.com/Daltonic/43da392512b88b6abf068be62d14eb7e?embedable=true 此代码定义了一个名为 的方法,该方法通过读取目录、检查每个文件的创建时间、删除超过目标时间的文件、记录作业的开始和结束以及任何错误或成功删除,从缓存目录中删除超过 7 天的文件。 deleteOldFiles 现在,让我们编写一个函数,利用 node-cron 包来安排何时执行文件删除。 https://gist.github.com/Daltonic/18b60b0bc1f7414a306f01f9087db435?embedable=true 此代码设置了一个每日 cron 作业,每天午夜 (00:00) 运行 方法以执行自动文件清理。 deleteOldFiles 我们还需要更新构造函数,以便在后台服务类实例化时安排日常作业。 https://gist.github.com/Daltonic/5f608cd3793ff6deea56c262bdfbc395?embedable=true 完美,最后,让我们在初始化时将此后台操作添加为服务器进程的一部分。转到 文件,并更新应用程序侦听器方法以导入后台服务文件。 backend/src/index.ts https://gist.github.com/Daltonic/7966a7b27fa7eade2c6d1a7e60b2e530?embedable=true 您应该使用 重新运行后端服务命令,并查看如下图所示的终端打印输出。 $ yarn build && yarn start 如果您想观看我如何编写整个后台服务,下面的视频适合您;只需确保您在 时间戳处停止即可。 02:16:07 https://www.youtube.com/watch?v=ZJ8YWdVTWUA&t=8167&si=4DZ27j0lqwufUgRf&embedable=true 恭喜您,您现在已经准备好学习本教程的最后一部分,即 。 下一步 第 3 部分 让我们深入了解本教程系列的最后一部分,我们将集成后端与前端,连接各个部分以完成文件上传应用程序。我们首先要确保前端的身份验证已启动并正在运行。 Web3 模态身份验证 – 第 3 部分 在 Frontend 目录下新建一个 config 文件夹,并添加一个 index 文件,路径为 ,我们来在其中添加如下代码。 /frontend/config/index.tsx https://gist.github.com/Daltonic/38bbe9fa325fb793dd59136ebdea8b43?embedable=true 此代码为我们的 Web3 应用程序设置 Wagmi 配置,定义元数据、支持的链和身份验证设置(包括钱包和社交登录选项),并将其存储在 导出中。我们还需要创建一个上下文 API 来跟踪身份验证状态。 config 接下来,仍在 Frontend 目录中创建一个名为“context”的新文件夹,并添加一个索引文件,路径为 。在其中添加以下代码。 Context API /frontend/context/index.tsx https://gist.github.com/Daltonic/db7330a9159ff83727cda0a384fd907e?embedable=true 此代码使用 Wagmi 和 React Query 设置 Web3Modal 提供程序,使用项目 ID 和主题变量配置 Web3 模型,并将应用程序包装在 WagmiProvider 和 QueryClientProvider 中。 :让我们更新应用程序布局以包含上述配置。前往 并将其代码替换为下面的代码。 更新布局 /frontend/app/layout.tsx https://gist.github.com/Daltonic/2b54f191d56fa02f0ae3974bd8ffd11b?embedable=true 上述代码设置了 Next.js 应用程序的根布局,包括元数据、字体、样式和 Web3 模式的提供程序、Toast 通知以及页眉和页脚等布局组件。 现在,我们需要在 和 组件中启用登录按钮,并使用以下信息更新其代码。 登录按钮 /frontend/app/components/layout/Header.tsx /frontend/app/components/shared/Menu.tsx https://gist.github.com/Daltonic/f9f60e85c18da94a5bbc97d1acb3d423?embedable=true 此代码为导航栏定义了一个 React 组件,其中包含徽标、导航链接、自定义菜单和登录按钮,该按钮可启动具有响应式设计的 Web3 Modal,适用于不同的屏幕尺寸。 当您单击登录按钮并继续使用您首选的提供商 X、Facebook、Google、Discord 或 Ethereum 时,以下图像应该会弹出,证明我们所做的工作有效。 太棒了,让我们更深入地设置我们的数据库和基于 NextJs API 的系统。如果您对这个过程有任何疑惑,请观看下面的视频部分;只要确保您在 处停止即可。 02:57:59 https://www.youtube.com/watch?v=ZJ8YWdVTWUA&t=9305&si=OadhxKlut7o3iLl5&embedable=true 数据库脚本 首先,让我们更新 NextJs 配置脚本以正确处理我们的页面和端点,并使我们的远程图像免受警告和审查。 https://gist.github.com/Daltonic/a4ecb4d168f8bb01cb8abb600653c4cf?embedable=true 此代码定义了一个 Next.js 配置对象,用于设置 API 路由重写和图像优化,允许来自任何 HTTPS 主机名的远程图像和来自 localhost 域的本地图像。 我们将使用 SQLite 来开发此应用程序,但您也可以自由使用更强大的解决方案,例如 MYSQL 或 NOSQL 提供程序。为了简单起见,我们使用 SQLite 平面文件。 数据库配置脚本 创建 文件路径并向其中添加以下代码。 /frontend/app/api/database.ts https://gist.github.com/Daltonic/b699c52587b28c2d9435827837019633?embedable=true 此代码设置了 SQLite 数据库连接,定义了两个 API 函数 和 ,用于对数据库执行 GET 和 POST 请求,并具有错误处理和基于承诺的异步执行。每当我们想要从数据库发送或检索数据时,我们都会使用这些代码。 apiGet apiPost 我们需要创建一个数据库平面文件和一个表来保存所有内容。创建 文件路径并将以下代码添加到其中。 数据库迁移脚本 /frontend/app/api/migrations.ts https://gist.github.com/Daltonic/4c213153fe53334fcf8444666587d6a5?embedable=true 此代码定义了一个数据库迁移函数,如果不存在,则使用 SQLite 创建具有指定列的“movies”表,并记录操作结果。现在在指向 目录的终端中运行以下命令。 /frontend $ cd frontend $ npx esrun app/api/migrations.ts 需要注意的是,此过程还将在前端目录的根目录中创建一个名为 的数据库平面文件。我们还将此命令添加到了 package.json 脚本中,因此在前端目录上运行 应该会产生相同的效果。 movies.db $ yarn migrate 为了获得视觉帮助,请观看下面的视频,只需在 标记处停止即可。 03:10:54 https://www.youtube.com/watch?v=ZJ8YWdVTWUA&t=10679&si=-uhv8Zw0T3Gx0XgQ&embedable=true 应用程序端点 现在,让我们定义一些用于创建、读取、更新和删除电影的端点。我们将使用 NextJs API 提供来创建这些端点。 创建电影所需的信息包括用户ID,电影名称,图片,视频URL,发布日期,类型,评分,语言,时长和背景描述。创建 文件路径,并将以下代码添加到其中。 创建电影端点 /frontend/app/api/movies/create/route.ts https://gist.github.com/Daltonic/bf8a431ec00aa71491ae71781fb99278?embedable=true 此代码定义了一个端点来处理 POST 请求、验证和处理电影数据、生成唯一的 slug,并使用 apiPost 函数将数据插入数据库,同时处理错误并返回 JSON 响应。 要更新电影,所需的信息包括用户 ID、slug 以及创建电影时提供的其他信息。创建 文件路径并将以下代码添加到其中。 更新电影端点 /frontend/app/api/movies/update/route.ts https://gist.github.com/Daltonic/2ed7d44cb8efe091675ebc0fc1bdf27c?embedable=true 此代码定义了一个端点来处理更新电影的 POST 请求、验证所需的属性以及执行 SQL 查询以使用 apiPost 函数更新数据库中的电影数据。 要删除电影,所需信息包括电影的用户 ID 和 slug。创建 文件路径并在其中添加以下代码。 删除电影端点 /frontend/app/api/movies/delete/route.ts https://gist.github.com/Daltonic/aa7ab36b982ad1f377b2a4d26930dd8d?embedable=true 此代码定义了一个端点来处理删除电影的 POST 请求、验证所需的属性(userId 和 slug)以及执行 SQL 查询以使用 apiPost 函数从数据库中删除电影。 获取电影所需的可选数据是pageSize和userId,可以将其作为查询参数传递以过滤和分页结果。创建 文件路径并将以下代码添加到其中。 所有电影端点 /frontend/app/api/movies/all/route.ts https://gist.github.com/Daltonic/23bb2aa55446995dad87084bb7968c3e?embedable=true 上述代码定义了一个端点来处理检索电影的 GET 请求,允许按 userId 进行可选过滤和按 pageSize 进行分页,并以 JSON 格式返回结果。 要检索单个电影,所需的数据是电影的 slug。创建 文件路径并将以下代码添加到其中。 单个电影端点 /frontend/app/api/movies/[slug]/route.ts https://gist.github.com/Daltonic/64e069e9bafd026a83796eaa95334ac8?embedable=true 此代码定义了一个端点来处理 GET 请求,以通过其 slug 检索电影、验证 slug 参数以及执行 SQL 查询以使用 apiGet 函数从数据库中检索电影数据。 这标记了此应用程序所需的所有端点。如果您需要视觉辅助来帮助您更好地理解这些端点,请观看下面的视频,只需确保您在 时间戳处停止即可。 03:48:22 https://www.youtube.com/watch?v=ZJ8YWdVTWUA&t=10679&si=3Ynq9tNLx5SZXHBE&embedable=true 端点集成 我们的任务是审查和更新预编码的组件和页面,解释每个组件和页面的用途和功能,并记录我们对现有代码所做的更改。我们将首先创建一个服务,用于与我们之前在 目录中创建的端点进行交互。 api 创建 文件路径并向其中添加以下代码。 /frontend/app/services/api.service.ts https://gist.github.com/Daltonic/fdf65c7ffaf3ea8219c617cdb7c96375?embedable=true 该服务提供了一组与电影数据库交互的功能,允许应用程序获取电影、通过 slug 获取单个电影、创建新电影、更新现有电影、删除电影以及使用 API 请求上传文件并处理错误。 应用程序页面 让我们查看并更新与我们的应用程序相关的各个页面。您不需要更改很多内容,只需更改此处突出显示的内容即可。 创建电影页面 该页面是一个电影发布表单,允许用户上传视频和图像文件,输入电影详细信息,并提交表单以发布电影,并使用 React 和 Wagmi 库进行验证和错误处理。 现在,使用以下代码更新 中的文件。 /frontend/app/pages/create/page.tsx https://gist.github.com/Daltonic/0ec440d6dfc2b46e07ecec3e81f532c6?embedable=true 此代码与原始代码相比所做的更改如下: 从 导入 函数,并在 函数中使用它来创建新电影。 api.service createMovie handleSubmit 在 函数调用中添加了 参数,从 钩子传递用户的地址。 createMovie userId useAccount 更新了 函数以使用 来处理 返回的承诺。 handleSubmit toast.promise createMovie 在 函数中为 函数调用添加了错误处理。 handleSubmit createMovie 这些更改使表单能够将电影数据提交给 API 并创建新的电影条目,同时处理错误并显示成功消息。 编辑电影页面 该电影编辑页面允许授权用户更新电影详细信息,上传海报和视频并保存更改,并通过验证和错误处理进行,使用专为用户编辑电影设计的 React、Wagmi 和 Next.js。 现在,使用以下代码更新 中的文件。 /frontend/app/pages/movies/edit/[slug]/page.tsx https://gist.github.com/Daltonic/63ddb6e3c65e3bcd2665ab0e3ffb6205?embedable=true 与原版不同的代码升级包括: 从 导入 和 函数,并分别在 hook 和 函数中使用它们。 @/app/services/api.service fetchMovie updateMovie useEffect handleSubmit 用 函数替换 方法来检索电影数据。 fetchMovie posters.find() 更新了 函数以使用更新的电影详细信息调用 函数。 handleSubmit updateMovie 在 函数中为 函数调用添加了错误处理。 handleSubmit updateMovie 这些变化使我们的应用程序能够与我们的 API 端点交互以检索和更新电影数据,而原始代码依赖于我们的本地 数组。 posters 主页 该主页利用 React 和 Next.js 呈现横幅组件、电影列表(来自 API 源或加载 UI)和订阅选项,为用户提供引人入胜且信息丰富的登录页面。 使用以下代码更新 中的文件。 /frontend/app/pages/page.tsx https://gist.github.com/Daltonic/97cb49662ed70be9b183b4f601b529d6?embedable=true 我们对主页所做的更改是: 从 导入 函数并在 钩子中使用它从我们的 API 中检索电影数据。 ./services/api.service fetchMovies useEffect 用从我们的 API 获取数据的 函数调用替换了本地 数据。 fetchMovies posters 添加了 关键字,以等待 返回的承诺得到解决,然后再设置 状态。 await fetchMovies movies 这些变化帮助我们的应用程序从我们的 API 中检索电影数据,而不是依赖本地数据,从而使应用程序更加动态和数据驱动。 用户帐户页面 该页面显示当前连接的用户发布的电影列表,并在获取数据时显示一个加载骨架占位符,如果用户尚未连接他们的帐户,则显示一条消息提示用户连接他们的帐户,使用 Wagmi 和 react-loading-skeleton。 使用以下代码更新 中的文件。 /frontend/app/pages/account/page.tsx https://gist.github.com/Daltonic/ba714bfa557f10aebacfa8b5ac3d7111?embedable=true 对页面所做的更改如下: 从 导入 函数并在 钩子中使用它从我们的 API 中检索电影数据。 @/app/services/api.service fetchMovies useEffect 用 函数调用替换了本地 数据,该函数调用从我们的 API 中获取数据。 fetchMovies posters 将 作为参数传递给 函数来检索特定于用户的电影数据。 address fetchMovies 在呈现电影列表之前删除了对 的条件检查,因为 函数现在可以处理这个逻辑。 address fetchMovies 简化了显示加载骨架的条件语句,因为它现在只取决于 状态。 loaded 这些更改从我们的 API 中检索特定于连接的用户的电影数据,并在获取数据时显示加载骨架。 电影详情页面 该页面显示单部电影的详细信息,包括其名称、上映年份、评级、时长、类型和背景信息,以及视频播放器和相关电影,并提供使用 Next.js 和 Wagmi 编辑或删除电影的选项(如果用户是所有者)。 使用以下代码更新 中的文件。 /frontend/app/pages/movies/[slug]/page.tsx https://gist.github.com/Daltonic/5e37c94db3d73005a481ffd0cd141140?embedable=true 我们在这里做了一些重大改变!以下是我们所做工作的总结: 从 导入 、 和 函数并使用它们与我们的 API 端点进行交互。 @/app/services/api.service deleteMovie fetchMovie fetchMovies 使用 API 调用替换本地数据来检索电影数据。 使用 函数实现电影删除功能。 deleteMovie 使用 在删除电影时显示通知。 toast.promise 删除了 本地数据并用 API 调用替换。 posters 更新了 函数以调用 函数并处理响应。 handleSubmit deleteMovie 更新了 钩子以调用 和 函数。 useEffect fetchMovie fetchMovies 这些变化导致我们的应用程序与我们的 API 交互以检索和删除电影数据并在删除过程中向用户显示通知。 以下视频的这一部分将向您展示我们如何将这些页面与端点集成,如果您遇到任何问题,请随时观看该部分。只需确保您在 时间戳处停止即可。 04:57:41 https://www.youtube.com/watch?v=ZJ8YWdVTWUA&t=14070&si=XCKxX3HvX3RjtNHY&embedable=true 应用程序组件 让我们讨论一下应用程序中每个组件的用途。我们将更新任何需要修改的组件。 横幅组件 此组件显示电影横幅的旋转背景图像,每 5 秒循环显示一组电影图像,从而创建简单且自动的幻灯片效果。此组件代码可在 处访问。 /frontend/app/components/home/Banner.tsx 海报组件 该组件使用 Swiper 库显示响应式、可交互的电影海报轮播,具有自动播放、分页和导航等功能,展示作为 prop 传递的电影列表,并具有可适应不同屏幕尺寸的动态布局。此组件代码可在 中查看。 /frontend/app/components/home/Posters.tsx 海报 UI 组件 此组件使用 react-loading-skeleton 库显示电影海报部分的占位符骨架布局,根据“posters”属性显示动态数量的骨架海报,采用自适应不同屏幕尺寸的响应式设计,指示加载状态,直到实际海报数据被提取和显示。此组件代码可在 中查看。 /frontend/app/components/home/PosterUI.tsx 订阅组件 此组件显示订阅计划部分,展示各种虚拟计划及其详细信息、价格和优惠。它允许用户选择适合自己需求的计划,利用响应式网格布局和交互式悬停效果来增强用户体验。此组件代码可在 中查看。 /frontend/app/components/home/Subscription.tsx 标题组件 此组件在页面顶部呈现一个固定导航栏,其中包含徽标、带有指向各个部分链接的导航菜单、用于响应式设计的菜单切换按钮和登录按钮,从而在整个应用程序中提供一致且可访问的标题部分。此组件代码可在 中查看。 /frontend/app/components/layout/Header.tsx 页脚组件 该组件在页面底部呈现页脚部分,其中包含应用程序的徽标、简要说明、导航链接、联系信息以及提及由 Sia Foundation 提供支持的去中心化存储解决方案的信用,提供清晰有序的页脚部分以及相关信息和链接。 可以在 中评估此组件代码。 /frontend/app/components/layout/Footer.tsx 菜单组件 此组件呈现一个响应式菜单切换按钮,单击该按钮时,会打开或关闭包含导航链接的下拉菜单,让用户可以在较小的屏幕上访问应用程序的各个部分,同时在导航链接已经可见的大屏幕上隐藏菜单。此组件代码可在 中查看。 /frontend/app/components/shared/Menu.tsx 电影卡片组件 此组件显示单部电影的海报,并带有悬停效果,显示其他信息,例如电影名称、上映年份和背景摘要,同时还可作为电影详情页面的链接,利用响应式设计和动画过渡来增强用户体验。此组件代码可在 处查看。 /frontend/app/components/shared/MovieCard.tsx 已上传组件 此组件显示已上传文件(图片或视频)的预览,并带有进度条和删除按钮,方便用户查看和删除已上传文件,同时还提供具有动画和悬停效果的美观且可交互的界面。此组件代码可在 中查看。 /frontend/app/components/shared/Uploaded.tsx 上传器组件 该组件提供了一个用于上传文件(特别是视频或海报)的用户界面,具有拖放、文件类型验证、大小限制、上传进度跟踪和成功/错误通知等功能,利用 React 状态管理、事件处理和 API 集成的组合来处理上传过程。 使用以下代码更新 中的文件。 /frontend/app/components/shared/uploader.tsx https://gist.github.com/Daltonic/2aee8838dedcd6f14ef0f25103106a3a?embedable=true 对此组件所做的更改如下: :原始代码未实现实际的上传文件功能。它仅显示成功提示,而不上传文件。此更新的代码包含来自 的 函数,用于处理文件上传。 上传文件功能 api.service uploadFile :更新后的代码会跟踪上传进度并将其显示在 UI 上。 进度跟踪 :更新后的代码包括文件上传过程的错误处理。 错误处理 :更新后的代码使用正则表达式进行更强大的文件类型验证。 文件类型验证 :更新后的代码组织得更好,具有用于处理不同任务的单独函数,使其更易于阅读和维护。 代码组织 :更新后的代码包括一些 UI 更新,例如显示上传进度和上传期间的取消按钮。 UI 更新 此更新的代码更加完整和强大,具有实际的文件上传功能、进度跟踪、错误处理和更好的代码组织。 下面的视频更详细地解释了每个组件的作用,请查看以获得更好的理解。 https://www.youtube.com/watch?v=ZJ8YWdVTWUA&t=17861&si=LNxLwBkKeE7kH3Xt&embedable=true 就这样,我们已经完成了这个项目,我们需要采取的最后一步是在浏览器上启动这个项目。运行 即可在浏览器上实时查看该项目。 $ yarn build && yarn start 如果您遇到任何问题,请参考以下资源进行故障排除。下次再见,祝一切顺利! 🏠 Sia 网站 🔥 Sia Renterd 👨💻 Sia Renterd API 🚀 Sia Discord 频道 💡 YouTube 视频播放列表 关于作者 我是一名 web3 开发人员,也是 的创始人,该公司致力于帮助企业和个人构建和发布去中心化应用程序。我在软件行业拥有超过 8 年的经验,并且热衷于使用区块链技术创建新的创新应用程序。我运营着一个 ,在那里我分享有关 web3 开发的教程和技巧,并定期在线发布有关区块链领域最新趋势的文章。 Dapp Mentors 名为 Dapp Mentors 的 YouTube 频道