other-platform-dify.md 6.8 KB

dify

由于此项目有嵌入dify部分功能的需求,针对dify源码做了部分调整。可以使用iframe的方式嵌入dify,并支持对其样式脚本的调整。

<template>
<iframe :src="defaultUrl" id="dify"></iframe>
</template>

<script setup>
import { ref, onMounted } from 'vue';

const defaultUrl = ref('http://192.168.20.119:28003');

onMounted(()=>{
  const ele = document.getElementById('dify');
  
  ele.onload = function(){
    if(ele && ele.contentwindow){
      const msg1 = {
        type:'insertStyle',
        value:`body{background-color:red;font-size:58px;}`
      };

      ele.contentWindow.postMessage(JSON.stringify(msg1), defaultUrl.value);

      const msg2 = {
        type: 'insertScript',
        value: `console.log('hello world');`
      }

      ele.contentWindow.postMessage(JSON.stringify(msg2), defaultUrl.value);
    }
  }
})
</script>

<style scoped lang="css"></style>

dify相关修改记录

2024-12-12 dify 配置跨域

为了解决无界微前端跨域的问题,修改了dify的配置文件。

nginx配置文件目录: /data/disk2/llm_platform/dify/docker/nginx/conf.d

nginx配置文件

修改:default.conf.template文件,添加如下内容:

添加内容如下:

    add_header 'Access-Control-Allow-Origin' '*';
    add_header 'Access-Control-Allow-Methods' '*';

最终结果如下:

# Please do not directly edit this file. Instead, modify the .env variables related to NGINX configuration.

server {
    listen ${NGINX_PORT};
    server_name ${NGINX_SERVER_NAME};

    add_header 'Access-Control-Allow-Origin' '*';
    add_header 'Access-Control-Allow-Methods' '*';

    location /console/api {
      proxy_pass http://api:5001;
      include proxy.conf;
    }

    location /api {
      proxy_pass http://api:5001;
      include proxy.conf;
    }

    location /v1 {
      proxy_pass http://api:5001;
      include proxy.conf;
    }

    location /files {
      proxy_pass http://api:5001;
      include proxy.conf;
    }

    location / {
      proxy_pass http://web:3000;
      include proxy.conf;
    }

    # placeholder for acme challenge location
    ${ACME_CHALLENGE_LOCATION}

    # placeholder for https config defined in https.conf.template
    ${HTTPS_CONFIG}
}

然后执行:docker restart docker-nginx-1重启容器即可。

2024-12-13 dify 添加事件监听,支持iframe样式和脚本插入

大模型2.0嵌入dify项目时,初始使用微前端方式,但是使用微前端时,发现dify的前端使用的是服务器端渲染框架nextjs,在加载dify项目时,会有报错,经过查询资料得知,无界当前不支持服务器端渲染(SSR),无界嵌入next.js或者nuxt.js都没有好的解决方案。

为了解决此问题,考虑了两个方案:

  1. 调整为使用iframe进行嵌入,通过postMessage进行通信,调整样式和脚本。此方案需要调整dify的源码,与初衷有些许背离。
  2. 继续使用微前端方式,但是需要修改无界的源码,调整起来比较困难。

由于修改无界的源码,需要的时间较多,暂时使用iframe方式嵌入。此方案需要调整dify的源码。下方记录对dify的修改。

修改位置

文件1

文件远程地址:http://192.168.20.116/_next/static/chunks/app/layout-4c8b096bae21994c.js

文件服务器路径:/data/disk2/llm_platform/dify/docker/web/.next/static/chunks/app/layout-4c8b096bae21994c.js

文件2

文件远程地址:http://192.168.20.116/_next/static/chunks/app/(commonLayout)/layout-f8be35226350c774.js

文件服务器路径:/data/disk2/llm_platform/dify/docker/web/.next/static/chunks/app/(commonLayout)/layout-f8be35226350c774.js

文件3

文件远程地址:http://192.168.20.116/_next/static/chunks/app/signin/layout-a9277f33772c3201.js

文件服务器目录位置:/data/disk2/llm_platform/dify/docker/web/.next/static/chunks/app/signin

修改内容

在上述列出的js文件末尾添加下方脚本:

此处的修改接收message,并进行相应的cssjs的操作。

function handleMessage(event) {
    const data = event.data;
    try{
        const dataInfo = JSON.parse(event.data);
        
        const type = dataInfo.type;
        const value = dataInfo.value;

        if(type === 'insertStyle'){
            // 插入样式表
            const ele = document.createElement('style');
            ele.innerHTML = value;
            document.head.appendChild(ele);
        }else if(type === 'insertScript'){
            // 插入脚本
            const ele = document.createElement('script');
            ele.innerHTML = value;
            document.head.appendChild(ele);
        }else{
            // 其他
        }
    }catch(err){
        console.log('自定义事件出错');
    }
}

window.addEventListener("message", handleMessage, false);

2024-12-13 dify 添加token参数处理

为了解决嵌入登录问题,修改部分代码。

需求描述:大模型2.0使用iframe嵌入dify,需要进行登录,此时在嵌入时,将token放入url后面,dify中需要处理此参数,将token通过localstorage进行保存,从而实现登录操作。

嵌入时链接示例

http://192.168.20.116/explore/apps?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoiODA1NGU5ZmMtNzViYS00N2FlLWFlMmItNTEwOWZlMDFkYjA0IiwiZXhwIjoxNzM0MDgzODg4LCJpc3MiOiJTRUxGX0hPU1RFRCIsInN1YiI6IkNvbnNvbGUgQVBJIFBhc3Nwb3J0In0.urrZl876HSqbgbmbvklvTvcvkTb05N21UKUSVfnlHsM

修改文件

  • 文件远程地址:http://192.168.20.116/_next/static/chunks/app/(commonLayout)/layout-f8be35226350c774.js
  • 文件路径: /data/disk2/llm_platform/dify/docker/web/.next/static/chunks/app/(commonLayout)/layout-f8be35226350c774.js

修改内容

function getSearchParams(href){
    const url = new URL(href);

    const searchParams = new URLSearchParams(url.search);

    // 将键值对列表转换为一个对象
    const res = Object.fromEntries(searchParams.entries());

    return res;
}

function setUrlToken(){
    // 获取URL值
    const href = location.href;

    const params = getSearchParams(href);

    if(params.token){
        localStorage.setItem('console_token', params.token);
        localStorage.setItem('refresh_token', '10846d07c926fe8db065246eea370067cfce547066865e6068792e78ebee3c41e841b0c0c41d0c59d3e149dbdfc746f6ea8638f4b99735fbe97b70d2aa0d78bb');
    }else{
        // 找不到token,提示错误
    }
}

setUrlToken();

dify身份凭据是console_token,但是在dify代码中,会判断refresh_token是否存在,如果不存在,则会跳回登录页面。

此部分代码手动创建一个refresh_token,再配合参数中的token,从而实现登录流程正常。