12
12
</div >
13
13
</template >
14
14
15
- <script lang="ts" setup>
16
- let sentence = ref ()
17
- let displayText = ref (' ' )
18
- let fullText = ref (' ' )
19
- let isTyping = ref (false ) // 添加打字状态控制
15
+ <script setup>
16
+ const sentence = ref ()
17
+ const displayText = ref (" " )
18
+ const fullText = ref (" " )
19
+ const isTyping = ref (false )
20
20
21
- // 改进的打字效果函数
21
+ // 打字效果函数
22
22
const typeText = async () => {
23
23
isTyping .value = true
24
- displayText .value = ' '
25
-
26
- // 为每个字符设置随机的打字间隔,模拟真实打字效果
24
+ displayText .value = " "
25
+
27
26
for (let i = 0 ; i < fullText .value .length ; i++ ) {
28
- if (! isTyping .value ) break // 允许中断打字
27
+ if (! isTyping .value ) break
29
28
displayText .value += fullText .value [i]
30
- // 根据标点符号调整停顿时间
31
29
const delay = fullText .value [i].match (/ [,。!?、] / ) ? 300 : 50
32
- await new Promise (resolve => setTimeout (resolve , delay ))
30
+ await new Promise (( resolve ) => setTimeout (resolve, delay))
33
31
}
34
-
32
+
35
33
isTyping .value = false
36
34
}
37
35
38
- const getSentence = async () => {
39
- const res = await fetch (" https://open.saintic.com/api/sentence/" , {
40
- method: " GET" ,
41
- })
42
- const data = await res .json ()
43
- sentence .value = data .data
44
- fullText .value = data .data .sentence
45
- await typeText ()
46
- }
36
+ // 获取随机句子
37
+ const { data } = await useAsyncData (
38
+ ` sentence-${ Math .floor (Date .now () / 60000 )} ` ,
39
+ async () => {
40
+ const res = await $fetch (" https://open.saintic.com/api/sentence/" )
41
+ return {
42
+ sentence: res? .data ? .sentence || " " ,
43
+ author: res? .data ? .author || " " ,
44
+ name: res? .data ? .name || " " ,
45
+ }
46
+ },
47
+ {
48
+ default : () => null ,
49
+ server: false
50
+ }
51
+ )
47
52
48
- onMounted (() => {
49
- getSentence ()
53
+ // 监听数据变化并执行打字效果
54
+ watch (data, async (newData ) => {
55
+ if (newData? .sentence ) {
56
+ sentence .value = newData
57
+ fullText .value = newData .sentence
58
+ await typeText ()
59
+ }
60
+ }, { immediate: true })
61
+
62
+ // 组件卸载时停止打字
63
+ onBeforeUnmount (() => {
64
+ isTyping .value = false
50
65
})
51
66
< / script>
52
67
@@ -59,6 +74,7 @@ onMounted(() => {
59
74
height: 45vh ;
60
75
background: rgb (var (-- mdui- color- surface- container- highest));
61
76
transform: translateY (calc (- 1 * var (-- inline- padding)));
77
+
62
78
.inner {
63
79
width: 70 % ;
64
80
min- width: 370px ;
@@ -68,28 +84,32 @@ onMounted(() => {
68
84
flex- direction: column;
69
85
align- items: center;
70
86
box- sizing: border- box;
87
+
71
88
.sentence {
72
89
font- size: 1 .5rem ;
73
- font-weight : 500 ;
90
+ line- height: 1.6 ;
91
+ margin- bottom: 1rem ;
92
+ min- height: 2em ;
93
+ cursor: pointer;
74
94
text- align: center;
75
- margin-bottom : 10px ;
76
- transform : translateX (7px );
95
+ font- weight: bold;
77
96
}
97
+
78
98
.source {
79
- width : 100% ;
80
99
font- size: 1rem ;
81
- font-weight : 400 ;
100
+ opacity : 0.7 ;
82
101
text- align: center;
83
- margin-top : 10px ;
102
+ }
103
+
104
+ .cursor {
105
+ animation: blink 1s infinite;
106
+ color: var (-- mdui- color- primary);
84
107
}
85
108
}
86
109
}
87
- .cursor {
88
- animation : blink 0.8s infinite ;
89
- }
90
110
91
111
@keyframes blink {
92
- 0% , 100 % { opacity : 1 ; }
93
- 50 % { opacity : 0 ; }
112
+ 0 % , 50 % { opacity: 1 ; }
113
+ 51 % , 100 % { opacity: 0 ; }
94
114
}
95
115
< / style>
0 commit comments