Baozhangchao 3 anos atrás
pai
commit
b769decdcb

+ 2
- 0
config/dev.js Ver arquivo

@@ -3,6 +3,8 @@ module.exports = {
3 3
     NODE_ENV: '"development"'
4 4
   },
5 5
   defineConstants: {
6
+    HOST: '"http://192.168.89.25:8080"',
7
+
6 8
   },
7 9
   mini: {},
8 10
   h5: {}

+ 2
- 0
config/prod.js Ver arquivo

@@ -3,6 +3,8 @@ module.exports = {
3 3
     NODE_ENV: '"production"'
4 4
   },
5 5
   defineConstants: {
6
+    HOST: '"http://192.168.89.25:8080"',
7
+
6 8
   },
7 9
   mini: {},
8 10
   h5: {

+ 16789
- 0
package-lock.json
Diferenças do arquivo suprimidas por serem muito extensas
Ver arquivo


+ 1
- 0
package.json Ver arquivo

@@ -41,6 +41,7 @@
41 41
     "@tarojs/react": "3.2.13",
42 42
     "@tarojs/runtime": "3.2.13",
43 43
     "@tarojs/taro": "3.2.13",
44
+    "@zjxpcyc/react-tiny-store": "^1.0.0",
44 45
     "react": "^17.0.0",
45 46
     "react-dom": "^17.0.0"
46 47
   },

+ 2
- 1
src/app.config.js Ver arquivo

