Commit e879c818 by Liu

fix: 按钮切换&&问答逻辑

parent 66d1d2fd
public-hoist-pattern[]=*@heroui/* public-hoist-pattern[]=*@heroui/*
# On Apple Silicon, optional native deps (e.g. @rspack/binding-*) follow the arch
# of the Node that ran `pnpm install`. If you later run Node as x64 (Rosetta),
# rsbuild needs @rspack/binding-darwin-x64 as well — install both CPU variants.
supportedArchitectures.cpu=x64,arm64
...@@ -24,7 +24,7 @@ export function fetchToolList() { ...@@ -24,7 +24,7 @@ export function fetchToolList() {
* @params * @params
* conversationId: 会话id * conversationId: 会话id
* busiType: 业务类型,固定值 '01' * busiType: 业务类型,固定值 '01'
* recordType: 记录类型,固定值 'A14' * recordType: 记录类型,由当前工具 get_tool_list 项的 userRole 第二段决定
*/ */
export function fetchEfficiencyQuestionList(data: any) { export function fetchEfficiencyQuestionList(data: any) {
return http.post('/conversation/api/conversation/mobile/v1/query_strategy_recommend_question', data) return http.post('/conversation/api/conversation/mobile/v1/query_strategy_recommend_question', data)
......
...@@ -10,6 +10,7 @@ import type { Conversation } from '@/types/conversation' ...@@ -10,6 +10,7 @@ import type { Conversation } from '@/types/conversation'
import { processConversationData } from '@/store/conversationSlice.helper' import { processConversationData } from '@/store/conversationSlice.helper'
import { clearCurrentToolId, clearShouldSendQuestion, setCurrentToolId, setShouldSendQuestion } from '@/store/conversationSlice' import { clearCurrentToolId, clearShouldSendQuestion, setCurrentToolId, setShouldSendQuestion } from '@/store/conversationSlice'
import { isMobile } from '@/utils' import { isMobile } from '@/utils'
import { findToolRowBySessionToolId, readToolListFromSessionStorage, toolRowTriggersHistoryEmptyQuestionSend } from '@/lib/toolRoleRecordTypes'
interface HistoryBarListProps { interface HistoryBarListProps {
searchValue: string searchValue: string
...@@ -40,10 +41,11 @@ export const HistoryBarList: React.FC<HistoryBarListProps> = ({ searchValue, onS ...@@ -40,10 +41,11 @@ export const HistoryBarList: React.FC<HistoryBarListProps> = ({ searchValue, onS
dispatch(clearCurrentToolId()) dispatch(clearCurrentToolId())
} }
// 仅当历史记录为“提质增效”时,进入对话页后自动触发一次提问接口 // 工具会话且列表配置需要时:进入对话页后用空格触发 shouldSendQuestion(trim 后为空,不展示用户气泡)
// 用空格字符串触发 shouldSendQuestion 的监听,但不会在 UI 中新增用户问题气泡(question.trim() 为 false)。 const list = readToolListFromSessionStorage()
const isQualityImprovement = conversation.toolId === '6712395743241' const toolRow = findToolRowBySessionToolId(list, conversation.toolId || '')
if (isQualityImprovement) { const shouldHistoryAutoQuestion = toolRowTriggersHistoryEmptyQuestionSend(toolRow)
if (shouldHistoryAutoQuestion) {
const autoShouldSendQuestion = ' ' const autoShouldSendQuestion = ' '
dispatch(setShouldSendQuestion(autoShouldSendQuestion)) dispatch(setShouldSendQuestion(autoShouldSendQuestion))
console.log('[HistoryBarList] shouldSendQuestion 000000:', { console.log('[HistoryBarList] shouldSendQuestion 000000:', {
......
...@@ -14,6 +14,7 @@ import { useAppDispatch, useAppSelector } from '@/store/hook' ...@@ -14,6 +14,7 @@ import { useAppDispatch, useAppSelector } from '@/store/hook'
import { isMobile } from '@/utils' import { isMobile } from '@/utils'
import { safeLocalStorageSetItem, waitForToken } from '@/lib/utils' import { safeLocalStorageSetItem, waitForToken } from '@/lib/utils'
import { fetchUserQaRecordPage } from '@/api/conversation' import { fetchUserQaRecordPage } from '@/api/conversation'
import { findToolRowBySessionToolId, getToolQuestionPairFromRow, readToolListFromSessionStorage, toolRowTriggersEmptyQuestionBootstrap } from '@/lib/toolRoleRecordTypes'
// import { User } from './components/User' // import { User } from './components/User'
interface NavbarProps { interface NavbarProps {
...@@ -129,52 +130,54 @@ const NavbarBase: React.FC<NavbarProps & WithAuthProps> = ({ isHistoryVisible, c ...@@ -129,52 +130,54 @@ const NavbarBase: React.FC<NavbarProps & WithAuthProps> = ({ isHistoryVisible, c
: `/chat/${currentConversationId}` : `/chat/${currentConversationId}`
// 通过 location.state 传递 toolId,避免在 Chat 页面被误判为"外链残留参数"而强制清空 // 通过 location.state 传递 toolId,避免在 Chat 页面被误判为"外链残留参数"而强制清空
// 如果有 shouldSendQuestion 或者是提质增效模式,传递 skipHistoryLoad 标记,跳过历史记录加载 // 如果有 shouldSendQuestion 或者是提质增效模式,传递 skipHistoryLoad 标记,跳过历史记录加载
const isQualityImprovement = currentToolId === '6712395743241' const hasSessionTool = Boolean(currentToolId?.trim())
navigate(url, { navigate(url, {
state: { state: {
toolId: currentToolId || null, toolId: currentToolId || null,
skipHistoryLoad: Boolean(shouldSendQuestion) || isQualityImprovement, skipHistoryLoad: Boolean(shouldSendQuestion) || hasSessionTool,
}, },
}) })
dispatch(clearNavigationFlag()) dispatch(clearNavigationFlag())
// 提质增效模式下,创建会话后: // 有当前工具且列表配置为需要首包空问题时:拉历史并触发 autoSubmitQuestion
// 1. 使用新会话ID + toolId 主动拉取一次历史记录(与数据助手保持一致) if (hasSessionTool && currentToolId) {
// 2. 再自动触发一次空问题提问(欢迎语)
if (isQualityImprovement && currentToolId) {
// 1) 拉取历史记录并通过自定义事件交给 Chat 渲染
;(async () => { ;(async () => {
try { try {
const list = readToolListFromSessionStorage()
const row = findToolRowBySessionToolId(list, currentToolId)
if (!toolRowTriggersEmptyQuestionBootstrap(row))
return
await waitForToken() await waitForToken()
const qaRes = await fetchUserQaRecordPage(currentConversationId, currentToolId) const qaRes = await fetchUserQaRecordPage(currentConversationId, currentToolId)
window.dispatchEvent(new CustomEvent('toolHistoryLoaded', { window.dispatchEvent(new CustomEvent('toolHistoryLoaded', {
detail: { detail: {
conversationId: currentConversationId, conversationId: currentConversationId,
toolId: currentToolId, toolId: currentToolId,
// 这里不传 toolName,由 Chat 自己根据 currentToolId 解析名称
qaRecords: qaRes?.data || [], qaRecords: qaRes?.data || [],
}, },
})) }))
const pair = getToolQuestionPairFromRow(row)
const recordTypeForAuto = pair.recordType || '01'
requestAnimationFrame(() => {
requestAnimationFrame(() => {
window.dispatchEvent(new CustomEvent('autoSubmitQuestion', {
detail: {
conversationId: currentConversationId,
question: '',
toolId: currentToolId,
recordType: recordTypeForAuto,
busiType: '01',
},
}))
})
})
} }
catch (error) { catch (error) {
console.error('[Navbar] 提质增效模式 - 创建会话后拉取历史记录失败:', error) console.error('[Navbar] 创建会话后拉取历史或自动提问失败:', error)
} }
})() })()
// 2) 使用 requestAnimationFrame 确保在下一个渲染周期执行自动提问
requestAnimationFrame(() => {
requestAnimationFrame(() => {
window.dispatchEvent(new CustomEvent('autoSubmitQuestion', {
detail: {
conversationId: currentConversationId,
question: '',
toolId: currentToolId,
recordType: 'B03',
busiType: '01',
},
}))
})
})
} }
} }
}, [shouldNavigateToNewConversation, currentConversationId, currentToolId, shouldSendQuestion, navigate, dispatch]) }, [shouldNavigateToNewConversation, currentConversationId, currentToolId, shouldSendQuestion, navigate, dispatch])
......
import type { ToolListRow } from '@/types/toolList'
import { getUserRolesForApi } from '@/lib/utils'
/** 与 ChatEditor 写入的 session 缓存键一致 */
export const TOOL_LIST_SESSION_KEY = 'toolList'
function asToolRows(toolList: unknown): ToolListRow[] {
return Array.isArray(toolList) ? (toolList as ToolListRow[]) : []
}
/** 规范化 toolId:空串视为无工具(制度活化会话) */
export function normalizeToolId(toolId: unknown): string {
if (toolId == null)
return ''
const s = String(toolId).trim()
return s
}
/**
* userRole:逗号分隔,依次为
* 1 提问流 recordType;2 左侧常见问题 recordType;3 答后推荐问 recordType
*/
export function parseUserRoleRecordTypes(userRole: unknown): {
questionRecordType: string
commonQuestionRecordType: string
recommendRecordType: string
} {
const raw = userRole != null ? String(userRole) : ''
const parts = raw.split(',').map(p => p.trim()).filter(p => p.length > 0)
return {
questionRecordType: parts[0] ?? '',
commonQuestionRecordType: parts[1] ?? '',
recommendRecordType: parts[2] ?? '',
}
}
/** 列表中无 toolId(或空)的项视为「制度活化 / 通用」会话行 */
export function isGeneralInstitutionalToolRow(row: ToolListRow | null | undefined): boolean {
if (!row)
return false
if (row.isGeneralSession === true || row.isGeneralSession === 1)
return true
return !normalizeToolId(row.toolId)
}
export function findGeneralToolRow(toolList: unknown): ToolListRow | null {
const list = asToolRows(toolList)
const hit = list.find(isGeneralInstitutionalToolRow)
return hit ?? null
}
export function findToolRowBySessionToolId(toolList: unknown, sessionToolId: string | null | undefined): ToolListRow | null {
const list = asToolRows(toolList)
const tid = normalizeToolId(sessionToolId)
if (!tid)
return findGeneralToolRow(toolList)
return list.find(r => normalizeToolId(r.toolId) === tid) ?? null
}
/**
* 提问接口用的 toolId + recordType(recordType 优先 userRole 首段,否则回退行上 recordType)
*/
export function getToolQuestionPairFromRow(row: ToolListRow | null | undefined): { toolId: string, recordType: string } {
if (!row) {
return { toolId: '', recordType: '' }
}
const toolId = normalizeToolId(row.toolId)
const fromRole = parseUserRoleRecordTypes(row.userRole)
const recordType = fromRole.questionRecordType
|| (row.recordType != null ? String(row.recordType).trim() : '')
return { toolId, recordType }
}
/** 左侧常见问题 recordType */
export function getCommonQuestionRecordTypeForToolRow(row: ToolListRow | null | undefined): string {
if (!row)
return ''
const { commonQuestionRecordType, questionRecordType } = parseUserRoleRecordTypes(row.userRole)
return commonQuestionRecordType || questionRecordType
|| (row.recordType != null ? String(row.recordType).trim() : '')
}
/** 答后推荐问 recordType */
export function getRecommendRecordTypeForToolRow(row: ToolListRow | null | undefined): string {
if (!row)
return ''
const { recommendRecordType, questionRecordType } = parseUserRoleRecordTypes(row.userRole)
return recommendRecordType || questionRecordType
|| (row.recordType != null ? String(row.recordType).trim() : '')
}
/** 是否走业务洞察常见问题(由列表行配置驱动,不写死名称或 toolId) */
export function toolRowUsesBusinessInsightCommonQuestions(row: ToolListRow | null | undefined): boolean {
if (!row)
return false
if (row.commonQuestionApi === 'business_insight')
return true
return Array.isArray(row.businessInsightConfigTypes) && row.businessInsightConfigTypes.length > 0
}
export function getBusinessInsightConfigTypesForRow(row: ToolListRow | null | undefined): string[] {
if (!row)
return ['10']
if (Array.isArray(row.businessInsightConfigTypes) && row.businessInsightConfigTypes.length > 0)
return row.businessInsightConfigTypes.map(String)
return ['10']
}
/** 新建会话进入聊天页后,是否需要与底部工具一致:拉历史并触发空问题首包(由配置驱动) */
export function toolRowTriggersEmptyQuestionBootstrap(row: ToolListRow | null | undefined): boolean {
if (!row || !normalizeToolId(row.toolId))
return false
return Boolean(parseUserRoleRecordTypes(row.userRole).questionRecordType)
}
/** 从历史进入会话时,是否派发 shouldSendQuestion 空格触发静默补问(与 toolRowTriggersEmptyQuestionBootstrap 一致) */
export function toolRowTriggersHistoryEmptyQuestionSend(row: ToolListRow | null | undefined): boolean {
return toolRowTriggersEmptyQuestionBootstrap(row)
}
export function readToolListFromSessionStorage(): ToolListRow[] {
try {
const raw = sessionStorage.getItem(TOOL_LIST_SESSION_KEY)
if (!raw)
return tryReadLegacyToolListCache()
const parsed = JSON.parse(raw) as { toolList?: unknown, timestamp?: number }
if (parsed?.toolList && Array.isArray(parsed.toolList))
return asToolRows(parsed.toolList)
if (Array.isArray(parsed))
return asToolRows(parsed)
}
catch {
// ignore
}
return tryReadLegacyToolListCache()
}
function tryReadLegacyToolListCache(): ToolListRow[] {
try {
const userRoles = getUserRolesForApi()
const cacheKey = `toolList_${JSON.stringify(userRoles)}`
const raw = sessionStorage.getItem(cacheKey)
if (!raw)
return []
const { toolList } = JSON.parse(raw) as { toolList?: unknown }
return asToolRows(toolList)
}
catch {
return []
}
}
import { getToolQuestionPairFromRow } from '@/lib/toolRoleRecordTypes'
import type { ToolListRow } from '@/types/toolList'
/**
* 工作流提问参数:首次使用列表项的 userRole 首段(或行上 recordType);
* 之后各次提问使用接口流式返回中最后一次带上的 toolId / recordType。
*/
const STORAGE_KEY = 'workflowLastToolPair'
/** 本次点击会话写入的「列表第 0 项」快照,供 Chat 首次提问在流式返回前读取 */
const SEED_KEY = 'workflowRequestSeedPair'
export function clearWorkflowLastToolPair(): void {
try {
sessionStorage.removeItem(STORAGE_KEY)
}
catch {
// ignore
}
}
export function setWorkflowRequestSeedPair(toolId: string, recordType: string): void {
const tid = toolId?.trim?.() ?? ''
const rt = recordType?.trim?.() ?? ''
if (!tid || !rt)
return
try {
sessionStorage.setItem(SEED_KEY, JSON.stringify({ toolId: tid, recordType: rt }))
}
catch {
// ignore
}
}
export function getWorkflowRequestSeedPair(): { toolId: string, recordType: string } | null {
try {
const raw = sessionStorage.getItem(SEED_KEY)
if (!raw)
return null
const parsed = JSON.parse(raw) as { toolId?: unknown, recordType?: unknown }
const toolId = parsed?.toolId != null ? String(parsed.toolId).trim() : ''
const recordType = parsed?.recordType != null ? String(parsed.recordType).trim() : ''
if (!toolId || !recordType)
return null
return { toolId, recordType }
}
catch {
return null
}
}
export function clearWorkflowRequestSeedPair(): void {
try {
sessionStorage.removeItem(SEED_KEY)
}
catch {
// ignore
}
}
/** 制度活化等场景:清空流式 last 与点击 seed */
export function clearWorkflowToolCaches(): void {
clearWorkflowLastToolPair()
clearWorkflowRequestSeedPair()
}
export function setWorkflowLastToolPair(toolId: string, recordType: string): void {
const tid = toolId?.trim?.() ?? ''
const rt = recordType?.trim?.() ?? ''
if (!tid || !rt)
return
try {
sessionStorage.setItem(STORAGE_KEY, JSON.stringify({ toolId: tid, recordType: rt }))
}
catch {
// ignore
}
}
export function getWorkflowLastToolPair(): { toolId: string, recordType: string } | null {
try {
const raw = sessionStorage.getItem(STORAGE_KEY)
if (!raw)
return null
const parsed = JSON.parse(raw) as { toolId?: unknown, recordType?: unknown }
const toolId = parsed?.toolId != null ? String(parsed.toolId).trim() : ''
const recordType = parsed?.recordType != null ? String(parsed.recordType).trim() : ''
if (!toolId || !recordType)
return null
return { toolId, recordType }
}
catch {
return null
}
}
/** get_tool_list 第 0 项的提问用 toolId / recordType(来自 userRole 首段) */
export function getToolListFirstPair(toolList: unknown[]): { toolId: string, recordType: string } {
const row = Array.isArray(toolList) && toolList.length > 0 ? (toolList[0] as ToolListRow) : null
return getToolQuestionPairFromRow(row)
}
/**
* 组装「提问主工作流」等接口所需的 toolId / recordType:
* 若已有流式返回缓存则优先;否则使用列表第 0 项的 userRole 首段(首次)。
*/
export function getWorkflowToolIdAndRecordTypeForRequest(toolList: unknown[]): { toolId: string, recordType: string } {
const last = getWorkflowLastToolPair()
if (last)
return last
const seed = getWorkflowRequestSeedPair()
if (seed)
return seed
return getToolListFirstPair(toolList)
}
/** Chat 提交:流式最后一次优先,否则为本次点击写入的 seed(get_tool_list[0]) */
export function getWorkflowToolIdAndRecordTypeForSubmit(): { toolId: string, recordType: string } | null {
return getWorkflowLastToolPair() ?? getWorkflowRequestSeedPair()
}
...@@ -3,6 +3,7 @@ import { useSearchParams } from 'react-router-dom' ...@@ -3,6 +3,7 @@ import { useSearchParams } from 'react-router-dom'
import { Button, Skeleton } from '@heroui/react' import { Button, Skeleton } from '@heroui/react'
import type { Answer } from '@/types/chat' import type { Answer } from '@/types/chat'
import { fetchOrderQueryRecommendQuestion } from '@/api/chat' import { fetchOrderQueryRecommendQuestion } from '@/api/chat'
import { findToolRowBySessionToolId, getRecommendRecordTypeForToolRow, readToolListFromSessionStorage } from '@/lib/toolRoleRecordTypes'
import SendIcon from '@/assets/svg/sendBlack.svg?react' import SendIcon from '@/assets/svg/sendBlack.svg?react'
interface ChatAnswerRecommendProps { interface ChatAnswerRecommendProps {
...@@ -47,17 +48,13 @@ export const ChatAnswerRecommend: React.FC<ChatAnswerRecommendProps> = ({ answer ...@@ -47,17 +48,13 @@ export const ChatAnswerRecommend: React.FC<ChatAnswerRecommendProps> = ({ answer
recordType = 'A19' recordType = 'A19'
} }
} }
// 非策略场景
else { else {
// 制度活化:toolId 为空或不存在 const list = readToolListFromSessionStorage()
if (!toolId) { const row = findToolRowBySessionToolId(list, toolId || '')
const rt = getRecommendRecordTypeForToolRow(row)
if (rt) {
busiType = '01' busiType = '01'
recordType = 'A17' recordType = rt
}
// 特殊工具ID
else if (toolId === '6712395743241') {
busiType = '01'
recordType = 'A15'
} }
} }
......
...@@ -2,6 +2,7 @@ import { Avatar } from '@heroui/react' ...@@ -2,6 +2,7 @@ import { Avatar } from '@heroui/react'
import { motion } from 'framer-motion' import { motion } from 'framer-motion'
import AvatarBot from '@/assets/avatarBot.png' import AvatarBot from '@/assets/avatarBot.png'
import AIIcon from '@/assets/ai-icon.png' import AIIcon from '@/assets/ai-icon.png'
import { findToolRowBySessionToolId, readToolListFromSessionStorage } from '@/lib/toolRoleRecordTypes'
interface ChatWelcomeProps { interface ChatWelcomeProps {
toolName?: string toolName?: string
...@@ -9,41 +10,33 @@ interface ChatWelcomeProps { ...@@ -9,41 +10,33 @@ interface ChatWelcomeProps {
} }
export const ChatWelcome: React.FC<ChatWelcomeProps> = ({ toolName: _toolName, welcomeText }) => { export const ChatWelcome: React.FC<ChatWelcomeProps> = ({ toolName: _toolName, welcomeText }) => {
const viteOutputObj = import.meta.env.VITE_OUTPUT_OBJ || 'open' const viteOutputObj = import.meta.env.VITE_OUTPUT_OBJ || 'open'
// 根据不同的 toolName 显示不同的提示语
const getWelcomeText = () => { const getWelcomeText = () => {
// 优先使用从接口返回的欢迎语(历史逻辑)
if (welcomeText) { if (welcomeText) {
return welcomeText return welcomeText
} }
// 回退到基于当前工具的欢迎语逻辑
const currentToolId = typeof window !== 'undefined' ? sessionStorage.getItem('currentToolId') : '' const currentToolId = typeof window !== 'undefined' ? sessionStorage.getItem('currentToolId') : ''
const list = readToolListFromSessionStorage()
const row = findToolRowBySessionToolId(list, currentToolId || '')
const name = row?.toolName?.trim()
// 提质增效:若 sessionStorage 中已有自动调用写入的欢迎语,优先使用该文案 try {
if (currentToolId === '6712395743241') { const stored = typeof window !== 'undefined' ? sessionStorage.getItem('toolStreamWelcomeText') : null
try { if (stored && stored.trim() && currentToolId?.trim()) {
const stored = typeof window !== 'undefined' ? sessionStorage.getItem('qualityWelcomeText') : null return stored
if (stored && stored.trim()) {
return stored
}
} }
catch {
// 读取失败时回退到默认文案
}
return 'Hi,我是AI提质增效助手,可以为您解答研发需求计划和业务功能流程等相关问题。请问有什么可以帮您?'
} }
catch {
if (currentToolId === '6712395743240') { // 读取失败时回退
return 'Hi~我是您的数据助手,可以帮你查询业务数据哦'
} }
if (currentToolId === '6712395743242') { if (name) {
return '业务洞察助手姨就位!当前支持客群洞察,分析客户特征、识别客群价值,请告诉我您的需求吧~' return `Hi,我是${name},请问有什么可以帮您?`
} }
return 'Hi,我是AI制度活化助手,可以为您提供公司规章制度、政策条款的查询与解读服务。请问您想了解什么呢?' return 'Hi,我是您的智能助手,请问有什么可以帮您?'
} }
return ( return (
...@@ -62,7 +55,6 @@ export const ChatWelcome: React.FC<ChatWelcomeProps> = ({ toolName: _toolName, w ...@@ -62,7 +55,6 @@ export const ChatWelcome: React.FC<ChatWelcomeProps> = ({ toolName: _toolName, w
> >
{getWelcomeText()} {getWelcomeText()}
</p> </p>
{/* <p className="text-[15px] mt-[4px] sm:mt-[8px] sm:text-13px text-[#27353C] font-300">作为您的智能保险伙伴,您有各类专业相关的问题都可以抛给我哟~让我们互相帮助共同成长吧~</p> */}
</div> </div>
</motion.div> </motion.div>
</div> </div>
......
import type { ChatRecord, OriginalRecord } from '@/types/chat' import type { Answer, ChatRecord, OriginalRecord } from '@/types/chat'
/**
* 从 query_user_qa_record_list 返回列表的「最后一条」中提取 workflow 上下文。
* 优先在最后一条记录的 answerList 中从后往前找到同时带有 recordType 与 workFlowSessionId 的答案。
*/
export function getLastQaRecordWorkflowContext(qaRecords: OriginalRecord[] | null | undefined): {
recordType?: string
workFlowSessionId?: string
busiType?: string
} {
if (!Array.isArray(qaRecords) || qaRecords.length === 0)
return {}
const lastRecord = qaRecords[qaRecords.length - 1]
const list = lastRecord?.answerList
if (!Array.isArray(list) || list.length === 0)
return {}
for (let i = list.length - 1; i >= 0; i--) {
const a = list[i] as Answer
const recordType = a?.recordType != null ? String(a.recordType).trim() : ''
const workFlowSessionId = a?.workFlowSessionId != null ? String(a.workFlowSessionId).trim() : ''
if (recordType && workFlowSessionId) {
const busiType = a?.busiType != null ? String(a.busiType).trim() : ''
return {
recordType,
workFlowSessionId,
...(busiType ? { busiType } : {}),
}
}
}
return {}
}
export function processApiResponse(data: OriginalRecord[]): ChatRecord[] { export function processApiResponse(data: OriginalRecord[]): ChatRecord[] {
const chatRecord: ChatRecord[] = [] const chatRecord: ChatRecord[] = []
......
...@@ -15,6 +15,13 @@ import { fetchLoginByToken, fetchLoginByUid } from '@/api/common' ...@@ -15,6 +15,13 @@ import { fetchLoginByToken, fetchLoginByUid } from '@/api/common'
import { fetchSessionConversationId } from '@/api/conversation' import { fetchSessionConversationId } from '@/api/conversation'
import { fetchBusinessInsightList, fetchCheckTokenApi } from '@/api/chat' import { fetchBusinessInsightList, fetchCheckTokenApi } from '@/api/chat'
import { getUserRolesFromRoute, safeLocalStorageGetItem, safeLocalStorageSetItem, safeSessionStorageGetItem, safeSessionStorageRemoveItem, safeSessionStorageSetItem, waitForToken } from '@/lib/utils' import { getUserRolesFromRoute, safeLocalStorageGetItem, safeLocalStorageSetItem, safeSessionStorageGetItem, safeSessionStorageRemoveItem, safeSessionStorageSetItem, waitForToken } from '@/lib/utils'
import {
findToolRowBySessionToolId,
getBusinessInsightConfigTypesForRow,
getCommonQuestionRecordTypeForToolRow,
readToolListFromSessionStorage,
toolRowUsesBusinessInsightCommonQuestions,
} from '@/lib/toolRoleRecordTypes'
// 从 localStorage 获取 token 的辅助函数 // 从 localStorage 获取 token 的辅助函数
function getTokenFromStorage(): string | null { function getTokenFromStorage(): string | null {
...@@ -68,6 +75,7 @@ export const Home: React.FC = () => { ...@@ -68,6 +75,7 @@ export const Home: React.FC = () => {
const dispatch = useAppDispatch() const dispatch = useAppDispatch()
const location = useLocation() const location = useLocation()
const currentConversationId = useAppSelector(state => state.conversation.currentConversationId) const currentConversationId = useAppSelector(state => state.conversation.currentConversationId)
const businessInsightConfigTypesRef = useRef<string[]>(['10'])
const hasFetched = useRef(false) const hasFetched = useRef(false)
const hasCalledBusinessApis = useRef(false) // 防止业务接口重复调用 const hasCalledBusinessApis = useRef(false) // 防止业务接口重复调用
const prevPathRef = useRef<string>(location.pathname) // 记录上一次路径,用于检测从收藏页面返回 const prevPathRef = useRef<string>(location.pathname) // 记录上一次路径,用于检测从收藏页面返回
...@@ -106,7 +114,7 @@ export const Home: React.FC = () => { ...@@ -106,7 +114,7 @@ export const Home: React.FC = () => {
} }
const fetchBusinessInsightQuestions = useCallback(async () => { const fetchBusinessInsightQuestions = useCallback(async () => {
const res = await fetchBusinessInsightList({ configTypeList: ['10'] }) const res = await fetchBusinessInsightList({ configTypeList: businessInsightConfigTypesRef.current })
const data = Array.isArray(res?.data) ? res.data[0] : res?.data const data = Array.isArray(res?.data) ? res.data[0] : res?.data
const normalized = parseBusinessInsightQuestions(data?.content ?? data?.questionList) const normalized = parseBusinessInsightQuestions(data?.content ?? data?.questionList)
setOtherQuestions((prev: any) => ({ setOtherQuestions((prev: any) => ({
...@@ -116,20 +124,11 @@ export const Home: React.FC = () => { ...@@ -116,20 +124,11 @@ export const Home: React.FC = () => {
})) }))
}, []) }, [])
// 根据 toolId 获取对应的 recordType const resolveCommonQuestionRecordType = useCallback(async (sessionToolId: string): Promise<string> => {
const getRecordTypeByToolId = (toolId: string | null | undefined): string => { const list = readToolListFromSessionStorage()
if (!toolId) { const row = findToolRowBySessionToolId(list, sessionToolId)
return 'A16' // 制度活化 return getCommonQuestionRecordTypeForToolRow(row) || '01'
} }, [])
if (toolId === '6712395743240') {
return 'A18' // 数据助手
}
if (toolId === '6712395743241') {
return 'A14' // 提质增效
}
// 未知的 toolId,默认返回制度活化
return 'A16'
}
// 获取会话ID并加载历史记录 // 获取会话ID并加载历史记录
const getSessionConversationId = async (data?: any): Promise<string | null> => { const getSessionConversationId = async (data?: any): Promise<string | null> => {
...@@ -185,9 +184,8 @@ export const Home: React.FC = () => { ...@@ -185,9 +184,8 @@ export const Home: React.FC = () => {
return return
} }
// 从 sessionStorage 获取 toolId 并确定 recordType
const toolId = safeSessionStorageGetItem('currentToolId') || '' const toolId = safeSessionStorageGetItem('currentToolId') || ''
const recordType = getRecordTypeByToolId(toolId) const recordType = await resolveCommonQuestionRecordType(toolId)
const res = await fetchEfficiencyQuestionList({ const res = await fetchEfficiencyQuestionList({
conversationId, conversationId,
...@@ -208,7 +206,7 @@ export const Home: React.FC = () => { ...@@ -208,7 +206,7 @@ export const Home: React.FC = () => {
finally { finally {
setIsDataLoaded(true) // 无论成功失败都标记为已加载 setIsDataLoaded(true) // 无论成功失败都标记为已加载
} }
}, [location.search, isBusinessInsightMode, fetchBusinessInsightQuestions]) }, [location.search, isBusinessInsightMode, fetchBusinessInsightQuestions, resolveCommonQuestionRecordType])
// 处理工具按钮点击 // 处理工具按钮点击
const _handleToolClick = useCallback(async (isToolBtn: boolean, toolId?: string, ignoreUrlToolId?: boolean, conversationIdParam?: string | null) => { const _handleToolClick = useCallback(async (isToolBtn: boolean, toolId?: string, ignoreUrlToolId?: boolean, conversationIdParam?: string | null) => {
...@@ -249,9 +247,8 @@ export const Home: React.FC = () => { ...@@ -249,9 +247,8 @@ export const Home: React.FC = () => {
return return
} }
// 从 sessionStorage 获取 toolId 并确定 recordType
const currentToolId = safeSessionStorageGetItem('currentToolId') || '' const currentToolId = safeSessionStorageGetItem('currentToolId') || ''
const recordType = getRecordTypeByToolId(currentToolId) const recordType = await resolveCommonQuestionRecordType(currentToolId)
// 调用真实 API 获取常见问题列表 // 调用真实 API 获取常见问题列表
const res = await fetchEfficiencyQuestionList({ const res = await fetchEfficiencyQuestionList({
...@@ -272,12 +269,12 @@ export const Home: React.FC = () => { ...@@ -272,12 +269,12 @@ export const Home: React.FC = () => {
finally { finally {
setIsDataLoaded(true) // 无论成功失败都标记为已加载 setIsDataLoaded(true) // 无论成功失败都标记为已加载
} }
}, [originalOtherQuestions, location.search, location.pathname, currentConversationId]) }, [originalOtherQuestions, location.search, location.pathname, currentConversationId, resolveCommonQuestionRecordType])
// 监听工具按钮点击事件 // 监听工具按钮点击事件
useEffect(() => { useEffect(() => {
const handleToolClickEvent = (event: CustomEvent) => { const handleToolClickEvent = (event: CustomEvent) => {
const { isToolBtn, toolId, conversationId, toolName, source } = event.detail const { isToolBtn, toolId, conversationId, source } = event.detail
setIsToolBtnActive(isToolBtn) setIsToolBtnActive(isToolBtn)
// 更新样式控制状态 // 更新样式控制状态
setShouldChangeStyle(true) setShouldChangeStyle(true)
...@@ -292,16 +289,14 @@ export const Home: React.FC = () => { ...@@ -292,16 +289,14 @@ export const Home: React.FC = () => {
dispatch(clearCurrentToolId()) dispatch(clearCurrentToolId())
} }
const isBusinessInsightClick = source === 'toolButton' && toolName === '业务洞察' const list = readToolListFromSessionStorage()
const rowForTool = findToolRowBySessionToolId(list, toolId || '')
const isBusinessInsightClick = source === 'toolButton' && toolRowUsesBusinessInsightCommonQuestions(rowForTool)
// 仅在点击“业务洞察”工具按钮时调用业务洞察常见问题接口;其余情况保持原有逻辑
if (isBusinessInsightClick) { if (isBusinessInsightClick) {
setIsBusinessInsightMode(true) setIsBusinessInsightMode(true)
// 清空业务洞察工作流状态
dispatch(clearBusinessInsightWorkflow()) dispatch(clearBusinessInsightWorkflow())
// 保存业务洞察工具ID businessInsightConfigTypesRef.current = getBusinessInsightConfigTypesForRow(rowForTool)
dispatch(setCurrentToolId('6712395743242'))
safeSessionStorageSetItem('currentToolId', '6712395743242')
// 先清空旧数据 // 先清空旧数据
setOtherQuestions((prev: any) => ({ setOtherQuestions((prev: any) => ({
...prev, ...prev,
......
/**
* get_tool_list 单条(字段以后端为准;部分为前端可选扩展)
*/
export interface ToolListRow {
toolId?: string | number | null
toolName?: string | null
userRole?: string | null
/** 兼容旧字段:无 userRole 时可回退 */
recordType?: string | null
toolType?: string | null
toolIcon?: string | null
/** 左侧常见问题走业务洞察配置接口时传入的 configType 列表,如 ['10'] */
businessInsightConfigTypes?: string[] | null
/** 左侧常见问题接口类型:efficiency = query_strategy_recommend_question;business_insight = query_config_list */
commonQuestionApi?: 'efficiency' | 'business_insight' | null
/** 为 true 时展示数据类输入提示并跳过答后推荐问请求 */
showStructuredQueryPlaceholder?: boolean | null
/**
* 为 true 或 1 时表示该列表项对应「无 busiId / 通用」会话(与 toolId 是否为空无关,便于后端仍返回 toolId)
*/
isGeneralSession?: boolean | number | 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