插件模态组件导入错误 - 遵循官方文档但仍出现错误

问题摘要

我正在开发一个 Discourse 插件,该插件会在编辑器中添加一个工具栏按钮,用于打开一个模态框表单。我已按照官方 DModal API 迁移文档一步一步操作,但仍然收到模块导入错误和“modal needs updating”的警告。我需要一些指导,告诉我缺少了什么。

快速说明: 我不懂编程,这个插件完全是 AI 帮助生成的。

当前错误

错误 1 - 模块导入:

Uncaught (in promise) Error: Could not find module `discourse/components/modal/lottery-form-modal` imported from `discourse/plugins/discourse-lottery-v3/discourse/initializers/lottery-toolbar`

错误 2 - 旧版模态框警告:

Error: the 'lottery-form' modal needs updating to work with the latest version of Discourse. See https://meta.discourse.org/t/268057.

错误 3 - 弃用通知:

Deprecation notice: Defining modals using a controller is no longer supported. Use the component-based API instead. (modal: lottery-form) [deprecated since Discourse 3.1] [removal in Discourse 3.2]

我已遵循的官方文档

我已仔细研究并根据以下官方资源进行实施:

  1. 将模态框从旧版控制器转换为新的 DModal 组件 API

    • URL:https://meta.discourse.org/t/268057
    • 遵循了所有 4 个步骤:将文件移至 /components/modal/,将 JS 更新为扩展 Component,将模板更新为使用 <DModal>,将 show 调用更新为使用 modal.show()
  2. 使用 DModal API 渲染模态框窗口

    • URL:https://meta.discourse.org/t/268304
    • 使用 @closeModal@title 和命名块实现了 DModal
  3. Discourse 核心插件 API

    • 来源:https://github.com/discourse/discourse/blob/main/app/assets/javascripts/discourse/app/lib/plugin-api.gjs
    • 使用了 api.onToolbarCreate() 和模态框服务注入
  4. Discourse 开发者文档 - 转换模态框

    • URL:https://github.com/discourse/discourse-developer-docs/blob/main/docs/03-code-internals/10-converting-modals.md
    • 交叉引用了迁移步骤

我想做什么

  • 在编辑器中添加一个工具栏按钮
  • 点击按钮打开一个模态框表单
  • 用户填写表单并点击提交
  • 模态框关闭并将内容插入编辑器

我已尝试过的方法

方法 1:动态导入 + 模态框服务(当前)

  • 出现模块导入错误

方法 2:showModal() 与控制器

  • 出现关于旧版控制器的弃用警告

方法 3:静态导入

  • 也尝试过静态导入,但遇到相同的模块解析问题

文件结构:

discourse-lottery-v3/
├── plugin.rb
└── assets/javascripts/discourse/
    ├── initializers/
    │   └── lottery-toolbar.js
    └── components/modal/
        ├── lottery-form-modal.js
        └── lottery-form-modal.hbs

工具栏按钮代码:

// assets/javascripts/discourse/initializers/lottery-toolbar.js
import { withPluginApi } from "discourse/lib/plugin-api";

export default {
  name: "lottery-toolbar",
  initialize() {
    withPluginApi("1.0.0", (api) => {
      api.onToolbarCreate((toolbar) => {
        toolbar.addButton({
          id: "lottery-insert",
          group: "extras",
          icon: "dice",
          title: "Insert Lottery",
          perform: () => {
            const modal = api.container.lookup("service:modal");

            // This line causes the import error:
            import("discourse/components/modal/lottery-form-modal").then((module) => {
              const LotteryFormModal = module.default;
              modal.show(LotteryFormModal, { model: {} });
            });
          }
        });
      });
    });
  }
};

模态框组件:

// assets/javascripts/discourse/components/modal/lottery-form-modal.js
import Component from "@ember/component";
import { tracked } from "@glimmer/tracking";
import { action } from "@ember/object";

export default class LotteryFormModal extends Component {
  @tracked inputValue = "";

  @action
  submit() {
    // Handle form submission
    this.args.closeModal();
  }
}

模态框模板:

{{! assets/javascripts/discourse/components/modal/lottery-form-modal.hbs }}
<DModal @title="My Modal" @closeModal={{this.args.closeModal}} class="my-modal">
  <:body>
    <input value={{this.inputValue}} />
  </:body>
  <:footer>
    <button {{on "click" this.submit}}>Submit</button>
  </:footer>
</DModal>

问题

根据以上提供的所有代码、错误和背景信息,我应该如何修改我的代码以正确实现我的功能?

非常感谢任何关于正确实现方法的指导。

请尝试从 ../components/modal/lottery-form-modal 导入。\n\n当您的导入以 discourse 开头时,它会在 Discourse 代码库中查找文件和目录,而不是您自己的项目。\n\n例如,您的这行代码:\n[quote="joo, post:1, topic:380016"]\n\nimport { withPluginApi } from \"discourse/lib/plugin-api\";\n\n[/quote]\n\n会从 Discourse 代码库中的 app/assets/javascripts/discourse/app/lib/plugin-api.gjs 导入。\n\n例如,您可以参考 @abroun_beholderGitHub - Beholder-Vision/discourse-insert-model-3d: A Discourse theme component for adding 3D models to topics 来了解如何操作。

谢谢!关于导入路径的解释正是我所需要的。模态框现在运行得很完美。非常感谢您的帮助!

2 个赞

没问题,很高兴能帮到您!

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.