Commit 57f63bd8 by Liu

fix:默认工具展示

parent e019d3ac
......@@ -40,12 +40,13 @@ export function fetchDeleteUserConversation(conversationIdList: string[]) {
* @params
*/
export function fetchSessionConversationId<T>(data: T) {
const toolId = safeSessionStorageGetItem('currentToolId') || ''
const payload = (data || {}) as Record<string, any>
const sessionToolId = safeSessionStorageGetItem('currentToolId') || ''
const requestData = {
...(data as Record<string, any>),
...payload,
busiType: '01',
busiId: (data as Record<string, any>)?.busiId || '',
toolId,
busiId: sessionToolId || payload?.busiId || '',
toolId: sessionToolId || payload?.toolId || '',
}
return http.post('/conversation/api/conversation/mobile/v1/get_user_conversation_session', requestData)
}
import http from '@/utils/request'
const TOOL_LIST_CACHE_TTL = 5 * 60 * 1000
const toolListCache = new Map<string, { timestamp: number, response: any }>()
const toolListPending = new Map<string, Promise<any>>()
function getToolListCacheKey(params?: { userRoles?: string[] }) {
return JSON.stringify({
toolType: '03',
userRoles: params?.userRoles || [],
})
}
/**
* 查询推荐问题列表
* @params
......@@ -13,13 +24,40 @@ export function fetchQuestionList(data: any) {
* @params params.userRoles: 角色数组,用于按角色返回工具
*/
export function fetchToolList(params?: { userRoles?: string[] }) {
const cacheKey = getToolListCacheKey(params)
const now = Date.now()
const cached = toolListCache.get(cacheKey)
if (cached && now - cached.timestamp < TOOL_LIST_CACHE_TTL) {
return Promise.resolve(cached.response)
}
const pending = toolListPending.get(cacheKey)
if (pending) {
return pending
}
const requestBody: Record<string, string | string[]> = {
toolType: '03',
userRoles: [],
}
if (params?.userRoles)
requestBody.userRoles = params.userRoles
return http.post('/config-center/api/tool/mobile/v1/get_tool_list', requestBody)
const request = http.post('/config-center/api/tool/mobile/v1/get_tool_list', requestBody)
.then((res) => {
toolListCache.set(cacheKey, {
timestamp: Date.now(),
response: res,
})
toolListPending.delete(cacheKey)
return res
})
.catch((error) => {
toolListPending.delete(cacheKey)
throw error
})
toolListPending.set(cacheKey, request)
return request
}
/**
......
......@@ -127,13 +127,23 @@ const ChatEditorBase: React.FC<ChatEditorProps & WithAuthProps> = ({ checkAuth,
// 获取工具列表
const getToolList = async () => {
try {
console.log('[get_tool_list][ChatEditor] start', {
pathname: location.pathname,
search: location.search,
hideTools,
})
// 等待 token 就绪后再调用接口
await waitForToken()
// 从路由中获取 userRoles 参数
const userRoles = getUserRolesForApi()
console.log('[get_tool_list][ChatEditor] request', { userRoles })
// 调用真实 API 获取工具列表
const res = await fetchToolList({ userRoles })
console.log('[get_tool_list][ChatEditor] response', {
success: Boolean(res),
length: Array.isArray(res?.data) ? res.data.length : -1,
})
if (res?.data && Array.isArray(res.data) && res.data.length > 0) {
setToolList(res.data)
// 存入第0个工具信息到缓存
......@@ -149,9 +159,11 @@ const ChatEditorBase: React.FC<ChatEditorProps & WithAuthProps> = ({ checkAuth,
// 根据 currentToolId 以及 sessionStorage 中的记录决定高亮逻辑
useEffect(() => {
console.log('[chat-toolid-log] ChatEditor currentToolId:', currentToolId, '| sessionToolId:', sessionToolId, '| fromCollect:', fromCollect)
if (currentToolId && !sessionToolId && !fromCollect) {
// 清除过期的 Redux 值
dispatch(clearCurrentToolId())
console.log('[chat-toolid-log] ChatEditor 清除 Redux - 逻辑三 - line:155')
// 如果 URL 中还有 toolId,也清除它
if (toolIdFromUrl) {
const newSearchParams = new URLSearchParams(searchParams)
......@@ -165,6 +177,7 @@ const ChatEditorBase: React.FC<ChatEditorProps & WithAuthProps> = ({ checkAuth,
const defaultTool = toolList[0]
safeSessionStorageSetItem('currentToolId', defaultTool.toolId)
safeSessionStorageSetItem('currentToolName', defaultTool.toolName)
console.log('[chat-toolid-log] ChatEditor 逻辑三 setItem:', defaultTool.toolId, '| line:169')
}
return
}
......@@ -238,6 +251,7 @@ const ChatEditorBase: React.FC<ChatEditorProps & WithAuthProps> = ({ checkAuth,
const storedToolId = safeSessionStorageGetItem('currentToolId')
// 如果 currentToolId 是空字符串,视为 null,确保制度活化能正确高亮
setSessionToolId(storedToolId && storedToolId.trim() ? storedToolId : null)
console.log('[chat-toolid-log] ChatEditor syncSessionToolId:', storedToolId && storedToolId.trim() ? storedToolId : null, '| line:242')
}
syncSessionToolId()
window.addEventListener('storage', syncSessionToolId)
......@@ -267,6 +281,7 @@ const ChatEditorBase: React.FC<ChatEditorProps & WithAuthProps> = ({ checkAuth,
const storedToolId = safeSessionStorageGetItem('currentToolId')
// 如果 currentToolId 是空字符串,视为 null,确保制度活化能正确高亮
setSessionToolId(storedToolId && storedToolId.trim() ? storedToolId : null)
console.log('[chat-toolid-log] ChatEditor location useEffect:', storedToolId && storedToolId.trim() ? storedToolId : null, '| line:272')
// 当路由切换(如点击历史记录)时,同步最新的 sessionStorage,避免同标签页删除后状态不同步
}, [toolIdFromUrl, location.pathname])
......@@ -355,9 +370,10 @@ const ChatEditorBase: React.FC<ChatEditorProps & WithAuthProps> = ({ checkAuth,
safeSessionStorageRemoveItem('showToolQuestion')
// 存入默认高亮按钮信息到缓存
if (toolList.length > 0) {
safeSessionStorageSetItem('currentToolId', defaultTool.toolId)
safeSessionStorageRemoveItem('currentToolId')
safeSessionStorageSetItem('currentToolName', defaultTool.toolName)
setSessionToolId(defaultTool.toolId)
setSessionToolId(null)
console.log('[chat-toolid-log] ChatEditor defaultTool clearSessionToolId', '| line:364')
}
setShowToolQuestion(false)
// 先通知上层更新欢迎语(即便后续接口异常也能生效)
......@@ -440,6 +456,7 @@ const ChatEditorBase: React.FC<ChatEditorProps & WithAuthProps> = ({ checkAuth,
safeSessionStorageSetItem('currentToolId', tool.toolId)
safeSessionStorageSetItem('currentToolName', tool.toolName)
setSessionToolId(tool.toolId)
console.log('[chat-toolid-log] ChatEditor tool click setSessionToolId:', tool.toolId, '| line:447')
// 先调用 fetchSessionConversationId 获取会话ID
// 等待 token 就绪后再调用接口
......@@ -530,6 +547,11 @@ const ChatEditorBase: React.FC<ChatEditorProps & WithAuthProps> = ({ checkAuth,
// 组件加载时和路由参数变化时获取工具列表
useEffect(() => {
if (!hideTools) {
console.log('[get_tool_list][ChatEditor] useEffect trigger', {
pathname: location.pathname,
search: location.search,
hideTools,
})
getToolList()
}
}, [location.pathname, location.search, hideTools])
......@@ -651,7 +673,17 @@ const ChatEditorBase: React.FC<ChatEditorProps & WithAuthProps> = ({ checkAuth,
const selectedColor = isSelected ? 'primary' : 'default'
const handleButtonPress = async () => {
// 高亮状态直接返回,避免重复触发
// 点击即同步缓存,制度活化清空 toolId,工具模式写入当前 toolId
if (index === 0) {
safeSessionStorageRemoveItem('currentToolId')
setSessionToolId(null)
}
else {
safeSessionStorageSetItem('currentToolId', toolIdStr)
setSessionToolId(toolIdStr)
}
safeSessionStorageSetItem('currentToolName', tool.toolName || '')
// 高亮状态直接返回,避免重复触发后续逻辑
if (isSelected)
return
if (index === 0)
......
......@@ -33,16 +33,26 @@ export const HistoryBarList: React.FC<HistoryBarListProps> = ({ searchValue, onS
})
if (conversation.toolId) {
sessionStorage.setItem('currentToolId', conversation.toolId)
console.log('[chat-toolid-log] HistoryBarList setItem:', conversation.toolId, '| line:35')
dispatch(setCurrentToolId(conversation.toolId))
}
else {
sessionStorage.removeItem('currentToolId')
console.log('[chat-toolid-log] HistoryBarList removeItem', '| line:39')
dispatch(clearCurrentToolId())
}
// 仅当历史记录为“提质增效”时,进入对话页后自动触发一次提问接口
// 用空格字符串触发 shouldSendQuestion 的监听,但不会在 UI 中新增用户问题气泡(question.trim() 为 false)。
const isQualityImprovement = conversation.toolId === '6712395743241'
const isBusinessInsight = conversation.toolId === '6712395743242'
console.log('工具ID:', {
conversationId: conversation.conversationId,
toolId: conversation.toolId,
isQualityImprovement,
isBusinessInsight,
willAutoSubmitByShouldSendQuestion: isQualityImprovement,
})
if (isQualityImprovement) {
const autoShouldSendQuestion = ' '
dispatch(setShouldSendQuestion(autoShouldSendQuestion))
......@@ -54,6 +64,10 @@ export const HistoryBarList: React.FC<HistoryBarListProps> = ({ searchValue, onS
}
else {
// 避免上一次残留的 shouldSendQuestion 误触发自动提问
console.log('工具ID:2', {
conversationId: conversation.conversationId,
toolId: conversation.toolId,
})
dispatch(clearShouldSendQuestion())
}
// 直接导航到历史记录,不设置shouldSendQuestion
......
......@@ -13,7 +13,11 @@ export function cn(...inputs: ClassValue[]) {
*/
export function safeSessionStorageGetItem(key: string): string | null {
try {
return sessionStorage.getItem(key)
const result = sessionStorage.getItem(key)
if (key === 'currentToolId') {
console.log('[chat-toolid-log] safeGetItem:', result, '| caller line')
}
return result
}
catch {
// 在无痕模式或存储被禁用时,静默失败
......@@ -27,6 +31,9 @@ export function safeSessionStorageGetItem(key: string): string | null {
*/
export function safeSessionStorageSetItem(key: string, value: string): void {
try {
if (key === 'currentToolId') {
console.log('[chat-toolid-log] safeSetItem:', value, '| caller line')
}
sessionStorage.setItem(key, value)
}
catch {
......
......@@ -77,13 +77,13 @@ export const Chat: React.FC = () => {
const hasAutoWelcomeCandidateRef = useRef<boolean>(false)
// 当外部系统直接以 /chat/:id 链接进入(没有 location.state,且 URL 中也没有 toolId)时,
// 视为一次新的会话入口:重置为制度活化,清除历史遗留的工具模式状态
useEffect(() => {
if (!location.state && !rawToolIdFromUrl) {
dispatch(clearCurrentToolId())
// sessionStorage.removeItem('currentToolId')
}
}, [location.state, rawToolIdFromUrl, dispatch])
// 首次进入不清除 sessionStorage 中的 toolId,保留首页点击工具后的状态
// useEffect(() => {
// if (!location.state && !rawToolIdFromUrl) {
// dispatch(clearCurrentToolId())
// // sessionStorage.removeItem('currentToolId')
// }
// }, [location.state, rawToolIdFromUrl, dispatch])
// 若链接中带有 toolId,进入页面后强制清空(避免沿用历史链接参数)
useEffect(() => {
if (!shouldForceClearUrlToolId)
......@@ -149,15 +149,18 @@ export const Chat: React.FC = () => {
useEffect(() => {
// 保存从 location.state 传递的 toolId 到 ref
toolIdFromStateRef.current = initialToolId
console.log('[chat-toolid-log] Chat initialToolId:', initialToolId, '| sessionStorage:', sessionStorage.getItem('currentToolId'))
if (typeof initialToolId === 'undefined')
return
if (initialToolId) {
// 统一转换为字符串,确保类型一致(真实API可能返回数字,需要转换为字符串)
const normalizedToolId = String(initialToolId)
dispatch(setCurrentToolId(normalizedToolId))
console.log('[chat-toolid-log] Chat setCurrentToolId:', normalizedToolId)
}
else {
dispatch(clearCurrentToolId())
console.log('[chat-toolid-log] Chat clearCurrentToolId')
}
}, [dispatch, initialToolId])
......@@ -305,6 +308,19 @@ export const Chat: React.FC = () => {
// 判断是否为提质增效模式的自动调用(空问题)
const isEmptyQuestion = !question.trim()
const isQualityImprovement = resolvedToolId === '6712395743241'
const isBusinessInsight = resolvedToolId === '6712395743242'
console.log('工具id3', {
question,
questionLength: question.length,
isEmptyQuestion,
toolIdFromArg: toolId,
sessionToolId,
reduxCurrentToolId: currentToolId,
resolvedToolId,
isQualityImprovement,
isBusinessInsight,
extraParams,
})
isAutoSubmitQualityImprovementRef.current = isEmptyQuestion && isQualityImprovement
if (isAutoSubmitQualityImprovementRef.current) {
// 重置欢迎语候选
......@@ -320,7 +336,9 @@ export const Chat: React.FC = () => {
dispatch(setIsAsking(true))
// 检查token
console.log('[Chat] before fetchCheckTokenApi')
await fetchCheckTokenApi()
console.log('[Chat] after fetchCheckTokenApi')
// 如果 question 不为空,才添加用户问题和空的AI回答(自动提问时 question 为空,不显示)
if (question.trim()) {
......@@ -671,14 +689,11 @@ export const Chat: React.FC = () => {
}
// 无条件同步到 sessionStorage,确保 ChatEditor 和 handleSubmitQuestion 能获取到正确的 toolId
sessionStorage.setItem('currentToolId', toolIdFromState)
console.log('[chat-toolid-log] Chat setItem:', toolIdFromState, '| line:676')
}
else {
// 如果从 location.state 传递的是 null,清除 toolId
if (currentToolId) {
dispatch(clearCurrentToolId())
}
// 清除 sessionStorage,确保制度活化模式正确
sessionStorage.removeItem('currentToolId')
// 如果从 location.state 传递的是 null,视为未指定 toolId,保留当前缓存,避免首次进入时误清空
console.log('[chat-toolid-log] Chat keep currentToolId when state toolId is null', '| line:684')
}
// 清除 ref,避免下次路由变化时误用
toolIdFromStateRef.current = undefined
......@@ -695,12 +710,14 @@ export const Chat: React.FC = () => {
// 从收藏返回时,同步到 sessionStorage,避免 ChatEditor 清除 toolId
if (fromCollect) {
sessionStorage.setItem('currentToolId', finalToolId)
console.log('[chat-toolid-log] Chat setItem:', finalToolId, '| line:702')
}
}
else {
// 从收藏返回时,确保 sessionStorage 中有值
if (fromCollect && !sessionStorage.getItem('currentToolId')) {
sessionStorage.setItem('currentToolId', finalToolId)
console.log('[chat-toolid-log] Chat setItem:', finalToolId, '| line:708')
}
}
}
......@@ -709,12 +726,14 @@ export const Chat: React.FC = () => {
// 如果有历史记录但没有 toolId,说明是制度活化,应该清除
if (hasQaRecords && currentToolId) {
dispatch(clearCurrentToolId())
console.log('[chat-toolid-log] Chat clearCurrentToolId - hasQaRecords && currentToolId', '| line:716')
}
// 如果没有历史记录,可能是新会话,但如果 Redux 中已经有 toolId(从 HistoryBarList 设置的),暂时保留
// 因为可能是刚点击历史记录但 API 还没返回,或者 location.state 传递失败但 Redux 中已有正确的值
else if (!hasQaRecords && currentToolId) {
if (fromCollect && !sessionStorage.getItem('currentToolId')) {
sessionStorage.setItem('currentToolId', currentToolId)
console.log('[chat-toolid-log] Chat setItem:', currentToolId, '| line:722')
}
}
}
......@@ -834,6 +853,15 @@ export const Chat: React.FC = () => {
// 处理shouldSendQuestion的变化 - 自动发送问题
useEffect(() => {
console.log('[Chat] auto-send effect check:', {
shouldSendQuestion,
currentIdRef: currentIdRef.current,
isLoading,
allItemsLength: allItems.length,
lastSentQuestion: lastSentQuestionRef.current,
historyLoadedConversationId: historyLoadedRef.current.conversationId,
currentToolId,
})
if (
shouldSendQuestion
&& currentIdRef.current
......@@ -864,9 +892,23 @@ export const Chat: React.FC = () => {
}
else {
// 如果历史记录还在加载中,保存待发送的问题,等待历史记录加载完成后再发送
console.log('[Chat] auto-send blocked by history loading, stash pending question:', {
shouldSendQuestion,
historyLoadedConversationId: historyLoadedRef.current.conversationId,
currentConversationId: currentIdRef.current,
allItemsLength: allItems.length,
})
pendingQuestionRef.current = shouldSendQuestion
}
}
else {
console.log('[Chat] auto-send conditions not met:', {
hasShouldSendQuestion: Boolean(shouldSendQuestion),
hasConversationId: Boolean(currentIdRef.current),
isLoading,
isDuplicateQuestion: shouldSendQuestion === lastSentQuestionRef.current,
})
}
}, [shouldSendQuestion, isLoading, allItems.length, currentToolId, id])
// 根据 currentToolId 获取对应的 toolName
......@@ -878,6 +920,12 @@ export const Chat: React.FC = () => {
const userRoles = getUserRolesForApi()
const cacheKey = `toolList_${JSON.stringify(userRoles)}`
const cached = sessionStorage.getItem(cacheKey)
console.log('[get_tool_list][Chat] check cache', {
currentToolId,
userRoles,
cacheKey,
hasCached: Boolean(cached),
})
if (cached) {
try {
......@@ -886,6 +934,10 @@ export const Chat: React.FC = () => {
if (Date.now() - timestamp < 5 * 60 * 1000) {
const tool = toolList.find((t: any) => t.toolId === currentToolId)
if (tool?.toolName) {
console.log('[get_tool_list][Chat] cache hit', {
currentToolId,
toolName: tool.toolName,
})
setCurrentToolName(tool.toolName)
return
}
......@@ -897,8 +949,16 @@ export const Chat: React.FC = () => {
}
// 缓存无效或找不到工具时才调用接口
console.log('[get_tool_list][Chat] cache miss, request get_tool_list', {
currentToolId,
userRoles,
})
await waitForToken()
const res = await fetchToolList({ userRoles })
console.log('[get_tool_list][Chat] response', {
success: Boolean(res),
length: Array.isArray(res?.data) ? res.data.length : -1,
})
if (res?.data) {
const tool = res.data.find((t: any) => t.toolId === currentToolId)
if (tool?.toolName) {
......
......@@ -54,13 +54,22 @@ export const ChatAnswerRecommend: React.FC<ChatAnswerRecommendProps> = ({ answer
busiType = '01'
recordType = 'A17'
}
// 特殊工具ID
// 特殊工具ID 提质增效
else if (toolId === '6712395743241') {
busiType = '01'
recordType = 'A15'
}
// 特殊工具ID 业务洞察
else if (toolId === '6712395743242') {
busiType = '01'
recordType = 'A12'
}
// 特殊工具ID 数据助手
else if (toolId === '6712395743240') {
busiType = '01'
recordType = 'A18'
}
}
try {
const res = await fetchOrderQueryRecommendQuestion(
answer.conversationId || '',
......
......@@ -70,6 +70,7 @@ export const Home: React.FC = () => {
const currentConversationId = useAppSelector(state => state.conversation.currentConversationId)
const hasFetched = useRef(false)
const hasCalledBusinessApis = useRef(false) // 防止业务接口重复调用
const initialToolIdRef = useRef<string>('') // 首次进入时缓存的 toolId,避免登录清理后首次请求丢失
const prevPathRef = useRef<string>(location.pathname) // 记录上一次路径,用于检测从收藏页面返回
// 使用 useState
const [otherQuestions, setOtherQuestions] = useState<any>({ content: [] })
......@@ -97,6 +98,9 @@ export const Home: React.FC = () => {
if (toolId === '6712395743241') {
return 'A14' // 提质增效
}
if (toolId === '6712395743242') {
return 'A12' // 业务洞察
}
// 未知的 toolId,默认返回制度活化
return 'A16'
}
......@@ -106,18 +110,12 @@ export const Home: React.FC = () => {
try {
// 等待 token 就绪后再调用接口
await waitForToken()
// 从 sessionStorage 获取 toolId 作为 busiId
const toolId = safeSessionStorageGetItem('currentToolId') || ''
const requestData = {
...(data || {}),
busiId: toolId,
}
const res = await fetchSessionConversationId(requestData)
// 仅透传业务方附加参数,busiId/toolId 统一在接口层按 sessionStorage 实时解析
const res = await fetchSessionConversationId(data || {})
if (res?.data?.conversationId) {
const conversationId = res.data.conversationId
dispatch(setCurrentConversation(conversationId))
dispatch(setNavigationFlag(true))
// 历史记录会在 Chat 页面自动渲染,不需要在这里获取
// 移除重复调用,避免接口被调用两次
return conversationId
......@@ -151,7 +149,7 @@ export const Home: React.FC = () => {
}
// 从 sessionStorage 获取 toolId 并确定 recordType
const toolId = safeSessionStorageGetItem('currentToolId') || ''
const toolId = safeSessionStorageGetItem('currentToolId') || initialToolIdRef.current || ''
const recordType = getRecordTypeByToolId(toolId)
const res = await fetchEfficiencyQuestionList({
......@@ -214,7 +212,7 @@ export const Home: React.FC = () => {
}
// 从 sessionStorage 获取 toolId 并确定 recordType
const currentToolId = safeSessionStorageGetItem('currentToolId') || ''
const currentToolId = safeSessionStorageGetItem('currentToolId') || finalToolId || initialToolIdRef.current || ''
const recordType = getRecordTypeByToolId(currentToolId)
// 调用真实 API 获取常见问题列表
......@@ -250,10 +248,14 @@ export const Home: React.FC = () => {
if (!isToolBtn && toolId) {
// 提质增效模式,保存 toolId
dispatch(setCurrentToolId(toolId))
safeSessionStorageSetItem('currentToolId', toolId)
console.log('[chat-toolid-log] HomeNew setItem:', toolId, '| line:253')
}
else {
// 制度活化,清除 toolId
dispatch(clearCurrentToolId())
sessionStorage.removeItem('currentToolId')
console.log('[chat-toolid-log] HomeNew removeItem', '| line:260')
}
// 如果事件传递了 conversationId,延迟调用以确保路由更新完成
......@@ -301,7 +303,10 @@ export const Home: React.FC = () => {
const searchParams = new URLSearchParams(url.search)
const from = searchParams.get('from')
const _loginCode = searchParams.get('loginCode')
// 记录首次进入时的 toolId,避免在登录流程清理后丢失首次会话参数
if (!initialToolIdRef.current) {
initialToolIdRef.current = safeSessionStorageGetItem('currentToolId') || ''
}
// 如果有 loginCode,执行 SSO 登录(包括 from=tactics 的情况)
if (_loginCode && viteOutputObj === 'inner') {
// 立即设置标志,防止重复执行(仅组件级别,每次组件挂载时会重置)
......
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