iframe模型供应商

This commit is contained in:
吴季分
2025-10-09 13:24:37 +08:00
parent f1a7232fdc
commit d2ee6c5d08
4 changed files with 165 additions and 1 deletions

View File

@@ -0,0 +1,13 @@
---
trigger: always_on
alwaysApply: true
---
# 概述
- 模型供应商内容需要内嵌dify平台模型供商内容
- src\views\agent\views\workflow\index.vue页面的内容已完成内嵌dify平台页面的内容可作参考
# 细节描述
- 本次需要内嵌的页面是dify的base_url + /apps
- 本次内嵌的页面上需要预留参数,用于后续隐藏侧边栏。
- 需要获取access_token同src\views\agent\views\workflow\index.vue页面实现方法

View File

@@ -4,7 +4,7 @@ module.exports = {
[
'transform-remove-console',
{
exclude: ['warn', 'error'] // 可选:保留 warn 和 error
exclude: ['warn', 'error', 'log'] // 可选:保留 warn 和 error
}
]
]

View File

@@ -287,6 +287,18 @@ export default [
accessToken: '',
refreshToken: ''
}
},
{
path: '/intelligentAgent/model-provider',
name: 'intelligentAgent-model-provider',
component: () =>
import('@/views/agent/views/model-provider/index.vue'),
meta: {
title: '模型供应商',
icon: 'el-icon-connection',
accessToken: '',
refreshToken: ''
}
}
]
}

View File

@@ -0,0 +1,139 @@
<script>
import { DIFY_URL } from '@/config/base-url'
import { getAccessToken } from '@/api/intelligent-agent/list'
export default {
name: 'model-provider',
data() {
return {
timer: null,
isLoading: true,
worker: {
instance: void 0
},
messageChannel: {
instance: void 0
},
modelProvider: {
// 默认不展示 header 和 sidebar预留参数用于后续隐藏侧边栏
params: {
sidebar: '0',
header: '0'
},
isVisible: true,
// 模型供应商页面地址 - dify的 /apps 页面
src: `${DIFY_URL}/apps`
}
}
},
computed: {
params() {
const _params = []
Object.keys(this.modelProvider.params).forEach(key => {
_params.push(`${key}=${this.modelProvider.params[key]}`)
})
return _params.join('&')
}
},
created() {
// 获取 header 和 sidebar 的内容, 重置参数状态
const { header, sidebar } = this.$route.query
this.modelProvider.params.header = header || '0'
this.modelProvider.params.sidebar = sidebar || '0'
// 设置模型供应商页面的URL预留参数用于后续隐藏侧边栏
this.modelProvider.src = `${DIFY_URL}/apps?${this.params}`
// 启用 web worker 和 dify 进行通信
this.worker.instance = new Worker('/js/message-channel.js')
this.messageChannel.instance = new MessageChannel()
// 递交 messageChannel port2的所有权
this.worker.instance.postMessage('init-worker', [
this.messageChannel.instance.port2
])
// 每 5 分钟执行一次获取token
// ✅ 先清理已有 timer防止重复创建
if (this.timer) {
clearInterval(this.timer)
this.timer = null
}
this.timer = setInterval(() => {
this.initTokenRefresh()
}, 1000 * 60 * 5)
},
destroyed() {
// 组件销毁时清除 web worker 和 messageChannel
this.worker.instance.terminate()
this.worker.instance = void 0
this.messageChannel.instance.port1.close()
this.messageChannel.instance = void 0
if (this.timer) {
clearInterval(this.timer)
this.timer = null
}
},
watch: {
'$route.query': {
handler() {
// 获取 header 和 sidebar 的内容, 重置参数状态
const { header, sidebar } = this.$route.query
this.modelProvider.params.header = header || '0'
this.modelProvider.params.sidebar = sidebar || '0'
console.log('路由:' + `${DIFY_URL}/apps?${this.params}`)
// 当路由参数变化时,更新 dify 的 src
this.modelProvider.src = `${DIFY_URL}/apps?${this.params}`
},
deep: true
}
},
methods: {
async initTokenRefresh() {
try {
const thirdContent = await getAccessToken()
const { refreshToken, accessToken } = thirdContent.content.content
// 存储token到localStorage
localStorage.setItem('refresh_token', refreshToken)
localStorage.setItem('console_token', accessToken)
} catch (error) {
console.error('Token refresh failed:', error)
}
},
handleModelProviderLoad() {
// 把 messageChannel port1 的所有权传递给 iframe
this.$refs.modelProvider.contentWindow.postMessage('init-iframe', '*', [
this.messageChannel.instance.port1
])
// 隐藏 loading
this.isLoading = false
}
},
mounted() {
console.log('路由:' + `${DIFY_URL}/apps?${this.params}`)
// 组件挂载后立即获取token
this.initTokenRefresh()
}
}
</script>
<template>
<div class="render-container">
<div class="flex align-items-c mb10" style="gap: 20px">
<BackButton></BackButton>
<span class="fs14 fw600">模型供应商</span>
</div>
<div
v-loading="isLoading"
style="width: 100%; height: calc(100% - 42px);border-radius: 16px;overflow: hidden"
>
<iframe
@load="handleModelProviderLoad"
ref="modelProvider"
:src="modelProvider.src"
frameborder="0"
style="width: 100%; height:100%;"
/>
</div>
</div>
</template>