feat: dify1.11.1进行适配
@@ -3,10 +3,10 @@ FROM node:22-alpine3.21 AS base
|
|||||||
LABEL maintainer="takatost@gmail.com"
|
LABEL maintainer="takatost@gmail.com"
|
||||||
|
|
||||||
# if you located in China, you can use aliyun mirror to speed up
|
# if you located in China, you can use aliyun mirror to speed up
|
||||||
# RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories
|
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories
|
||||||
|
|
||||||
# if you located in China, you can use taobao registry to speed up
|
# if you located in China, you can use taobao registry to speed up
|
||||||
# RUN npm config set registry https://registry.npmmirror.com
|
RUN npm config set registry https://registry.npmmirror.com
|
||||||
|
|
||||||
RUN apk add --no-cache tzdata
|
RUN apk add --no-cache tzdata
|
||||||
RUN corepack enable
|
RUN corepack enable
|
||||||
|
|||||||
80
dify_1.11.1/web/app/components/base/iframe-postmessage.tsx
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
'use client'
|
||||||
|
import { useEffect, useRef } from 'react'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IframePostMessage
|
||||||
|
* 页面加载完成后向父页面发送一次消息,并每 5 秒发送一次。
|
||||||
|
* 仅当当前窗口运行在 iframe 中时才发送。
|
||||||
|
*/
|
||||||
|
const IframePostMessage = () => {
|
||||||
|
const initializedRef = useRef(false)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sendMessage
|
||||||
|
* 向父页面发送消息的函数:收集当前页面的 localStorage 全量键值并发送。
|
||||||
|
* 如果不在 iframe 环境中则不发送。
|
||||||
|
*/
|
||||||
|
const sendMessage = () => {
|
||||||
|
try {
|
||||||
|
if (typeof window === 'undefined') return
|
||||||
|
// 只在 iframe 环境下发送
|
||||||
|
if (window.parent === window) return
|
||||||
|
// 收集 localStorage 全量数据
|
||||||
|
const localStorageData: Record<string, string | null> = {}
|
||||||
|
try {
|
||||||
|
const { localStorage } = window
|
||||||
|
for (let i = 0; i < localStorage.length; i++) {
|
||||||
|
const key = localStorage.key(i)
|
||||||
|
if (!key) continue
|
||||||
|
localStorageData[key] = localStorage.getItem(key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
// 可能因浏览器隐私设置导致不可访问 localStorage
|
||||||
|
}
|
||||||
|
window.parent.postMessage(
|
||||||
|
{
|
||||||
|
type: 'dify-localstorage',
|
||||||
|
status: 1,
|
||||||
|
message: '将智能体本地缓存发送给父页面!',
|
||||||
|
data: localStorageData,
|
||||||
|
},
|
||||||
|
'*',
|
||||||
|
)
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
// 忽略跨域或其他运行时错误
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (initializedRef.current) return
|
||||||
|
initializedRef.current = true
|
||||||
|
|
||||||
|
let timer: number | undefined
|
||||||
|
|
||||||
|
const init = () => {
|
||||||
|
sendMessage()
|
||||||
|
timer = window.setInterval(sendMessage, 5000)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (document.readyState === 'loading') {
|
||||||
|
const onReady = () => {
|
||||||
|
init()
|
||||||
|
document.removeEventListener('DOMContentLoaded', onReady)
|
||||||
|
}
|
||||||
|
document.addEventListener('DOMContentLoaded', onReady)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
init()
|
||||||
|
}
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
if (timer) window.clearInterval(timer)
|
||||||
|
}
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
export default IframePostMessage
|
||||||
@@ -4,6 +4,7 @@ import type { Viewport } from 'next'
|
|||||||
import I18nServer from './components/i18n-server'
|
import I18nServer from './components/i18n-server'
|
||||||
import BrowserInitializer from './components/browser-initializer'
|
import BrowserInitializer from './components/browser-initializer'
|
||||||
import SentryInitializer from './components/sentry-initializer'
|
import SentryInitializer from './components/sentry-initializer'
|
||||||
|
import IframePostMessage from './components/base/iframe-postmessage'
|
||||||
import { getLocaleOnServer } from '@/i18n-config/server'
|
import { getLocaleOnServer } from '@/i18n-config/server'
|
||||||
import { TanstackQueryInitializer } from '@/context/query-client'
|
import { TanstackQueryInitializer } from '@/context/query-client'
|
||||||
import { ThemeProvider } from 'next-themes'
|
import { ThemeProvider } from 'next-themes'
|
||||||
@@ -109,6 +110,7 @@ const LocaleLayout = async ({
|
|||||||
</BrowserInitializer>
|
</BrowserInitializer>
|
||||||
</ThemeProvider>
|
</ThemeProvider>
|
||||||
<RoutePrefixHandle />
|
<RoutePrefixHandle />
|
||||||
|
<IframePostMessage />
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
)
|
)
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 173 KiB |
|
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 173 KiB |
|
Before Width: | Height: | Size: 5.0 KiB After Width: | Height: | Size: 48 KiB |
|
Before Width: | Height: | Size: 9.0 KiB After Width: | Height: | Size: 48 KiB |
|
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 173 KiB |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 173 KiB |
BIN
dify_1.11.1/web/public/logo/logo.png
Normal file
|
After Width: | Height: | Size: 163 KiB |
@@ -128,7 +128,35 @@ export const createFirstDocument = ({ body }: { body: CreateDocumentReq }): Prom
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const createDocument = ({ datasetId, body }: { datasetId: string; body: CreateDocumentReq }): Promise<createDocumentResponse> => {
|
export const createDocument = ({ datasetId, body }: { datasetId: string; body: CreateDocumentReq }): Promise<createDocumentResponse> => {
|
||||||
|
const IsHsAiApp = localStorage.getItem('IsHsAiApp')
|
||||||
|
if (IsHsAiApp == null) {
|
||||||
|
// 当 IsHsAiApp 为 null 时,调用 post 方法并返回其结果
|
||||||
return post<createDocumentResponse>(`/datasets/${datasetId}/documents`, { body })
|
return post<createDocumentResponse>(`/datasets/${datasetId}/documents`, { body })
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
// 当 IsHsAiApp 不为 null 时,调用 Electron 的 IPC 方法
|
||||||
|
// 需要返回一个 Promise,以符合 Fetcher 的返回类型
|
||||||
|
return new Promise<createDocumentResponse>((resolve, reject) => {
|
||||||
|
if (typeof window !== 'undefined' && 'electron' in window) {
|
||||||
|
// 安全地使用 window.electron
|
||||||
|
// @ts-ignore
|
||||||
|
window.electron.ipcRenderer
|
||||||
|
.invoke('difyWebUploadFileToApi', datasetId, JSON.stringify(body))
|
||||||
|
.then((response: any) => {
|
||||||
|
console.log(response)
|
||||||
|
// 假设 response 是符合 createDocumentResponse 类型的
|
||||||
|
resolve(response as createDocumentResponse)
|
||||||
|
})
|
||||||
|
.catch((error: any) => {
|
||||||
|
console.error(error)
|
||||||
|
reject(error) // 捕获错误并拒绝 Promise
|
||||||
|
})
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
console.warn('Electron API is not available in this environment.')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const fetchIndexingEstimate = ({ datasetId, documentId }: CommonDocReq): Promise<IndexingEstimateResponse> => {
|
export const fetchIndexingEstimate = ({ datasetId, documentId }: CommonDocReq): Promise<IndexingEstimateResponse> => {
|
||||||
|
|||||||