@@ -1,7 +1,8 @@
1 1
 export default {
2 2
   pages: [
3 3
     'pages/index/index',
4
-    'pages/topList/index'
4
+    'pages/topList/index',
5
+    'pages/topListCopy/index'
5 6
   ],
6 7
   window: {
7 8
     backgroundTextStyle: 'light',

+ 34
- 6
src/app.js Ver arquivo

@@ -1,19 +1,47 @@
1 1
 import { Component } from 'react'
2
+import Taro from '@tarojs/taro'
3
+import { userLogin } from './services/user'
4
+import store, { StoreRoot } from './store'
5
+
2 6
 import './app.less'
3 7
 
4 8
 class App extends Component {
5 9
 
6
-  componentDidMount () {}
7 10
 
8
-  componentDidShow () {}
9 11
 
10
-  componentDidHide () {}
12
+  componentDidMount() {
13
+    const { signIn } = store.getModel('useFoo').getState()
14
+
15
+    Taro.login({
16
+      success: (res) => {
17
+        const { code } = res;
18
+        signIn({ code })
19
+      }
20
+    }).catch(e => {
21
+      Taro.showToast({
22
+        title: '网络异常, 请退出重试',
23
+        icon: 'none',
24
+      })
25
+    })
26
+
27
+
28
+
29
+
30
+  }
31
+
32
+  componentDidShow() { }
33
+
34
+  componentDidHide() { }
11 35
 
12
-  componentDidCatchError () {}
36
+  componentDidCatchError() { }
13 37
 
14 38
   // this.props.children 是将要会渲染的页面
15
-  render () {
16
-    return this.props.children
39
+  render() {
40
+    return (
41
+      <StoreRoot>
42
+        {this.props.children}
43
+      </StoreRoot>
44
+    )
17 45
   }
18 46
 }
19 47
 

+ 198
- 0
src/components/CanvasParty/index.jsx Ver arquivo

@@ -0,0 +1,198 @@
1
+import { View, Text, Image, Canvas } from '@tarojs/components'
2
+import React, { useMemo, useState, useEffect } from 'react'
3
+import Taro from '@tarojs/taro'
4
+
5
+
6
+
7
+export default (props) => {
8
+
9
+
10
+
11
+  // let cvs =this.sharedCanvas.getContext('2d')
12
+
13
+  useEffect(() => {
14
+    Taro.nextTick(() => {
15
+      setTimeout(() => {
16
+
17
+        Taro.createSelectorQuery()
18
+          .select('#CanvasAnotherClass')
19
+          .fields({ node: true, size: true })
20
+          .exec((res) => {
21
+            const canvas = res[0].node
22
+
23
+            const context = canvas.getContext('2d')
24
+
25
+
26
+            const width = canvas.width = window.innerWidth;
27
+            const height = canvas.height = window.innerHeight;
28
+
29
+
30
+            // création d'un tableau
31
+            let particle = [];
32
+            const particleCount = 0;
33
+            const gravity = 0.3;
34
+            const colors = [
35
+              '#f44336', '#e91e63', '#9c27b0', '#673ab7', '#3f51b5',
36
+              '#2196f3', '#03a9f4', '#00bcd4', '#009688', '#4CAF50',
37
+              '#8BC34A', '#CDDC39', '#FFEB3B', '#FFC107', '#FF9800',
38
+              '#FF5722', '#795548', '#000000'
39
+            ];
40
+
41
+
42
+
43
+            for (var i = 0; i < 300; i++) {
44
+
45
+              particle.push({
46
+                x: width / 2,
47
+                y: height / 2,
48
+                boxW: randomRange(5, 20),
49
+                boxH: randomRange(5, 20),
50
+                size: randomRange(2, 8),
51
+
52
+                spikeran: randomRange(3, 5),
53
+
54
+                velX: randomRange(-8, 8),
55
+                velY: randomRange(-50, -10),
56
+
57
+                angle: convertToRadians(randomRange(0, 360)),
58
+                color: colors[Math.floor(Math.random() * colors.length)],
59
+                anglespin: randomRange(-0.2, 0.2),
60
+
61
+                draw: function () {
62
+
63
+
64
+                  context.save();
65
+                  context.translate(this.x, this.y);
66
+                  context.rotate(this.angle);
67
+                  context.fillStyle = this.color;
68
+                  context.beginPath();
69
+                  // drawStar(0, 0, 5, this.boxW, this.boxH);
70
+                  context.fillRect(this.boxW / 2 * -1, this.boxH / 2 * -1, this.boxW, this.boxH);
71
+                  context.fill();
72
+                  context.closePath();
73
+                  context.restore();
74
+                  this.angle += this.anglespin;
75
+                  this.velY *= 0.999;
76
+                  this.velY += 0.3;
77
+
78
+                  this.x += this.velX;
79
+                  this.y += this.velY;
80
+                  if (this.y < 0) {
81
+                    this.velY *= -0.2;
82
+                    this.velX *= 0.9;
83
+                  };
84
+                  if (this.y > height) {
85
+                    this.anglespin = 0;
86
+                    this.y = height;
87
+                    this.velY *= -0.2;
88
+                    this.velX *= 0.9;
89
+                  };
90
+                  if (this.x > width || this.x < 0) {
91
+
92
+                    this.velX *= -0.5;
93
+                  };
94
+
95
+                },
96
+
97
+
98
+              });
99
+
100
+            }
101
+            const r1 = {
102
+              x: width / 2 - 150,
103
+              y: height / 2 - 150,
104
+
105
+              velX: 0,
106
+              velY: -10,
107
+              alphatop: 0
108
+            };
109
+
110
+
111
+            function drawScreen() {
112
+              const size = 50;
113
+              const pFontName = "Lucida Sans Unicode";
114
+              context.font = size + "pt " + pFontName;
115
+              // context.fillText("Confetti party !!!", width / 2, 150);
116
+              if (r1.alphatop < 1) {
117
+                r1.alphatop += 0.01;
118
+              } else {
119
+                r1.alphatop = 1;
120
+              }
121
+              context.globalAlpha = r1.alphatop;
122
+              context.textAlign = 'center';
123
+
124
+
125
+
126
+              if (r1.alphatop === 1) {
127
+                r1.velY *= 0.999;
128
+                r1.velY += 0.3;
129
+
130
+                r1.x += r1.velX;
131
+                r1.y += r1.velY;
132
+                setTimeout(() => {
133
+                  particle = []
134
+
135
+                }, 2700);
136
+
137
+              }
138
+
139
+              if (r1.y + r1.height > height) {
140
+                r1.anglespin = 0;
141
+                r1.y = height - r1.height;
142
+                r1.velY *= -0.8;
143
+                r1.velX *= 0.9;
144
+
145
+              };
146
+
147
+              context.globalAlpha = 1;
148
+              for (var i = 0; i < particle.length; i++) {
149
+                particle[i].draw();
150
+
151
+
152
+              }
153
+
154
+            }
155
+
156
+            function update() {
157
+
158
+
159
+              context.clearRect(0, 0, width, height);
160
+
161
+              drawScreen();
162
+
163
+              requestAnimationFrame(update);
164
+            }
165
+
166
+            update();
167
+
168
+
169
+            function randomRange(min, max) {
170
+              return min + Math.random() * (max - min);
171
+            }
172
+
173
+
174
+
175
+            function convertToRadians(degree) {
176
+              return degree * (Math.PI / 180);
177
+
178
+            }
179
+
180
+
181
+
182
+
183
+          })
184
+      }, 1000);
185
+
186
+
187
+
188
+    })
189
+
190
+  }, [])
191
+
192
+
193
+  return (
194
+
195
+    <Canvas id='CanvasAnotherClass' type='2d'></Canvas>
196
+
197
+  )
198
+}

BIN
src/components/assets/Crown.png Ver arquivo


BIN
src/components/assets/Top10.png Ver arquivo


BIN
src/components/familys/Cunia-Bold.woff Ver arquivo


BIN
src/components/familys/Cunia-Bold.woff2 Ver arquivo


+ 7
- 3
src/pages/index/components/TopBar/index.jsx Ver arquivo

@@ -1,6 +1,7 @@
1
-import { View } from '@tarojs/components'
1
+import { View, Image } from '@tarojs/components'
2 2
 import Taro from '@tarojs/taro'
3 3
 import React from 'react'
4
+import Top10 from '@/components/assets/Top10.png'
4 5
 // import { Tab, Tabs } from '@antmjs/vantui';
5 6
 
6 7
 import './style.less'
@@ -9,13 +10,16 @@ export default (props) => {
9 10
 
10 11
   const showTopList = () => {
11 12
     console.log('----------------------')
12
-    Taro.navigateTo({ url: '/pages/topList/index' })
13
+    // Taro.navigateTo({ url: '/pages/topList/index' })
14
+    Taro.navigateTo({ url: '/pages/topListCopy/index' })
13 15
   }
14 16
 
15 17
   return (
16 18
     <View className='top-list'>
19
+      <Image src={Top10} className='top-list-image' />
20
+
17 21
       <View className='top-list-item' onClick={showTopList}>高分榜</View>
18
-      <View className='top-list-item'>低分榜</View>
22
+
19 23
     </View>
20 24
   )
21 25
 }

+ 11
- 5
src/pages/index/components/TopBar/style.less Ver arquivo

@@ -6,17 +6,23 @@
6 6
   border: 2px solid rgba(255, 255, 255, 0.4);
7 7
   color: #fff;
8 8
   font-size: 1em;
9
-  float: right;
10
-  margin-top: 5vh;
11
-  margin-right: 5vw;
9
+  float: left;
10
+  margin-top: 10vh;
11
+  margin-left: 4vw;
12
+  align-items: center;
13
+  &-image {
14
+    width: 48px;
15
+    height: 48px;
16
+    margin-left: 20px;
17
+  }
12 18
 
13 19
   &-item {
14 20
     display: inline-block;
15 21
     flex: 1;
16
-    padding: .5em 1em;
22
+    padding: 0.5em 0.7em;
17 23
 
18 24
     & + & {
19 25
       border-left: 2px solid rgba(255, 255, 255, 0.4);
20 26
     }
21 27
   }
22
-}
28
+}

+ 1
- 1
src/pages/index/hooks/useCountDown.js Ver arquivo

@@ -15,7 +15,7 @@ export default function useCountDown() {
15 15
 
16 16
   const start = useCallback((startNum) => {
17 17
     numRef.current = startNum
18
-    setVal(startNum)
18
+    setVal(3)
19 19
   }, [])
20 20
 
21 21
   return [val, countDown, start]

+ 4
- 4
src/pages/index/hooks/useShake.js Ver arquivo

@@ -15,7 +15,7 @@ export default function useShake() {
15 15
   // eslint-disable-next-line react-hooks/exhaustive-deps
16 16
   const handleShake = useCallback(throttle((val) => {
17 17
     setTimes(val)
18
-  }, 1000, { trailing: true, immediate: true }), [])
18
+  }, 1300, { trailing: true, immediate: true }), [])
19 19
 
