Commit 5835a5f030414fce82bf67a3cf6b11821d0d2d0d
1 parent
8ee3a286
feat: 徽智制联-deepSeek-按照UI稿重新写一版,再增加切换问题功能
Showing
9 changed files
with
296 additions
and
105 deletions
1 | 1 | ||
2 | .mark-down { | 2 | .mark-down { |
3 | width: auto; | 3 | width: auto; |
4 | - max-width: 60%; | 4 | + max-width: 355px; |
5 | background: #fff; | 5 | background: #fff; |
6 | - border-radius: 10px; | ||
7 | - padding: 20px; | 6 | + border-radius: 15px; |
7 | + padding: 12px 28px 12px 16px; | ||
8 | .group { | 8 | .group { |
9 | margin-bottom: 10px; | 9 | margin-bottom: 10px; |
10 | } | 10 | } |
11 | } | 11 | } |
12 | - | ||
13 | -.role { | ||
14 | - width: 40px; | ||
15 | - height: 28px; | ||
16 | - line-height: 28px; | ||
17 | - font-size: 14px; | ||
18 | - border-radius: 14px; | ||
19 | - text-align: center; | ||
20 | -} | ||
21 | - | ||
22 | -.text-right { | ||
23 | - display: flex; | ||
24 | - flex-direction: row-reverse; | ||
25 | - padding-right: 2%; | ||
26 | - .role { | ||
27 | - margin-left: 20px; | ||
28 | - background: #0A84FE; | ||
29 | - color: #fff; | ||
30 | - } | ||
31 | - .mark-down { | ||
32 | - background: #0A84FE; | ||
33 | - color: #fff; | ||
34 | - padding: 10px; | ||
35 | - } | ||
36 | -} | ||
37 | -.text-left { | ||
38 | - display: flex; | ||
39 | - padding-left: 2%; | ||
40 | - .role { | ||
41 | - margin-right: 20px; | ||
42 | - background: #fff; | ||
43 | - } | ||
44 | - .mark-down { | ||
45 | - p { | ||
46 | - overflow-wrap:break-word; | ||
47 | - word-break: break-all; | ||
48 | - } | ||
49 | - } | ||
50 | -} |
src/pages/deep-seek-index/banner_base.png
0 → 100644
273 KB
src/pages/deep-seek-index/bg_base.jpg
0 → 100644
658 KB
src/pages/deep-seek-index/head_base.png
0 → 100644
53.8 KB
1 | import React, {useState, useEffect, useRef} from "react"; | 1 | import React, {useState, useEffect, useRef} from "react"; |
2 | import './style.less' | 2 | import './style.less' |
3 | -import { Button, Input } from 'antd'; | 3 | +import { Input, Button } from '@chatui/core'; |
4 | import Markdown from '@/components/deepSeekIndex/Markdown' | 4 | import Markdown from '@/components/deepSeekIndex/Markdown' |
5 | -import laBanner from "./laBanner.png"; | 5 | +import banner from "./banner_base.png"; |
6 | +import bg from "./bg_base.jpg"; | ||
7 | +import refresh from "./refresh.png"; | ||
8 | +import _ from 'lodash'; | ||
9 | + | ||
10 | +export const getTime = () => { | ||
11 | + // 创建 Date 对象 | ||
12 | + const now = new Date(); | ||
13 | + | ||
14 | + // 获取月份(0-11,需 +1 转为实际月份) | ||
15 | + const month = String(now.getMonth() + 1).padStart(2, '0'); // 补零成两位数 | ||
16 | + // 获取日期 | ||
17 | + const day = String(now.getDate()).padStart(2, '0'); | ||
18 | + // 获取小时 | ||
19 | + const hours = String(now.getHours()).padStart(2, '0'); | ||
20 | + // 获取分钟 | ||
21 | + const minutes = String(now.getMinutes()).padStart(2, '0'); | ||
22 | + // 组合成目标格式 | ||
23 | + const result = `${month}月${day}日 ${hours}:${minutes}`; | ||
24 | + | ||
25 | + console.log(result); // 示例输出:07月15日 08:30 | ||
26 | + | ||
27 | + return result; | ||
28 | +} | ||
29 | +const example_1 = [ | ||
30 | + { | ||
31 | + name: '联通提供哪些服务?', | ||
32 | + id: '1' | ||
33 | + }, | ||
34 | + { | ||
35 | + name: '怎么办理国际漫游服务?', | ||
36 | + id: '2' | ||
37 | + }, | ||
38 | + { | ||
39 | + name: '如何办理宽带?', | ||
40 | + id: '3' | ||
41 | + } | ||
42 | +] | ||
43 | + | ||
44 | +const example_2 = [ | ||
45 | + { | ||
46 | + name: '5G套餐推荐', | ||
47 | + id: '4' | ||
48 | + }, | ||
49 | + { | ||
50 | + name: '如何办理语音通话和短信的基础套餐?', | ||
51 | + id: '5' | ||
52 | + }, | ||
53 | + { | ||
54 | + name: '上不了网怎么办?', | ||
55 | + id: '6' | ||
56 | + } | ||
57 | +] | ||
6 | 58 | ||
7 | const DeepSeekIndex: React.FC = () => { | 59 | const DeepSeekIndex: React.FC = () => { |
8 | const [searchValue, setSearchValue] = useState<any>(); | 60 | const [searchValue, setSearchValue] = useState<any>(); |
61 | + const [disabled, setDisabled] = useState<boolean>(false); | ||
62 | + const [exampleFlag, setExampleFlag] = useState<string>('1') | ||
9 | 63 | ||
10 | const [chatHistory, setChatHistory] = useState<any[]>([]); | 64 | const [chatHistory, setChatHistory] = useState<any[]>([]); |
11 | const [currentResponse, setCurrentResponse] = useState<string>(''); | 65 | const [currentResponse, setCurrentResponse] = useState<string>(''); |
12 | 66 | ||
13 | const chatRef = useRef(null); | 67 | const chatRef = useRef(null); |
14 | 68 | ||
15 | - const send = async () => { | 69 | + useEffect(() => { |
70 | + const _time = getTime(); | ||
71 | + const newHistory = [...chatHistory, | ||
72 | + {role: 'time', answer: _time}, | ||
73 | + { | ||
74 | + role: 'example', | ||
75 | + answer: example_1 | ||
76 | + } | ||
77 | + ]; | ||
78 | + console.log('newHistory', newHistory) | ||
79 | + setChatHistory(newHistory); | ||
80 | + }, []) | ||
81 | + | ||
82 | + const refreshFun = () => { | ||
83 | + const _exampleFlag = _.cloneDeep(exampleFlag); | ||
84 | + const _example = _exampleFlag === '1' ? example_2 : example_1; | ||
85 | + const _chatHistory = _.cloneDeep(chatHistory); | ||
86 | + _chatHistory?.forEach((item: any) => { | ||
87 | + if (item?.role === 'example') { | ||
88 | + item.answer = _example | ||
89 | + } | ||
90 | + }) | ||
91 | + setChatHistory(_chatHistory); | ||
92 | + const _newExampleFlag = _exampleFlag === '1' ? '2' : '1' | ||
93 | + setExampleFlag(_newExampleFlag); | ||
94 | + } | ||
95 | + | ||
96 | + const send = async (_searchValue?: string) => { | ||
97 | + if (disabled) return; | ||
98 | + setDisabled(true); | ||
16 | console.log('searchValue', searchValue) | 99 | console.log('searchValue', searchValue) |
100 | + const _value = _searchValue ? _searchValue : searchValue; | ||
17 | const data = { | 101 | const data = { |
18 | - "query": searchValue, | 102 | + "query": _value, |
19 | "inputs": {}, | 103 | "inputs": {}, |
20 | "response_mode": "streaming", | 104 | "response_mode": "streaming", |
21 | "user": "11", | 105 | "user": "11", |
22 | "conversation_id": "" | 106 | "conversation_id": "" |
23 | } | 107 | } |
24 | const customHeaders = { | 108 | const customHeaders = { |
25 | - 'Authorization': 'Bearer app-nvw8Y9taTRWuKg9ZfaoMXwNC' | 109 | + 'Authorization': 'Bearer app-XxOBqpQr6u4c43tIl6by4vpK' |
26 | } | 110 | } |
27 | 111 | ||
28 | - const newHistory = [...chatHistory, { role: 'user', answer: searchValue }]; | 112 | + const _time = getTime(); |
113 | + const newHistory = [...chatHistory, | ||
114 | + {role: 'time', answer: _time}, | ||
115 | + {role: 'user', answer: _value} | ||
116 | + ]; | ||
29 | setChatHistory(newHistory); | 117 | setChatHistory(newHistory); |
30 | setSearchValue(''); | 118 | setSearchValue(''); |
31 | let _currentResponse = ''; | 119 | let _currentResponse = ''; |
32 | 120 | ||
33 | try { | 121 | try { |
34 | - const response = await fetch('http://10.9.5.168/v1/chat-messages', { | 122 | + const response = await fetch('http://36.34.99.80:8088/v1/chat-messages', { |
35 | method: 'POST', | 123 | method: 'POST', |
36 | headers: { | 124 | headers: { |
37 | 'Content-Type': 'application/json', | 125 | 'Content-Type': 'application/json', |
38 | // 这里可以添加自定义请求头 | 126 | // 这里可以添加自定义请求头 |
39 | ...customHeaders | 127 | ...customHeaders |
40 | }, | 128 | }, |
41 | - body: JSON.stringify({...data }) | 129 | + body: JSON.stringify({...data}) |
42 | }); | 130 | }); |
43 | 131 | ||
44 | if (!response.ok) { | 132 | if (!response.ok) { |
@@ -50,9 +138,9 @@ const DeepSeekIndex: React.FC = () => { | @@ -50,9 +138,9 @@ const DeepSeekIndex: React.FC = () => { | ||
50 | let buffer = ''; | 138 | let buffer = ''; |
51 | 139 | ||
52 | while (true) { | 140 | while (true) { |
53 | - const { done, value } = await reader.read(); | 141 | + const {done, value} = await reader.read(); |
54 | if (done) break; | 142 | if (done) break; |
55 | - buffer += decoder?.decode(value, { stream: true }); | 143 | + buffer += decoder?.decode(value, {stream: true}); |
56 | const lines = buffer?.split('\n'); | 144 | const lines = buffer?.split('\n'); |
57 | buffer = lines.pop(); | 145 | buffer = lines.pop(); |
58 | lines.forEach(line => { | 146 | lines.forEach(line => { |
@@ -64,10 +152,12 @@ const DeepSeekIndex: React.FC = () => { | @@ -64,10 +152,12 @@ const DeepSeekIndex: React.FC = () => { | ||
64 | }); | 152 | }); |
65 | } | 153 | } |
66 | 154 | ||
67 | - const updatedHistory = [...newHistory, { role: 'assistant', answer: _currentResponse }]; | 155 | + const updatedHistory = [...newHistory, {role: 'assistant', answer: _currentResponse}]; |
68 | setChatHistory(updatedHistory); | 156 | setChatHistory(updatedHistory); |
69 | setCurrentResponse(''); | 157 | setCurrentResponse(''); |
70 | 158 | ||
159 | + setDisabled(false); | ||
160 | + | ||
71 | 161 | ||
72 | } catch (error) { | 162 | } catch (error) { |
73 | console.error('Stream error:', error); | 163 | console.error('Stream error:', error); |
@@ -87,45 +177,68 @@ const DeepSeekIndex: React.FC = () => { | @@ -87,45 +177,68 @@ const DeepSeekIndex: React.FC = () => { | ||
87 | console.log('chatHistory', chatHistory) | 177 | console.log('chatHistory', chatHistory) |
88 | }, [chatHistory]) | 178 | }, [chatHistory]) |
89 | 179 | ||
180 | + const handleKeyDown = (e) => { | ||
181 | + if (e.key === 'Enter' && !e.shiftKey) { | ||
182 | + e.preventDefault(); // 阻止默认换行 | ||
183 | + send(); | ||
184 | + } | ||
185 | + }; | ||
186 | + | ||
90 | return ( | 187 | return ( |
91 | - <div className={'deep-seek'}> | ||
92 | - <div className={'deep-seek_header'}> | ||
93 | - <img src={laBanner} alt=""/> | ||
94 | - </div> | ||
95 | - <div | ||
96 | - ref={chatRef} | ||
97 | - className={'deep-seek_content'} | ||
98 | - > | ||
99 | - {chatHistory?.map((msg, index) => ( | ||
100 | - <p key={index} className={`mb-2 ${msg.role === 'user' ? 'text-right' : 'text-left'}`}> | ||
101 | - { | ||
102 | - msg?.role ? <div className={'role'}> | ||
103 | - {msg?.role === 'user' ? '问' : msg?.role === 'assistant' ? '答' : ''} | ||
104 | - </div> : '' | ||
105 | - } | ||
106 | - <Markdown content={msg?.answer}/> | ||
107 | - </p> | ||
108 | - ))} | ||
109 | - {currentResponse && ( | ||
110 | - <p className="mb-2 text-left current"> | ||
111 | - <div className={'role'}>答</div> | ||
112 | - <Markdown content={currentResponse} /> | ||
113 | - </p> | ||
114 | - )} | ||
115 | - </div> | ||
116 | - <div className={'deep-seek_footer'}> | ||
117 | - <Input | ||
118 | - type="text" | ||
119 | - value={searchValue} | ||
120 | - className="company-list-search-input" | ||
121 | - placeholder="输入..." | ||
122 | - onChange={(e) => setSearchValue(e.target.value)} | ||
123 | - onPressEnter={send} | ||
124 | - /> | ||
125 | - <Button type={'primary'} onClick={send}>发送</Button> | ||
126 | - </div> | ||
127 | - | ||
128 | - </div> | 188 | + <div className={'deep-seek'}> |
189 | + <img className={'deep-seek_bg'} src={bg} alt=""/> | ||
190 | + <div | ||
191 | + ref={chatRef} | ||
192 | + className={'deep-seek_content'} | ||
193 | + > | ||
194 | + <div className={'deep-seek_header'}> | ||
195 | + <img src={banner} alt=""/> | ||
196 | + </div> | ||
197 | + {chatHistory?.map((msg, index) => ( | ||
198 | + <div key={index} className={`${msg.role === 'user' ? 'content-right' : msg.role === 'assistant' ? 'content-left' : 'content-center' }`}> | ||
199 | + { | ||
200 | + msg.role === 'time' ? | ||
201 | + <div className={'current-time'}>{msg?.answer}</div>: | ||
202 | + msg.role === 'example'? <div className={'current-example'}> | ||
203 | + <div className={'current-example_head'}> | ||
204 | + <p className={'current-example_head-name'}>你想了解什么呢</p> | ||
205 | + <img src={refresh} className={'refresh'} alt="" onClick={refreshFun}/> | ||
206 | + </div> | ||
207 | + { | ||
208 | + msg?.answer?.map((item:any) => { | ||
209 | + return <div | ||
210 | + className={'omit1 current-example_title'} | ||
211 | + key={item?.id} | ||
212 | + onClick={() => send(item?.name || '')} | ||
213 | + >{item?.name}</div> | ||
214 | + }) | ||
215 | + } | ||
216 | + </div> : | ||
217 | + msg.role === 'user' ? <p className={'current-ask'}>{msg?.answer}</p> : | ||
218 | + <Markdown content={msg?.answer}/> | ||
219 | + } | ||
220 | + | ||
221 | + </div> | ||
222 | + ))} | ||
223 | + {currentResponse && ( | ||
224 | + <div className="content-left"> | ||
225 | + <Markdown content={currentResponse}/> | ||
226 | + </div> | ||
227 | + )} | ||
228 | + </div> | ||
229 | + <div className={'deep-seek_footer'}> | ||
230 | + <Input | ||
231 | + type="text" | ||
232 | + value={searchValue} | ||
233 | + className="deep-seek_footer-search" | ||
234 | + placeholder="输入..." | ||
235 | + onChange={(val: string) => setSearchValue(val)} | ||
236 | + onKeyDown={handleKeyDown} | ||
237 | + /> | ||
238 | + <Button className={`deep-seek_footer-send ${disabled ? 'disabled' : ''}`} color={'primary'} onClick={send}>发送</Button> | ||
239 | + </div> | ||
240 | + | ||
241 | + </div> | ||
129 | ); | 242 | ); |
130 | }; | 243 | }; |
131 | 244 |
src/pages/deep-seek-index/laBanner.png
deleted
100644 → 0
696 KB
src/pages/deep-seek-index/refresh.png
0 → 100644
852 Bytes
1 | .deep-seek { | 1 | .deep-seek { |
2 | - background: #f1f1f1; | ||
3 | height: 100%; | 2 | height: 100%; |
4 | width: 100%; | 3 | width: 100%; |
5 | - padding-bottom: calc( 2% + 50px); | ||
6 | - padding-top: calc( 2% + 300px); | 4 | + padding-bottom: calc(71px + constant(safe-area-inset-bottom)); |
5 | + padding-bottom: calc(71px + env(safe-area-inset-bottom)); | ||
7 | 6 | ||
8 | - &_header { | 7 | + &_bg { |
9 | position: fixed; | 8 | position: fixed; |
10 | top: 0; | 9 | top: 0; |
11 | left: 0; | 10 | left: 0; |
12 | right: 0; | 11 | right: 0; |
12 | + bottom: 0; | ||
13 | + z-index: 1; | ||
14 | + width: 100vw; | ||
15 | + height: 100vh; | ||
16 | + } | ||
17 | + | ||
18 | + &_header { | ||
19 | + padding-top: 15px; | ||
20 | + margin-bottom: 4px; | ||
13 | img { | 21 | img { |
14 | - height: 300px; | ||
15 | - width: auto; | 22 | + width: 345px; |
23 | + height: 96px; | ||
24 | + margin: 0 auto; | ||
16 | } | 25 | } |
17 | } | 26 | } |
18 | 27 | ||
19 | &_footer { | 28 | &_footer { |
20 | position: fixed; | 29 | position: fixed; |
21 | - bottom: 2%; | ||
22 | - left: 0; | ||
23 | - right: 0; | 30 | + bottom: calc(10px + constant(safe-area-inset-bottom)); |
31 | + bottom: calc(10px + env(safe-area-inset-bottom)); | ||
32 | + left: 10px; | ||
33 | + right: 10px; | ||
24 | display: flex; | 34 | display: flex; |
25 | align-items: center; | 35 | align-items: center; |
26 | justify-content: space-between; | 36 | justify-content: space-between; |
27 | - padding: 0 20%; | ||
28 | - input { | ||
29 | - width: 80%; | 37 | + z-index: 3; |
38 | + background: #FFFFFF; | ||
39 | + border-radius: 15px; | ||
40 | + padding: 11px 12px 11px 20px; | ||
41 | + &-search { | ||
42 | + width: 250px; | ||
43 | + height: 32px; | ||
44 | + line-height: 32px; | ||
45 | + border: none; | ||
46 | + padding: 0; | ||
47 | + font-size: 16px; | ||
48 | + } | ||
49 | + &-send { | ||
50 | + width: 54px; | ||
51 | + min-width: 54px; | ||
52 | + background: #F53F3F !important; | ||
53 | + border-radius: 5px; | ||
54 | + height: 32px; | ||
55 | + line-height: 32px; | ||
56 | + font-size: 14px; | ||
57 | + color: #FFFFFF; | ||
58 | + text-align: center; | ||
59 | + padding: 0; | ||
60 | + &.disabled { | ||
61 | + opacity: 0.5; | ||
62 | + } | ||
30 | } | 63 | } |
31 | } | 64 | } |
32 | 65 | ||
@@ -37,6 +70,9 @@ | @@ -37,6 +70,9 @@ | ||
37 | transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); | 70 | transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); |
38 | transition-duration: 0.3s; | 71 | transition-duration: 0.3s; |
39 | 72 | ||
73 | + position: relative; | ||
74 | + z-index: 2; | ||
75 | + | ||
40 | /* Webkit 浏览器(Chrome, Safari, Edge) */ | 76 | /* Webkit 浏览器(Chrome, Safari, Edge) */ |
41 | ::-webkit-scrollbar { | 77 | ::-webkit-scrollbar { |
42 | width: 5px; /* 或者 height: 12px; 对于水平滚动条 */ | 78 | width: 5px; /* 或者 height: 12px; 对于水平滚动条 */ |
@@ -56,3 +92,84 @@ | @@ -56,3 +92,84 @@ | ||
56 | } | 92 | } |
57 | } | 93 | } |
58 | 94 | ||
95 | +.content-center { | ||
96 | + .current-time { | ||
97 | + height: 48px; | ||
98 | + line-height: 48px; | ||
99 | + font-size: 12px; | ||
100 | + color: #999999; | ||
101 | + text-align: center; | ||
102 | + } | ||
103 | + .current-example { | ||
104 | + margin: 0 10px 4px; | ||
105 | + background: #FFFFFF; | ||
106 | + box-shadow: 0 4px 0 0 rgba(217,217,217,0.50); | ||
107 | + border-radius: 15px; | ||
108 | + overflow: hidden; | ||
109 | + &_head { | ||
110 | + height: 50px; | ||
111 | + width: 100%; | ||
112 | + background: url("./head_base.png") center center no-repeat; | ||
113 | + background-size: cover; | ||
114 | + padding-left: 109px; | ||
115 | + padding-top: 17px; | ||
116 | + display: flex; | ||
117 | + justify-content: space-between; | ||
118 | + padding-right: 15px; | ||
119 | + | ||
120 | + &-name { | ||
121 | + font-size: 16px; | ||
122 | + color: #1C1C1C; | ||
123 | + line-height: 24px; | ||
124 | + height: 24px; | ||
125 | + font-weight: 500; | ||
126 | + } | ||
127 | + .refresh { | ||
128 | + width: 20px; | ||
129 | + height: 20px; | ||
130 | + margin-top: 2px; | ||
131 | + } | ||
132 | + } | ||
133 | + &_title { | ||
134 | + width: 327px; | ||
135 | + margin: 0 12px 12px; | ||
136 | + background: #F5F9FE; | ||
137 | + border-radius: 3px; | ||
138 | + font-size: 15px; | ||
139 | + color: #00A1FF; | ||
140 | + line-height: 48px; | ||
141 | + height: 48px; | ||
142 | + text-align: center; | ||
143 | + padding: 0 10px; | ||
144 | + cursor: pointer; | ||
145 | + } | ||
146 | + } | ||
147 | +} | ||
148 | + | ||
149 | +.content-right { | ||
150 | + padding-right: 10px; | ||
151 | + display: flex; | ||
152 | + justify-content: flex-end; | ||
153 | + margin-bottom: 14px; | ||
154 | + .current-ask { | ||
155 | + display: inline-block; | ||
156 | + background: #F8E4DD; | ||
157 | + padding: 12px 16px; | ||
158 | + line-height: 22px; | ||
159 | + width: auto; | ||
160 | + max-width: 355px; | ||
161 | + border-radius: 15px; | ||
162 | + font-size: 16px; | ||
163 | + color: #1C1C1C; | ||
164 | + } | ||
165 | +} | ||
166 | +.content-left { | ||
167 | + display: flex; | ||
168 | + padding-left: 10px; | ||
169 | + .mark-down { | ||
170 | + p { | ||
171 | + overflow-wrap:break-word; | ||
172 | + word-break: break-all; | ||
173 | + } | ||
174 | + } | ||
175 | +} |
@@ -3,8 +3,8 @@ import react from '@vitejs/plugin-react' | @@ -3,8 +3,8 @@ import react from '@vitejs/plugin-react' | ||
3 | import postCssPxToViewport from 'postcss-px-to-viewport'; | 3 | import postCssPxToViewport from 'postcss-px-to-viewport'; |
4 | 4 | ||
5 | const _pxToViewPort = { | 5 | const _pxToViewPort = { |
6 | - viewportWidth: 750, // 视窗的宽度,对应的是我们设计稿的宽度,一般是750 | ||
7 | - viewportHeight: 1334, // 视窗的高度,根据750设备的宽度来指定,一般指定1334,也可以不配置 | 6 | + viewportWidth: 375, // 视窗的宽度,对应的是我们设计稿的宽度,一般是750 |
7 | + viewportHeight: 667, // 视窗的高度,根据750设备的宽度来指定,一般指定1334,也可以不配置 | ||
8 | unitPrecision: 5, // 指定`px`转换为视窗单位值的小数位数(很多时候无法整除) | 8 | unitPrecision: 5, // 指定`px`转换为视窗单位值的小数位数(很多时候无法整除) |
9 | viewportUnit: 'vw', // 指定需要转换成的视窗单位,建议使用vw | 9 | viewportUnit: 'vw', // 指定需要转换成的视窗单位,建议使用vw |
10 | selectorBlackList: [], // 指定不转换为视窗单位的类,可以自定义,可以无限添加,建议定义一至两个通用的类名 | 10 | selectorBlackList: [], // 指定不转换为视窗单位的类,可以自定义,可以无限添加,建议定义一至两个通用的类名 |