vue 接入dify ai智能体(可拖动悬浮球吸壁,点击球体出现菜单,移动球体菜单跟随)

 首先需要打开dify

点击嵌入网站

地址可以看图中框起来的位置,但是注意,网站没有给端口号,需要自己补充

代码可直接复制封装成组件(记得改地址!!

<template>
  <div>
    <!-- 悬浮球 -->
    <div
      class="chat-bubble"
      ref="floatingBall"
      :style="{ left: ballLeft + 'px', top: ballTop + 'px' }"
      @mousedown="handleMouseDown"
    >
      <img
        src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='white'%3E%3Cpath d='M20 2H4c-1.1 0-2 .9-2 2v18l4-4h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2z'/%3E%3C/svg%3E"
        alt="ai助手"
      />
    </div>
    <!-- 菜单 -->
    <div
      class="menu"
      id="chatContainer"
      v-if="isMenuVisible"
      :style="{ left: menuLeft + 'px', top: menuTop + 'px' }"
    >
    
    <!--  Dify ai智能体地址-图中红线框起来的地方 -->
      <iframe
        src="http://你自己的地址/chatbot/R1HNviMUst0xjdBz"
        class="chat-iframe"
      ></iframe>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      ballLeft: window.innerWidth - 80, // 初始位置
      ballTop: window.innerHeight - 120,
      isDragging: false,
      startX: 0,
      startY: 0,
      offsetX: 0,
      offsetY: 0,
      isMenuVisible: false,
      menuLeft: 0,
      menuTop: 0,
      clickThreshold: 5, // 点击判断阈值
      menuWidth: 350,
      menuHeight: 500,
      minEdgeDistance: 10, // 距离边缘最小距离
    };
  },
  methods: {
    handleMouseDown(event) {
      event.preventDefault();
      this.isDragging = false;
      this.startX = event.clientX;
      this.startY = event.clientY;
      this.offsetX = this.ballLeft;
      this.offsetY = this.ballTop;
      document.addEventListener("mousemove", this.handleMouseMove);
      document.addEventListener("mouseup", this.handleMouseUp);
      // 拖动时移除过渡效果
      this.$refs.floatingBall.style.transition = "none";
    },
    handleMouseMove(event) {
      if (this.isDragging) {
        const dx = event.clientX - this.startX;
        const dy = event.clientY - this.startY;
        this.ballLeft = this.offsetX + dx;
        this.ballTop = this.offsetY + dy;
        // 边界处理,考虑最小边缘距离
        this.ballLeft = Math.max(
          this.minEdgeDistance,
          Math.min(this.ballLeft, window.innerWidth - 60 - this.minEdgeDistance)
        );
        this.ballTop = Math.max(
          this.minEdgeDistance,
          Math.min(this.ballTop, window.innerHeight - 60 - this.minEdgeDistance)
        );

        // 更新菜单位置
        if (this.isMenuVisible) {
          this.updateMenuPosition();
        }
      } else {
        const dx = Math.abs(event.clientX - this.startX);
        const dy = Math.abs(event.clientY - this.startY);
        if (dx > this.clickThreshold || dy > this.clickThreshold) {
          this.isDragging = true;
        }
      }
    },
    handleMouseUp() {
      document.removeEventListener("mousemove", this.handleMouseMove);
      document.removeEventListener("mouseup", this.handleMouseUp);
      if (!this.isDragging) {
        this.toggleMenu();
      }
      // 吸壁效果,考虑最小边缘距离
      const targetLeft =
        this.ballLeft < window.innerWidth / 2
          ? this.minEdgeDistance
          : window.innerWidth - 60 - this.minEdgeDistance;

      // 添加过渡效果
      this.$refs.floatingBall.style.transition = "left 0.3s ease";
      this.ballLeft = targetLeft;

      // 吸壁后更新菜单位置
      if (this.isMenuVisible) {
        this.updateMenuPosition();
      }
      this.isDragging = false;
    },
    toggleMenu() {
      this.isMenuVisible = !this.isMenuVisible;
      this.updateMenuPosition();
    },
    updateMenuPosition() {
      let left = 0;
      let top = 0;
      if (
        this.ballLeft + this.menuWidth >
        window.innerWidth - this.minEdgeDistance
      ) {
        // 悬浮球在右边,菜单显示在左边
        left = this.ballLeft - this.menuWidth;
      } else {
        // 悬浮球在左边,菜单显示在右边
        left = this.ballLeft + 80;
      }
      // 处理垂直方向菜单超出屏幕的情况
      if (
        this.ballTop + this.menuHeight >
        window.innerHeight - this.minEdgeDistance
      ) {
        // 若菜单底部超出屏幕,将菜单向上偏移
        top = Math.max(
          this.minEdgeDistance,
          window.innerHeight - this.menuHeight - this.minEdgeDistance
        );
      } else {
        top = this.ballTop;
      }
      this.menuLeft = left;
      this.menuTop = top;
    },
  },
};
</script>

