Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
S
sdream-ai-fe
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
侯明涛
sdream-ai-fe
Commits
b4dc7dee
Commit
b4dc7dee
authored
Dec 12, 2025
by
Liu
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat:新建会话逻辑&&重新分析&&清除记录
parent
887c7712
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
206 additions
and
115 deletions
+206
-115
src/components/TacticsChatEditor.tsx
+125
-0
src/pages/Chat/Chat.module.less
+2
-2
src/pages/ChatTactics/TacticsChat.tsx
+0
-0
src/pages/ChatTactics/TacticsHome.tsx
+58
-108
src/pages/ChatTactics/components/TacticsWelcome/index.tsx
+2
-2
src/routes/AppRoutes.tsx
+2
-3
src/routes/RouteChangeHandler.tsx
+17
-0
No files found.
src/components/TacticsChatEditor.tsx
0 → 100644
View file @
b4dc7dee
import
React
,
{
useRef
,
useState
}
from
'react'
import
{
Button
,
Tooltip
}
from
'@heroui/react'
import
SendIcon
from
'@/assets/svg/send.svg?react'
import
{
type
WithAuthProps
,
withAuth
}
from
'@/auth/withAuth'
import
{
useAppSelector
}
from
'@/store/hook'
import
type
{
RootState
}
from
'@/store'
interface
TacticsChatEditorProps
{
onSubmit
?:
(
value
:
string
)
=>
void
onChange
?:
(
value
:
string
)
=>
void
placeholders
?:
string
[]
initialValue
?:
string
}
const
defaultPlaceholders
:
string
[]
=
[]
const
TacticsChatEditorBase
:
React
.
FC
<
TacticsChatEditorProps
&
WithAuthProps
>
=
({
onSubmit
,
onChange
,
placeholders
=
defaultPlaceholders
,
initialValue
=
''
,
checkAuth
,
})
=>
{
const
[
content
,
setContent
]
=
useState
(
initialValue
)
const
textareaRef
=
useRef
<
HTMLTextAreaElement
>
(
null
)
const
isAsking
=
useAppSelector
((
state
:
RootState
)
=>
state
.
chat
.
isAsking
)
const
[
placeholderIndex
]
=
useState
(
0
)
const
currentPlaceholder
=
placeholders
[
placeholderIndex
]
||
'输入您想问的问题吧'
const
adjustHeight
=
()
=>
{
if
(
textareaRef
.
current
)
{
textareaRef
.
current
.
style
.
height
=
'auto'
textareaRef
.
current
.
style
.
height
=
`
${
textareaRef
.
current
.
scrollHeight
}
px`
}
}
const
handleChange
=
(
value
:
string
)
=>
{
setContent
(
value
)
onChange
?.(
value
)
adjustHeight
()
}
const
handleSubmit
=
()
=>
{
// eslint-disable-next-line no-console
console
.
log
(
'[TacticsChatEditor] submit click'
,
{
content
,
isAsking
,
hasOnSubmit
:
Boolean
(
onSubmit
),
})
if
(
isAsking
)
{
// eslint-disable-next-line no-console
console
.
log
(
'[TacticsChatEditor] blocked: isAsking true'
)
return
}
const
authed
=
checkAuth
()
// eslint-disable-next-line no-console
console
.
log
(
'[TacticsChatEditor] auth checked'
,
{
authed
})
if
(
!
authed
)
return
const
trimmed
=
content
.
trim
()
if
(
!
trimmed
)
{
// eslint-disable-next-line no-console
console
.
log
(
'[TacticsChatEditor] blocked: empty content'
)
return
}
// eslint-disable-next-line no-console
console
.
log
(
'[TacticsChatEditor] fire onSubmit'
,
{
trimmed
,
hasOnSubmit
:
Boolean
(
onSubmit
)
})
try
{
onSubmit
?.(
trimmed
)
// eslint-disable-next-line no-console
console
.
log
(
'[TacticsChatEditor] after onSubmit'
)
}
catch
(
error
)
{
console
.
error
(
'[TacticsChatEditor] onSubmit error'
,
error
)
}
setContent
(
''
)
if
(
textareaRef
.
current
)
{
textareaRef
.
current
.
value
=
''
adjustHeight
()
}
}
const
handleKeyDown
=
(
e
:
React
.
KeyboardEvent
<
HTMLTextAreaElement
>
)
=>
{
if
(
e
.
key
===
'Enter'
&&
!
e
.
shiftKey
)
{
e
.
preventDefault
()
handleSubmit
()
}
}
return
(
<
div
className=
"flex items-end w-full h-auto relative mx-auto rounded-[24px] overflow-hidden transition duration-200 py-[8px] pl-[12px] pr-[12px] bg-white border border-[#0a0a0a78] shadow-[0_8px_12px_0_rgba(235,235,235,0.30)]"
>
<
textarea
ref=
{
textareaRef
}
defaultValue=
{
initialValue
}
className=
"w-full min-h-[40px] max-h-[120px] p-2 rounded overflow-y-auto outline-none resize-none"
placeholder=
{
currentPlaceholder
}
onChange=
{
e
=>
handleChange
(
e
.
target
.
value
)
}
onKeyDown=
{
handleKeyDown
}
rows=
{
1
}
/>
<
Tooltip
isOpen=
{
!
content
&&
!
isAsking
}
color=
"foreground"
content=
"请输入您的问题📖"
placement=
"top-end"
>
<
Button
className=
"ask-send"
onPress=
{
handleSubmit
}
radius=
"full"
isDisabled=
{
!
content
||
isAsking
}
isIconOnly
color=
"primary"
>
<
SendIcon
/>
</
Button
>
</
Tooltip
>
</
div
>
)
}
export
const
TacticsChatEditor
=
withAuth
(
TacticsChatEditorBase
)
export
default
TacticsChatEditor
src/pages/Chat/Chat.module.less
View file @
b4dc7dee
...
@@ -24,8 +24,8 @@
...
@@ -24,8 +24,8 @@
overflow: hidden;
overflow: hidden;
}
}
.scrollable {
.scrollable {
flex-direction: column
-reverse
;
flex-direction: column;
align-items:
center
;
align-items:
stretch
;
display: flex;
display: flex;
overflow-x: hidden;
overflow-x: hidden;
overflow-y: scroll;
overflow-y: scroll;
...
...
src/pages/ChatTactics/TacticsChat.tsx
View file @
b4dc7dee
This diff is collapsed.
Click to expand it.
src/pages/ChatTactics/TacticsHome.tsx
View file @
b4dc7dee
// 问答功能独立首页
// 问答功能独立首页
import
type
React
from
'react'
import
type
React
from
'react'
import
{
useCallback
,
useEffect
,
useRef
}
from
'react'
import
{
useCallback
,
useEffect
,
use
Memo
,
use
Ref
}
from
'react'
import
{
useLocation
,
useNavigate
}
from
'react-router-dom'
import
{
useLocation
,
useNavigate
,
useSearchParams
}
from
'react-router-dom'
import
{
useLocalStorageState
}
from
'ahooks'
import
{
useLocalStorageState
}
from
'ahooks'
import
styles
from
'../Home/Home.module.less'
import
styles
from
'../Home/Home.module.less'
import
{
TacticsWelcome
}
from
'./components/TacticsWelcome'
import
{
TacticsWelcome
}
from
'./components/TacticsWelcome'
import
{
clearTacticsNavigationFlag
,
createTacticsConversation
,
deleteTacticsConversations
,
fetchTacticsConversations
}
from
'@/store/tacticsSlice'
import
{
clearTacticsNavigationFlag
,
createTacticsConversation
,
fetchTacticsConversations
}
from
'@/store/tacticsSlice'
import
{
useAppDispatch
,
useAppSelector
}
from
'@/store/hook'
import
{
useAppDispatch
,
useAppSelector
}
from
'@/store/hook'
import
type
{
RootState
}
from
'@/store'
import
type
{
RootState
}
from
'@/store'
import
{
fetchLoginByToken
,
fetchLoginByUid
}
from
'@/api/common'
import
{
fetchLoginByToken
,
fetchLoginByUid
}
from
'@/api/common'
import
{
getUserRolesFromRoute
}
from
'@/lib/utils'
import
{
getUserRolesFromRoute
}
from
'@/lib/utils'
import
{
ChatEditor
}
from
'@/components/ChatEditor'
import
{
TacticsChatEditor
}
from
'@/components/TacticsChatEditor'
import
{
RECOMMEND_QUESTIONS_OTHER
}
from
'@/config/recommendQuestion'
import
{
fetchCheckTokenApi
,
fetchStreamResponse
}
from
'@/api/chat'
import
DeleteIcon
from
'@/assets/svg/delete.svg?react'
import
RefreshIcon
from
'@/assets/svg/refresh.svg?react'
export
const
TacticsHome
:
React
.
FC
=
()
=>
{
export
const
TacticsHome
:
React
.
FC
=
()
=>
{
const
viteOutputObj
=
import
.
meta
.
env
.
VITE_OUTPUT_OBJ
||
'open'
const
viteOutputObj
=
import
.
meta
.
env
.
VITE_OUTPUT_OBJ
||
'open'
const
dispatch
=
useAppDispatch
()
const
dispatch
=
useAppDispatch
()
const
location
=
useLocation
()
const
location
=
useLocation
()
const
navigate
=
useNavigate
()
const
navigate
=
useNavigate
()
const
[
searchParams
]
=
useSearchParams
()
const
hasFetched
=
useRef
(
false
)
const
hasFetched
=
useRef
(
false
)
const
{
shouldNavigateToNewConversation
,
currentConversationId
,
shouldSendQuestion
}
=
useAppSelector
((
state
:
RootState
)
=>
state
.
tactics
)
const
{
shouldNavigateToNewConversation
,
currentConversationId
,
shouldSendQuestion
}
=
useAppSelector
((
state
:
RootState
)
=>
state
.
tactics
)
const
[
token
,
setToken
]
=
useLocalStorageState
<
string
|
undefined
>
(
'__TOKEN__'
,
{
const
[
token
,
setToken
]
=
useLocalStorageState
<
string
|
undefined
>
(
'__TOKEN__'
,
{
defaultValue
:
''
,
defaultValue
:
''
,
})
})
const
abortControllerRef
=
useRef
<
AbortController
|
null
>
(
null
)
// 仅在 from=tactics 且 version=2 时读取并缓存额外参数
const
tacticsMetaFromSearch
=
useMemo
(()
=>
{
const
from
=
searchParams
.
get
(
'from'
)
const
version
=
searchParams
.
get
(
'version'
)
if
(
from
!==
'tactics'
||
version
!==
'2'
)
{
return
undefined
}
return
{
version
,
taskId
:
searchParams
.
get
(
'taskId'
)
||
undefined
,
pinBeginTime
:
searchParams
.
get
(
'pinBeginTime'
)
||
undefined
,
pinEndTime
:
searchParams
.
get
(
'pinEndTime'
)
||
undefined
,
partOrAll
:
searchParams
.
get
(
'partOrAll'
)
||
'all'
,
channel
:
searchParams
.
get
(
'channel'
)
||
'AIphone'
,
channelName
:
searchParams
.
get
(
'channelName'
)
||
undefined
,
}
},
[
searchParams
])
const
tacticsMetaFromStorage
=
useMemo
(()
=>
{
const
raw
=
sessionStorage
.
getItem
(
'tacticsMeta'
)
if
(
!
raw
)
{
return
undefined
}
try
{
const
parsed
=
JSON
.
parse
(
raw
)
if
(
parsed
?.
from
===
'tactics'
&&
parsed
?.
version
===
'2'
)
{
return
parsed
}
}
catch
{
// ignore
}
return
undefined
},
[])
const
tacticsMeta
=
useMemo
(()
=>
tacticsMetaFromSearch
||
tacticsMetaFromStorage
,
[
tacticsMetaFromSearch
,
tacticsMetaFromStorage
])
// 同步到 sessionStorage,便于跳转后读取;仅在有 meta 时写入,避免覆盖重定向缓存
useEffect
(()
=>
{
if
(
tacticsMeta
)
{
sessionStorage
.
setItem
(
'tacticsMeta'
,
JSON
.
stringify
(
tacticsMeta
))
}
},
[
tacticsMeta
])
const
initTacticsConversation
=
()
=>
{
const
initTacticsConversation
=
()
=>
{
const
fromCollect
=
location
.
state
?.
fromCollect
const
fromCollect
=
location
.
state
?.
fromCollect
...
@@ -51,47 +89,12 @@ export const TacticsHome: React.FC = () => {
...
@@ -51,47 +89,12 @@ export const TacticsHome: React.FC = () => {
const
handleCreateConversation
=
useCallback
(
async
(
question
:
string
)
=>
{
const
handleCreateConversation
=
useCallback
(
async
(
question
:
string
)
=>
{
// 如果已有会话,直接调用 submit 接口提交问题,然后跳转到聊天页面
// 如果已有会话,直接调用 submit 接口提交问题,然后跳转到聊天页面
if
(
currentConversationId
)
{
if
(
currentConversationId
)
{
// 停止之前的请求
navigate
(
`/tactics/chat/
${
currentConversationId
}
`
,
{
if
(
abortControllerRef
.
current
)
{
state
:
{
abortControllerRef
.
current
.
abort
()
shouldSendQuestion
:
question
,
}
tacticsMeta
,
// 检查token
await
fetchCheckTokenApi
()
// 创建新的 AbortController
abortControllerRef
.
current
=
new
AbortController
()
let
fetchUrl
=
`/conversation/api/conversation/mobile/v1/submit_question_stream`
const
viteOutputObj
=
import
.
meta
.
env
.
VITE_OUTPUT_OBJ
||
'open'
let
proxy
=
''
if
(
viteOutputObj
===
'open'
)
{
proxy
=
import
.
meta
.
env
.
MODE
!==
'prod'
?
'/api'
:
'/dev-sdream-api'
}
else
{
proxy
=
import
.
meta
.
env
.
MODE
===
'dev'
?
'/api'
:
'/dev-sdream-api'
}
fetchUrl
=
proxy
+
fetchUrl
// 直接调用 submit 接口(消息流会在聊天页面处理,这里只负责发起请求)
fetchStreamResponse
(
fetchUrl
,
{
question
,
conversationId
:
currentConversationId
,
stream
:
true
,
},
()
=>
{
// 在首页不需要处理消息,跳转到聊天页面后会自动刷新加载最新消息
},
},
abortControllerRef
.
current
.
signal
,
})
)
// 跳转到聊天页面查看结果
navigate
(
`/tactics/chat/
${
currentConversationId
}
`
)
return
return
}
}
// 如果没有会话,才创建新会话
// 如果没有会话,才创建新会话
...
@@ -102,7 +105,7 @@ export const TacticsHome: React.FC = () => {
...
@@ -102,7 +105,7 @@ export const TacticsHome: React.FC = () => {
shouldSendQuestion
:
question
,
shouldSendQuestion
:
question
,
}),
}),
)
)
},
[
dispatch
,
currentConversationId
,
navigate
])
},
[
dispatch
,
currentConversationId
,
navigate
,
tacticsMeta
])
// 监听导航到新对话
// 监听导航到新对话
useEffect
(()
=>
{
useEffect
(()
=>
{
...
@@ -111,11 +114,13 @@ export const TacticsHome: React.FC = () => {
...
@@ -111,11 +114,13 @@ export const TacticsHome: React.FC = () => {
navigate
(
url
,
{
navigate
(
url
,
{
state
:
{
state
:
{
shouldSendQuestion
,
shouldSendQuestion
,
tacticsMeta
,
},
},
replace
:
true
,
})
})
dispatch
(
clearTacticsNavigationFlag
())
dispatch
(
clearTacticsNavigationFlag
())
}
}
},
[
shouldNavigateToNewConversation
,
currentConversationId
,
shouldSendQuestion
,
navigate
,
dispatch
])
},
[
shouldNavigateToNewConversation
,
currentConversationId
,
shouldSendQuestion
,
navigate
,
dispatch
,
tacticsMeta
])
const
login
=
useCallback
(
async
()
=>
{
const
login
=
useCallback
(
async
()
=>
{
if
(
hasFetched
.
current
)
{
if
(
hasFetched
.
current
)
{
...
@@ -178,35 +183,6 @@ export const TacticsHome: React.FC = () => {
...
@@ -178,35 +183,6 @@ export const TacticsHome: React.FC = () => {
},
[])
},
[])
// 处理清除记录
// 处理清除记录
const
handleClearRecord
=
useCallback
(
async
()
=>
{
if
(
!
currentConversationId
)
{
return
}
try
{
await
dispatch
(
deleteTacticsConversations
([
currentConversationId
])).
unwrap
()
// 清除后创建新会话
dispatch
(
createTacticsConversation
({
conversationData
:
{},
shouldNavigate
:
false
,
shouldSendQuestion
:
''
,
}),
)
}
catch
(
error
)
{
console
.
error
(
'清除记录失败:'
,
error
)
}
},
[
currentConversationId
,
dispatch
])
// 处理重新分析
const
handleReanalyze
=
useCallback
(
async
()
=>
{
// 重新获取会话列表
await
dispatch
(
fetchTacticsConversations
())
// 如果有当前会话,可以重新加载
if
(
currentConversationId
)
{
navigate
(
`/tactics/chat/
${
currentConversationId
}
`
)
}
},
[
currentConversationId
,
dispatch
,
navigate
])
return
(
return
(
<
div
<
div
...
@@ -215,36 +191,12 @@ export const TacticsHome: React.FC = () => {
...
@@ -215,36 +191,12 @@ export const TacticsHome: React.FC = () => {
height
:
'100vh'
,
height
:
'100vh'
,
display
:
'flex'
,
display
:
'flex'
,
flexDirection
:
'column'
,
flexDirection
:
'column'
,
width
:
'420px'
,
marginLeft
:
'auto'
,
marginLeft
:
'auto'
,
marginRight
:
0
,
marginRight
:
0
,
position
:
'fixed'
,
right
:
0
,
top
:
0
,
backgroundColor
:
'#FFFFFF'
,
backgroundColor
:
'#FFFFFF'
,
zIndex
:
1000
,
zIndex
:
1000
,
}
}
}
}
>
>
{
/* 按钮区域 - 右侧展示 */
}
<
div
className=
"flex justify-end items-center gap-[16px] px-[16px] pt-[16px] pb-[8px]"
>
<
button
type=
"button"
onClick=
{
handleClearRecord
}
className=
"flex items-center gap-[4px] text-[#4A90E2] text-[14px] hover:opacity-80 transition-opacity cursor-pointer bg-transparent border-none outline-none"
>
<
DeleteIcon
className=
"w-[16px] h-[16px] text-[#B2B8C1]"
/>
<
span
>
清除记录
</
span
>
</
button
>
<
button
type=
"button"
onClick=
{
handleReanalyze
}
className=
"flex items-center gap-[4px] text-[#4A90E2] text-[14px] hover:opacity-80 transition-opacity cursor-pointer bg-transparent border-none outline-none"
>
<
RefreshIcon
className=
"w-[16px] h-[16px] text-[#B2B8C1]"
/>
<
span
>
重新分析
</
span
>
</
button
>
</
div
>
<
div
className=
"h-full w-full flex flex-col"
>
<
div
className=
"h-full w-full flex flex-col"
>
{
/* 主要内容区域 - 全屏显示 */
}
{
/* 主要内容区域 - 全屏显示 */
}
<
div
className=
"flex-1 overflow-hidden flex flex-col"
>
<
div
className=
"flex-1 overflow-hidden flex flex-col"
>
...
@@ -254,11 +206,9 @@ export const TacticsHome: React.FC = () => {
...
@@ -254,11 +206,9 @@ export const TacticsHome: React.FC = () => {
</
div
>
</
div
>
{
/* 底部输入框 */
}
{
/* 底部输入框 */
}
<
div
className=
"box-border px-[16px] pb-[18px] pt-[12px] bg-white border-t border-gray-100"
>
<
div
className=
"box-border px-[16px] pb-[18px] pt-[12px] bg-white border-t border-gray-100"
>
<
ChatEditor
<
TacticsChatEditor
showContentTips
onSubmit=
{
handleCreateConversation
}
onSubmit=
{
handleCreateConversation
}
placeholders=
{
RECOMMEND_QUESTIONS_OTHER
}
placeholders=
{
[
''
]
}
hideTools
/>
/>
<
div
className=
"w-full text-center mt-[12px] text-[#3333334d] text-[12px]"
>
<
div
className=
"w-full text-center mt-[12px] text-[#3333334d] text-[12px]"
>
内容由AI模型生成,其准确性和完整性无法保证,仅供参考
内容由AI模型生成,其准确性和完整性无法保证,仅供参考
...
...
src/pages/ChatTactics/components/TacticsWelcome/index.tsx
View file @
b4dc7dee
...
@@ -10,7 +10,7 @@ export const TacticsWelcome: React.FC = () => {
...
@@ -10,7 +10,7 @@ export const TacticsWelcome: React.FC = () => {
return
(
return
(
<
div
className=
"chatWelcomeContainer w-full"
>
<
div
className=
"chatWelcomeContainer w-full"
>
<
div
className=
"h-[
20px] sm:h-[32
px] w-full"
></
div
>
<
div
className=
"h-[
8px] sm:h-[16
px] w-full"
></
div
>
<
div
className=
"flex items-start"
>
<
div
className=
"flex items-start"
>
<
Avatar
className=
"mr-[12px] flex-shrink-0"
src=
{
viteOutputObj
===
'inner'
?
AIIcon
:
AvatarBot
}
/>
<
Avatar
className=
"mr-[12px] flex-shrink-0"
src=
{
viteOutputObj
===
'inner'
?
AIIcon
:
AvatarBot
}
/>
<
motion
.
div
<
motion
.
div
...
@@ -27,7 +27,7 @@ export const TacticsWelcome: React.FC = () => {
...
@@ -27,7 +27,7 @@ export const TacticsWelcome: React.FC = () => {
</
div
>
</
div
>
</
motion
.
div
>
</
motion
.
div
>
</
div
>
</
div
>
<
div
className=
"h-[
20px] sm:h-[32
px] w-full"
></
div
>
<
div
className=
"h-[
12px] sm:h-[24
px] w-full"
></
div
>
</
div
>
</
div
>
)
)
}
}
src/routes/AppRoutes.tsx
View file @
b4dc7dee
...
@@ -15,9 +15,8 @@ const AppRoutesComponent: React.FC = () => {
...
@@ -15,9 +15,8 @@ const AppRoutesComponent: React.FC = () => {
<
Route
path=
"/chat/:id"
element=
{
<
Chat
/>
}
/>
<
Route
path=
"/chat/:id"
element=
{
<
Chat
/>
}
/>
</
Route
>
</
Route
>
<
Route
path=
"/home"
element=
{
<
Home
/>
}
></
Route
>
<
Route
path=
"/home"
element=
{
<
Home
/>
}
></
Route
>
<
Route
path=
"/tactics"
element=
{
<
TacticsHome
/>
}
>
<
Route
path=
"/tactics"
element=
{
<
TacticsHome
/>
}
/>
<
Route
path=
"/tactics/chat/:id"
element=
{
<
TacticsChat
/>
}
/>
<
Route
path=
"/tactics/chat/:id"
element=
{
<
TacticsChat
/>
}
/>
</
Route
>
<
Route
path=
"/collect"
element=
{
<
Collect
/>
}
/>
<
Route
path=
"/collect"
element=
{
<
Collect
/>
}
/>
<
Route
path=
"/tools"
element=
{
<
Tools
/>
}
/>
<
Route
path=
"/tools"
element=
{
<
Tools
/>
}
/>
<
Route
path=
"/protocol/:id"
element=
{
<
Protocol
/>
}
/>
<
Route
path=
"/protocol/:id"
element=
{
<
Protocol
/>
}
/>
...
...
src/routes/RouteChangeHandler.tsx
View file @
b4dc7dee
...
@@ -23,6 +23,23 @@ export function withRouteChangeHandler(WrappedComponent: React.ComponentType) {
...
@@ -23,6 +23,23 @@ export function withRouteChangeHandler(WrappedComponent: React.ComponentType) {
const
searchParams
=
new
URLSearchParams
(
location
.
search
)
const
searchParams
=
new
URLSearchParams
(
location
.
search
)
const
from
=
searchParams
.
get
(
'from'
)
const
from
=
searchParams
.
get
(
'from'
)
if
(
from
===
'tactics'
)
{
if
(
from
===
'tactics'
)
{
// 在重定向前缓存查询参数,供 /tactics 页读取(避免 from 被清理导致丢失)
try
{
const
meta
=
{
version
:
searchParams
.
get
(
'version'
)
||
undefined
,
taskId
:
searchParams
.
get
(
'taskId'
)
||
undefined
,
pinBeginTime
:
searchParams
.
get
(
'pinBeginTime'
)
||
undefined
,
pinEndTime
:
searchParams
.
get
(
'pinEndTime'
)
||
undefined
,
partOrAll
:
searchParams
.
get
(
'partOrAll'
)
||
'all'
,
channel
:
searchParams
.
get
(
'channel'
)
||
'AIphone'
,
channelName
:
searchParams
.
get
(
'channelName'
)
||
undefined
,
from
,
}
sessionStorage
.
setItem
(
'tacticsMeta'
,
JSON
.
stringify
(
meta
))
}
catch
{
// ignore
}
// 重定向到 /tactics,保留其他查询参数
// 重定向到 /tactics,保留其他查询参数
const
newSearchParams
=
new
URLSearchParams
(
location
.
search
)
const
newSearchParams
=
new
URLSearchParams
(
location
.
search
)
newSearchParams
.
delete
(
'from'
)
newSearchParams
.
delete
(
'from'
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment