Преглед изворни кода

feat: 世系铭远-英文版

lanxin пре 6 часа
родитељ
комит
fb6d53ae76

+ 9 - 2
public/myData/myDataEN.js

@@ -1401,7 +1401,7 @@ const myDataTemp2 = {
       extra: 'younger brother of Xi',
       position: {
         x: -449,
-        y: 16
+        y: 54
       },
       text: [
         {
@@ -1521,6 +1521,7 @@ const myDataTemp2 = {
       name: 'Xia',
       customN: '',
       type: 'nodeTurnBottomRight_n',
+      arrowHeight: 115,
       addTxt: {
         time: 'During the Jianping reign of Emperor Ming (Shi Le) of Later Zhao(330-333 CE)',
         pos: 'Minister of Education and Civil Administration',
@@ -1609,10 +1610,11 @@ const myDataTemp2 = {
         backEnd: '',
         precondition: ''
       },
+      arrowHeight: 94,
       extra: `Zhi's eldest son`,
       position: {
         x: 264,
-        y: -306
+        y: -336
       },
       text: [
         { title: '碑铭功绩', content: '' },
@@ -1784,6 +1786,7 @@ const myDataTemp2 = {
         x: 581,
         y: -38
       },
+      height: 124,
       text: [
         { title: '碑铭功绩', content: '' },
         { title: '人物考证', content: '' }
@@ -1805,6 +1808,7 @@ const myDataTemp2 = {
         x: 581,
         y: 36
       },
+      height: 124,
       text: [
         { title: '碑铭功绩', content: '' },
         { title: '人物考证', content: '' }
@@ -1868,6 +1872,7 @@ const myDataTemp2 = {
         x: 876,
         y: -39
       },
+      height: 113,
       text: [
         { title: '碑铭功绩', content: '' },
         { title: '人物考证', content: '' }
@@ -1889,6 +1894,7 @@ const myDataTemp2 = {
         x: 876,
         y: 38
       },
+      height: 103,
       text: [
         { title: '碑铭功绩', content: '' },
         { title: '人物考证', content: '' }
@@ -1910,6 +1916,7 @@ const myDataTemp2 = {
         x: 876,
         y: 115
       },
+      height: 103,
       text: [
         { title: '碑铭功绩', content: '' },
         { title: '人物考证', content: '' }

BIN
src/assets/img/A6_gen_sxmy_E.png


+ 8 - 8
src/pages/A6ybwx/Genealogy/components/Graph/index.tsx

@@ -275,10 +275,10 @@ function Graph({ setCurrentNodeIndex }: { setCurrentNodeIndex: (index: number) =
         if (item.type === 'nodeRight_a') res = <NodeRight key={index} data={item} style={{ transform: `translate(${item.position.x}px, ${item.position.y}px)` }} type='active' />
         if (item.type === 'nodeRight_f') res = <NodeRight key={index} data={item} style={{ transform: `translate(${item.position.x}px, ${item.position.y}px)` }} type='false' />
         if (item.type === 'nodeBottom_n') res = <NodeBottom key={index} data={item} style={{ transform: `translate(${item.position.x}px, ${item.position.y}px)` }} type='normal' />
-        if (item.type === 'nodeTurnRight_n') res = <NodeTurnRight key={index} data={item} style={{ transform: `translate(${item.position.x}px, ${item.position.y}px)` }} type='normal' />
-        if (item.type === 'nodeTurnRight_a') res = <NodeTurnRight key={index} data={item} style={{ transform: `translate(${item.position.x}px, ${item.position.y}px)` }} type='active' />
-        if (item.type === 'nodeTurnBottomRight_a') res = <NodeTurnBottomRight key={index} data={item} style={{ transform: `translate(${item.position.x}px, ${item.position.y}px)` }} type='active' />
-        if (item.type === 'nodeTurnBottomRight_n') res = <NodeTurnBottomRight key={index} data={item} style={{ transform: `translate(${item.position.x}px, ${item.position.y}px)` }} type='normal' />
+        if (item.type === 'nodeTurnRight_n') res = <NodeTurnRight key={index} data={item} style={{ transform: `translate(${item.position.x}px, ${item.position.y}px)` }} arrowHeight={item.arrowHeight} type='normal' />
+        if (item.type === 'nodeTurnRight_a') res = <NodeTurnRight key={index} data={item} style={{ transform: `translate(${item.position.x}px, ${item.position.y}px)` }} arrowHeight={item.arrowHeight} type='active' />
+        if (item.type === 'nodeTurnBottomRight_a') res = <NodeTurnBottomRight key={index} data={item} style={{ transform: `translate(${item.position.x}px, ${item.position.y}px)` }} arrowHeight={item.arrowHeight} type='active' />
+        if (item.type === 'nodeTurnBottomRight_n') res = <NodeTurnBottomRight key={index} data={item} style={{ transform: `translate(${item.position.x}px, ${item.position.y}px)` }} arrowHeight={item.arrowHeight} type='normal' />
         if (item.type === 'nodeRight_dash_n') res = <NodeRightDash key={index} data={item} style={{ transform: `translate(${item.position.x}px, ${item.position.y}px)` }} type='normal' />
         if (item.type === 'nodeRight_dash_a') res = <NodeRightDash key={index} data={item} style={{ transform: `translate(${item.position.x}px, ${item.position.y}px)` }} type='active' />
         if (item.type === 'nodeRight_dash_f') res = <NodeRightDash key={index} data={item} style={{ transform: `translate(${item.position.x}px, ${item.position.y}px)` }} type='false' />
@@ -300,10 +300,10 @@ function Graph({ setCurrentNodeIndex }: { setCurrentNodeIndex: (index: number) =
           if (item.type === 'nodeRight_a') res = <NodeRight key={index} data={item} style={{ transform: `translate(${item.position.x}px, ${item.position.y}px)` }} type='active' />
           if (item.type === 'nodeRight_f') res = <NodeRight key={index} data={item} style={{ transform: `translate(${item.position.x}px, ${item.position.y}px)` }} type='false' nameClick={() => handleNameClick(index)} />
           if (item.type === 'nodeBottom_n') res = <NodeBottom key={index} data={item} style={{ transform: `translate(${item.position.x}px, ${item.position.y}px)` }} type='normal' nameClick={() => handleNameClick(index)} />
-          if (item.type === 'nodeTurnRight_n') res = <NodeTurnRight key={index} data={item} style={{ transform: `translate(${item.position.x}px, ${item.position.y}px)` }} type='normal' nameClick={() => handleNameClick(index)} />
-          if (item.type === 'nodeTurnRight_a') res = <NodeTurnRight key={index} data={item} style={{ transform: `translate(${item.position.x}px, ${item.position.y}px)` }} type='active' />
-          if (item.type === 'nodeTurnBottomRight_a') res = <NodeTurnBottomRight key={index} data={item} style={{ transform: `translate(${item.position.x}px, ${item.position.y}px)` }} type='active' />
-          if (item.type === 'nodeTurnBottomRight_n') res = <NodeTurnBottomRight key={index} data={item} style={{ transform: `translate(${item.position.x}px, ${item.position.y}px)` }} type='normal' nameClick={() => handleNameClick(index)} />
+          if (item.type === 'nodeTurnRight_n') res = <NodeTurnRight key={index} data={item} style={{ transform: `translate(${item.position.x}px, ${item.position.y}px)` }} arrowHeight={item.arrowHeight} type='normal' nameClick={() => handleNameClick(index)} />
+          if (item.type === 'nodeTurnRight_a') res = <NodeTurnRight key={index} data={item} style={{ transform: `translate(${item.position.x}px, ${item.position.y}px)` }} arrowHeight={item.arrowHeight} type='active' />
+          if (item.type === 'nodeTurnBottomRight_a') res = <NodeTurnBottomRight key={index} data={item} style={{ transform: `translate(${item.position.x}px, ${item.position.y}px)`, height: item.height || undefined }} arrowHeight={item.arrowHeight} type='active' />
+          if (item.type === 'nodeTurnBottomRight_n') res = <NodeTurnBottomRight key={index} data={item} style={{ transform: `translate(${item.position.x}px, ${item.position.y}px)`, height: item.height || undefined }} arrowHeight={item.arrowHeight} type='normal' nameClick={() => handleNameClick(index)} />
           if (item.type === 'nodeRight_dash_n') res = <NodeRightDash key={index} data={item} style={{ transform: `translate(${item.position.x}px, ${item.position.y}px)` }} type='normal' nameClick={() => handleNameClick(index)} />
           if (item.type === 'nodeRight_dash_a') res = <NodeRightDash key={index} data={item} style={{ transform: `translate(${item.position.x}px, ${item.position.y}px)` }} type='active' />
           if (item.type === 'nodeRight_dash_f') res = <NodeRightDash key={index} data={item} style={{ transform: `translate(${item.position.x}px, ${item.position.y}px)` }} type='false' nameClick={() => handleNameClick(index)} />

+ 4 - 0
src/pages/A6ybwx/Genealogy/components/Utils/index.module.scss

@@ -384,6 +384,10 @@
   }
 }
 
+.nodeTurnBottomRightEn {
+  height: 160px;
+}
+
 .nodeTurnBottomDashRight {
   pointer-events: none;
   width: 165px;

+ 14 - 9
src/pages/A6ybwx/Genealogy/components/Utils/index.tsx

@@ -1,5 +1,8 @@
 import React from 'react'
 import styles from './index.module.scss'
+import { useSelector } from 'react-redux'
+import { RootState } from '@/store'
+import classNames from 'classnames'
 
 interface dataType {
   name: string
@@ -23,6 +26,7 @@ interface nodeProps {
   nameClick?: () => void
   style?: React.CSSProperties
   data: dataType
+  arrowHeight?: number
 }
 
 const RightLine = () => {
@@ -61,18 +65,18 @@ const BottomLineDash = () => {
   )
 }
 
-const TurnRightLine = () => {
+const TurnRightLine = ({ arrowHeight }: { arrowHeight?: number }) => {
   return (
-    <div className={styles.turnRightLine} id='turnRightLine'>
+    <div className={styles.turnRightLine} id='turnRightLine' style={{ height: arrowHeight ? `${arrowHeight}px` : '80px' }}>
       <div className='line'></div>
       <div className='arrow'></div>
     </div>
   )
 }
 
-const TurnBottomRightLine = () => {
+const TurnBottomRightLine = ({ arrowHeight }: { arrowHeight?: number }) => {
   return (
-    <div className={styles.turnBottomRightLine} id='turnBottomRightLine'>
+    <div className={styles.turnBottomRightLine} id='turnBottomRightLine' style={{ height: arrowHeight ? `${arrowHeight}px` : '80px' }}>
       <div className='line'></div>
       <div className='arrow'></div>
     </div>
@@ -190,10 +194,10 @@ const NodeBottomDash = ({ type, className, nameClick, style, data }: nodeProps)
   )
 }
 
-const NodeTurnRight = ({ type, className, nameClick, style, data }: nodeProps) => {
+const NodeTurnRight = ({ type, className, nameClick, style, data, arrowHeight }: nodeProps) => {
   return (
     <div className={`${styles.nodeTurnRight} ${className}`} id='nodeTurnRight' style={style}>
-      <TurnRightLine />
+      <TurnRightLine arrowHeight={arrowHeight || undefined} />
       {type === 'normal' && <NodeNormal nameClick={nameClick} data={data} />}
       {type === 'active' && <NodeActive nameClick={nameClick} data={data} />}
       {type === 'false' && <NodeFalse nameClick={nameClick} data={data} />}
@@ -201,14 +205,15 @@ const NodeTurnRight = ({ type, className, nameClick, style, data }: nodeProps) =
   )
 }
 
-const NodeTurnBottomRight = ({ type, className, nameClick, style, data }: nodeProps) => {
+const NodeTurnBottomRight = ({ type, className, nameClick, style, data, arrowHeight }: nodeProps) => {
+  const { myLangue } = useSelector((state: RootState) => state.A0Layout)
   return (
     <div
-      className={`${styles.nodeTurnBottomRight} ${className}`}
+      className={classNames(`${styles.nodeTurnBottomRight} ${className}`, myLangue === 'EN' ? styles.nodeTurnBottomRightEn : '')}
       id='nodeTurnBottomRight'
       style={style}
     >
-      <TurnBottomRightLine />
+      <TurnBottomRightLine arrowHeight={arrowHeight || undefined} />
       {type === 'normal' && <NodeNormal nameClick={nameClick} data={data} />}
       {type === 'active' && <NodeActive nameClick={nameClick} data={data} />}
       {type === 'false' && <NodeFalse nameClick={nameClick} data={data} />}

+ 282 - 0
src/pages/A6ybwx/Genealogy/index.module.scss

@@ -292,3 +292,285 @@
     }
   }
 }
+
+.GenealogyEn {
+  position: absolute;
+  top: 50%;
+  left: 50%;
+  transform: translate(-50%, -50%);
+  z-index: 3;
+  width: 100%;
+  height: 100%;
+  background: url('../../../assets/img/A6_gen_bg.jpg') no-repeat center center;
+  background-size: 100% 100%;
+
+  :global {
+    .back {
+      width: 80px;
+      height: 40px;
+      position: absolute;
+      z-index: 1;
+      top: 3%;
+      left: 4%;
+      cursor: pointer;
+
+      & > img {
+        height: 100%;
+        object-fit: fill !important;
+      }
+    }
+
+    .icon1 {
+      width: 30px;
+      height: 30px;
+      position: absolute;
+      top: 4%;
+      left: 16%;
+      cursor: pointer;
+
+      & > img {
+        height: 100%;
+        object-fit: contain;
+      }
+    }
+
+    .miniGraph {
+      position: relative;
+      width: 200px;
+      height: 100px;
+      bottom: 5%;
+      left: 5%;
+    }
+
+    .hideD {
+      opacity: 0;
+      pointer-events: none;
+      transition: all 0.3s ease-in-out 0.3s;
+
+      .sider {
+        transition: all 0.3s ease-in-out;
+        transform: translateX(-100%);
+      }
+    }
+
+    .showD {
+      opacity: 1;
+      pointer-events: auto;
+      transition: all 0.3s ease-in-out;
+
+      .sider {
+        transform: translateX(0);
+        transition: all 0.3s ease-in-out 0.3s;
+      }
+    }
+  }
+}
+
+.introEn {
+  position: fixed;
+  z-index: 3;
+  top: 0;
+  left: 0;
+  width: 100%;
+  height: 100%;
+  background: url('../../../assets/img/A6_gen_introBg.png') no-repeat center center;
+  background-size: 100% 100%;
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  justify-content: center;
+  gap: 10px;
+  backdrop-filter: blur(3px);
+
+  :global {
+    .title {
+      width: 60%;
+      height: 26px;
+      text-align: center;
+      position: relative;
+
+      .big {
+        width: 100%;
+        height: 24px;
+        font-size: 24px;
+        color: rgba(255, 233, 182, 1);
+        margin-bottom: 8px;
+        & > img {
+          height: 100%;
+          object-fit: contain;
+        }
+      }
+
+      .small {
+        width: 100%;
+        height: 25px;
+        font-size: 16px;
+        color: rgba(255, 255, 255, 1);
+      }
+
+      .sun {
+        opacity: 0;
+        position: absolute;
+        top: -3%;
+        right: 57%;
+        width: 15px;
+        height: 15px;
+        border-radius: 50%;
+        box-shadow: 0 0 10px rgba(255, 233, 182, 1);
+        background-color: rgba(255, 233, 182, 0.6);
+        filter: blur(3px);
+      }
+    }
+
+    .line {
+      width: 38%;
+      height: 20px;
+
+      & > img {
+        height: 100%;
+        object-fit: contain;
+      }
+    }
+
+    .intro_content {
+      width: 73%;
+      height: 220px;
+      font-size: 12px;
+      color: rgb(209, 201, 178);
+      text-align: justify;
+      line-height: 23px;
+    }
+
+    .close {
+      cursor: pointer;
+      width: 80px;
+      height: 40px;
+
+      & > img {
+        height: 100%;
+        object-fit: contain;
+      }
+    }
+  }
+}
+
+.nodeDetailEn {
+  position: fixed;
+  z-index: 3;
+  top: 0;
+  left: 0;
+  width: 100%;
+  height: 100%;
+  backdrop-filter: blur(1px);
+
+  :global {
+    .sider {
+      position: relative;
+      width: 40%;
+      height: 100%;
+      background: url('../../../assets/img/A6_gen_nodeDetailBg.png') no-repeat center center;
+      background-size: 100% 100%;
+      display: flex;
+      align-items: center;
+
+      .name {
+        writing-mode: vertical-rl;
+        text-orientation: upright; // 保持文字直立
+        display: flex;
+        align-items: center;
+        letter-spacing: 10px;
+        padding-top: 60px;
+        width: 20%;
+        height: 100%;
+        font-size: 20px;
+        color: rgba(255, 233, 182, 1);
+
+        .customN {
+          letter-spacing: 5px;
+          padding-top: 20px;
+          font-size: 16px;
+        }
+      }
+
+      .info {
+        width: 80%;
+        height: 80%;
+        padding: 0 25px;
+        display: flex;
+        flex-direction: column;
+        align-items: center;
+        gap: 10px;
+        overflow: auto;
+        margin-bottom: 26px;
+        padding-bottom: 20px;
+        mask-image: linear-gradient(
+          to bottom,
+          rgba(0, 0, 0, 1) 0%,
+          rgba(0, 0, 0, 1) 80%,
+          /* 保留顶部70%不透明 */ rgba(0, 0, 0, 0) 100% /* 底部30%完全透明 */
+        );
+        -webkit-mask-image: linear-gradient(
+          to bottom,
+          rgba(0, 0, 0, 1) 0%,
+          rgba(0, 0, 0, 1) 80%,
+          rgba(0, 0, 0, 0) 100%
+        );
+
+        &::-webkit-scrollbar {
+          width: 0;
+          height: 0;
+        }
+
+        .infoitem {
+          width: 100%;
+
+          .name_I {
+            width: 100%;
+            height: 20px;
+            font-size: 17px;
+            line-height: 13px;
+            font-weight: bold;
+            color: rgba(124, 75, 54, 1);
+            .customN_I {
+              font-size: 13px;
+              color: rgba(175, 135, 100, 1);
+            }
+          }
+
+          .title {
+            width: 100%;
+            height: 20px;
+            font-size: 12px;
+            line-height: 13px;
+            font-weight: bold;
+            color: rgba(124, 75, 54, 1);
+          }
+
+          .txt {
+            margin-top: 6px;
+            width: 93%;
+            font-size: 10px;
+            color: rgba(93, 96, 96, 1);
+            max-height: calc(100% - 50px);
+            text-align: justify;
+            hyphens: auto;
+          }
+        }
+      }
+
+      .close {
+        position: absolute;
+        bottom: 2%;
+        right: 9%;
+        cursor: pointer;
+        width: 70px;
+        height: 50px;
+
+        & > img {
+          height: 100%;
+          object-fit: contain;
+        }
+      }
+    }
+  }
+}

+ 24 - 14
src/pages/A6ybwx/Genealogy/index.tsx

@@ -4,7 +4,9 @@ import Graph from './components/Graph'
 import MemuSider from '@/components/MenuSider'
 import { useSelector } from 'react-redux'
 import { RootState } from '@/store'
+import classNames from 'classnames'
 import { isMobiileFu } from '@/utils/history'
+import Zback from '@/components/Zback'
 // import SvgGraph from './components/GraphSVG'
 function Genealogy({ setGotoTab }: { setGotoTab: (tab: number) => void }) {
   const [isShowIntro, setIsShowIntro] = useState(true)
@@ -31,25 +33,26 @@ function Genealogy({ setGotoTab }: { setGotoTab: (tab: number) => void }) {
   }, [isShowIntro])
 
   return (
-    <div className={styles.Genealogy}>
-      <div className='back' onClick={() => setGotoTab(0)}>
-        <img src={require('@/assets/img/btn_back.png')} alt='' />
-      </div>
+    <div className={classNames(styles.Genealogy, myLangue === 'EN' ? styles.GenealogyEn : '')}>
+      <Zback clickFu={() => setGotoTab(0)} />
       <MemuSider activeTab={1} />
       <Graph setCurrentNodeIndex={setCurrentNodeIndex} />
       {/* <SvgGraph /> */}
       <div className='icon1' onClick={() => setIsShowIntro(true)}>
         <img src={require('@/assets/img/A6_gen_icon1.png')} alt='' />
       </div>
-      <div className={`${styles.gesture} ${gestureState1}`} onClick={() => setIsShowGesture(false)}>
+      <div className={`${styles.gesture} ${gestureState1}`} style={{ width: myLangue === 'EN' ? '155px' : '55px' }} onClick={() => setIsShowGesture(false)}>
         <img src={require(`@/assets/img/${isMobiileFu() ? 'A6_gen_gesture1' : 'A6_gen_gesture'}.png`)} draggable='false' alt='' />
-        {isMobiileFu() ? '左右滑动查看更多' : <>滚轮放大< br /> 左右拖拽移动</>}
+        {myLangue === 'ZH' ? (
+          isMobiileFu() ? '左右滑动查看更多' : <>滚轮放大<br /> 左右拖拽移动</>
+        ) : (
+          isMobiileFu() ? 'Swipe left or right to view more' : <>Scroll to zoom<br /> Drag left or right to move</>
+        )}
       </div>
-      )
       {isShowIntro && (
-        <div className={styles.intro}>
+        <div className={classNames(styles.intro, myLangue === 'EN' ? styles.introEn : '')}>
           <div className='title'>
-            <div className='big songFont'><img src={require('@/assets/img/A6_gen_sxmy.png')} draggable='false' alt="" /></div>
+            <div className='big songFont'><img src={require(`@/assets/img/A6_gen_sxmy${myLangue === 'EN' ? '_E' : ''}.png`)} draggable='false' alt="" /></div>
             {/* <div className='small'>{myData?.genealogyIntro?.smallTitle}</div> */}
             <div className='sun'></div>
           </div>
@@ -61,19 +64,26 @@ function Genealogy({ setGotoTab }: { setGotoTab: (tab: number) => void }) {
             dangerouslySetInnerHTML={{ __html: myData?.genealogyIntro?.content }}
           ></div>
           <div className='close' onClick={() => setIsShowIntro(false)}>
-            <img src={require('@/assets/img/closeWithTxt.png')} draggable='false' alt='' />
+            <img src={require(`@/assets/img/closeWithTxt${myLangue === 'EN' ? '_E' : ''}.png`)} draggable='false' alt='' />
           </div>
         </div>
       )}
-      <div className={`${styles.nodeDetail} ${currentNodeIndex !== -1 ? 'showD' : 'hideD'}`}>
+      <div className={classNames(`${styles.nodeDetail} ${currentNodeIndex !== -1 ? 'showD' : 'hideD'}`, myLangue === 'EN' ? styles.nodeDetailEn : '')}>
         <div className='sider'>
-          <div className='name songFont'>
+          {myLangue === 'ZH' ? <div className='name songFont'>
             {myData?.genealogyData?.[currentNodeIndex]?.name}
             <div className='customN songFont'>
               {myData?.genealogyData?.[currentNodeIndex]?.customN}
             </div>
-          </div>
+          </div> : <div className='name' />}
           <div className='info'>
+            <div className='infoitem'> {myLangue === 'EN' && <div className='name_I songFont'>
+              {myData?.genealogyData?.[currentNodeIndex]?.name}
+              <span className='customN_I songFont'>
+                ({myData?.genealogyData?.[currentNodeIndex]?.customN})
+              </span>
+            </div>}</div>
+
             {myData?.genealogyData?.[currentNodeIndex]?.text?.map((item, index) => {
               if (!!item.content) {
                 return (
@@ -94,7 +104,7 @@ function Genealogy({ setGotoTab }: { setGotoTab: (tab: number) => void }) {
               setIsShowGesture(false)
             }}
           >
-            <img src={require('@/assets/img/closeWithTxt2.png')} draggable='false' alt='' />
+            <img src={require(`@/assets/img/closeWithTxt2${myLangue === 'EN' ? 'En' : ''}.png`)} draggable='false' alt='' />
           </div>
         </div>
       </div>

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

@@ -110,6 +110,8 @@ type MyDataType = {
     extra: string
     position: { x: number; y: number }
     text: { title: string; content: string }[]
+    arrowHeight?: number
+    height?: number
   }[]
 
   // 丧葬因素