20 20
   const start = useCallback(() => {
21 21
     isReadyRef.current = true
@@ -24,7 +24,7 @@ export default function useShake() {
24 24
   }, [])
25 25
 
26 26
   const handleEndRef = useRef()
27
-  const onEnd = useCallback(callback => handleEndRef.current = callback, []) 
27
+  const onEnd = useCallback(callback => handleEndRef.current = callback, [])
28 28
 
29 29
   useEffect(() => {
30 30
     const interval = setInterval(() => {
@@ -44,8 +44,8 @@ export default function useShake() {
44 44
     }, 1000)
45 45
 
46 46
     return () => clearInterval(interval)
47
-  },[])
48
-  
47
+  }, [])
48
+
49 49
   useDidShow(() => {
50 50
     Taro.startAccelerometer()
51 51
 

+ 3
- 1
src/pages/index/index.config.js Ver arquivo

@@ -1,3 +1,5 @@
1 1
 export default {
2
-  navigationBarTitleText: '首页'
2
+  navigationBarTitleText: '首页',
3
+  navigationStyle: 'custom'
4
+
3 5
 }

+ 75
- 8
src/pages/index/index.jsx Ver arquivo

@@ -1,21 +1,30 @@
1 1
 
2 2
 import { useEffect, useMemo, useRef, useState } from 'react';
3
+import Taro from '@tarojs/taro';
3 4
 import { View } from '@tarojs/components'
4 5
 import Counter from '@/components/Counter'
5 6
 import { Button } from '@antmjs/vantui';
6 7
 import useInterval from '@/hooks/useInterval';
8
+import { score } from '../../services/user';
9
+
7 10
 import TopBar from './components/TopBar'
8 11
 import useCountDown from './hooks/useCountDown';
9 12
 import useShake from './hooks/useShake';
13
+import { useModel } from '../../store'
14
+
10 15
 import './index.less'
11 16
 
12 17
 const IndexPage = (props) => {
13 18
   const modRef = useRef('ready')
19
+
14 20
   const [num, setNum] = useState(0)
15 21
   const [btnDisable, setBtnDisable] = useState(false)
22
+  const { getAvatar, sessionKey, person } = useModel('useFoo')
23
+  const [buttonTitle, setbuttonTitle] = useState(true)
24
+  console.log("🚀 ~ file: index.jsx ~ line 23 ~ IndexPage ~ person", person)
16 25
 
17 26
   // 定时器
18
-  const [add2TickerList] = useInterval(1000)
27
+  const [add2TickerList] = useInterval(1400)
19 28
 
20 29
   // 倒计时
21 30
   const [count, countFn, startCount] = useCountDown();
@@ -23,17 +32,75 @@ const IndexPage = (props) => {
23 32
 
24 33
   // 摇一摇
25 34
   const [times, startShake, onShakeEnd] = useShake()
35
+
26 36
   onShakeEnd(() => {
27 37
     // 摇一摇结束
28
-    modRef.current = 'ready'
29
-    setBtnDisable(false)
38
+
39
+    Taro.showToast({
40
+      title: '游戏结束',
41
+      icon: 'none',
42
+      duration: 2000
43
+
44
+
45
+    }).then(e => {
46
+      score({ personId: person?.personId, createDate: person?.createDate, score: times }).then(e => {
47
+        modRef.current = 'ready'
48
+        setBtnDisable(false)
49
+        console.log(" 摇一摇结束")
50
+        setbuttonTitle(false)
51
+
52
+
53
+      })
54
+
55
+    })
56
+
30 57
     // do something
31 58
   })
32 59
 
60
+
61
+
33 62
   const handleStart = () => {
34
-    modRef.current = 'countdown'
35
-    startCount(3)
36
-    setBtnDisable(true)
63
+
64
+    if (!person?.avatar) {
65
+      Taro.getUserProfile({
66
+        lang: 'zh_CN',
67
+        desc: "获取你的昵称、头像、地区及性别",
68
+        success: (res) => {
69
+          const data = {
70
+            encryptedData: res.encryptedData,
71
+            iv: res.iv,
72
+            rawData: res.rawData,
73
+            sessionKey: sessionKey,
74
+            signature: res.signature
75
+          }
76
+          getAvatar(data)
77
+          Taro.showToast({
78
+            title: '授权头像成功',
79
+            icon: 'success',
80
+            duration: 2000
81
+          })
82
+
83
+
84
+        },
85
+        fail: () => {
86
+          //拒绝授权
87
+          console.error("拒绝了请求");
88
+          return;
89
+        }
90
+      })
91
+    } else {
92
+
93
+      modRef.current = 'countdown'
94
+      startCount(3)
95
+      setBtnDisable(true)
96
+    }
97
+
98
+
99
+
100
+
101
+
102
+
103
+
37 104
   }
38 105
 
39 106
   useEffect(() => {
@@ -64,8 +131,8 @@ const IndexPage = (props) => {
64 131
           color='linear-gradient(to right, rgb(255, 96, 52), rgb(238, 10, 36))'
65 132
           onClick={handleStart}
66 133
           disabled={btnDisable}
67
-        >开 始</Button>
68
-      </View>      
134
+        >{buttonTitle ? '开始游戏' : '继续游戏'}</Button>
135
+      </View>
69 136
     </View>
70 137
   )
71 138
 }

+ 33
- 0
src/pages/topListCopy/components/Topic1/index.jsx Ver arquivo

@@ -0,0 +1,33 @@
1
+import React from 'react'
2
+import { View } from '@tarojs/components'
3
+import { Image } from '@antmjs/vantui'
4
+import Crown from '@/components/assets/Crown.png'
5
+import numFormat from '@/utils/numFormat'
6
+
7
+import './style.less'
8
+
9
+export default (props) => {
10
+  const { list } = props
11
+  console.log("🚀 ~ file: index.jsx ~ line 11 ~ list", list)
12
+
13
+
14
+  return (
15
+
16
+    <View className='section_3'>
17
+      <View className='Top-Rank-one'>
18
+        <View className='Top-name'>排名</View>
19
+        <View className='Top-Number' >1</View>
20
+      </View>
21
+      <View className='section_1'>
22
+        <Image className='section_img' src={Crown} />
23
+        <image className='section2_img' src={list[0]?.avatar} />
24
+
25
+        <View className='user-name'>{list[0]?.nickName} </View>
26
+      </View>
27
+      <View className='Shaking-box'>
28
+        <View className='Shaking-name'>次数</View>
29
+        <View className='Shaking-Number'>{numFormat(list[0]?.score)}</View>
30
+      </View>
31
+    </View>
32
+  )
33
+}

+ 95
- 0
src/pages/topListCopy/components/Topic1/style.less Ver arquivo

@@ -0,0 +1,95 @@
1
+@font-face {
2
+  font-family: "Cunia";
3
+  src: url("../../../../components/familys/Cunia-Bold.woff2") format("woff2"),
4
+    url("../../../../components/familys/Cunia-Bold.woff") format("woff");
5
+  font-weight: bold;
6
+  font-style: normal;
7
+  font-display: swap;
8
+}
9
+
10
+.section_3 {
11
+  display: flex;
12
+  text-align: center;
13
+  background-color: #fff;
14
+  // background-color: #ffda4d;//金色
15
+  // background-color: #ff5085;//粉色
16
+  background-image: linear-gradient(to right, #ff3974, #ff5085);
17
+  border-radius: 0.47rem;
18
+  width: 92%;
19
+  margin: 0 auto;
20
+  top: 1em;
21
+
22
+  box-shadow: 0px 8px 38px 0px rgba(0, 0, 0, 0.12);
23
+
24
+  .Top-Rank-one {
25
+    width: 30%;
26
+    margin-top: 2em;
27
+
28
+    .Top-name {
29
+      color: rgb(241, 241, 241);
30
+      font-size: 30px;
31
+    }
32
+    .Top-Number {
33
+      margin-top: 0.6em;
34
+      font-family: "Cunia";
35
+      color: white;
36
+      font-weight: 800;
37
+      font-size: 40px;
38
+    }
39
+  }
40
+
41
+  .section_1 {
42
+    width: auto;
43
+    margin-top: 1.3em;
44
+
45
+    // .img-box {
46
+    //   width: 100%;
47
+    //   height: auto;
48
+
49
+    .section_img {
50
+      width: 2.5em;
51
+      height: 2.5em;
52
+      position: absolute;
53
+      transform: rotate(50deg);
54
+      left: 53.4vw;
55
+      top: 20vw;
56
+    }
57
+
58
+    .section2_img {
59
+      margin: auto;
60
+      width: 4.5em;
61
+      height: 4.5em;
62
+      border: 3px solid white;
63
+      border-radius: 50%;
64
+    }
65
+    // }
66
+
67
+    .user-name {
68
+      padding-bottom: 0.8em;
69
+      margin: auto;
70
+      width: 100%;
71
+      margin-top: 1.2em;
72
+      color: white;
73
+      font-size: 1.4em;
74
+      font-weight: 700;
75
+    }
76
+  }
77
+
78
+  .Shaking-box {
79
+    width: 30%;
80
+    margin-top: 2em;
81
+
82
+    .Shaking-name {
83
+      color: rgb(241, 241, 241);
84
+      font-size: 30px;
85
+      font-family: "Cunia";
86
+    }
87
+    .Shaking-Number {
88
+      font-family: "Cunia";
89
+      margin-top: 0.6em;
90
+      color: white;
91
+      // font-weight: 800;
92
+      font-size: 40px;
93
+    }
94
+  }
95
+}

+ 30
- 0
src/pages/topListCopy/components/TopicItem/index.jsx Ver arquivo

@@ -0,0 +1,30 @@
1
+import React, { useMemo } from 'react'
2
+import { View } from '@tarojs/components'
3
+import { Image } from '@antmjs/vantui'
4
+import './style.less'
5
+
6
+export default (props) => {
7
+  const { info, num } = props
8
+  const { avatar, nickname, score } = info || {}
9
+
10
+  const size = 64
11
+
12
+  const avatarStyle = useMemo(() => {
13
+    return {
14
+      width: `${size}px`
15
+    }
16
+  }, [size])
17
+
18
+  return (
19
+    <View className='topic-item flex-box'>
20
+      <View className='topic-item-num flex-box-item-fixed'>{num}</View>
21
+      <View className='flex-box topic-item-border flex-box-item'>
22
+        <View className='flex-box-item-fixed topic-item-avatar' style={avatarStyle}>
23
+          <Image src={avatar} width={size} height={size} round></Image>
24
+        </View>
25
+        <View className='flex-box-item topic-item-nickname'>{nickname}</View>
26
+        <View className='flex-box-item topic-item-score'>{score}</View>
27
+      </View>
28
+    </View>
29
+  )
30
+}

+ 46
- 0
src/pages/topListCopy/components/TopicItem/style.less Ver arquivo

@@ -0,0 +1,46 @@
1
+@import '../../../../theme.less';
2
+
3
+@numWidth : 80rpx;
4
+@tpHeight : 120rpx;
5
+
6
+.topic-item {
7
+  position: relative;
8
+  width: 100%;
9
+  overflow-x: hidden;
10
+  box-sizing: border-box;
11
+  height: @tpHeight;
12
+  color: @primary-color;
13
+  background: #fff;
14
+
15
+  &-num {
16
+    width: @numWidth;
17
+    text-align: center;
18
+    line-height: @tpHeight;
19
+    font-size: 1.2em;
20
+    font-weight: bold;
21
+  }
22
+
23
+  &-avatar {
24
+    display: flex;
25
+    align-items: center;
26
+  }
27
+
28
+  &-nickname {
29
+    font-size: 1em;
30
+    line-height: @tpHeight;
31
+  }
32
+
33
+  &-score {
34
+    text-align: right;
35
+    font-size: 1.2em;
36
+    font-weight: bold;
37
+    line-height: @tpHeight;
38
+    padding-right: 2em;
39
+  }
40
+
41
+  & + & {
42
+    .topic-item-border {
43
+      border-top: 1rpx solid #ccc;
44
+    }
45
+  }
46
+}

+ 6
- 0
src/pages/topListCopy/index.config.js Ver arquivo

@@ -0,0 +1,6 @@
1
+export default {
2
+  navigationBarTitleText: '排行榜',
3
+  disableScroll: true,
4
+
5
+  navigationStyle: 'custom'
6
+}

+ 101
- 0
src/pages/topListCopy/index.jsx Ver arquivo

@@ -0,0 +1,101 @@
1
+import { View, Text, Image, Canvas } from '@tarojs/components'
2
+import React, { useMemo, useState, useEffect } from 'react'
3
+import Taro from '@tarojs/taro'
4
+import CanvasPart from '@/components/CanvasParty'
5
+import numFormat from '@/utils/numFormat'
6
+
7
+import Topic1 from './components/Topic1'
8
+import TopicItem from './components/TopicItem'
9
+import { scoreTop } from '../../services/user'
10
+
11
+import './style.less'
12
+
13
+
14
+export default (props) => {
15
+
16
+  const [list, setList] = useState([])
17
+  const menuBtnBounding = useMemo(() => Taro.getMenuButtonBoundingClientRect(), [])
18
+  const style = useMemo(() => {
19
+    const top = menuBtnBounding.height + menuBtnBounding.top
20
+
21
+    return {
22
+      paddingTop: `${top}px`
23
+    }
24
+  }, [menuBtnBounding.height, menuBtnBounding.top])
25
+
26
+  // const [first, leftData] = useMemo(() => {
27
+  //   const [f, ...l] = list || []
28
+  //   return [f, l]
29
+  // }, [list])
30
+
31
+
32
+  useEffect(() => {
33
+    scoreTop().then(e => {
34
+      setList(e)
35
+    })
36
+
37
+  }, [])
38
+
39
+
40
+
41
+  return (
42
+    <View className='page-wrapper page-topListCopy' style={style}>
43
+
44
+      <Topic1 list={list} />
45
+      <View className='TopConten-box'>
46
+        <View className='title-name'>排名</View>
47
+        <View className='title-name'>用户</View>
48
+        <View className='title-name'>昵称</View>
49
+        <View className='title-name'>次数</View>
50
+      </View>
51
+      {/* #B99764  铜牌
52
+      #C9C9CF */}
53
+
54
+      <scroll-view scrollY style={{ height: '100%', marginTop: '1em' }}>
55
+
56
+
57
+
58
+        {
59
+          list.map((item, index) => {
60
+            console.log("🚀 ~ file: index.jsx ~ line 60 ~ list.map ~ index", index)
61
+
62
+            const styles = {
63
+              backgroundColor: '#C9C9CF',
64
+              animationDelay: `${100 * index + 80}ms`
65
+            }
66
+            if (index >= 1) {
67
+              return (
68
+
69
+                <View key={index} className='UserContent-box' style={styles}>
70
+                  <View className='topsum'>{index + 1}</View>
71
+                  <Image style={{
72
+                    width: '47px',
73
+                    height: '47px',
74
+                    borderRadius: '50%',
75
+                    position: 'absolute',
76
+                    left: '8.3em'
77
+
78
+                  }} src={item.avatar}
79
+                  />
80
+                  <View className='topNumber-name'>
81
+                    {item.nickName}
82
+                  </View>
83
+                  <View className='topNumber-text'>
84
+                    {numFormat(item.score)}
85
+
86
+                  </View>
87
+                </View>
88
+              )
89
+            }
90
+
91
+
92
+          })
93
+        }
94
+      </scroll-view>
95
+
96
+
97
+
98
+
99
+    </View>
100
+  )
101
+}

+ 92
- 0
src/pages/topListCopy/style.less Ver arquivo

@@ -0,0 +1,92 @@
1
+@font-face {
2
+  font-family: "Cunia";
3
+  src: url("../../components/familys/Cunia-Bold.woff2") format("woff2"),
4
+    url("../../components/familys/Cunia-Bold.woff") format("woff");
5
+  font-weight: bold;
6
+  font-style: normal;
7
+  font-display: swap;
8
+}
9
+
10
+.page-topListCopy {
11
+  background-color: white;
12
+
13
+  .TopConten-box {
14
+    display: flex;
15
+    align-items: center;
16
+    width: 92%;
17
+    height: 6%;
18
+    background-color: rgba(85, 123, 226, 1);
19
+    border-radius: 10px;
20
+    margin: 5em auto 0;
21
+
22
+    .title-name {
23
+      color: white;
24
+      font-size: 30px;
25
+      flex: 4;
26
+      text-align: center;
27
+    }
28
+  }
29
+  .UserContent-box {
30
+    animation: TopConten-box 1.3s 1 cubic-bezier(0.215, 0.61, 0.355, 1);
31
+    align-items: center;
32
+    display: flex;
33
+    width: 92%;
34
+    height: 115.47px;
35
+    background-color: rgba(255, 255, 255, 1);
36
+    border-radius: 14px;
37
+    box-shadow: 0px 8px 38px 0px rgba(0, 0, 0, 0.12);
38
+    margin: 0.8em auto 0;
39
+    flex: 4;
40
+
41
+    .topsum {
42
+      font-family: "Cunia";
43
+      font-size: 30px;
44
+      position: absolute;
45
+      left: 3.5em;
46
+    }
47
+    .topNumber-name {
48
+      font-family: "Cunia";
49
+      font-size: 30px;
50
+      position: absolute;
51
+      left: 13em;
52
+      width: 180px;
53
+      white-space: nowrap;
54
+      text-overflow: ellipsis;
55
+      overflow: hidden;
56
+    }
57
+    .topNumber-text {
58
+      font-family: "Cunia";
59
+      font-size: 30px;
60
+      position: absolute;
61
+      left: 20em;
62
+    }
63
+  }
64
+}
65
+
66
+@keyframes TopConten-box {
67
+  0% {
68
+    opacity: 0;
69
+    transform: translate3d(-3000px, 0, 0);
70
+  }
71
+  60% {
72
+    opacity: 1;
73
+    transform: translate3d(25px, 0, 0);
74
+  }
75
+  75% {
76
+    transform: translate3d(-10px, 0, 0);
77
+  }
78
+  90% {
79
+    transform: translate3d(5px, 0, 0);
80
+  }
81
+  100% {
82
+    transform: none;
83
+  }
84
+}
85
+canvas {
86
+  position: absolute;
87
+  width: 100%;
88
+  height: 100%;
89
+  left: 20px;
90
+  top: -10;
91
+  z-index: 0;
92
+}

+ 33
- 0
src/services/user.js Ver arquivo

@@ -0,0 +1,33 @@
1
+import request from '@/utils/request'
2
+/**
3
+ * 登录
4
+ * @param {*} id 
5
+ * @returns 
6
+ * loginParam
7
+ */
8
+export const userLogin = (code) => request(`/ma/login?code=${code}`, { method: 'post' })
9
+
10
+
11
+/**
12
+ * 授权头像
13
+ * @param {*} data 
14
+ * @returns 
15
+ */
16
+export const authAvatar = (data) => request('/ma/auth-user', { data, method: 'put' })
17
+
18
+/**
19
+ * 摇一摇结束
20
+ * @param {*} data 
21
+ * @returns 
22
+ */
23
+export const score = (data) => request('/ma/score', { data, method: 'post' })
24
+
25
+
26
+
27
+/**
28
+ * 摇一摇结束
29
+ * @param {*} data 
30
+ * @returns 
31
+ */
32
+export const scoreTop = () => request('/score/top',)
33
+

+ 20
- 0
src/store/index.js Ver arquivo

@@ -0,0 +1,20 @@
1
+import { createStoreRoot, createModelHook, createStore } from '@zjxpcyc/react-tiny-store'
2
+
3
+import useBar from './models/useBar'
4
+import useFoo from './models/useFoo'
5
+
6
+const store = createStore()
7
+const models = {
8
+  useBar,
9
+  useFoo,
10
+}
11
+const StoreRoot = createStoreRoot(store, models)
12
+const useModel = createModelHook(store)
13
+
14
+
15
+export default store
16
+export {
17
+  StoreRoot,
18
+  useModel,
19
+
20
+}

+ 10
- 0
src/store/models/useBar.js Ver arquivo

@@ -0,0 +1,10 @@
1
+import { useState } from "react";
2
+
3
+export default function useSystem() {
4
+  const [messageTpls, setMessageTpls] = useState([])
5
+
6
+  return {
7
+    messageTpls,
8
+    setMessageTpls,
9
+  }
10
+}

+ 45
- 0
src/store/models/useFoo.js Ver arquivo

@@ -0,0 +1,45 @@
1
+import { useState } from "react"
2
+import Taro, { stopDeviceMotionListening } from '@tarojs/taro'
3
+import { userLogin, authAvatar } from '../../services/user'
4
+
5
+
6
+
7
+
8
+export default function useUser() {
9
+  const [user, setUser] = useState({})
10
+  const [person, setPerson] = useState()
11
+  const [sessionKey, setSessionKey] = useState()
12
+
13
+
14
+
15
+  const signIn = (params) => {
16
+    userLogin(params.code).then((res) => {
17
+      const { person: taPerson, skey, token } = res;
18
+      setPerson(taPerson);
19
+      setSessionKey(skey);
20
+
21
+      Taro.setStorage({ key: 'token', data: token })
22
+    })
23
+  }
24
+
25
+  const signOut = () => {
26
+    // xxx
27
+  }
28
+
29
+  const getAvatar = (data) => {
30
+    return authAvatar(data).then((res) => {
31
+      setPerson(res);
32
+    })
33
+  }
34
+
35
+  return {
36
+    user,
37
+    person,
38
+    sessionKey,
39
+
40
+    signIn,
41
+    signOut,
42
+    getAvatar,
43
+
44
+  }
45
+}

+ 54
- 32
src/utils/index.js Ver arquivo

@@ -1,35 +1,57 @@
1 1
 
2 2
 export function throttle(fn, delay, options = {}) {
3
-  let timer = null;
4
-  let last = 0;
5
-
6
-  return function() {
7
-      const context = this;
8
-      const args = arguments;
9
-
10
-      const now = +new Date();
11
-      
12
-      if (last === 0 && options.immediate === false) {
13
-          last = now;
14
-      }
15
-
16
-      const offset = now - last;
17
-
18
-      if (offset > delay) {
19
-          if (timer) {
20
-              clearTimeout(timer);
21
-              timer = null;
22
-          }
23
-
24
-          last = now;
25
-          fn.apply(context, args);
26
-      }
27
-      else if (!timer && options.trailing !== false) {
28
-          timer = setTimeout(() => {
29
-              last = options.immediate === false ? 0 : +new Date();;
30
-              timer = null;
31
-              fn.apply(context, args);
32
-          }, delay - offset);
33
-      }
34
-  };
3
+    let timer = null;
4
+    let last = 0;
5
+
6
+    return function () {
7
+        const context = this;
8
+        const args = arguments;
9
+
10
+        const now = +new Date();
11
+
12
+        if (last === 0 && options.immediate === false) {
13
+            last = now;
14
+        }
15
+
16
+        const offset = now - last;
17
+
18
+        if (offset > delay) {
19
+            if (timer) {
20
+                clearTimeout(timer);
21
+                timer = null;
22
+            }
23
+
24
+            last = now;
25
+            fn.apply(context, args);
26
+        }
27
+        else if (!timer && options.trailing !== false) {
28
+            timer = setTimeout(() => {
29
+                last = options.immediate === false ? 0 : +new Date();;
30
+                timer = null;
31
+                fn.apply(context, args);
32
+            }, delay - offset);
33
+        }
34
+    };
35
+}
36
+
37
+
38
+
39
+/**
40
+ * object 转 queryStr
41
+ * @param {*} params 
42
+ * @returns 
43
+ */
44
+export function getQueryString(params) {
45
+    if (!params) return;
46
+
47
+    const keys = Object.keys(params)
48
+    const arr = keys.map((key) => {
49
+        const val = params[key]
50
+        if (val === null || val === undefined) return false;
51
+
52
+        return `${key}=${encodeURIComponent(val)}`
53
+    })
54
+
55
+    return arr.filter(Boolean).join('&')
35 56
 }
57
+

+ 20
- 0
src/utils/numFormat.js Ver arquivo

@@ -0,0 +1,20 @@
1
+//大于1k会自动转换为1k digits是小数点保留位数
2
+
3
+export default function numFormat(num, digits) {
4
+  var si = [
5
+    { value: 1, symbol: "" },
6
+    { value: 1E3, symbol: "k" },
7
+    { value: 1E4, symbol: "W" }
8
+  ];
9
+  var rx = /\.0+$|(\.[0-9]*[1-9])0+$/;
10
+  var i;
11
+  for (i = si.length - 1; i > 0; i--) {
12
+    if (num >= si[i].value) {
13
+      break;
14
+    }
15
+  }
16
+  return (num / si[i].value).toFixed(digits).replace(rx, "$1") + si[i].symbol;
17
+
18
+
19
+
20
+}

+ 53
- 0
src/utils/request.js Ver arquivo

@@ -0,0 +1,53 @@
1
+import Taro from "@tarojs/taro";
2
+import { getQueryString } from ".";
3
+
4
+
5
+
6
+export default (url, options) => {
7
+  const { params, header, ...leftOptions } = options || {}
8
+
9
+
10
+  const queryStr = getQueryString(params)
11
+
12
+  const urlWithParams = queryStr ? `${url}?${queryStr}` : url;
13
+  const nwUrl = `${HOST}/api${urlWithParams}`
14
+
15
+  const authToken = Taro.getStorageSync('token')
16
+  const tokenHeader = authToken ? { 'X-Authorization-JWT': authToken } : {}
17
+  const nwHeader = {
18
+    ...(header || {}),
19
+    ...tokenHeader,
20
+  }
21
+
22
+
23
+
24
+
25
+  return new Promise((resolve, reject) => {
26
+    Taro.request({
27
+      ...leftOptions,
28
+      url: nwUrl,
29
+      header: nwHeader,
30
+      success: (res) => {
31
+        const { code, message, data, token } = res.data
32
+        if (token || data?.token) {
33
+          Taro.setStorage({ key: 'token', data: token || data?.token })
34
+        }
35
+        if (code === 1000) {
36
+          resolve(data)
37
+        } else {
38
+          console.error(res)
39
+
40
+
41
+          reject(message?.indexOf('java') > -1 ? '系统内部错误' : message)
42
+        }
43
+      },
44
+
45
+      fail: (err) => {
46
+        const message = err.message || err.errMsg || err
47
+
48
+        reject(message)
49
+      }
50
+    })
51
+  })
52
+
53
+}

+ 10
- 3
yarn.lock Ver arquivo

@@ -1827,6 +1827,13 @@
1827 1827
   resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d"
1828 1828
   integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==
1829 1829
 
1830
+"@zjxpcyc/react-tiny-store@^1.0.0":
1831
+  version "1.0.0"
1832
+  resolved "https://registry.npmmirror.com/@zjxpcyc/react-tiny-store/download/@zjxpcyc/react-tiny-store-1.0.0.tgz#316a2a0336273c1c014bf2f55a513583770c7181"
1833
+  integrity sha1-MWoqAzYnPBwBS/L1WlE1g3cMcYE=
1834
+  dependencies:
1835
+    fast-deep-equal "^3.1.3"
1836
+
1830 1837
 abab@^2.0.0:
1831 1838
   version "2.0.5"
1832 1839
   resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.5.tgz#c0b678fb32d60fc1219c784d6a826fe385aeb79a"
@@ -4629,10 +4636,10 @@ extsprintf@^1.2.0:
4629 4636
   resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.1.tgz#8d172c064867f235c0c84a596806d279bf4bcc07"
4630 4637
   integrity sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA==
4631 4638
 
4632
-fast-deep-equal@^3.1.1:
4639
+fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3:
4633 4640
   version "3.1.3"
4634
-  resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525"
4635
-  integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==
4641
+  resolved "https://registry.nlark.com/fast-deep-equal/download/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525"
4642
+  integrity sha1-On1WtVnWy8PrUSMlJE5hmmXGxSU=
4636 4643
 
4637 4644
 fast-glob@^2.0.2:
4638 4645
   version "2.2.7"