feat: allow fill inputs from url params (#20630)

This commit is contained in:
非法操作
2025-06-05 09:44:41 +08:00
committed by GitHub
parent 5ccfb1f4ba
commit f2dcfc976d
18 changed files with 55 additions and 5 deletions

View File

@@ -16,7 +16,7 @@ import type {
Feedback, Feedback,
} from '../types' } from '../types'
import { CONVERSATION_ID_INFO } from '../constants' import { CONVERSATION_ID_INFO } from '../constants'
import { buildChatItemTree, getProcessedSystemVariablesFromUrlParams } from '../utils' import { buildChatItemTree, getProcessedSystemVariablesFromUrlParams, getRawInputsFromUrlParams } from '../utils'
import { addFileInfos, sortAgentSorts } from '../../../tools/utils' import { addFileInfos, sortAgentSorts } from '../../../tools/utils'
import { getProcessedFilesFromResponse } from '@/app/components/base/file-uploader/utils' import { getProcessedFilesFromResponse } from '@/app/components/base/file-uploader/utils'
import { import {
@@ -195,6 +195,7 @@ export const useChatWithHistory = (installedAppInfo?: InstalledApp) => {
const { t } = useTranslation() const { t } = useTranslation()
const newConversationInputsRef = useRef<Record<string, any>>({}) const newConversationInputsRef = useRef<Record<string, any>>({})
const [newConversationInputs, setNewConversationInputs] = useState<Record<string, any>>({}) const [newConversationInputs, setNewConversationInputs] = useState<Record<string, any>>({})
const [initInputs, setInitInputs] = useState<Record<string, any>>({})
const handleNewConversationInputsChange = useCallback((newInputs: Record<string, any>) => { const handleNewConversationInputsChange = useCallback((newInputs: Record<string, any>) => {
newConversationInputsRef.current = newInputs newConversationInputsRef.current = newInputs
setNewConversationInputs(newInputs) setNewConversationInputs(newInputs)
@@ -202,20 +203,29 @@ export const useChatWithHistory = (installedAppInfo?: InstalledApp) => {
const inputsForms = useMemo(() => { const inputsForms = useMemo(() => {
return (appParams?.user_input_form || []).filter((item: any) => !item.external_data_tool).map((item: any) => { return (appParams?.user_input_form || []).filter((item: any) => !item.external_data_tool).map((item: any) => {
if (item.paragraph) { if (item.paragraph) {
let value = initInputs[item.paragraph.variable]
if (value && item.paragraph.max_length && value.length > item.paragraph.max_length)
value = value.slice(0, item.paragraph.max_length)
return { return {
...item.paragraph, ...item.paragraph,
default: value || item.default,
type: 'paragraph', type: 'paragraph',
} }
} }
if (item.number) { if (item.number) {
const convertedNumber = Number(initInputs[item.number.variable]) ?? undefined
return { return {
...item.number, ...item.number,
default: convertedNumber || item.default,
type: 'number', type: 'number',
} }
} }
if (item.select) { if (item.select) {
const isInputInOptions = item.select.options.includes(initInputs[item.select.variable])
return { return {
...item.select, ...item.select,
default: (isInputInOptions ? initInputs[item.select.variable] : undefined) || item.default,
type: 'select', type: 'select',
} }
} }
@@ -234,17 +244,30 @@ export const useChatWithHistory = (installedAppInfo?: InstalledApp) => {
} }
} }
let value = initInputs[item['text-input'].variable]
if (value && item['text-input'].max_length && value.length > item['text-input'].max_length)
value = value.slice(0, item['text-input'].max_length)
return { return {
...item['text-input'], ...item['text-input'],
default: value || item.default,
type: 'text-input', type: 'text-input',
} }
}) })
}, [appParams]) }, [initInputs, appParams])
const allInputsHidden = useMemo(() => { const allInputsHidden = useMemo(() => {
return inputsForms.length > 0 && inputsForms.every(item => item.hide === true) return inputsForms.length > 0 && inputsForms.every(item => item.hide === true)
}, [inputsForms]) }, [inputsForms])
useEffect(() => {
// init inputs from url params
(async () => {
const inputs = await getRawInputsFromUrlParams()
setInitInputs(inputs)
})()
}, [])
useEffect(() => { useEffect(() => {
const conversationInputs: Record<string, any> = {} const conversationInputs: Record<string, any> = {}
@@ -362,11 +385,11 @@ export const useChatWithHistory = (installedAppInfo?: InstalledApp) => {
if (conversationId) if (conversationId)
setClearChatList(false) setClearChatList(false)
}, [handleConversationIdInfoChange, setClearChatList]) }, [handleConversationIdInfoChange, setClearChatList])
const handleNewConversation = useCallback(() => { const handleNewConversation = useCallback(async () => {
currentChatInstanceRef.current.handleStop() currentChatInstanceRef.current.handleStop()
setShowNewConversationItemInList(true) setShowNewConversationItemInList(true)
handleChangeConversation('') handleChangeConversation('')
handleNewConversationInputsChange({}) handleNewConversationInputsChange(await getRawInputsFromUrlParams())
setClearChatList(true) setClearChatList(true)
}, [handleChangeConversation, setShowNewConversationItemInList, handleNewConversationInputsChange, setClearChatList]) }, [handleChangeConversation, setShowNewConversationItemInList, handleNewConversationInputsChange, setClearChatList])
const handleUpdateConversationList = useCallback(() => { const handleUpdateConversationList = useCallback(() => {

View File

@@ -15,6 +15,17 @@ async function decodeBase64AndDecompress(base64String: string) {
} }
} }
async function getRawInputsFromUrlParams(): Promise<Record<string, any>> {
const urlParams = new URLSearchParams(window.location.search)
const inputs: Record<string, any> = {}
const entriesArray = Array.from(urlParams.entries())
entriesArray.forEach(([key, value]) => {
if (!key.startsWith('sys.'))
inputs[key] = decodeURIComponent(value)
})
return inputs
}
async function getProcessedInputsFromUrlParams(): Promise<Record<string, any>> { async function getProcessedInputsFromUrlParams(): Promise<Record<string, any>> {
const urlParams = new URLSearchParams(window.location.search) const urlParams = new URLSearchParams(window.location.search)
const inputs: Record<string, any> = {} const inputs: Record<string, any> = {}
@@ -184,6 +195,7 @@ function getThreadMessages(tree: ChatItemInTree[], targetMessageId?: string): Ch
} }
export { export {
getRawInputsFromUrlParams,
getProcessedInputsFromUrlParams, getProcessedInputsFromUrlParams,
getProcessedSystemVariablesFromUrlParams, getProcessedSystemVariablesFromUrlParams,
isValidGeneratedAnswer, isValidGeneratedAnswer,

View File

@@ -280,6 +280,7 @@ const translation = {
'inputPlaceholder': 'Por favor ingresa', 'inputPlaceholder': 'Por favor ingresa',
'content': 'Contenido', 'content': 'Contenido',
'required': 'Requerido', 'required': 'Requerido',
'hide': 'Ocultar',
'errorMsg': { 'errorMsg': {
varNameRequired: 'Nombre de la variable es requerido', varNameRequired: 'Nombre de la variable es requerido',
labelNameRequired: 'Nombre de la etiqueta es requerido', labelNameRequired: 'Nombre de la etiqueta es requerido',

View File

@@ -315,6 +315,7 @@ const translation = {
'inputPlaceholder': 'لطفاً وارد کنید', 'inputPlaceholder': 'لطفاً وارد کنید',
'content': 'محتوا', 'content': 'محتوا',
'required': 'مورد نیاز', 'required': 'مورد نیاز',
'hide': 'مخفی کردن',
'errorMsg': { 'errorMsg': {
varNameRequired: 'نام متغیر مورد نیاز است', varNameRequired: 'نام متغیر مورد نیاز است',
labelNameRequired: 'نام برچسب مورد نیاز است', labelNameRequired: 'نام برچسب مورد نیاز است',

View File

@@ -268,6 +268,7 @@ const translation = {
'labelName': 'Label Name', 'labelName': 'Label Name',
'inputPlaceholder': 'Please input', 'inputPlaceholder': 'Please input',
'required': 'Required', 'required': 'Required',
'hide': 'Caché',
'errorMsg': { 'errorMsg': {
varNameRequired: 'Variable name is required', varNameRequired: 'Variable name is required',
labelNameRequired: 'Label name is required', labelNameRequired: 'Label name is required',

View File

@@ -312,6 +312,7 @@ const translation = {
'inputPlaceholder': 'कृपया इनपुट करें', 'inputPlaceholder': 'कृपया इनपुट करें',
'content': 'सामग्री', 'content': 'सामग्री',
'required': 'आवश्यक', 'required': 'आवश्यक',
'hide': 'छुपाएँ',
'errorMsg': { 'errorMsg': {
varNameRequired: 'वेरिएबल नाम आवश्यक है', varNameRequired: 'वेरिएबल नाम आवश्यक है',
labelNameRequired: 'लेबल नाम आवश्यक है', labelNameRequired: 'लेबल नाम आवश्यक है',

View File

@@ -314,6 +314,7 @@ const translation = {
'inputPlaceholder': 'Per favore inserisci', 'inputPlaceholder': 'Per favore inserisci',
'content': 'Contenuto', 'content': 'Contenuto',
'required': 'Richiesto', 'required': 'Richiesto',
'hide': 'Nascondi',
'errorMsg': { 'errorMsg': {
varNameRequired: 'Il nome della variabile è richiesto', varNameRequired: 'Il nome della variabile è richiesto',
labelNameRequired: 'Il nome dell\'etichetta è richiesto', labelNameRequired: 'Il nome dell\'etichetta è richiesto',

View File

@@ -359,6 +359,7 @@ const translation = {
'labelName': 'ラベル名', 'labelName': 'ラベル名',
'inputPlaceholder': '入力してください', 'inputPlaceholder': '入力してください',
'required': '必須', 'required': '必須',
'hide': '非表示',
'file': { 'file': {
supportFileTypes: 'サポートされたファイルタイプ', supportFileTypes: 'サポートされたファイルタイプ',
image: { image: {

View File

@@ -279,6 +279,7 @@ const translation = {
'labelName': '레이블명', 'labelName': '레이블명',
'inputPlaceholder': '입력하세요', 'inputPlaceholder': '입력하세요',
'required': '필수', 'required': '필수',
'hide': '숨기기',
'errorMsg': { 'errorMsg': {
varNameRequired: '변수명은 필수입니다', varNameRequired: '변수명은 필수입니다',
labelNameRequired: '레이블명은 필수입니다', labelNameRequired: '레이블명은 필수입니다',

View File

@@ -309,6 +309,7 @@ const translation = {
'labelName': 'Nazwa etykiety', 'labelName': 'Nazwa etykiety',
'inputPlaceholder': 'Proszę wpisać', 'inputPlaceholder': 'Proszę wpisać',
'required': 'Wymagane', 'required': 'Wymagane',
'hide': 'Ukryj',
'errorMsg': { 'errorMsg': {
varNameRequired: 'Wymagana nazwa zmiennej', varNameRequired: 'Wymagana nazwa zmiennej',
labelNameRequired: 'Wymagana nazwa etykiety', labelNameRequired: 'Wymagana nazwa etykiety',

View File

@@ -285,6 +285,7 @@ const translation = {
'labelName': 'Nome do Rótulo', 'labelName': 'Nome do Rótulo',
'inputPlaceholder': 'Por favor, insira', 'inputPlaceholder': 'Por favor, insira',
'required': 'Obrigatório', 'required': 'Obrigatório',
'hide': 'Ocultar',
'errorMsg': { 'errorMsg': {
varNameRequired: 'O nome da variável é obrigatório', varNameRequired: 'O nome da variável é obrigatório',
labelNameRequired: 'O nome do rótulo é obrigatório', labelNameRequired: 'O nome do rótulo é obrigatório',

View File

@@ -285,6 +285,7 @@ const translation = {
'labelName': 'Nume etichetă', 'labelName': 'Nume etichetă',
'inputPlaceholder': 'Vă rugăm să introduceți', 'inputPlaceholder': 'Vă rugăm să introduceți',
'required': 'Obligatoriu', 'required': 'Obligatoriu',
'hide': 'Ascundeți',
'errorMsg': { 'errorMsg': {
varNameRequired: 'Numele variabilei este obligatoriu', varNameRequired: 'Numele variabilei este obligatoriu',
labelNameRequired: 'Numele etichetei este obligatoriu', labelNameRequired: 'Numele etichetei este obligatoriu',

View File

@@ -322,6 +322,7 @@ const translation = {
'inputPlaceholder': 'Пожалуйста, введите', 'inputPlaceholder': 'Пожалуйста, введите',
'content': 'Содержимое', 'content': 'Содержимое',
'required': 'Обязательно', 'required': 'Обязательно',
'hide': 'Скрыть',
'errorMsg': { 'errorMsg': {
labelNameRequired: 'Имя метки обязательно', labelNameRequired: 'Имя метки обязательно',
varNameCanBeRepeat: 'Имя переменной не может повторяться', varNameCanBeRepeat: 'Имя переменной не может повторяться',

View File

@@ -239,4 +239,4 @@ const translation = {
}, },
} }
module.exports = translation export default translation

View File

@@ -279,6 +279,7 @@ const translation = {
'labelName': 'Назва мітки', 'labelName': 'Назва мітки',
'inputPlaceholder': 'Будь ласка, введіть', 'inputPlaceholder': 'Будь ласка, введіть',
'required': 'Обов\'язково', 'required': 'Обов\'язково',
'hide': 'Приховати',
'errorMsg': { 'errorMsg': {
varNameRequired: 'Потрібно вказати назву змінної', varNameRequired: 'Потрібно вказати назву змінної',
labelNameRequired: 'Потрібно вказати назву мітки', labelNameRequired: 'Потрібно вказати назву мітки',

View File

@@ -279,6 +279,7 @@ const translation = {
'labelName': 'Tên nhãn', 'labelName': 'Tên nhãn',
'inputPlaceholder': 'Vui lòng nhập', 'inputPlaceholder': 'Vui lòng nhập',
'required': 'Bắt buộc', 'required': 'Bắt buộc',
'hide': 'Ẩn',
'errorMsg': { 'errorMsg': {
varNameRequired: 'Tên biến là bắt buộc', varNameRequired: 'Tên biến là bắt buộc',
labelNameRequired: 'Tên nhãn là bắt buộc', labelNameRequired: 'Tên nhãn là bắt buộc',

View File

@@ -361,6 +361,7 @@ const translation = {
'inputPlaceholder': '请输入', 'inputPlaceholder': '请输入',
'labelName': '显示名称', 'labelName': '显示名称',
'required': '必填', 'required': '必填',
'hide': '隐藏',
'file': { 'file': {
supportFileTypes: '支持的文件类型', supportFileTypes: '支持的文件类型',
image: { image: {

View File

@@ -264,6 +264,7 @@ const translation = {
'inputPlaceholder': '請輸入', 'inputPlaceholder': '請輸入',
'labelName': '顯示名稱', 'labelName': '顯示名稱',
'required': '必填', 'required': '必填',
'hide': '隱藏',
'errorMsg': { 'errorMsg': {
varNameRequired: '變數名稱必填', varNameRequired: '變數名稱必填',
labelNameRequired: '顯示名稱必填', labelNameRequired: '顯示名稱必填',