lanxin пре 1 месец
родитељ
комит
4a0a339a57

Разлика између датотеке није приказан због своје велике величине
+ 9 - 9
public/myData/data.js


+ 47 - 13
src/pages/A3detailPannel/index.tsx

@@ -1,6 +1,7 @@
 import React, { useState, useEffect } from 'react'
 import styles from './index.module.scss'
-import { useNavigate } from 'react-router-dom'
+import { useNavigate, useSearchParams } from 'react-router-dom'
+import { buildIntroPath } from '@/utils/detailNav'
 import closeBtn from '@/assets/img/closeBtn.png'
 import searchIcon from '@/assets/img/searchIcon.png'
 import { Pagination } from 'antd'
@@ -9,15 +10,48 @@ import Intro2D from '../A5Intro2D'
 import Intro3D from '../A6Intro3D'
 function DetailPanel() {
   const navigate = useNavigate()
+  const [searchParams, setSearchParams] = useSearchParams()
   // 三维文物0,二维文物1
   const [showTabIndex, setShowTabIndex] = useState(0)
   // 1级:1,2级:2,3级:3,未定级:0,全部:-1
   const [showLevelIndex, setShowLevelIndex] = useState(-1)
   const [inputVal, setInputVal] = useState('')
   const [oreData, setOreData] = useState([])
-  const [currentPage, setCurrentPage] = useState(1)
+  const [currentPage, setCurrentPage] = useState(() => {
+    const page = Number(searchParams.get('page'))
+    return page > 0 ? page : 1
+  })
   // 遮罩层
   const [showMoodIndex, setShowMoodIndex] = useState(-1)
+
+  const resetToFirstPage = () => {
+    setCurrentPage(1)
+    setSearchParams(prev => {
+      const next = new URLSearchParams(prev)
+      next.delete('page')
+      return next
+    }, { replace: true })
+  }
+
+  const handlePageChange = (page: number) => {
+    setCurrentPage(page)
+    setSearchParams(prev => {
+      const next = new URLSearchParams(prev)
+      if (page <= 1) next.delete('page')
+      else next.set('page', String(page))
+      return next
+    }, { replace: true })
+  }
+
+  const handleTabChange = (index: number) => {
+    setShowTabIndex(index)
+    resetToFirstPage()
+  }
+
+  const handleSearchChange = (value: string) => {
+    setInputVal(value)
+    resetToFirstPage()
+  }
   const Mood: React.FC<{ title?: string; showMood?: boolean }> = ({ title, showMood }) => {
     return (
       <div className={styles.mood} style={{ opacity: showMood ? '1' : '0' }}>
@@ -26,25 +60,25 @@ function DetailPanel() {
     )
   }
   const handleLevelClick = (index: number) => {
-    console.log(index, showLevelIndex, index === showLevelIndex)
     if (index === showLevelIndex) {
       setShowLevelIndex(-1)
     } else {
       setShowLevelIndex(index)
     }
+    resetToFirstPage()
   }
   const searchFc = () => {
     console.log(inputVal)
   }
 
   useEffect(() => {
-    setOreData(infoTemo.oreData)
-  }, [])
-
-  useEffect(() => {
-    setCurrentPage(1)
     setOreData(infoTemo.oreData.filter(item => item.type === showTabIndex && (item.level === showLevelIndex || showLevelIndex === -1) && item.title.includes(inputVal)))
   }, [showLevelIndex, showTabIndex, inputVal])
+
+  useEffect(() => {
+    const page = Number(searchParams.get('page'))
+    setCurrentPage(page > 0 ? page : 1)
+  }, [searchParams])
   return (
     <div className={styles.detailPanel}>
       {/* 侧边栏 */}
@@ -52,7 +86,7 @@ function DetailPanel() {
         <img draggable={false} src={Logo} alt='' className='Logo2' />
         <div className='searchInp'>
           <div className='leftSearch'>
-            <input className='search' placeholder='请输入搜索内容' type='text' value={inputVal} onChange={e => setInputVal(e.target.value)} />
+            <input className='search' placeholder='请输入搜索内容' type='text' value={inputVal} onChange={e => handleSearchChange(e.target.value)} />
           </div>
           <div className='rightSearch'>
             <img draggable={false} src={searchIcon} alt='' />
@@ -75,10 +109,10 @@ function DetailPanel() {
       <div className='rightContainner'>
         {/* 顶部tab */}
         <div className='topTab'>
-          <div className={`tab ${showTabIndex === 0 ? 'tabActive' : ''}`} onClick={() => setShowTabIndex(0)}>
+          <div className={`tab ${showTabIndex === 0 ? 'tabActive' : ''}`} onClick={() => handleTabChange(0)}>
             三维文物
           </div>
-          <div className={`tab ${showTabIndex === 1 ? 'tabActive' : ''}`} onClick={() => setShowTabIndex(1)}>
+          <div className={`tab ${showTabIndex === 1 ? 'tabActive' : ''}`} onClick={() => handleTabChange(1)}>
             二维文物
           </div>
         </div>
@@ -92,7 +126,7 @@ function DetailPanel() {
           {oreData
             .filter((item, index) => index >= 8 * (currentPage - 1) && index < 8 * currentPage)
             .map((item, index) => (
-              <div className='Ditem' onClick={() => navigate(item.type === 0 ? `/intro3D?title=${item.title}` : `/intro2D?title=${item.title}`)} onMouseEnter={() => setShowMoodIndex(index)} onMouseLeave={() => setShowMoodIndex(-1)} key={index}>
+              <div className='Ditem' onClick={() => navigate(buildIntroPath(item.type, item.id, currentPage))} onMouseEnter={() => setShowMoodIndex(index)} onMouseLeave={() => setShowMoodIndex(-1)} key={item.id}>
                 <img src={item.src[0]} alt='' />
                 <Mood title={item.title} showMood={showMoodIndex === index} />
               </div>
@@ -105,7 +139,7 @@ function DetailPanel() {
           {/* </div> */}
         </div>
         {/* 分页 */}
-        <Pagination current={currentPage} defaultCurrent={currentPage} defaultPageSize={8} total={oreData.length} showSizeChanger={false} onChange={setCurrentPage} />
+        <Pagination current={currentPage} defaultPageSize={8} total={oreData.length} showSizeChanger={false} onChange={handlePageChange} />
 
       </div>
     </div>

+ 2 - 1
src/pages/A3detailPannelM/index.tsx

@@ -4,6 +4,7 @@ import closeBtn from '@/assets/img/closeBtn.png'
 import searchIcon from '@/assets/img/searchIcon.png'
 import { Pagination } from 'antd'
 import { useNavigate } from 'react-router-dom'
+import { buildIntroPath } from '@/utils/detailNav'
 import Logo from '../components/LOGOM'
 import Intro2D from '../A5Intro2D'
 import Intro3D from '../A6Intro3D'
@@ -154,7 +155,7 @@ function DetailPanel() {
         <div className='Dcontent'>
           {/* 二维文物 */}
           {oreData.map((item, index) => (
-              <div className='Ditem' onClick={() => navigate(item.type === 0 ? `/intro3D?title=${item.title}` : `/intro2D?title=${item.title}`)} onTouchStart={() => setShowMoodIndex(index)} key={item.title}>
+              <div className='Ditem' onClick={() => navigate(buildIntroPath(item.type, item.id, currentPage))} onTouchStart={() => setShowMoodIndex(index)} key={item.id}>
                 <img src={item.src[0]} alt='' loading='lazy' />
                 <PicTitle title={item.title} />
                 {/* <Mood title={item.title} showMood={showMoodIndex === index} /> */}

+ 18 - 10
src/pages/A5Intro2D/index.tsx

@@ -1,9 +1,10 @@
 import React, { useEffect, useRef, useState } from "react";
 import closeBtn from '@/assets/img/closeBtn.png'
 import styles from "./index.module.scss";
-import { useNavigate } from 'react-router-dom'
+import { useNavigate, useSearchParams } from 'react-router-dom'
+import { getDetailBackPath } from '@/utils/detailNav'
 import { useSelector } from 'react-redux'
-import store from '@/store'
+import store, { RootState } from '@/store'
 import { Swiper } from 'antd-mobile'
 
 const TYPE_MAP = {
@@ -19,13 +20,20 @@ const LEVEL_MAP = {
 
 function Intro2D() {
   const navigate = useNavigate()
-  const [item, setItem] = useState(null)
+  const [searchParams] = useSearchParams()
+  const [item, setItem] = useState<OreDataItem | null>(null)
   const lookBigImg = useSelector((state: RootState) => state.A0Layout.lookBigImg)
 
   useEffect(() => {
-    const title = new URLSearchParams(window.location.href.split('?')[1]).get('title')
-    setItem(infoTemo.oreData.find(item => item.title === title))
-  }, [])
+    const id = searchParams.get('id')
+    setItem(infoTemo.oreData.find(entry => entry.id === Number(id)) ?? null)
+  }, [searchParams])
+
+  const handleBack = () => {
+    const backPath = getDetailBackPath(searchParams)
+    if (backPath) navigate(backPath)
+    else navigate(-1)
+  }
   const audioRef = useRef<HTMLAudioElement>(null);
   const handleMusicClick = () => {
     if (audioRef.current) {
@@ -39,7 +47,7 @@ function Intro2D() {
   return (
     <div className={styles.intro2D}>
       <div className="iClose">
-        <img draggable={false} src={closeBtn} alt='' onClick={() => navigate(-1)} />
+        <img draggable={false} src={closeBtn} alt='' onClick={handleBack} />
       </div>
       <div className="iLeft">
         {item?.src && (
@@ -73,14 +81,14 @@ function Intro2D() {
       <div className="iRight">
         <div className="ititle">{item?.title}</div>
         <div className="idate">质地:{item?.date}</div>
-        <div className="itype">类型:{TYPE_MAP[item?.type]}</div>
-        <div className="ilevel">级别:{LEVEL_MAP[item?.level]}</div>
+        <div className="itype">类型:{item ? TYPE_MAP[item.type as keyof typeof TYPE_MAP] : ''}</div>
+        <div className="ilevel">级别:{item ? LEVEL_MAP[item.level as keyof typeof LEVEL_MAP] : ''}</div>
         {
           item?.musicLink && (
             <div className="imusic" onClick={handleMusicClick}><audio ref={audioRef} style={{ width: '0', height: '0' }} src={item?.musicLink} controls></audio></div>
           )
         }
-        <div className="idesc" dangerouslySetInnerHTML={{ __html: item?.desc }}></div>
+        <div className="idesc" dangerouslySetInnerHTML={{ __html: item?.desc ?? '' }}></div>
       </div>
     </div>
   )

+ 15 - 7
src/pages/A5Intro2DM/index.tsx

@@ -1,19 +1,27 @@
 import React, { useEffect, useRef, useState } from "react";
 import closeBtn from '@/assets/img/closeBtn.png'
 import styles from "./index.module.scss";
-import { useNavigate } from 'react-router-dom'
+import { useNavigate, useSearchParams } from 'react-router-dom'
+import { getDetailBackPath } from '@/utils/detailNav'
 import { useSelector } from 'react-redux'
 import store, { RootState } from '@/store'
 import { Swiper } from 'antd-mobile'
 
 function Intro2D() {
   const navigate = useNavigate()
+  const [searchParams] = useSearchParams()
   const lookBigImg = useSelector((state: RootState) => state.A0Layout.lookBigImg)
-  const [item, setItem] = useState(null)
+  const [item, setItem] = useState<OreDataItem | null>(null)
   useEffect(() => {
-    const title = new URLSearchParams(window.location.href.split('?')[1]).get('title')
-    setItem(infoTemo.oreData.find(item => item.title === title))
-  }, [])
+    const id = searchParams.get('id')
+    setItem(infoTemo.oreData.find(entry => entry.id === Number(id)) ?? null)
+  }, [searchParams])
+
+  const handleBack = () => {
+    const backPath = getDetailBackPath(searchParams)
+    if (backPath) navigate(backPath)
+    else navigate(-1)
+  }
   const audioRef = useRef<HTMLAudioElement>(null);
   const handleMusicClick = () => {
     if (audioRef.current) {
@@ -26,7 +34,7 @@ function Intro2D() {
   }
   return (
     <div className={styles.intro2D}>
-      <div className="iClose" onClick={() => navigate(-1)}>
+      <div className="iClose" onClick={handleBack}>
         <img draggable={false} src={closeBtn} alt="" />
       </div>
       <div className="iLeft">
@@ -56,7 +64,7 @@ function Intro2D() {
         <div className="itype">类型:{item?.type}</div>
         <div className="ilevel">级别:{item?.level}</div>
         <div className="imusic" onClick={handleMusicClick}><audio ref={audioRef} style={{ width: '0', height: '0' }} src={item?.musicLink} controls></audio></div>
-        <div className="idesc" dangerouslySetInnerHTML={{ __html: item?.desc }}></div>
+        <div className="idesc" dangerouslySetInnerHTML={{ __html: item?.desc ?? '' }}></div>
       </div>
     </div>
   )

+ 13 - 5
src/pages/A6Intro3D/index.tsx

@@ -7,14 +7,22 @@ import homeBtn from '@/assets/img/homeBtn.png'
 import introBtn from '@/assets/img/introBtn.png'
 import MusicOpen from '@/assets/img/musicOpen.png'
 import MusicClose from '@/assets/img/musicClose.png'
-import { useNavigate } from 'react-router-dom'
+import { useNavigate, useSearchParams } from 'react-router-dom'
+import { getDetailBackPath } from '@/utils/detailNav'
 function Intro3D() {
+  const [searchParams] = useSearchParams()
   const [item, setItem] = useState<OreDataItem | null>(null)
   useEffect(() => {
-    const title = new URLSearchParams(window.location.href.split('?')[1]).get('title')
-    setItem(infoTemo.oreData.find(entry => entry.title === title) ?? null)
-  }, [])
+    const id = searchParams.get('id')
+    setItem(infoTemo.oreData.find(entry => entry.id === Number(id)) ?? null)
+  }, [searchParams])
   const navigate = useNavigate()
+
+  const handleBack = () => {
+    const backPath = getDetailBackPath(searchParams)
+    if (backPath) navigate(backPath)
+    else navigate(-1)
+  }
   const [showDesc, setShowDesc] = useState(false);
   const [musicOpen, setMusicOpen] = useState(false)
   const containerRef = useRef<HTMLDivElement>(null)
@@ -69,7 +77,7 @@ function Intro3D() {
     <div className={styles.Intro3D}>
       <div className="Logo"><img src={Logo} alt="" /></div>
       <div className="iClose">
-        <img draggable={false} src={closeBtn} alt='' onClick={() => navigate(-1)} />
+        <img draggable={false} src={closeBtn} alt='' onClick={handleBack} />
       </div>
       <div className="Intro3DContent">
         <div className="Intro3DContentTitle">{item?.title}</div>

+ 16 - 8
src/pages/A6Intro3DM/index.tsx

@@ -5,14 +5,22 @@ import fullIcon from '@/assets/img/full.png'
 import closeBtn from '@/assets/img/closeBtn.png'
 import homeBtn from '@/assets/img/homeBtn.png'
 import introBtn from '@/assets/img/introBtn.png'
-import { useNavigate } from 'react-router-dom'
+import { useNavigate, useSearchParams } from 'react-router-dom'
+import { getDetailBackPath } from '@/utils/detailNav'
 function Intro3D() {
-  const [item, setItem] = useState(null)
+  const [searchParams] = useSearchParams()
+  const [item, setItem] = useState<OreDataItem | null>(null)
   useEffect(() => {
-    const title = new URLSearchParams(window.location.href.split('?')[1]).get('title')
-    setItem(infoTemo.oreData.find(item => item.title === title))
-  }, [])
+    const id = searchParams.get('id')
+    setItem(infoTemo.oreData.find(item => item.id === Number(id)) ?? null)
+  }, [searchParams])
   const navigate = useNavigate()
+
+  const handleBack = () => {
+    const backPath = getDetailBackPath(searchParams)
+    if (backPath) navigate(backPath)
+    else navigate(-1)
+  }
   const [showDesc, setShowDesc] = useState(false);
   const iframeRef = useRef<HTMLIFrameElement>(null)
 
@@ -48,7 +56,7 @@ function Intro3D() {
   return (
     <div className={styles.Intro3D}>
       <div className="Logo"><img src={Logo} alt="" draggable={false} /></div>
-      <div className="iClose" onClick={() => navigate(-1)}>
+      <div className="iClose" onClick={handleBack}>
         <img draggable={false} src={closeBtn} alt="" />
       </div>
       <div className="Intro3DContent">
@@ -66,9 +74,9 @@ function Intro3D() {
         </div>
         <div className="Intro3DContentDescContent">
           <div className="Intro3DContentDescTitle">
-            {item.title}
+            {item?.title}
           </div>
-          <div className="Intro3DContentDescText" dangerouslySetInnerHTML={{ __html: item.desc }}>
+          <div className="Intro3DContentDescText" dangerouslySetInnerHTML={{ __html: item?.desc ?? '' }}>
           </div>
         </div>
 

+ 1 - 0
src/types/declaration.d.ts

@@ -9,6 +9,7 @@ declare module 'js-export-excel'
 declare module 'braft-utils'
 
 type OreDataItem = {
+  id: number
   title: string
   date: string
   type: number

+ 9 - 0
src/utils/detailNav.ts

@@ -0,0 +1,9 @@
+export function getDetailBackPath(searchParams: URLSearchParams) {
+  const page = searchParams.get('page')
+  return page ? `/detailP?page=${page}` : null
+}
+
+export function buildIntroPath(type: number, id: number, page: number) {
+  const base = type === 0 ? `/intro3D?id=${id}` : `/intro2D?id=${id}`
+  return page > 1 ? `${base}&page=${page}` : base
+}