Commit 2115e7da by Liu

feat(chat): 工作流卡片字段、会话状态与聊天页联动

- 新增 CardWorkflowField,调整 CardWorkflowForm 与附件展示
- 扩展 conversation/chat 类型与 conversationSlice 业务洞察工作流状态
- Chat 与 HomeNew 对接工作流提交与参数逻辑

Co-authored-by: Cursor <cursoragent@cursor.com>
parent 69439c2d
import React from 'react'
import { Input } from '@heroui/react'
export interface WorkflowFieldOption {
id?: string
text?: string
type?: string
}
export interface WorkflowFieldItem {
key: string
label: string
type: string
required?: boolean
multiple?: boolean
options?: WorkflowFieldOption[]
}
interface CardWorkflowFieldProps {
field: WorkflowFieldItem
value: string | string[]
disabled: boolean
onChange: (key: string, value: string | string[]) => void
}
export const CardWorkflowField: React.FC<CardWorkflowFieldProps> = ({
field,
value,
disabled,
onChange,
}) => {
const requiredMark = field.required ? '*' : ''
const label = `${requiredMark}${field.label}`
if (field.type === 'select') {
if (field.multiple) {
const selectedValues = Array.isArray(value) ? value : []
return (
<div>
<label className="block text-[14px] text-[#4b5563] mb-[6px]">{label}</label>
<select
multiple
value={selectedValues}
disabled={disabled}
onChange={(e) => {
const nextValues = Array.from(e.target.selectedOptions).map(option => option.value)
onChange(field.key, nextValues)
}}
className="w-full min-h-[96px] border border-[#d4d4d8] rounded-[12px] px-[12px] py-[8px] text-[14px] bg-white"
>
{(field.options || []).map(option => (
<option key={option.id || option.text} value={option.id || ''}>
{option.text || option.id}
</option>
))}
</select>
</div>
)
}
const selectedValue = typeof value === 'string' ? value : ''
return (
<div>
<label className="block text-[14px] text-[#4b5563] mb-[6px]">{label}</label>
<select
value={selectedValue}
disabled={disabled}
onChange={e => onChange(field.key, e.target.value)}
className="w-full h-[40px] border border-[#d4d4d8] rounded-[12px] px-[12px] text-[14px] bg-white"
>
<option value="">
请选择
{field.label}
</option>
{(field.options || []).map(option => (
<option key={option.id || option.text} value={option.id || ''}>
{option.text || option.id}
</option>
))}
</select>
</div>
)
}
return (
<Input
label={label}
value={typeof value === 'string' ? value : ''}
onChange={e => onChange(field.key, e.target.value)}
isDisabled={disabled}
variant="bordered"
className="w-full"
/>
)
}
......@@ -173,8 +173,8 @@ export const ChatAnswerAttachment: React.FC<ChatAnswerAttachmentProps> = ({
)}
{/* 工作流卡片:card-workflow */}
{attachment.type === 'card-workflow'
&& attachment.content?.name === 'form_input'
&& attachment.content?.fieldList?.some(field => field.type === 'text') && (
&& attachment.content?.name === 'form_input'
&& attachment.content?.fieldList?.length > 0 && (
<CardWorkflowForm
key={`workflow-form-${attachment.id || index}-${answer.recordId || 'new'}`}
attachment={attachment}
......
......@@ -7,7 +7,7 @@ import styles from './Home.module.less'
import { QuestionList } from './components/QuestionList'
import HomeIcon2 from '@/assets/homeIcon2.png'
import SmartIce from '@/assets/smart-ice.png'
import { clearCurrentToolId, fetchConversations, setCurrentConversation, setCurrentToolId, setNavigationFlag } from '@/store/conversationSlice'
import { clearBusinessInsightWorkflow, clearCurrentToolId, fetchConversations, setCurrentConversation, setCurrentToolId, setNavigationFlag } from '@/store/conversationSlice'
import { useAppDispatch, useAppSelector } from '@/store/hook'
import { fetchEfficiencyQuestionList } from '@/api/home'
import SdreamLoading from '@/components/SdreamLoading'
......@@ -297,6 +297,11 @@ export const Home: React.FC = () => {
// 仅在点击“业务洞察”工具按钮时调用业务洞察常见问题接口;其余情况保持原有逻辑
if (isBusinessInsightClick) {
setIsBusinessInsightMode(true)
// 清空业务洞察工作流状态
dispatch(clearBusinessInsightWorkflow())
// 保存业务洞察工具ID
dispatch(setCurrentToolId('6712395743242'))
safeSessionStorageSetItem('currentToolId', '6712395743242')
// 先清空旧数据
setOtherQuestions((prev: any) => ({
...prev,
......
......@@ -13,6 +13,14 @@ const initialState: ConversationState = {
shouldNavigateToNewConversation: false,
shouldSendQuestion: '',
currentToolId: undefined,
businessInsightWorkflow: {
mainWorkflowSessionId: null,
subWorkflowSessionId: null,
subWorkflowRecordType: null,
paramMap: {},
isInSubWorkflow: false,
pendingQuestion: null,
},
}
export const fetchConversations = createAsyncThunk(
......@@ -119,6 +127,47 @@ const conversationSlice = createSlice({
clearCurrentToolId: (state) => {
state.currentToolId = undefined
},
setBusinessInsightMainWorkflow: (state, action: PayloadAction<string>) => {
state.businessInsightWorkflow.mainWorkflowSessionId = action.payload
state.businessInsightWorkflow.isInSubWorkflow = false
},
setBusinessInsightSubWorkflow: (state, action: PayloadAction<{ sessionId: string, recordType: string }>) => {
state.businessInsightWorkflow.subWorkflowSessionId = action.payload.sessionId
state.businessInsightWorkflow.subWorkflowRecordType = action.payload.recordType
state.businessInsightWorkflow.isInSubWorkflow = true
state.businessInsightWorkflow.paramMap = {}
},
updateBusinessInsightParamMap: (state, action: PayloadAction<Record<string, string>>) => {
state.businessInsightWorkflow.paramMap = {
...state.businessInsightWorkflow.paramMap,
...action.payload,
}
},
clearBusinessInsightSubWorkflow: (state) => {
state.businessInsightWorkflow.subWorkflowSessionId = null
state.businessInsightWorkflow.subWorkflowRecordType = null
state.businessInsightWorkflow.isInSubWorkflow = false
state.businessInsightWorkflow.paramMap = {}
},
exitBusinessInsightSubWorkflow: (state) => {
state.businessInsightWorkflow.isInSubWorkflow = false
state.businessInsightWorkflow.subWorkflowSessionId = null
state.businessInsightWorkflow.subWorkflowRecordType = null
state.businessInsightWorkflow.paramMap = {}
},
setBusinessInsightPendingQuestion: (state, action: PayloadAction<string | null>) => {
state.businessInsightWorkflow.pendingQuestion = action.payload
},
clearBusinessInsightWorkflow: (state) => {
state.businessInsightWorkflow = {
mainWorkflowSessionId: null,
subWorkflowSessionId: null,
subWorkflowRecordType: null,
paramMap: {},
isInSubWorkflow: false,
pendingQuestion: null,
}
},
removeConversation: (state, action: PayloadAction<string>) => {
state.conversations = state.conversations.filter(conv => conv.conversationId !== action.payload)
if (state.currentConversationId === action.payload) {
......@@ -164,6 +213,6 @@ const conversationSlice = createSlice({
},
})
export const { setCurrentConversation, clearCurrentConversation, clearNavigationFlag, setNavigationFlag, clearShouldSendQuestion, setShouldSendQuestion, setCurrentToolId, clearCurrentToolId } = conversationSlice.actions
export const { setCurrentConversation, clearCurrentConversation, clearNavigationFlag, setNavigationFlag, clearShouldSendQuestion, setShouldSendQuestion, setCurrentToolId, clearCurrentToolId, setBusinessInsightMainWorkflow, setBusinessInsightSubWorkflow, updateBusinessInsightParamMap, clearBusinessInsightSubWorkflow, exitBusinessInsightSubWorkflow, setBusinessInsightPendingQuestion, clearBusinessInsightWorkflow } = conversationSlice.actions
export default conversationSlice.reducer
......@@ -21,6 +21,13 @@ interface AttachmentContentField {
label: string
type: string
required?: boolean
multiple?: boolean
value?: string
options?: {
id?: string
text?: string
type?: string
}[]
}
interface AttachmentContent {
......
......@@ -16,4 +16,12 @@ export interface ConversationState {
error: string | null
shouldSendQuestion: string
currentToolId: string | undefined
businessInsightWorkflow: {
mainWorkflowSessionId: string | null
subWorkflowSessionId: string | null
subWorkflowRecordType: string | null
paramMap: Record<string, string>
isInSubWorkflow: boolean
pendingQuestion: string | null
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment