Leon преди 2 години
родител
ревизия
6d34b1225f

+ 1 - 0
package.json

@@ -72,6 +72,7 @@
 		"@tarojs/taro": "3.6.19",
 		"@tarojs/taro-rn": "3.6.19",
 		"@xstate/react": "^3.2.2",
+		"ahooks": "^3.7.8",
 		"expo": "~47.0.3",
 		"expo-av": "~13.0.0",
 		"expo-barcode-scanner": "~12.0.0",

+ 2 - 2
src/app.config.ts

@@ -1,8 +1,8 @@
 const appConfig = defineAppConfig({
   pages: [
-    
-    'pages/clock/Clock',
     'pages/demo',
+    'pages/clock/Clock',
+    
     
     
     'pages/index/index',

+ 1 - 1
src/components/layout/layout.tsx

@@ -91,7 +91,7 @@ export default function Layout(props: {
             {
                 children
             }
-            <View style={{ height: 50 }} />
+            <View style={{ height: 0 }} />
         </View>
     }
 

+ 8 - 0
src/features/trackSomething/components/Activity.scss

@@ -0,0 +1,8 @@
+.activity_container{
+    display: flex;
+    flex-direction: row;
+    flex-wrap: wrap;
+    justify-content: space-between;
+    margin-left: 46px;
+    margin-right: 46px;
+}

+ 67 - 28
src/features/trackSomething/components/Activity.tsx

@@ -12,13 +12,17 @@ import Layout from '@/components/layout/layout'
 import NoData from "@/components/view/NoData";
 import { ResultType, checkFail, checkRetry, checkStart, checkSuccess, resetStatus, setResult } from "@/store/action_results";
 import RequestType, { thirdPartRequest } from "@/services/thirdPartRequest";
-import { NaviBarTitleShowType, TemplateType } from "@/utils/types";
+import { ModalType, NaviBarTitleShowType, TemplateType } from "@/utils/types";
 import { useTranslation } from "react-i18next";
 import { jumpPage } from "@/features/trackTimeDuration/hooks/Common";
+import TitleView from "@/features/trackTimeDuration/components/TitleView";
+import './Activity.scss'
+import Modal from "@/components/layout/Modal";
+import MoveList from "./MoveList";
 // import { useNavigation } from "@react-navigation/native";
 
 let useNavigation;
-if (process.env.TARO_ENV=='rn'){
+if (process.env.TARO_ENV == 'rn') {
     useNavigation = require("@react-navigation/native").useNavigation
 }
 
@@ -38,10 +42,11 @@ export default function Component(props: any) {
     const [latestRecord, setLatestRecord] = useState(null)
     const [triggered, setTriggered] = useState(true)
     const [showErrorPage, setErrorPage] = useState(false)
-    
+    const [showModal, setShowModal] = useState(false)
+
     const [count, setCount] = useState(0)
     let navigation;
-    if (useNavigation){
+    if (useNavigation) {
         navigation = useNavigation()
     }
 
@@ -142,11 +147,11 @@ export default function Component(props: any) {
                 checkout()
             }
             else {
-                setAuth(successAuth, refuseAuth,t)
+                setAuth(successAuth, refuseAuth, t)
             }
         }
         else {
-            jumpPage('/pages/account/ChooseAuth','ChooseAuth',navigation)
+            jumpPage('/pages/account/ChooseAuth', 'ChooseAuth', navigation)
         }
     }
 
@@ -277,7 +282,7 @@ export default function Component(props: any) {
             jumpPage('/pages/common/RecordsHistory?type=activity&refreshList=getCards&title=' + item.name + '&themeColor=' + item.theme_color)
         }
         else {
-            jumpPage('/pages/account/ChooseAuth','ChooseAuth',navigation)
+            jumpPage('/pages/account/ChooseAuth', 'ChooseAuth', navigation)
         }
 
     }
@@ -332,8 +337,17 @@ export default function Component(props: any) {
         isEnable = true;
     }
 
+    function addBtnClick() {
+        setShowModal(true)
+    }
+
+    function headerView() {
+        return <TitleView title={t('page.activity.title')} showAddBtn={true} onClick={addBtnClick}>
+        </TitleView>
+    }
+
     function detail() {
-        return <View>
+        return <View className="activity_container">
             {
                 list.map((item: any, index) => {
                     var value = '0'
@@ -376,7 +390,7 @@ export default function Component(props: any) {
                             }
                             else {
                                 value = t('feature.track_something.activity.today_un_check')
-                                desc =  t('feature.track_something.activity.check_history')//'查看历史记录'
+                                desc = t('feature.track_something.activity.check_history')//'查看历史记录'
                             }
                         }
                     }
@@ -402,31 +416,56 @@ export default function Component(props: any) {
         </View>
     }
 
-    // return <ScrollView style={{ backgroundColor: '#000',flex:1 }} scrollY refresherEnabled={true}
-    //     refresherThreshold={100} refresherBackground="#000"
-    //     refresherDefaultStyle="white" onRefresherRefresh={getCards}
-    //     refresherTriggered={triggered}>
-    //     {showErrorPage ? <NoData refresh={() => { getCards() }} /> : detail()}
-    // </ScrollView>
-    // return showErrorPage ? <NoData refresh={() => { getCards() }} /> : detail()
-
+    function modalDetail() {
+        return <View>
+            <MoveList list={[
+          { id: 1, name: '集美仓' },
+          { id: 2, name: '海沧仓' },
+          { id: 3, name: '思明仓' },
+          { id: 4, name: '湖里仓' },
+          { id: 11, name: '集美仓1' },
+          { id: 21, name: '海沧仓1' },
+          { id: 31, name: '思明仓1' },
+          { id: 41, name: '湖里仓1' },
+          { id: 10, name: '集美仓2' },
+          { id: 20, name: '海沧仓2' },
+          { id: 30, name: '思明仓2' },
+          { id: 40, name: '湖里仓2' }
+        ]}
+        itemHeight={45}
+        renderItem={(item) => (
+          <View
+            style={{
+              height: 40,
+              lineHeight: '40px',
+              borderBottom: '1px solid #e8e8e8',
+              padding: '0 15px',
+              color:'#fff'
+            }}
+          >
+             {item.name}
+          </View>
+        )}
+        onchange={(e) => {
+          console.log(e)
+        }}/>
+        </View>
+    }
 
     return <View style={{ position: 'relative' }}>
-        <Layout children={showErrorPage ? <NoData refresh={() => { getCards() }} /> : detail()}
+        <Layout type={TemplateType.customHeader} header={headerView()} children={showErrorPage ? <NoData refresh={() => { getCards() }} /> : detail()}
             title={t('page.activity.title')}
-            type={process.env.TARO_ENV == 'rn' ? TemplateType.flex : TemplateType.grid}
+            // type={process.env.TARO_ENV == 'rn' ? TemplateType.flex : TemplateType.grid}
             refresh={() => { getCards() }}
             triggered={triggered}
             titleShowStyle={NaviBarTitleShowType.scrollToShow}
         />
+        {
+            showModal && <Modal modalType={ModalType.bottom} dismiss={() => setShowModal(false)} confirm={() => { }}>
+                {
+                    modalDetail()
+                }
+            </Modal>
+        }
     </View>
-    // return <Layout children={showErrorPage ? <NoData refresh={() => { getCards() }} /> : detail()}
-    //     title={t('page.activity.title')}
-    //     type={TemplateType.grid}
-    //     refresh={() => { getCards() }}
-    //     triggered={triggered}
-    //     more={() => { getCards() }}
-    //     titleShowStyle={NaviBarTitleShowType.scrollToShow}
-    // />
-
 }

+ 18 - 0
src/features/trackSomething/components/MoveList.scss

@@ -0,0 +1,18 @@
+.itemDrag {
+    height: 100px;
+    width: 100%;
+    line-height: 100px;
+    border-bottom: 1px solid #ccc;
+}
+
+.drag_list {
+    position: relative;
+}
+
+.drag_item {
+    background-color: #fff;
+    width: 100%;
+    position: absolute;
+    left: 0;
+    transition: top linear 0.3s;
+}

+ 104 - 0
src/features/trackSomething/components/MoveList.tsx

@@ -0,0 +1,104 @@
+import React, { useState } from 'react'
+import styles from './index.module.less'
+import { View } from '@tarojs/components'
+import Taro from '@tarojs/taro'
+import { useThrottleFn } from 'ahooks'
+
+interface IProps {
+  list: any[]
+  itemHeight: number
+  renderItem: any
+  onchange: (value: any) => void
+}
+
+const DragSortList: React.FC<IProps> = (props) => {
+  const [list, setList] = useState(
+    props.list.map((item, index) => ({
+      ...item,
+      top: index * props.itemHeight
+    }))
+  )
+  const [dragging, setDragging] = useState(null)
+  const [startY, setStartY] = useState(0)
+
+  //  拖拽长按
+  const handleLongPress = (e, index) => {
+    // 震动
+    // Taro.vibrateShort()
+    setStartY(e.touches[0].clientY)
+    setDragging(index)
+  }
+
+  const { run: handleTouchMove } = useThrottleFn(
+    (e) => {
+      if (dragging === null) return
+      const newY = e.touches[0].clientY
+      const diff = newY - startY
+      // 计算新的 top 值
+      let newTop = list[dragging].top + diff
+      // 确保元素不会超出列表范围
+      newTop = Math.max(0, newTop)
+      newTop = Math.min(newTop, (list.length - 1) * props.itemHeight)
+      // 计算拖拽元素的当前索引
+      const currentIndex = Math.round(newTop / props.itemHeight)
+      // 只有当拖拽元素移动到新位置时才更新列表
+      if (currentIndex !== dragging) {
+        const newList = [...list]
+        // 移除拖拽元素并插入到新位置
+        const [draggingItem] = newList.splice(dragging, 1)
+        newList.splice(currentIndex, 0, draggingItem)
+        // 更新列表中每个元素的 top 值
+        newList.forEach((item, index) => {
+          item.top = index * props.itemHeight
+        })
+        setList(newList)
+        // @ts-ignore
+        setDragging(currentIndex) // 更新拖拽元素的索引
+      }
+      // 更新 startY
+      setStartY(newY)
+    },
+    { wait: 500 }
+  )
+
+  //  拖拽结束
+  const handleTouchEnd = () => {
+    if (dragging === null) return
+    // 根据最终位置更新列表顺序
+    const targetIndex = Math.round(list[dragging].top / props.itemHeight)
+    const newList = [...list]
+    const movedItem = newList.splice(dragging, 1)[0]
+    newList.splice(targetIndex, 0, movedItem)
+    // 重置元素位置
+    const arr = newList.map((item, index) => ({ ...item, top: index * props.itemHeight }))
+    setList(arr)
+    setDragging(null)
+    props.onchange(arr)
+  }
+
+  return (
+    <View className='drag_list'>
+      {list.map((item, index) => (
+        <View
+          className='drag_item'
+          key={item.id}
+          style={{
+            top: `${item.top}px`,
+            zIndex: dragging === index ? 999 : 1,
+            opacity: dragging === index ? 0.5 : 1
+          }}
+          onLongPress={(e) => {
+            console.log('【长按】', e)
+            handleLongPress(e, index)
+          }}
+          onTouchMove={handleTouchMove}
+          onTouchEnd={handleTouchEnd}
+        >
+          {props.renderItem(item)}
+        </View>
+      ))}
+    </View>
+  )
+}
+
+export default DragSortList

+ 14 - 0
src/features/trackSomething/components/MoveOrderList.scss

@@ -0,0 +1,14 @@
+.drag_item{
+    // background-color: gray;
+
+}
+
+.last_item{
+    // background-color: ;
+    color: #fff;
+}
+
+.demo_item{
+    width: 750px;
+    background-color: #000;
+}

+ 182 - 0
src/features/trackSomething/components/MoveOrderList.tsx

@@ -0,0 +1,182 @@
+import { MovableArea, MovableView, View, ScrollView } from '@tarojs/components'
+import './MoveOrderList.scss'
+import { useState } from 'react';
+import { ColorType } from '@/context/themes/color';
+
+export default function Component(props: { array: any, itemHeight: number }) {
+    const [list, setList] = useState(props.array)
+    const [movaleViewY, setMovaleViewY] = useState(0)
+    const [dragElement, setDragElement] = useState(null)
+    const [lastTarget, setLastTarget] = useState(null)
+    const [startOffsetY, setStartOffsetY] = useState(0)
+    const [startPageY, setStartPageY] = useState(0)
+    const [dragIndex, setDragIndex] = useState(-1)
+    const [scrollThreshold, setScrollThreshold] = useState(0.5)
+    const [upperThreshold, setUpperThreshold] = useState(100)
+    const [lowThreshold, setLowThreshold] = useState(100)
+    const [duration, setDuration] = useState(1000)
+    const [canScroll, setCanScroll] = useState(true)
+    const [y,setY] = useState(0)
+    const [changedIndex,setChangedIndex] = useState(-1)
+    const [hiddenContent,setHiddenContent] = useState(false)
+
+    function longPress(e, index) {
+        setChangedIndex(index)
+        setStartOffsetY(e.target.offsetTop)
+        setStartPageY(e.touches[0].pageY)
+        setDragIndex(index)
+        setDragElement(list[index])
+        setMovaleViewY(e.target.offsetTop)
+        setCanScroll(false)
+
+        setY(e.touches[0].pageY-index*props.itemHeight)
+
+        console.log(e.touches[0].pageY)
+        console.log(e.touches[0].pageY-index*props.itemHeight)
+    }
+
+    function touchMove(e) {
+        if (dragElement) {
+            let clientY = e.touches[0].clientY;
+            //this._pageScroll(clientY);
+            let pageY = e.touches[0].pageY;
+            let targetMoveDistance = pageY - startPageY
+            let movaleViewY2 = startOffsetY + targetMoveDistance
+
+            let targetIndex = computeFutureIndex(targetMoveDistance, dragIndex)
+            if (targetIndex!==false && targetIndex!=changedIndex){
+                var temps = swapListItems(list,targetIndex,changedIndex)
+                setList(temps)
+                setChangedIndex(targetIndex)
+
+            }
+            // if (targetIndex !==false){
+            //     var temps = swapListItems(list,targetIndex,dragIndex)
+            //     setList(temps)
+            //     setDragIndex(targetIndex)
+            //     // setStartPageY(targetIndex*props.itemHeight+y)
+            // }
+            // console.log(targetIndex)
+
+            // const futrueIndex = computeFutureIndex(targetMoveDistance, dragIndex)
+            // if (futrueIndex !== false) {
+            //     var temps = list
+            //     temps.splice(futrueIndex, 0, temps.splice(dragIndex, 1)[0])
+
+            //     setList(temps)
+            // }
+
+            setMovaleViewY(movaleViewY2)
+            setLastTarget(targetIndex as any)
+            setHiddenContent(true)
+        }
+    }
+
+    function swapListItems<T>(list: T[], index1: number, index2: number): T[] {
+        const newList = [...list];
+        const temp = newList[index1];
+        newList[index1] = newList[index2];
+        newList[index2] = temp;
+
+        return newList;
+    }
+
+
+    function touchEnd(e) {
+        if (dragElement) {
+            let pageY = e.changedTouches[0].pageY
+            let targetMoveDistance = pageY - startPageY;
+            /** 初始点击项索引 */
+            let dragElementIndex = dragIndex;
+            const futrueIndex = computeFutureIndex(targetMoveDistance, dragElementIndex)
+            if (futrueIndex !== false) {
+                var temps = list
+                temps.splice(futrueIndex, 0, temps.splice(dragIndex, 1)[0])
+
+                setList(temps)
+            }
+            setDragElement(null)
+            setLastTarget(null)
+            setDragIndex(-1)
+            
+        }
+        setChangedIndex(-1)
+        setCanScroll(true)
+        setHiddenContent(false)
+    }
+
+    function computeFutureIndex(targetMoveDistance, dragElementIndex) {
+        let willInsertAfter = getSwapDirection(targetMoveDistance);
+        if (willInsertAfter !== false) {
+            /** 偏移索引 */
+            let offsetElementIndex = dragElementIndex + willInsertAfter;
+            /** 移动步数 */
+            let step = targetMoveDistance / props.itemHeight;
+            /** 步数补偿,当只有移动距离超过单项 _scrollThreshold 时才算有效 */
+            if (step <= -1) {
+                step += scrollThreshold;
+            } else if (step >= 1) {
+                step -= scrollThreshold;
+            }
+            /** 目标索引 */
+            let futureIndex = parseInt(step) + offsetElementIndex;
+
+            // 避免越界
+            if (futureIndex < 0) {
+                futureIndex = 0;
+            } else if (futureIndex > list.length - 1) {
+                futureIndex = list.length - 1;
+            }
+
+            return futureIndex;
+        } else {
+            return willInsertAfter;
+        }
+    }
+
+    function getSwapDirection(targetMoveDistance) {
+        if (Math.abs(targetMoveDistance) < props.itemHeight / 2) {
+            // 轻轻拂动,滑动距离小于1/2单项高度
+            return false;
+        } else if (targetMoveDistance >= props.itemHeight / 2) {
+            // console.log('[_getSwapDirection] 👇👇👇');
+            return 1;  // 下滑
+        } else if (targetMoveDistance <= props.itemHeight / -2) {
+            // console.log('[_getSwapDirection] 👆👆👆');
+            return -1;  // 上滑
+        }
+    }
+
+    return <ScrollView scrollY={canScroll} style={{ height: 400 }}>
+        <MovableArea style={{ height: list.length * props.itemHeight }}>
+            {list.map((item, index) => {
+                var className = 'demo_item'
+                if (lastTarget == index) {
+                    className += ' last_item'
+                }
+
+                if (dragIndex == index) {
+                    className += ' drag_item'
+
+                    // console.log(className)
+                }
+                return <View style={{ opacity: changedIndex == index && hiddenContent ? 0 : 1,height:props.itemHeight}}
+                    className={className}
+                    onLongPress={(e) => longPress(e, index)}
+                    onTouchMove={(e) => touchMove(e)}
+                    onTouchEnd={(e) => touchEnd(e)}
+                >{item}</View>
+            })}
+            <MovableView style={{ height: props.itemHeight }}
+                direction='vertical'
+                disabled
+                animation={false}
+                y={movaleViewY}
+            >
+                <View className='demo_item' style={{backgroundColor:ColorType.fast}}>
+                    {dragElement}
+                </View>
+            </MovableView>
+        </MovableArea>
+    </ScrollView>
+}

+ 4 - 0
src/features/trackTimeDuration/components/TitleView.scss

@@ -9,6 +9,10 @@
     background-color: 'pink';
 }
 
+.no_sub_element{
+    height: 120px;
+}
+
 .title {
     flex-shrink: 0;
     color: #fff;

+ 10 - 4
src/features/trackTimeDuration/components/TitleView.tsx

@@ -9,9 +9,11 @@ import { jumpPage } from '../hooks/Common';
 export default function Component(props: {
     children?: any,
     subTitle?: string,
-    title: string, titleColor?: string,
+    title: string,
+    titleColor?: string,
     secondPage?: boolean,
-    showAddBtn?: boolean
+    showAddBtn?: boolean,
+    onClick?: Function
 }) {
     const time = useSelector((state: any) => state.time);
     const user = useSelector((state: any) => state.user);
@@ -22,6 +24,10 @@ export default function Component(props: {
 
 
     function more() {
+        if (props.onClick) {
+            props.onClick()
+            return
+        }
         Taro.showActionSheet({
             itemList: [
                 t('feature.track_time_duration.action_sheet.switch_scenario'),
@@ -67,7 +73,7 @@ export default function Component(props: {
 
     var showAddIcon = user.isLogin && props.showAddBtn
 
-    return <View className='title_view' >
+    return <View className={props.children ? 'title_view' : 'title_view no_sub_element'} >
         <View className='title_bg'>
             <Text className='title' style={{
                 color: props.titleColor ? props.titleColor : '#fff',
@@ -76,7 +82,7 @@ export default function Component(props: {
             {
                 showAddIcon ? <View className='iconAddBg' onClick={more}>
                     <Image src={require('@/assets/images/add.png')} className='iconAdd' />
-                </View>:<View className='iconAddBg' style={{opacity:0}}>
+                </View> : <View className='iconAddBg' style={{ opacity: 0 }}>
                     <Image src={require('@/assets/images/add.png')} className='iconAdd' />
                 </View>
             }

+ 7 - 0
src/pages/demo.config.ts

@@ -0,0 +1,7 @@
+export default definePageConfig({
+    usingComponents:{
+      // 'ec-canvas': '../../lib/ec-canvas/ec-canvas',
+      // 'demo':'../../components/demo'
+    },
+    "disableScroll": true,
+  })

+ 0 - 0
src/pages/demo.scss


+ 34 - 10
src/pages/demo.tsx

@@ -1,12 +1,36 @@
-import { Canvas, View,Text } from '@tarojs/components';
+import MoveList from '@/features/trackSomething/components/MoveList';
+import MoveOrderList from '@/features/trackSomething/components/MoveOrderList';
+import { Canvas, View, Text, PageContainer } from '@tarojs/components';
+
+import { MovableArea, MovableView } from "@tarojs/components";
+import { useEffect, useState } from 'react';
+
 export default function Demo() {
-  return <View style={{width:'100vw',height:'100vh',backgroundColor:'#000'}}>
-    <View style={{
-      width:200,
-      height:200,
-      marginTop:200,
-      borderRadius:32,
-      backgroundColor:'#1c1c1c'
-    }}></View>
-  </View>
+  const [show,setShow] = useState(false)
+
+  function items() {
+    var array = []
+    for (var i = 0; i < 5; i++) {
+      var item = (
+        <View style={{ height: 60, color: '#fff', width: 375, display: 'flex', flexDirection: 'row', alignItems: 'center' }}><Text style={{}}>第{i}咧</Text></View>
+      )
+      array.push(item)
+    }
+    return array
+  }
+
+
+  return (
+
+
+    <View>
+      <MoveOrderList itemHeight={60} array={items()} />
+      <Text style={{color:'#fff',fontWeight:'bold'}} onClick={()=>setShow(true)}>打开page container</Text>
+      <PageContainer style={{backgroundColor:'transparent'}} 
+      overlayStyle='background:transparent'
+      show={show} round={true} overlay={true} position='center' onAfterLeave={()=>setShow(false)}>
+        <View style={{width:200,height:200,backgroundColor:'pink',margin:50}}/>
+      </PageContainer>
+    </View>
+  )
 }

+ 55 - 2
yarn.lock

@@ -1206,6 +1206,13 @@
   dependencies:
     regenerator-runtime "^0.14.0"
 
+"@babel/runtime@^7.21.0":
+  version "7.23.6"
+  resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.23.6.tgz#c05e610dc228855dc92ef1b53d07389ed8ab521d"
+  integrity sha512-zHd0eUrf5GZoOWVCXp6koAKQTfZV07eit6bGPmJgnZdnSAvvZee6zniW2XMF7Cmc4ISOOnPy3QaSiIJGJkVEDQ==
+  dependencies:
+    regenerator-runtime "^0.14.0"
+
 "@babel/template@^7.0.0", "@babel/template@^7.22.15", "@babel/template@^7.22.5":
   version "7.22.15"
   resolved "https://registry.npmmirror.com/@babel/template/-/template-7.22.15.tgz#09576efc3830f0430f4548ef971dde1350ef2f38"
@@ -3313,6 +3320,11 @@
   dependencies:
     "@types/istanbul-lib-report" "*"
 
+"@types/js-cookie@^2.x.x":
+  version "2.2.7"
+  resolved "https://registry.yarnpkg.com/@types/js-cookie/-/js-cookie-2.2.7.tgz#226a9e31680835a6188e887f3988e60c04d3f6a3"
+  integrity sha512-aLkWa0C0vO5b4Sr798E26QgOkss68Un0bLjs7u9qxzPT5CG+8DuNTffWES58YzJs3hrVAOs1wonycqEBqNJubA==
+
 "@types/json-schema@*", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9":
   version "7.0.13"
   resolved "https://registry.npmmirror.com/@types/json-schema/-/json-schema-7.0.13.tgz#02c24f4363176d2d18fc8b70b9f3c54aba178a85"
@@ -3964,6 +3976,27 @@ aggregate-error@^3.0.0:
     clean-stack "^2.0.0"
     indent-string "^4.0.0"
 
+ahooks-v3-count@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/ahooks-v3-count/-/ahooks-v3-count-1.0.0.tgz#ddeb392e009ad6e748905b3cbf63a9fd8262ca80"
+  integrity sha512-V7uUvAwnimu6eh/PED4mCDjE7tokeZQLKlxg9lCTMPhN+NjsSbtdacByVlR1oluXQzD3MOw55wylDmQo4+S9ZQ==
+
+ahooks@^3.7.8:
+  version "3.7.8"
+  resolved "https://registry.yarnpkg.com/ahooks/-/ahooks-3.7.8.tgz#3fa3c491cd153e884a32b0c4192fc72cf84c4332"
+  integrity sha512-e/NMlQWoCjaUtncNFIZk3FG1ImSkV/JhScQSkTqnftakRwdfZWSw6zzoWSG9OMYqPNs2MguDYBUFFC6THelWXA==
+  dependencies:
+    "@babel/runtime" "^7.21.0"
+    "@types/js-cookie" "^2.x.x"
+    ahooks-v3-count "^1.0.0"
+    dayjs "^1.9.1"
+    intersection-observer "^0.12.0"
+    js-cookie "^2.x.x"
+    lodash "^4.17.21"
+    resize-observer-polyfill "^1.5.1"
+    screenfull "^5.0.0"
+    tslib "^2.4.1"
+
 ajv-formats@^2.1.1:
   version "2.1.1"
   resolved "https://registry.npmmirror.com/ajv-formats/-/ajv-formats-2.1.1.tgz#6e669400659eb74973bbf2e33327180a0996b520"
@@ -6130,7 +6163,7 @@ data-urls@^4.0.0:
     whatwg-mimetype "^3.0.0"
     whatwg-url "^12.0.0"
 
-dayjs@^1.7.7, dayjs@^1.8.15:
+dayjs@^1.7.7, dayjs@^1.8.15, dayjs@^1.9.1:
   version "1.11.10"
   resolved "https://registry.npmmirror.com/dayjs/-/dayjs-1.11.10.tgz#68acea85317a6e164457d6d6947564029a6a16a0"
   integrity sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ==
@@ -9324,6 +9357,11 @@ internal-slot@^1.0.5:
     has "^1.0.3"
     side-channel "^1.0.4"
 
+intersection-observer@^0.12.0:
+  version "0.12.2"
+  resolved "https://registry.yarnpkg.com/intersection-observer/-/intersection-observer-0.12.2.tgz#4a45349cc0cd91916682b1f44c28d7ec737dc375"
+  integrity sha512-7m1vEcPCxXYI8HqnL8CKI6siDyD+eIWSwgB3DZA+ZTogxk9I4CDnj4wilt9x/+/QbHI4YG5YZNmC6458/e9Ktg==
+
 intersection-observer@^0.7.0:
   version "0.7.0"
   resolved "https://registry.npmmirror.com/intersection-observer/-/intersection-observer-0.7.0.tgz#ee16bee978db53516ead2f0a8154b09b400bbdc9"
@@ -10099,6 +10137,11 @@ js-base64@^2.1.9:
   resolved "https://registry.npmmirror.com/js-base64/-/js-base64-2.6.4.tgz#f4e686c5de1ea1f867dbcad3d46d969428df98c4"
   integrity sha512-pZe//GGmwJndub7ZghVHz7vjb2LgC1m8B07Au3eYqeqv9emhESByMXxaEgkUkEqJe87oBbSniGYoQNIBklc7IQ==
 
+js-cookie@^2.x.x:
+  version "2.2.1"
+  resolved "https://registry.yarnpkg.com/js-cookie/-/js-cookie-2.2.1.tgz#69e106dc5d5806894562902aa5baec3744e9b2b8"
+  integrity sha512-HvdH2LzI/EAZcUwA8+0nKNtWHqS+ZmijLA30RwZA0bo7ToCckjK5MkGhjED9KoRcXO6BaGI3I9UIzSA1FKFPOQ==
+
 js-tokens@^3.0.0:
   version "3.0.2"
   resolved "https://registry.npmmirror.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b"
@@ -14161,6 +14204,11 @@ reselect@^4.0.0, reselect@^4.1.8:
   resolved "https://registry.npmmirror.com/reselect/-/reselect-4.1.8.tgz#3f5dc671ea168dccdeb3e141236f69f02eaec524"
   integrity sha512-ab9EmR80F/zQTMNeneUr4cv+jSwPJgIlvEmVwLerwrWVbpLlBuls9XHzIeTFy4cegU2NHBp3va0LKOzU5qFEYQ==
 
+resize-observer-polyfill@^1.5.1:
+  version "1.5.1"
+  resolved "https://registry.yarnpkg.com/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz#0e9020dd3d21024458d4ebd27e23e40269810464"
+  integrity sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==
+
 resolve-dir@^1.0.0, resolve-dir@^1.0.1:
   version "1.0.1"
   resolved "https://registry.npmmirror.com/resolve-dir/-/resolve-dir-1.0.1.tgz#79a40644c362be82f26effe739c9bb5382046f43"
@@ -14499,6 +14547,11 @@ schema-utils@^4.0.0:
     ajv-formats "^2.1.1"
     ajv-keywords "^5.1.0"
 
+screenfull@^5.0.0:
+  version "5.2.0"
+  resolved "https://registry.yarnpkg.com/screenfull/-/screenfull-5.2.0.tgz#6533d524d30621fc1283b9692146f3f13a93d1ba"
+  integrity sha512-9BakfsO2aUQN2K9Fdbj87RJIEZ82Q9IGim7FqM5OsebfoFC6ZHXgDq/KvniuLTPdeM8wY2o6Dj3WQ7KeQCj3cA==
+
 scss-bundle@^3.0.2:
   version "3.1.2"
   resolved "https://registry.npmmirror.com/scss-bundle/-/scss-bundle-3.1.2.tgz#8919dd7603d01a84822e8aab5210e5b0b50c548b"
@@ -16012,7 +16065,7 @@ tslib@^1.10.0, tslib@^1.8.1, tslib@^1.9.0:
   resolved "https://registry.npmmirror.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
   integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==
 
-tslib@^2.0.1, tslib@^2.0.3, tslib@^2.1.0, tslib@^2.3.0, tslib@^2.4.0:
+tslib@^2.0.1, tslib@^2.0.3, tslib@^2.1.0, tslib@^2.3.0, tslib@^2.4.0, tslib@^2.4.1:
   version "2.6.2"
   resolved "https://registry.npmmirror.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae"
   integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==