ipanel-rnapp-ajb-base 1.0.39 → 1.0.41

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,950 @@
1
+ import React, { useState, useEffect, useCallback, useRef } from "react";
2
+ import {
3
+ View,
4
+ ScrollView,
5
+ Text,
6
+ TextInput,
7
+ StyleSheet,
8
+ Alert,
9
+ Platform,
10
+ StatusBar,
11
+ TouchableOpacity,
12
+ NativeModules,
13
+ ImageBackground,
14
+ TouchableWithoutFeedback,
15
+ Dimensions,
16
+ } from "react-native";
17
+ import { useSafeArea } from "react-native-safe-area-context";
18
+ import CryptoJS from "crypto-js";
19
+ import UUIDGenerator from "react-native-uuid-generator";
20
+ import { Icon, Image, CheckBox, Button } from "@rneui/themed";
21
+ import DeviceInfo from "react-native-device-info";
22
+
23
+ import SmsCodeInput from "../../components/common/SmsCodeInput";
24
+
25
+ import storage from "../../storage";
26
+ import { replace } from "../../utils/RootNavigation";
27
+ import {
28
+ getUserLocation,
29
+ updateHomedToken,
30
+ initOperatorHomedTouristAccount,
31
+ appReport,
32
+ } from "../../utils/common";
33
+ import { obtainSmscode, smscodeLogin, accountLogin } from "../../api";
34
+ import { hideLoading, showLoading, showToast } from "../../utils/notice";
35
+
36
+ import { confirmWithContent } from "../../utils/registerDialog";
37
+ import config from "../../utils/config";
38
+ import ProtocolType from "../../components/common/LoginType/protocol";
39
+ let protocolAgreeResolve = null;
40
+
41
+ function LoginScreen({ navigation, route }) {
42
+ const insets = useSafeArea();
43
+
44
+ const [isLoading, setIsLoading] = useState(true);
45
+ const [isLogined, setIsLogined] = useState(false);
46
+ const timer = useRef(null);
47
+ const [isLogining, setIsLogining] = useState(false);
48
+
49
+ useEffect(() => {
50
+ // 获取登录状态
51
+ storage.get("accessToken").then((token) => {
52
+ // const appUserAgreement = await storage.get('appUserAgreement');
53
+ // if (!appUserAgreement) {
54
+ // setProtocolAgree(false);
55
+ // }
56
+
57
+ if (token) {
58
+ if (DeviceInfo.getBrand() === "Allwinner") {
59
+ replace("SbkScreen", {
60
+ redirect: true,
61
+ });
62
+ } else {
63
+ replace("Home", {
64
+ redirect: true,
65
+ });
66
+ }
67
+
68
+ // 上报APP启动事件
69
+ appReport("APP_STARTUP");
70
+ }
71
+ setTimeout(() => {
72
+ setIsLoading(false);
73
+ setIsLogined(!!token);
74
+ }, 0);
75
+ });
76
+ }, []);
77
+
78
+ // useEffect(() => {
79
+ // if (isLogined) {
80
+ // // console.log("检测到已登录,自动跳转首页");
81
+ // // TODO update account_data
82
+ // replace('Home', {
83
+ // redirect: true,
84
+ // });
85
+ // }
86
+ // }, [isLogined]);
87
+
88
+ const [phone, setPhone] = useState("");
89
+ const [smsId, setSmsId] = useState("");
90
+ const [userInputSmsCode, setUserInputSmsCode] = useState("");
91
+ const [smsCodeRightBtnDisabled, setSmsCodeRightBtnDisabled] = useState(false);
92
+ const [smsCodeRightBtnText, setSmsCodeRightBtnText] = useState("获取验证码");
93
+ const [smsCodeResendTime, setSmsCodeResendTime] = useState(0);
94
+
95
+ useEffect(() => {
96
+ if (phone && smsCodeResendTime === 0) {
97
+ setSmsCodeRightBtnDisabled(false);
98
+ setSmsCodeRightBtnText("获取验证码");
99
+ } else {
100
+ setSmsCodeRightBtnDisabled(true);
101
+ }
102
+ }, [phone, smsCodeResendTime]);
103
+ useEffect(() => {
104
+ if (smsCodeResendTime > 0) {
105
+ setSmsCodeRightBtnText(`${smsCodeResendTime}s后重发`);
106
+ timer.current = setTimeout(() => {
107
+ setSmsCodeResendTime(smsCodeResendTime - 1);
108
+ }, 1000);
109
+ }
110
+
111
+ return () => {
112
+ clearTimeout(timer.current);
113
+ };
114
+ }, [smsCodeResendTime]);
115
+
116
+ // 0 手机号+短信验证码登录
117
+ // 1 账号密码登录
118
+ const [loginWay, setLoginWay] = useState(0);
119
+
120
+ const [username, setUsername] = useState("");
121
+ const [password, setPassword] = useState("");
122
+
123
+ const [protocolAgree, setProtocolAgree] = useState(false);
124
+ const [protocolDialogVisible, setProtocolDialogVisible] = useState(false);
125
+
126
+ const [serviceAgree, setServiceAgree] = useState(false);
127
+ const [serviceDialogVisible, setServiceDialogVisible] = useState(false);
128
+ const [privacyAgree, setPrivacyAgree] = useState(false);
129
+ const [privacyDialogVisible, setPrivacyDialogVisible] = useState(false);
130
+
131
+ useEffect(() => {
132
+ if (!route.params?.skip) {
133
+ openProtocolDialog();
134
+ }
135
+ }, []);
136
+
137
+ useEffect(() => {
138
+ if (serviceAgree && privacyAgree) {
139
+ setProtocolAgree(true);
140
+ } else {
141
+ setProtocolAgree(false);
142
+ }
143
+ }, [serviceAgree, privacyAgree]);
144
+
145
+ const loginDisabled = !(
146
+ (loginWay === 0 && phone && userInputSmsCode) ||
147
+ (loginWay === 1 && username && password)
148
+ );
149
+
150
+ let smsCodeTimer;
151
+
152
+ function validPhone(phone) {
153
+ if (!phone) {
154
+ Alert.alert("请输入手机号");
155
+ return false;
156
+ }
157
+ if (!/^[1][3,4,5,7,8,9][0-9]{9}$/.test(phone)) {
158
+ Alert.alert("请输入正确的手机号");
159
+ return false;
160
+ }
161
+ return true;
162
+ }
163
+
164
+ const handleGetSmsId = async () => {
165
+ if (!validPhone(phone)) {
166
+ return;
167
+ }
168
+ // 60s后重发
169
+ setSmsCodeResendTime(60);
170
+
171
+ setSmsCodeRightBtnDisabled(true);
172
+
173
+ const res = await obtainSmscode({
174
+ phone_number: phone,
175
+ length: 4,
176
+ type: 1, // type=1 表示登录用途
177
+ }).catch((err) => {
178
+ console.log(err);
179
+ setSmsCodeRightBtnText("获取验证码");
180
+ setSmsCodeRightBtnDisabled(false);
181
+ });
182
+
183
+ if (res && res.code === 0) {
184
+ setSmsId(res.result.sms_id);
185
+
186
+ smsCodeTimer = setTimeout(() => {
187
+ setSmsCodeRightBtnText("获取验证码");
188
+ setSmsCodeRightBtnDisabled(false);
189
+ }, 120000);
190
+ } else {
191
+ setSmsCodeRightBtnText("获取验证码");
192
+ setSmsCodeRightBtnDisabled(false);
193
+ }
194
+ };
195
+
196
+ const handleUserAgree = () => {
197
+ // setProtocolDialogVisible(false);
198
+ // handleLogin();
199
+ // storage.set('appUserAgreement', true);
200
+
201
+ // getUserLocation().then(geoRes => {
202
+ // global.base.storage.set('location', geoRes);
203
+ // });
204
+ setProtocolAgree(true);
205
+ typeof protocolAgreeResolve === "function" && protocolAgreeResolve();
206
+ protocolAgreeResolve = null;
207
+ };
208
+
209
+ const handleUserDisagree = async () => {
210
+ // await storage.set('appUserAgreement', false);
211
+ // NativeModules?.RNToNativeEmitter?.exitApp();
212
+ setProtocolDialogVisible(false);
213
+ setProtocolAgree(false);
214
+ setServiceAgree(false);
215
+ setPrivacyAgree(false);
216
+ };
217
+
218
+ const handleLoginPress = () => {
219
+ if (loginDisabled) {
220
+ return;
221
+ }
222
+ if (protocolAgree) {
223
+ handleLogin();
224
+ } else {
225
+ // setProtocolDialogVisible(true);
226
+ openProtocolDialog().then(() => {
227
+ handleLogin();
228
+ });
229
+ }
230
+ };
231
+
232
+ const openProtocolDialog = () => {
233
+ return new Promise((resolve) => {
234
+ // setProtocolDialogVisible(true);
235
+ protocolAgreeResolve = resolve;
236
+ }).then(() => {
237
+ setProtocolDialogVisible(false);
238
+ });
239
+ };
240
+
241
+ const handleLogin = async () => {
242
+ let res;
243
+
244
+ const { deviceModal, appName } = NativeModules?.RNToNativeEmitter || {};
245
+
246
+ const appID = await global.base.getAppId();
247
+
248
+ console.log("appID", appID);
249
+
250
+ let finallyAppID = appID;
251
+ if (!appID) {
252
+ // 兼容本地开发测试
253
+ finallyAppID = await UUIDGenerator.getRandomUUID();
254
+ }
255
+
256
+ if (loginWay === 0) {
257
+ if (!validPhone(phone)) {
258
+ return;
259
+ }
260
+
261
+ if (!smsId) {
262
+ Alert.alert("请先获取验证码");
263
+ return;
264
+ }
265
+
266
+ if (!userInputSmsCode) {
267
+ Alert.alert("请输入短信验证码");
268
+ return;
269
+ }
270
+ showLoading("登录中...");
271
+ setIsLogining(true);
272
+ res = await smscodeLogin({
273
+ phone_number: phone,
274
+ sms_id: smsId,
275
+ sms_code: userInputSmsCode,
276
+ create_address: 1, // 注册时自动建默认家庭
277
+ extend: {
278
+ appid: finallyAppID,
279
+ model: deviceModal || "开发测试",
280
+ application: appName || "爱家宝",
281
+ },
282
+ });
283
+ } else {
284
+ if (!username) {
285
+ Alert.alert("请输入账号");
286
+ return;
287
+ }
288
+
289
+ if (!password) {
290
+ Alert.alert("请输入密码");
291
+ return;
292
+ }
293
+ console.log(global.loading, "global.loading");
294
+ showLoading("登录中...");
295
+ setIsLogining(true);
296
+ res = await accountLogin({
297
+ account_name: username,
298
+ password: CryptoJS.MD5(password).toString(),
299
+ create_address: 1, // 注册时自动建默认家庭
300
+ extend: {
301
+ appid: finallyAppID,
302
+ model: deviceModal || "开发测试",
303
+ application: appName || "爱家宝",
304
+ },
305
+ });
306
+ }
307
+ if (res.code === 0) {
308
+ console.log(res.result, "ipanelClound用户信息");
309
+ await storage.set("accessToken", res.result.access_token);
310
+ await storage.set("refreshToken", res.result.refresh_token);
311
+
312
+ if (res.result.address && res.result.address[0]) {
313
+ const defaultAddr = res.result.address[0];
314
+ await storage.set("activeAddr", defaultAddr);
315
+ await storage.set("addressList", res.result.address || []);
316
+ await updateHomedToken();
317
+ } else {
318
+ await storage.set("activeAddr", {});
319
+ await storage.set("addressList", []);
320
+ }
321
+
322
+ delete res.result.address;
323
+ await storage.set("accountData", res.result);
324
+
325
+ // 放开这段重新登录就会置空运营商(进入标准版)
326
+ // await storage.set(
327
+ // `${res.result?.account?.account_id || ''}currentOperator`,
328
+ // {},
329
+ // );
330
+
331
+ /**
332
+ * ☆☆☆使用homed token的完整方案:☆☆☆
333
+ - 对于 homed 数据只读的业务场景,使用游客令牌(由 http://access.homed.me/account/get_accesstoken 接口产生)。该方式的优点是不依赖ipanelcloud用户登录(当前APP实现上是ipanelcloud登录后才能看到内容,因此这个可以不着急实现),不产生垃圾用户数据
334
+ - 涉及到产生个人数据但 又不想走绑定正式homed用户流程 的业务场景,使用ipanelcloud登录后返回的 account_id 注册的游客用户token(即:await storage.get("homedTouristAccessToken") )
335
+ - 涉及到产生个人数据且 数据需要关联到正式homed用户 的业务场景,走绑定正式homed用户的流程(即:await storage.get("homedAccessToken") )
336
+ */
337
+ // 初始化默认运营商对应的homed游客账号
338
+ console.log("account_id", res.result.account_id);
339
+ const envVersion =
340
+ NativeModules?.RNToNativeEmitter?.serverCluster || "dev";
341
+ await initOperatorHomedTouristAccount({
342
+ touristUsername: res.result.account_id, // 使用ipanelcloud account_id 作为homed游客账号的用户名
343
+ domain: envVersion === "dev" ? "homed.me" : "homed.tv",
344
+ touristGroupId: envVersion === "dev" ? 115017 : 4664, // 4664: tv集群的手机APP游客用户组. 115017: 运营集群手机APP游客用户组
345
+ });
346
+ clearTimeout(smsCodeTimer);
347
+ // setIsLogined(true);
348
+ // 判断是否已经选了运营商
349
+ const currentOperator = await storage.get(
350
+ `${res.result?.account?.account_id || ""}currentOperator`
351
+ );
352
+
353
+ // 上报APP启动事件
354
+ appReport("APP_STARTUP");
355
+
356
+ hideLoading();
357
+ setIsLogining(false);
358
+ const appName =
359
+ NativeModules?.RNToNativeEmitter?.appName || config.LOCALTEST_APP_NAME;
360
+
361
+ if (DeviceInfo.getBrand() === "Allwinner") {
362
+ // 声必可屏幕
363
+ replace("SbkScreen", {
364
+ redirect: false,
365
+ });
366
+ } else if (currentOperator || appName.includes("安电工")) {
367
+ replace("Home", {
368
+ redirect: false,
369
+ });
370
+ } else {
371
+ confirmWithContent({
372
+ title: "选择运营商",
373
+ component: "你是否要选择运营商",
374
+ confirmButtonText: "确定",
375
+ confirmCallback: () => {
376
+ replace("OperatorSelectScreen", {
377
+ purpose: "init",
378
+ });
379
+ },
380
+ cancelButtonText: "先不选",
381
+ cancelCallback: () => {
382
+ replace("Home", {
383
+ redirect: false,
384
+ });
385
+ },
386
+ });
387
+ }
388
+ } else {
389
+ hideLoading();
390
+ setIsLogining(false);
391
+ global.toast.showToast(res.message + "(code: " + res.code + ")");
392
+ }
393
+ };
394
+
395
+ const statusBarPlaceholderStyle = {
396
+ height: (Platform.OS === "ios" ? insets.top : 0) + StatusBar.currentHeight,
397
+ };
398
+
399
+ const handleSwitchLoginWay = () => {
400
+ if (loginWay === 0) {
401
+ setLoginWay(1);
402
+ } else {
403
+ setLoginWay(0);
404
+ }
405
+ };
406
+
407
+ const handleViewUserAgreement = () => {
408
+ navigation.navigate("WebviewScreen", {
409
+ title: "用户协议",
410
+ url: "https://ipanelcloud2.ipanel.cn:50443/iapp/ajbstatic/service_agreement/user_agreement.html",
411
+ });
412
+ };
413
+ const handleViewPrivacyClause = () => {
414
+ navigation.navigate("WebviewScreen", {
415
+ title: "隐私条款",
416
+ url: "https://ipanelcloud2.ipanel.cn:50443/iapp/ajbstatic/service_agreement/privacy_policy.html",
417
+ });
418
+ };
419
+ const handleViewUserAgreementByType = (type) => {
420
+ if (type === "service") {
421
+ setServiceDialogVisible(true);
422
+ } else if (type === "privacy") {
423
+ setPrivacyDialogVisible(true);
424
+ }
425
+ };
426
+
427
+ const handleSetProtocolAgree = (isAgree) => {
428
+ setProtocolAgree(isAgree);
429
+ setServiceAgree(isAgree);
430
+ setPrivacyAgree(isAgree);
431
+ };
432
+
433
+ const handleOneDisagree = async (type) => {
434
+ setProtocolAgree(false);
435
+ if (type === "service") {
436
+ setServiceAgree(false);
437
+ setServiceDialogVisible(false);
438
+ } else if (type === "privacy") {
439
+ setPrivacyAgree(false);
440
+ setPrivacyDialogVisible(false);
441
+ }
442
+ };
443
+ const handleOneAgree = (type) => {
444
+ if (type === "service") {
445
+ setServiceAgree(true);
446
+ setServiceDialogVisible(false);
447
+ } else if (type === "privacy") {
448
+ setPrivacyAgree(true);
449
+ setPrivacyDialogVisible(false);
450
+ }
451
+
452
+ typeof protocolAgreeResolve === "function" && protocolAgreeResolve();
453
+ protocolAgreeResolve = null;
454
+ };
455
+
456
+ loginDisabled;
457
+ const loginBtnBg = {
458
+ backgroundColor: loginDisabled
459
+ ? "rgba(234, 96, 0, 0.3)"
460
+ : "rgba(234, 96, 0, 1)",
461
+ };
462
+
463
+ return (
464
+ <ImageBackground
465
+ source={require("../../assets/img/login_bg.png")}
466
+ style={[
467
+ styles.container,
468
+ { paddingTop: Platform.OS === "ios" ? insets.top : 0 },
469
+ ]}
470
+ >
471
+ {isLoading || isLogined ? (
472
+ <View style={styles.welcomeView}>{/* 白屏界面 */}</View>
473
+ ) : (
474
+ <View style={styles.loginView}>
475
+ <View style={statusBarPlaceholderStyle} />
476
+
477
+ <View style={styles.changeLoginWay}>
478
+ <TouchableOpacity
479
+ activeOpacity={0.7}
480
+ onPress={handleSwitchLoginWay}
481
+ >
482
+ <View style={styles.changeLoginWayInner}>
483
+ <Image
484
+ source={require("../../assets/img/qiehuan.png")}
485
+ style={styles.exchangeIcon}
486
+ />
487
+
488
+ <Text style={styles.changeLoginWayText}>
489
+ {loginWay === 0 ? "密码登录" : "验证码登录"}
490
+ </Text>
491
+ </View>
492
+ </TouchableOpacity>
493
+ </View>
494
+
495
+ <View style={styles.content}>
496
+ <View style={styles.titleBox}>
497
+ <Text style={styles.title}>
498
+ {loginWay === 0 ? "验证码登录" : "密码登录"}
499
+ </Text>
500
+
501
+ <Text style={styles.subTitle}>
502
+ {loginWay === 0
503
+ ? "未注册过的手机号验证通过后将自动注册"
504
+ : "请使用账号和密码登录"}
505
+ </Text>
506
+ </View>
507
+
508
+ {loginWay === 0 && (
509
+ <>
510
+ <View style={styles.inputBox}>
511
+ <TextInput
512
+ style={styles.input}
513
+ value={phone}
514
+ placeholder="手机号"
515
+ onChangeText={(text) => setPhone(text)}
516
+ />
517
+ </View>
518
+ <View style={styles.inputBox}>
519
+ <SmsCodeInput
520
+ value={userInputSmsCode}
521
+ placeholder="验证码"
522
+ rightBtnDisabled={smsCodeRightBtnDisabled}
523
+ rightBtnText={smsCodeRightBtnText}
524
+ onChangeText={(text) => setUserInputSmsCode(text)}
525
+ onRightBtnPress={handleGetSmsId}
526
+ />
527
+ </View>
528
+ </>
529
+ )}
530
+
531
+ {loginWay === 1 && (
532
+ <>
533
+ <View style={styles.inputBox}>
534
+ <TextInput
535
+ style={styles.input}
536
+ value={username}
537
+ placeholder="账号"
538
+ onChangeText={(text) => setUsername(text)}
539
+ />
540
+ </View>
541
+ <View style={styles.inputBox}>
542
+ <TextInput
543
+ style={styles.input}
544
+ value={password}
545
+ secureTextEntry
546
+ placeholder="密码"
547
+ onChangeText={(text) => setPassword(text)}
548
+ />
549
+ </View>
550
+ </>
551
+ )}
552
+
553
+ <View style={styles.protocol}>
554
+ <CheckBox
555
+ center
556
+ checked={protocolAgree}
557
+ containerStyle={{
558
+ margin: 0,
559
+ padding: 0,
560
+ backgroundColor: "transparent",
561
+ }}
562
+ onPress={() => handleSetProtocolAgree(!protocolAgree)}
563
+ checkedIcon={
564
+ <Icon
565
+ name="checkmark-circle-outline"
566
+ type="ionicon"
567
+ color={styles.protocolLinkAgree.color}
568
+ size={20}
569
+ />
570
+ }
571
+ uncheckedIcon={
572
+ <Icon
573
+ name="radio-button-off"
574
+ type="ionicon"
575
+ color={styles.protocolText.color}
576
+ size={20}
577
+ />
578
+ }
579
+ />
580
+ <TouchableWithoutFeedback
581
+ onPress={() => setProtocolAgree(!protocolAgree)}
582
+ >
583
+ <Text style={styles.protocolText}>
584
+ 已阅读并同意
585
+ <TouchableWithoutFeedback
586
+ style={{ paddingVertical: 100 }}
587
+ onPress={() => handleViewUserAgreementByType("service")}
588
+ >
589
+ <Text
590
+ style={
591
+ protocolAgree || serviceAgree
592
+ ? styles.protocolLinkAgree
593
+ : styles.protocolLink
594
+ }
595
+ >
596
+ 用户协议
597
+ </Text>
598
+ </TouchableWithoutFeedback>
599
+ 和
600
+ <TouchableWithoutFeedback
601
+ style={{ paddingVertical: 100 }}
602
+ onPress={() => handleViewUserAgreementByType("privacy")}
603
+ >
604
+ <Text
605
+ style={
606
+ protocolAgree || privacyAgree
607
+ ? styles.protocolLinkAgree
608
+ : styles.protocolLink
609
+ }
610
+ >
611
+ 隐私条款
612
+ </Text>
613
+ </TouchableWithoutFeedback>
614
+ </Text>
615
+ </TouchableWithoutFeedback>
616
+ </View>
617
+
618
+ <TouchableOpacity
619
+ activeOpacity={0.7}
620
+ onPress={handleLoginPress}
621
+ disabled={loginDisabled}
622
+ >
623
+ <View style={styles.loginBtnBox}>
624
+ <View style={[styles.loginBtn, loginBtnBg]}>
625
+ <Text style={styles.loginBtnText}>
626
+ {isLogining ? "正在登录中..." : "登录"}
627
+ </Text>
628
+ </View>
629
+ </View>
630
+ </TouchableOpacity>
631
+ </View>
632
+ </View>
633
+ )}
634
+
635
+ {serviceDialogVisible && !isLoading && (
636
+ <ProtocolType
637
+ handleOneDisagree={handleOneDisagree}
638
+ handleOneAgree={handleOneAgree}
639
+ url="https://ipanelcloud2.ipanel.cn:50443/iapp/ajbstatic/service_agreement/user_agreement.html"
640
+ type="service"
641
+ />
642
+ )}
643
+ {privacyDialogVisible && !isLoading && (
644
+ <ProtocolType
645
+ handleOneDisagree={handleOneDisagree}
646
+ handleOneAgree={handleOneAgree}
647
+ url="https://ipanelcloud2.ipanel.cn:50443/iapp/ajbstatic/service_agreement/privacy_policy.html"
648
+ type="privacy"
649
+ />
650
+ )}
651
+
652
+ {protocolDialogVisible && !isLoading && (
653
+ <View style={styles.agreementMask}>
654
+ <View style={styles.agreementConfirmContent}>
655
+ <View style={styles.agreementConfirmHead}>
656
+ <TouchableOpacity
657
+ style={styles.headerLeft}
658
+ onPress={() => {
659
+ console.log(111);
660
+ setProtocolDialogVisible(false);
661
+ }}
662
+ >
663
+ <Image
664
+ source={require("../../assets/img/goBack.png")}
665
+ style={styles.goBackImg}
666
+ resizeMode="contain"
667
+ />
668
+ </TouchableOpacity>
669
+ <View style={styles.agreementConfirmTitleBox}>
670
+ <Text style={styles.agreementConfirmTitle}>欢迎使用爱家宝</Text>
671
+ </View>
672
+ </View>
673
+ <ScrollView>
674
+ <View>
675
+ <Text style={styles.agreementConfirmText}>
676
+ 为了更好的保障您的合法权益,请您阅读并同意
677
+ <TouchableWithoutFeedback onPress={handleViewUserAgreement}>
678
+ <Text style={styles.agreementConfirmImportantText}>
679
+ 用户协议
680
+ </Text>
681
+ </TouchableWithoutFeedback>
682
+ 和
683
+ <TouchableWithoutFeedback onPress={handleViewPrivacyClause}>
684
+ <Text style={styles.agreementConfirmImportantText}>
685
+ 隐私条款
686
+ </Text>
687
+ </TouchableWithoutFeedback>
688
+ 。为向您提供更优质的服务,我们可能会向您申请下列相关权限:
689
+ </Text>
690
+ </View>
691
+ <View>
692
+ <Text style={styles.agreementConfirmText}>
693
+ 1. 读写设备存储权限(Android
694
+ 版本):用于用于用户反馈、客服等功能中读写设备上的照片及文件;
695
+ </Text>
696
+ </View>
697
+ <View>
698
+ <Text style={styles.agreementConfirmText}>
699
+ 2. 地理位置权限(Android、iOS
700
+ 版本):用于家庭位置管理、判断地区提供天气服务、发现附近智能设备;
701
+ </Text>
702
+ </View>
703
+ <View>
704
+ <Text style={styles.agreementConfirmText}>
705
+ 3. 相机权限(Android、iOS
706
+ 版本):用于扫码绑定电视账户、扫码进行设备添加等功能;
707
+ </Text>
708
+ </View>
709
+ <View>
710
+ <Text style={styles.agreementConfirmText}>
711
+ 4. 相册权限(Android、ios
712
+ 版本):用于用户反馈等功能中读写设备上的照片及视频;
713
+ </Text>
714
+ </View>
715
+ <View>
716
+ <Text style={styles.agreementConfirmText}>
717
+ 5. 麦克风权限(Android、ioS 版本):智能客服等功能;
718
+ </Text>
719
+ </View>
720
+ <View>
721
+ <Text style={styles.agreementConfirmText}>
722
+ 6. 读取电话联系人权限(Android):用于电视通讯功能;
723
+ </Text>
724
+ </View>
725
+ <View>
726
+ <Text style={styles.agreementConfirmText}>
727
+ 7. 开启蓝牙权限(Android、ios
728
+ 版本):用于连接设备时连接设备发出的蓝牙信号,以进行设备通信,对于通过蓝牙连接的智能设备,也需要蓝牙权限用于通信;
729
+ </Text>
730
+ </View>
731
+ <View>
732
+ <Text style={styles.agreementConfirmText}>
733
+ 8. 开启蓝牙权限(Android、ios
734
+ 版本):用于连接设备时连接设备发出的蓝牙信号,以进行设备通信,对于通过蓝牙连接的智能设备,也需要蓝牙权限用于通信;
735
+ </Text>
736
+ </View>
737
+ <View>
738
+ <Text style={styles.agreementConfirmText}>
739
+ 7. 开启蓝牙权限(Android、ios
740
+ 版本):用于连接设备时连接设备发出的蓝牙信号,以进行设备通信,对于通过蓝牙连接的智能设备,也需要蓝牙权限用于通信;
741
+ </Text>
742
+ </View>
743
+ </ScrollView>
744
+
745
+ <View style={styles.agreementButtons}>
746
+ <TouchableOpacity
747
+ style={styles.disagreeBtn}
748
+ activeOpacity={0.7}
749
+ onPress={handleUserDisagree}
750
+ >
751
+ <Text style={styles.disagreeBtnText}>不同意</Text>
752
+ </TouchableOpacity>
753
+ <TouchableOpacity
754
+ style={styles.agreeBtn}
755
+ activeOpacity={0.7}
756
+ onPress={handleUserAgree}
757
+ >
758
+ <Text style={styles.agreeBtnText}>同意</Text>
759
+ </TouchableOpacity>
760
+ </View>
761
+ </View>
762
+ </View>
763
+ )}
764
+ </ImageBackground>
765
+ );
766
+ }
767
+
768
+ const styles = StyleSheet.create({
769
+ container: {
770
+ flex: 1,
771
+ backgroundColor: "#fff",
772
+ },
773
+ welcomeView: {
774
+ flex: 1,
775
+ alignItems: "center",
776
+ justifyContent: "center",
777
+ },
778
+ content: {
779
+ paddingHorizontal: 30,
780
+ },
781
+ titleBox: {
782
+ justifyContent: "center",
783
+ },
784
+ title: {
785
+ fontSize: 24,
786
+ color: "rgba(48, 48, 48, 1)",
787
+ },
788
+ subTitle: {
789
+ fontSize: 14,
790
+ marginTop: 10,
791
+ },
792
+ inputBox: {
793
+ borderBottomWidth: 1,
794
+ marginVertical: 10,
795
+ borderBottomColor: "rgba(217, 217, 217, 1)",
796
+ },
797
+ input: {
798
+ height: 50,
799
+ color: "#333",
800
+ },
801
+ welcomText: {
802
+ fontSize: 30,
803
+ },
804
+ loginView: {
805
+ flex: 1,
806
+ },
807
+ changeLoginWay: {
808
+ // height: 70,
809
+ justifyContent: "center",
810
+ alignItems: "flex-end",
811
+ marginRight: 20,
812
+ },
813
+ changeLoginWayInner: {
814
+ flexDirection: "row",
815
+ alignItems: "center",
816
+ },
817
+ changeLoginWayText: {
818
+ color: "rgba(51, 51, 51, 1)",
819
+ fontSize: 16,
820
+ },
821
+ exchangeIcon: {
822
+ width: 16,
823
+ height: 16,
824
+ marginRight: 3,
825
+ },
826
+ protocol: {
827
+ marginVertical: 15,
828
+ flexDirection: "row",
829
+ alignItems: "center",
830
+ },
831
+ protocolText: {
832
+ color: "rgba(102, 102, 102, 1)",
833
+ },
834
+ protocolLink: {
835
+ color: "rgba(234, 96, 0, 1)",
836
+ },
837
+ protocolLinkAgree: {
838
+ color: "#0EC12C",
839
+ },
840
+ agreementMask: {
841
+ position: "absolute",
842
+ left: 0,
843
+ top: 0,
844
+ bottom: 0,
845
+ right: 0,
846
+ zIndex: 2,
847
+ },
848
+ agreementConfirmContent: {
849
+ position: "absolute",
850
+ width: Dimensions.get("window").width - 60,
851
+ height: 400,
852
+ left: 30,
853
+ top: Dimensions.get("window").height / 2 - 200,
854
+ backgroundColor: "#fff",
855
+ paddingBottom: 0,
856
+ borderWidth: 1,
857
+ borderColor: "#a1a1a1",
858
+ borderRadius: 20,
859
+ },
860
+ agreementConfirmHead: {
861
+ position: "relative",
862
+ flexDirection: "row",
863
+ alignItems: "center",
864
+ paddingTop: 10,
865
+ paddingLeft: 10,
866
+ marginBottom: 5,
867
+ height: 40,
868
+ },
869
+ headerLeft: {
870
+ position: "absolute",
871
+ top: 15,
872
+ left: 10,
873
+ zIndex: 2,
874
+ },
875
+ goBackImg: {
876
+ width: 20,
877
+ height: 20,
878
+ },
879
+ agreementConfirmTitleBox: {
880
+ // flex: 1,
881
+ position: "absolute",
882
+ top: 10,
883
+ bottom: 0,
884
+ left: 0,
885
+ right: 0,
886
+ zIndex: 1,
887
+ },
888
+ agreementConfirmTitle: {
889
+ fontSize: 20,
890
+ // lineHeight: 50,
891
+ color: "#000",
892
+ textAlign: "center",
893
+ // paddingTop: 20,
894
+ },
895
+ agreementConfirmText: {
896
+ fontSize: 16,
897
+ lineHeight: 30,
898
+ paddingHorizontal: 20,
899
+ color: "#000",
900
+ },
901
+ agreementConfirmImportantText: {
902
+ color: "rgba(234, 96, 0, 1)",
903
+ },
904
+ agreementButtons: {
905
+ height: 50,
906
+ flexDirection: "row",
907
+ justifyContent: "space-around",
908
+ borderTopColor: "#c1c1c1",
909
+ borderTopWidth: 0.5,
910
+ },
911
+ disagreeBtn: {
912
+ flex: 1,
913
+ alignItems: "center",
914
+ justifyContent: "center",
915
+ borderBottomLeftRadius: 20,
916
+ },
917
+ disagreeBtnText: {
918
+ color: "#ccc",
919
+ },
920
+ agreeBtn: {
921
+ flex: 1,
922
+ alignItems: "center",
923
+ justifyContent: "center",
924
+ borderLeftColor: "#c1c1c1",
925
+ borderLeftWidth: 0.5,
926
+ borderBottomRightRadius: 20,
927
+ },
928
+ agreeBtnText: {
929
+ color: "#333",
930
+ fontSize: 16,
931
+ },
932
+ loginBtnBox: {
933
+ flexDirection: "row",
934
+ alignItems: "center",
935
+ },
936
+ loginBtn: {
937
+ flex: 1,
938
+ height: 48,
939
+ marginHorizontal: 10,
940
+ borderRadius: 24,
941
+ alignItems: "center",
942
+ justifyContent: "center",
943
+ },
944
+ loginBtnText: {
945
+ color: "#fff",
946
+ fontSize: 18,
947
+ },
948
+ });
949
+
950
+ export default LoginScreen;