<style scoped>
.chat-bubble {
  position: fixed;
  bottom: 60px;
  right: 20px;
  width: 60px;
  height: 60px;
  background-color: #15dbf5;
  border-radius: 50%;
  display: flex;
  justify-content: center;
  align-items: center;
  cursor: pointer;
  user-select: none;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
  z-index: 9999;
  transition: left 0.3s ease;
}

.chat-bubble img {
  width: 30px;
  height: 30px;
  user-select: none;
}

.menu {
  position: fixed;
  width: 350px;
  height: 500px;
  background: white;
  border-radius: 10px;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
  z-index: 9999;
}

.chat-iframe {
  width: 100%;
  height: 100%;
  border: none;
  border-radius: 10px;
}
</style>

### 集成 Markmap 到 Dify 的方法 Dify 是一个用于构建 AI 应用程序的强大框架,而 Markmap 是一种可视化工具,可以将 Markdown 数据转换为思维导图。为了在 Dify 中使用或集成 Markmap,可以通过以下几种技术手段实现。 #### 1. 使用前端嵌入的方式 如果希望在基于 Web 的 Dify 应用中展示 Markmap 思维导图,则可以在应用的前端部分引入 Markmap 库并配置其运行环境。具体操作如下: - 安装 `markmap-lib` 和其他依赖项: ```bash npm install @markmap/lib markmap-view react-dom ``` - 在 React 或 Vue 组件中初始化 Markmap 并渲染数据[^1]: ```javascript import { createRoot } from 'react-dom/client'; import Markmap from '@markmap/react'; const container = document.getElementById('app'); const root = createRoot(container); root.render( <Markmap> { ` # 主题 - 子主题 1 - 子主题 2 - 更深层次的主题 ` } </Markmap> ); ``` 通过上述代码片段,在 Dify 前端界面中即可呈现由 Markdown 转化的动态思维导图。 #### 2. 后端处理 Markdown 文件 对于需要服务器支持的情况,可利用 Node.js 处理 Markdown 输入文件,并将其转化为 JSON 格式的结构化数据供 Markmap 渲染。以下是简单的后端逻辑示例: - 创建解析器函数来读取和转化 Markdown 文本: ```javascript const markdownParser = require('markdown-parser'); function parseMarkdownToJSON(markdownText) { const parsedData = markdownParser.parse(markdownText); // 自定义解析库 return convertToMarkmapFormat(parsedData); // 将标准树形结构转为 Markmap 支持的数据格式 } ``` 随后,该 JSON 结果可通过 API 接口返回给客户端以完成最终显示。 #### 3. GitHub 源码辅助开发 根据提供的链接资源,开发者可以从项目仓库获取更多关于 roo code 实现的具体细节以及 ai-agent-demo 示例的应用场景。这些资料有助于理解如何更好地适配不同类型的输入源至目标平台。 --- ### 注意事项 确保前后端通信顺畅的同时也要注意安全性问题;另外还需测试各种边界条件下的表现情况,比如复杂层级关系或者特殊字符编码等问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值