dify自带聊天页实现uid参数参数

This commit is contained in:
2025-11-13 15:40:57 +08:00
parent 88f7076630
commit a19dc232c1
16 changed files with 80 additions and 18 deletions

View File

@@ -74,6 +74,7 @@ const ChatItem: FC<ChatItemProps> = ({
handleRestart,
} = useChat(
config,
userProfile.id,
{
inputs,
inputsForm,

View File

@@ -80,6 +80,7 @@ const DebugWithSingleModel = (
handleAnnotationRemoved,
} = useChat(
config,
userProfile.id,
{
inputs,
inputsForm,

View File

@@ -51,6 +51,7 @@ const ChatWrapper = () => {
setIsResponding,
allInputsHidden,
initUserVariables,
userIdFromQuery,
} = useChatWithHistoryContext()
// Semantic variable for better code readability
@@ -76,17 +77,24 @@ const ChatWrapper = () => {
handleStop,
isResponding: respondingState,
suggestedQuestions,
} = useChat(
appConfig,
{
inputs: (isHistoryConversation ? currentConversationInputs : newConversationInputs) as any,
inputsForm: inputsForms,
} = useChat({
appData: appData!,
appParams: appData?.site.default_language ? { ...appParams, language: appData?.site.default_language } : appParams,
isInstalledApp,
appId,
conversationId: currentConversationId,
inputs: currentConversationInputs,
promptVariables: allInputsHidden ? currentConversationInputs : {},
prevChatList: appPrevChatTree,
onNewConversation: handleNewConversationCompleted,
onConversationIdChange: (id) => {
handleNewConversationCompleted(id)
},
appPrevChatTree,
taskId => stopChatMessageResponding('', taskId, isInstalledApp, appId),
clearChatList,
setClearChatList,
)
onRespondingChanged: setIsResponding,
onClearChatList: clearChatList,
onClearChatListFinished: () => setClearChatList(false),
user: userIdFromQuery || initUserVariables?.user_id,
})
const inputsFormValue = isHistoryConversation ? currentConversationInputs : newConversationInputsRef?.current
const inputDisabled = useMemo(() => {
if (allInputsHidden)

View File

@@ -60,6 +60,7 @@ export type ChatWithHistoryContextValue = {
name?: string
avatar_url?: string
}
userIdFromQuery?: string
}
export const ChatWithHistoryContext = createContext<ChatWithHistoryContextValue>({
@@ -95,5 +96,6 @@ export const ChatWithHistoryContext = createContext<ChatWithHistoryContextValue>
setCurrentConversationInputs: noop,
allInputsHidden: false,
initUserVariables: {},
userIdFromQuery: '',
})
export const useChatWithHistoryContext = () => useContext(ChatWithHistoryContext)

View File

@@ -16,7 +16,7 @@ import type {
Feedback,
} from '../types'
import { CONVERSATION_ID_INFO } from '../constants'
import { buildChatItemTree, getProcessedSystemVariablesFromUrlParams, getRawInputsFromUrlParams, getRawUserVariablesFromUrlParams } from '../utils'
import { buildChatItemTree, getProcessedSystemVariablesFromUrlParams, getRawInputsFromUrlParams, getRawUserVariablesFromUrlParams, getUserIdFromUrlParams } from '../utils'
import { addFileInfos, sortAgentSorts } from '../../../tools/utils'
import { getProcessedFilesFromResponse } from '@/app/components/base/file-uploader/utils'
import {
@@ -68,7 +68,7 @@ function getFormattedChatList(messages: any[]) {
return newChatList
}
export const useChatWithHistory = (installedAppInfo?: InstalledApp) => {
export const useChatWithHistory = (installedAppInfo?: InstalledApp, user_id?: string) => {
const isInstalledApp = useMemo(() => !!installedAppInfo, [installedAppInfo])
const appInfo = useWebAppStore(s => s.appInfo)
const appParams = useWebAppStore(s => s.appParams)
@@ -108,11 +108,18 @@ export const useChatWithHistory = (installedAppInfo?: InstalledApp) => {
const appId = useMemo(() => appData?.app_id, [appData])
const [userId, setUserId] = useState<string>()
const [userIdFromQuery, setUserIdFromQuery] = useState<string>('')
useEffect(() => {
getProcessedSystemVariablesFromUrlParams().then(({ user_id }) => {
if (user_id)
setUserId(user_id)
})
}, [])
else
getProcessedSystemVariablesFromUrlParams().then(({ user_id }) => {
setUserId(user_id)
})
// Get userid from URL query parameter
const queryUserId = getUserIdFromUrlParams()
setUserIdFromQuery(queryUserId)
}, [user_id])
useEffect(() => {
const setLocaleFromProps = async () => {
@@ -570,5 +577,6 @@ export const useChatWithHistory = (installedAppInfo?: InstalledApp) => {
setCurrentConversationInputs,
allInputsHidden,
initUserVariables,
userIdFromQuery,
}
}

View File

@@ -22,6 +22,7 @@ import { checkOrSetAccessToken } from '@/app/components/share/utils'
import AppUnavailable from '@/app/components/base/app-unavailable'
import cn from '@/utils/classnames'
import useDocumentTitle from '@/hooks/use-document-title'
import { useSearchParams } from 'next/navigation'
type ChatWithHistoryProps = {
className?: string
@@ -40,6 +41,8 @@ const ChatWithHistory: FC<ChatWithHistoryProps> = ({
const isSidebarCollapsed = sidebarCollapseState
const customConfig = appData?.custom_config
const site = appData?.site
const searchParams = useSearchParams()
const userid = searchParams.get('userid')
const [showSidePanel, setShowSidePanel] = useState(false)
@@ -109,6 +112,8 @@ const ChatWithHistoryWrap: FC<ChatWithHistoryWrapProps> = ({
const media = useBreakpoints()
const isMobile = media === MediaType.mobile
const themeBuilder = useThemeContext()
const searchParams = useSearchParams()
const userid = searchParams.get('userid')
const {
appData,
@@ -148,7 +153,8 @@ const ChatWithHistoryWrap: FC<ChatWithHistoryWrapProps> = ({
setCurrentConversationInputs,
allInputsHidden,
initUserVariables,
} = useChatWithHistory(installedAppInfo)
userIdFromQuery,
} = useChatWithHistory(installedAppInfo, userid)
return (
<ChatWithHistoryContext.Provider value={{
@@ -191,6 +197,7 @@ const ChatWithHistoryWrap: FC<ChatWithHistoryWrapProps> = ({
setCurrentConversationInputs,
allInputsHidden,
initUserVariables,
userIdFromQuery,
}}>
<ChatWithHistory className={className} />
</ChatWithHistoryContext.Provider>

View File

@@ -46,6 +46,7 @@ type SendCallback = {
export const useChat = (
config?: ChatConfig,
user?: string,
formSettings?: {
inputs: Inputs
inputsForm: InputForm[]
@@ -276,6 +277,7 @@ export const useChat = (
const bodyParams = {
response_mode: 'streaming',
conversation_id: conversationId.current,
user: user || '',
files: getProcessedFiles(files || []),
query,
inputs: getProcessedInputs(inputs || {}, formSettings?.inputsForm || []),

View File

@@ -51,6 +51,7 @@ const ChatWrapper = () => {
setIsResponding,
allInputsHidden,
initUserVariables,
userIdFromQuery,
} = useEmbeddedChatbotContext()
const appConfig = useMemo(() => {
const config = appParams || {}
@@ -74,6 +75,7 @@ const ChatWrapper = () => {
suggestedQuestions,
} = useChat(
appConfig,
userIdFromQuery || initUserVariables?.user_id,
{
inputs: (currentConversationId ? currentConversationInputs : newConversationInputs) as any,
inputsForm: inputsForms,

View File

@@ -56,6 +56,7 @@ export type EmbeddedChatbotContextValue = {
name?: string
avatar_url?: string
}
userIdFromQuery?: string
}
export const EmbeddedChatbotContext = createContext<EmbeddedChatbotContextValue>({
@@ -86,5 +87,6 @@ export const EmbeddedChatbotContext = createContext<EmbeddedChatbotContextValue>
setCurrentConversationInputs: noop,
allInputsHidden: false,
initUserVariables: {},
userIdFromQuery: '',
})
export const useEmbeddedChatbotContext = () => useContext(EmbeddedChatbotContext)

View File

@@ -15,7 +15,7 @@ import type {
Feedback,
} from '../types'
import { CONVERSATION_ID_INFO } from '../constants'
import { buildChatItemTree, getProcessedInputsFromUrlParams, getProcessedSystemVariablesFromUrlParams, getProcessedUserVariablesFromUrlParams } from '../utils'
import { buildChatItemTree, getProcessedInputsFromUrlParams, getProcessedSystemVariablesFromUrlParams, getProcessedUserVariablesFromUrlParams, getUserIdFromUrlParams } from '../utils'
import { getProcessedFilesFromResponse } from '../../file-uploader/utils'
import {
fetchAppInfo,
@@ -82,11 +82,15 @@ export const useEmbeddedChatbot = () => {
const [userId, setUserId] = useState<string>()
const [conversationId, setConversationId] = useState<string>()
const [userIdFromQuery, setUserIdFromQuery] = useState<string>('')
useEffect(() => {
getProcessedSystemVariablesFromUrlParams().then(({ user_id, conversation_id }) => {
setUserId(user_id)
setConversationId(conversation_id)
})
// Get userid from URL query parameter
const queryUserId = getUserIdFromUrlParams()
setUserIdFromQuery(queryUserId)
}, [])
useEffect(() => {
@@ -436,5 +440,6 @@ export const useEmbeddedChatbot = () => {
setCurrentConversationInputs,
allInputsHidden,
initUserVariables,
userIdFromQuery,
}
}

View File

@@ -132,6 +132,7 @@ const EmbeddedChatbotWrapper = () => {
setCurrentConversationInputs,
allInputsHidden,
initUserVariables,
userIdFromQuery,
} = useEmbeddedChatbot()
return <EmbeddedChatbotContext.Provider value={{
@@ -169,6 +170,7 @@ const EmbeddedChatbotWrapper = () => {
setCurrentConversationInputs,
allInputsHidden,
initUserVariables,
userIdFromQuery,
}}>
<Chatbot />
</EmbeddedChatbotContext.Provider>

View File

@@ -88,6 +88,12 @@ async function getRawUserVariablesFromUrlParams(): Promise<Record<string, any>>
return userVariables
}
function getUserIdFromUrlParams(): string {
const urlParams = new URLSearchParams(window.location.search)
const userId = urlParams.get('userid')
return userId ? decodeURIComponent(userId) : ''
}
function isValidGeneratedAnswer(item?: ChatItem | ChatItemInTree): boolean {
return !!item && item.isAnswer && !item.id.startsWith('answer-placeholder-') && !item.isOpeningStatement
}
@@ -236,6 +242,7 @@ export {
getProcessedSystemVariablesFromUrlParams,
getProcessedUserVariablesFromUrlParams,
getRawUserVariablesFromUrlParams,
getUserIdFromUrlParams,
isValidGeneratedAnswer,
getLastAnswer,
buildChatItemTree,

View File

@@ -41,6 +41,7 @@ import { AccessMode } from '@/models/access-control'
import { useGlobalPublicStore } from '@/context/global-public-context'
import useDocumentTitle from '@/hooks/use-document-title'
import { useWebAppStore } from '@/context/web-app-context'
import { getUserIdFromUrlParams } from '@/app/components/base/chat/utils'
const GROUP_SIZE = 5 // to avoid RPM(Request per minute) limit. The group task finished then the next group.
enum TaskStatus {
@@ -125,6 +126,13 @@ const TextGeneration: FC<IMainProps> = ({
transfer_methods: [TransferMethod.local_file],
})
const [completionFiles, setCompletionFiles] = useState<VisionFile[]>([])
const [userIdFromQuery, setUserIdFromQuery] = useState<string>('')
useEffect(() => {
// Get userid from URL query parameter
const queryUserId = getUserIdFromUrlParams()
setUserIdFromQuery(queryUserId)
}, [])
const handleSend = () => {
setIsCallBatchAPI(false)
@@ -433,6 +441,7 @@ const TextGeneration: FC<IMainProps> = ({
isShowTextToSpeech={!!textToSpeechConfig?.enabled}
siteInfo={siteInfo}
onRunStart={() => setResultExisted(true)}
userIdFromQuery={userIdFromQuery}
/>)
const renderBatchRes = () => {

View File

@@ -46,6 +46,7 @@ export type IResultProps = {
completionFiles: VisionFile[]
siteInfo: SiteInfo | null
onRunStart: () => void
userIdFromQuery?: string
}
const Result: FC<IResultProps> = ({
@@ -71,6 +72,7 @@ const Result: FC<IResultProps> = ({
completionFiles,
siteInfo,
onRunStart,
userIdFromQuery,
}) => {
const [isResponding, { setTrue: setRespondingTrue, setFalse: setRespondingFalse }] = useBoolean(false)
useEffect(() => {
@@ -162,6 +164,7 @@ const Result: FC<IResultProps> = ({
const data: Record<string, any> = {
inputs: formatBooleanInputs(promptConfig?.prompt_variables, inputs),
user: userIdFromQuery || '',
}
if (visionConfig.enabled && completionFiles && completionFiles?.length > 0) {
data.files = completionFiles.map((item) => {

View File

@@ -23,6 +23,7 @@ import { getLastAnswer, isValidGeneratedAnswer } from '@/app/components/base/cha
import type { FileEntity } from '@/app/components/base/file-uploader/types'
import { useEventEmitterContextContext } from '@/context/event-emitter'
import { EVENT_WORKFLOW_STOP } from '@/app/components/workflow/variable-inspect/types'
import { useAppContext } from '@/context/app-context'
type ChatWrapperProps = {
showConversationVariableModal: boolean
@@ -42,6 +43,7 @@ const ChatWrapper = (
ref: React.RefObject<ChatWrapperRefType>;
},
) => {
const { userProfile } = useAppContext()
const nodes = useNodes<StartNodeType>()
const startNode = nodes.find(node => node.data.type === BlockEnum.Start)
const startVariables = startNode?.data.variables
@@ -89,6 +91,7 @@ const ChatWrapper = (
setTargetMessageId,
} = useChat(
config,
userProfile.id,
{
inputs,
inputsForm: (startVariables || []) as any,