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.
@@ -32,7 +32,7 @@ import {
32
32
  accountLogin,
33
33
  getHouseType,
34
34
  loginByType,
35
- } from '../../api';
35
+ } from "../../api";
36
36
  import px from "../../utils/scaleSize";
37
37
  import storage from "../../storage";
38
38
  import { replace, goBack } from "../../utils/RootNavigation";
@@ -181,7 +181,7 @@ const Index = ({ route }) => {
181
181
  });
182
182
  };
183
183
 
184
- const dealLoginInfo = async (ress, finallyAppID, callback) => {
184
+ const dealLoginInfo = async (ress, ipanelCloudAccountId, callback) => {
185
185
  await storage.set("accountType", activeType);
186
186
  await storage.set("accessToken", ress.result.access_token);
187
187
  await storage.set("refreshToken", ress.result.refresh_token);
@@ -236,7 +236,7 @@ const Index = ({ route }) => {
236
236
  ? 115017
237
237
  : 4664;
238
238
  await initOperatorHomedTouristAccount({
239
- touristUsername: finallyAppID,
239
+ touristUsername: ipanelCloudAccountId,
240
240
  domain: domain,
241
241
  touristGroupId: touristGroupId, // 4664: tv集群的手机APP游客用户组. 115017: 运营集群手机APP游客用户组
242
242
  });
@@ -246,44 +246,46 @@ const Index = ({ route }) => {
246
246
  `${ress.result?.account?.account_id || ""}currentOperator`
247
247
  );
248
248
  // 获取公寓token
249
- getHouseType().then(async apartmentRes => {
250
- if (apartmentRes.code === 0) {
251
- let list = apartmentRes.data || [];
252
- if (list.length) {
253
- // 拥有角色列表
254
- const minUserType = list.reduce(
255
- (min, current) =>
256
- current.userType < min.userType ? current : min,
257
- list[0],
258
- );
259
- if (minUserType?.userType) {
260
- const loginRes = await loginByType(minUserType?.userType, {});
261
- console.log(loginRes, 'loginRes');
262
- if (loginRes.code === 0 && loginRes.data) {
263
- await storage.set('apartmentData', {
264
- ...loginRes.data,
265
- userType: minUserType?.userType,
266
- userTypeName: minUserType?.userTypeName,
267
- });
268
- await storage.set('apartmentToken', loginRes.data.accessToken);
269
- } else {
270
- await storage.set('apartmentData', {});
271
- await storage.set('apartmentToken', '');
249
+ getHouseType()
250
+ .then(async (apartmentRes) => {
251
+ if (apartmentRes.code === 0) {
252
+ let list = apartmentRes.data || [];
253
+ if (list.length) {
254
+ // 拥有角色列表
255
+ const minUserType = list.reduce(
256
+ (min, current) =>
257
+ current.userType < min.userType ? current : min,
258
+ list[0]
259
+ );
260
+ if (minUserType?.userType) {
261
+ const loginRes = await loginByType(minUserType?.userType, {});
262
+ console.log(loginRes, "loginRes");
263
+ if (loginRes.code === 0 && loginRes.data) {
264
+ await storage.set("apartmentData", {
265
+ ...loginRes.data,
266
+ userType: minUserType?.userType,
267
+ userTypeName: minUserType?.userTypeName,
268
+ });
269
+ await storage.set("apartmentToken", loginRes.data.accessToken);
270
+ } else {
271
+ await storage.set("apartmentData", {});
272
+ await storage.set("apartmentToken", "");
273
+ }
272
274
  }
275
+ } else {
276
+ await storage.set("apartmentData", {});
277
+ await storage.set("apartmentToken", "");
273
278
  }
274
279
  } else {
275
- await storage.set('apartmentData', {});
276
- await storage.set('apartmentToken', '');
280
+ await storage.set("apartmentData", {});
281
+ await storage.set("apartmentToken", "");
277
282
  }
278
- } else {
279
- await storage.set('apartmentData', {});
280
- await storage.set('apartmentToken', '');
281
- }
282
- }).catch(async e => {
283
- console.log(e, 'getHouseType');
284
- await storage.set('apartmentData', {});
285
- await storage.set('apartmentToken', '');
286
- })
283
+ })
284
+ .catch(async (e) => {
285
+ console.log(e, "getHouseType");
286
+ await storage.set("apartmentData", {});
287
+ await storage.set("apartmentToken", "");
288
+ });
287
289
  callback();
288
290
  };
289
291
 
@@ -354,7 +356,7 @@ const Index = ({ route }) => {
354
356
  };
355
357
  const ress = await accountLogin(params, activeType);
356
358
  if (ress.code === 0) {
357
- dealLoginInfo(ress, finallyAppID, async () => {
359
+ dealLoginInfo(ress, ress.result.account_id, async () => {
358
360
  console.log("12333appName:" + appName);
359
361
  appReport("APP_STARTUP");
360
362
  if (["禺乐慧家", "悦慧家"].includes(appName)) {
@@ -441,7 +443,7 @@ const Index = ({ route }) => {
441
443
  const ress = await accountLogin(params, activeType);
442
444
  console.log(ress, "login");
443
445
  if (ress.code === 0) {
444
- dealLoginInfo(ress, finallyAppID, () => {
446
+ dealLoginInfo(ress, ress.result.account_id, () => {
445
447
  setStep(1);
446
448
  });
447
449
  } else {
@@ -1,29 +1,172 @@
1
- import React, {useState, useEffect} from 'react';
2
- import {View, Text, StyleSheet, TouchableHighlight} from 'react-native';
1
+ import React, { useState, useEffect, useRef } from "react";
2
+ import {
3
+ View,
4
+ Text,
5
+ StyleSheet,
6
+ TouchableHighlight,
7
+ TouchableOpacity,
8
+ BackHandler,
9
+ Platform,
10
+ StatusBar,
11
+ } from "react-native";
12
+ import { useSafeAreaInsets } from "react-native-safe-area-context";
3
13
 
4
- import {WebView} from 'react-native-webview';
5
- import ScreenBackHeader from '../components/common/ScreenBackHeader';
14
+ import { WebView } from "react-native-webview";
15
+ import ScreenBackHeader from "../components/common/ScreenBackHeader";
16
+
17
+ const Index = ({ navigation, route }) => {
18
+ // WebView状态管理
19
+ const [canGoBack, setCanGoBack] = useState(false);
20
+ const webViewRef = useRef(null);
21
+ const insets = useSafeAreaInsets();
22
+
23
+ // Android回退键处理
24
+ useEffect(() => {
25
+ const onBackPress = () => {
26
+ if (canGoBack && webViewRef.current) {
27
+ webViewRef.current.goBack();
28
+ return true; // 阻止默认回退行为
29
+ }
30
+ return false; // 允许默认回退行为(退出WebView页面)
31
+ };
32
+
33
+ if (Platform.OS === "android") {
34
+ const backHandler = BackHandler.addEventListener(
35
+ "hardwareBackPress",
36
+ onBackPress
37
+ );
38
+ return () => backHandler.remove();
39
+ }
40
+ }, [canGoBack]);
41
+
42
+ // 主流方案:禁用手势避免冲突
43
+ useEffect(() => {
44
+ navigation.setOptions({
45
+ gestureEnabled: !canGoBack, // WebView可回退时禁用系统手势
46
+ });
47
+ }, [navigation, canGoBack]);
48
+
49
+ // 统一的智能回退处理逻辑
50
+ const handleSmartBack = () => {
51
+ if (canGoBack && webViewRef.current) {
52
+ webViewRef.current.goBack(); // WebView内回退
53
+ } else {
54
+ navigation.goBack(); // 退出WebView页面
55
+ }
56
+ };
57
+
58
+ // WebView导航状态变化处理
59
+ const handleNavigationStateChange = (navState) => {
60
+ setCanGoBack(navState.canGoBack);
61
+
62
+ // 支持外部传入的onNavigationStateChange回调
63
+ if (!navState.loading && route?.params?.onNavigationStateChange) {
64
+ route?.params?.onNavigationStateChange(navState);
65
+ }
66
+ };
67
+
68
+ // iOS需要onMessage处理器才能执行injectedJavaScript
69
+ const handleMessage = (event) => {
70
+ // 支持外部传入的onMessage回调
71
+ if (route?.params?.webviewParams?.onMessage) {
72
+ route.params.webviewParams.onMessage(event);
73
+ }
74
+ // 默认情况下什么都不做,但这个处理器必须存在,否则在IOS上injectedJavaScript不会执行
75
+ };
76
+
77
+ // 生成注入的JavaScript代码
78
+ const getInjectedJavaScript = () => {
79
+ const statusBarHeight =
80
+ Platform.OS === "ios" ? insets.top : StatusBar.currentHeight || 0;
81
+ const userJS = route.params.webviewParams?.injectedJavaScript || "";
82
+
83
+ // 如果设置了覆盖标志,直接返回用户JS
84
+ if (route.params.overrideStatusBarJS) {
85
+ return userJS || undefined;
86
+ }
87
+
88
+ // 构建状态栏处理JS
89
+ const statusBarJS = route.params.fullScreen
90
+ ? `document.body.style.paddingTop = '${statusBarHeight}px';`
91
+ : "";
92
+
93
+ // 如果都有,合并执行
94
+ if (statusBarJS && userJS) {
95
+ return `
96
+ (function() {
97
+ ${statusBarJS}
98
+ ${userJS}
99
+ true; // 必须返回true
100
+ })();
101
+ `;
102
+ }
103
+
104
+ // 只有状态栏JS
105
+ if (statusBarJS) {
106
+ return `
107
+ (function() {
108
+ ${statusBarJS}
109
+ true; // 必须返回true
110
+ })();
111
+ `;
112
+ }
113
+
114
+ // 只有用户JS或都没有
115
+ return userJS || undefined;
116
+ };
6
117
 
7
- const Index = ({navigation, route}) => {
8
118
  return (
9
119
  <View style={styles.container}>
10
- <ScreenBackHeader title={route.params.title} />
120
+ {route.params.fullScreen ? null : (
121
+ <ScreenBackHeader
122
+ title={route.params.title}
123
+ onBackPress={handleSmartBack}
124
+ />
125
+ )}
11
126
 
12
127
  <View style={styles.webviewContainer}>
13
128
  <WebView
129
+ ref={webViewRef}
14
130
  bounces={false}
15
131
  domStorageEnabled
16
132
  javaScriptEnabled
17
133
  useWebKit
18
- // onNavigationStateChange={val => {
19
- // if (!val.loading && route?.params?.onNavigationStateChange) {
20
- // route?.params?.onNavigationStateChange(val);
21
- // }
22
- // }}
134
+ onNavigationStateChange={handleNavigationStateChange}
23
135
  source={{
24
136
  uri: route.params.url,
25
137
  }}
138
+ {...(() => {
139
+ const webviewParams = route.params.webviewParams || {};
140
+ const { injectedJavaScript, onMessage, ...otherParams } =
141
+ webviewParams;
142
+ return {
143
+ ...otherParams,
144
+ injectedJavaScript: getInjectedJavaScript(),
145
+ onMessage: handleMessage,
146
+ };
147
+ })()}
26
148
  />
149
+
150
+ {/* 悬浮返回按钮 - 仅在全屏模式且WebView可回退时显示 */}
151
+ {route.params.fullScreen && canGoBack && (
152
+ <TouchableOpacity
153
+ style={[
154
+ styles.floatingBackButton,
155
+ {
156
+ top:
157
+ Platform.OS === "ios"
158
+ ? insets.top + 10
159
+ : StatusBar.currentHeight + 10,
160
+ },
161
+ ]}
162
+ onPress={handleSmartBack}
163
+ activeOpacity={0.8}
164
+ >
165
+ <View style={styles.backButtonInner}>
166
+ <Text style={styles.backButtonText}>‹</Text>
167
+ </View>
168
+ </TouchableOpacity>
169
+ )}
27
170
  </View>
28
171
  </View>
29
172
  );
@@ -35,6 +178,68 @@ const styles = StyleSheet.create({
35
178
  },
36
179
  webviewContainer: {
37
180
  flex: 1,
181
+ position: "relative",
182
+ },
183
+ floatingBackButton: {
184
+ position: "absolute",
185
+ left: 15,
186
+ width: 44,
187
+ height: 44,
188
+ zIndex: 9999,
189
+ },
190
+ backButtonOuterWrapper: {
191
+ width: 46, // 稍微大一点,确保阴影完整显示
192
+ height: 46,
193
+ borderRadius: 23,
194
+ backgroundColor: "transparent",
195
+ justifyContent: "center",
196
+ alignItems: "center",
197
+ elevation: 8, // 增加elevation让阴影更明显
198
+ // Android特有:强制圆形遮罩
199
+ overflow: "hidden",
200
+ },
201
+ backButtonInner: {
202
+ width: 44,
203
+ height: 44,
204
+ backgroundColor: "rgba(0, 0, 0, 0.6)",
205
+ justifyContent: "center",
206
+ alignItems: "center",
207
+ // 跨平台阴影统一处理
208
+ ...Platform.select({
209
+ ios: {
210
+ borderRadius: 22,
211
+ shadowColor: "#000",
212
+ shadowOffset: {
213
+ width: 0,
214
+ height: 2,
215
+ },
216
+ shadowOpacity: 0.25,
217
+ shadowRadius: 3.84,
218
+ },
219
+ android: {
220
+ borderRadius: 22,
221
+ elevation: 0,
222
+ // Android圆形强制方案
223
+ transform: [{ scaleX: 1 }, { scaleY: 1 }],
224
+ },
225
+ }),
226
+ },
227
+ backButtonText: {
228
+ fontSize: Platform.select({
229
+ ios: 28, // iOS上使用稍大的字号
230
+ android: 24, // Android保持原有字号
231
+ }),
232
+ color: "#fff",
233
+ fontWeight: Platform.select({
234
+ ios: "600", // iOS使用稍轻的字重
235
+ android: "bold", // Android保持bold
236
+ }),
237
+ marginTop: Platform.select({
238
+ ios: -3, // iOS的视觉居中调整
239
+ android: -2, // Android的视觉居中调整
240
+ }),
241
+ textAlign: "center",
242
+ includeFontPadding: false, // Android特有,移除字体padding
38
243
  },
39
244
  });
40
245
 
@@ -263,6 +263,7 @@ const MSG_TYPES = {
263
263
  VIDEO: "video",
264
264
  EVENT: "event",
265
265
  TEMPLATE: "template",
266
+ CHAT: "chat",
266
267
  };
267
268
 
268
269
  const MSG_EVENT_TYPES = {
@@ -452,6 +453,12 @@ const checkToken = async () => {
452
453
  });
453
454
  };
454
455
 
456
+ const CONNECT_STATUS = {
457
+ CONNECTING: -1,
458
+ CONNECTED: 0,
459
+ DISCONNECTED: 1,
460
+ };
461
+
455
462
  export {
456
463
  updateHomedToken,
457
464
  initOperatorHomedTouristAccount,
@@ -465,4 +472,5 @@ export {
465
472
  appReport,
466
473
  checkToken,
467
474
  updateApartmentToken,
475
+ CONNECT_STATUS,
468
476
  };
package/app/utils/http.js CHANGED
@@ -68,7 +68,7 @@ async function http(options) {
68
68
  if (TOKEN) {
69
69
  data.access_token = TOKEN;
70
70
  }
71
- Object.keys(data).forEach(key => {
71
+ Object.keys(data).forEach((key) => {
72
72
  query.push(`${key}=${data[key]}`);
73
73
  });
74
74
  if (query.length > 0) {
@@ -93,38 +93,44 @@ async function http(options) {
93
93
  console.log("req:", url, config, "reqid=", reqid);
94
94
 
95
95
  return fetch(url, config)
96
- .then(response => {
97
- // console.log(response, "url");
98
- return response.json();
99
- })
100
- .then(json => {
101
- if (
102
- typeof json.error_code !== "undefined" &&
103
- typeof json.code === "undefined"
104
- ) {
105
- json.code = json.error_code;
106
- }
96
+ .then(async (response) => {
97
+ const jsonText = await response.text();
98
+ try {
99
+ const json = JSON.parse(jsonText);
100
+
101
+ if (
102
+ typeof json.error_code !== "undefined" &&
103
+ typeof json.code === "undefined"
104
+ ) {
105
+ json.code = json.error_code;
106
+ }
107
107
 
108
- if (typeof json.code !== "undefined") {
109
- if (json.code !== 0 && !selfHandleErrCodes.includes(json.code)) {
110
- // global.toast.showToast(
111
- // errCodes[json.code] ||
112
- // `${json.message || '请求失败'}(code:${json.code})`,
113
- // );
108
+ if (typeof json.code !== "undefined") {
109
+ if (json.code !== 0 && !selfHandleErrCodes.includes(json.code)) {
110
+ // global.toast.showToast(
111
+ // errCodes[json.code] ||
112
+ // `${json.message || '请求失败'}(code:${json.code})`,
113
+ // );
114
+ }
114
115
  }
116
+ console.log("res:", url, config, "reqid=", reqid, "json=", json);
117
+
118
+ return json;
119
+ } catch (e) {
120
+ console.log("jsonText", jsonText);
121
+ console.log("status:", response.status);
122
+ console.log("headers:", response.headers);
123
+ throw new Error(e);
115
124
  }
116
- console.log("res:", url, config, "reqid=", reqid, "json=", json);
117
-
118
- return json;
119
125
  })
120
- .catch(err => {
126
+ .catch((err) => {
121
127
  console.log("req error:", url, config, "reqid=", reqid, "error=", err);
122
128
  throw err;
123
129
  // Alert.alert('服务繁忙,请稍候重试');
124
130
  });
125
131
  }
126
132
 
127
- export const homedHttp = async options => {
133
+ export const homedHttp = async (options) => {
128
134
  let url = options.url;
129
135
  const method = options.method.toLowerCase();
130
136
 
@@ -174,7 +180,7 @@ export const homedHttp = async options => {
174
180
  if (TOKEN) {
175
181
  data.accesstoken = TOKEN;
176
182
  }
177
- Object.keys(data).forEach(key => {
183
+ Object.keys(data).forEach((key) => {
178
184
  query.push(`${key}=${data[key]}`);
179
185
  });
180
186
  if (query.length > 0) {
@@ -185,13 +191,13 @@ export const homedHttp = async options => {
185
191
  console.log(url, config);
186
192
 
187
193
  return fetch(url, config)
188
- .then(response => {
194
+ .then((response) => {
189
195
  return response.json();
190
196
  })
191
- .then(json => {
197
+ .then((json) => {
192
198
  return json;
193
199
  })
194
- .catch(err => {
200
+ .catch((err) => {
195
201
  console.log(err);
196
202
  // Alert.alert('服务繁忙,请稍候重试');
197
203
  return Promise.reject(err);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "ipanel-rnapp-ajb-base",
3
- "version": "1.0.39",
4
- "ipanelVersion": "1.0.521",
3
+ "version": "1.0.41",
4
+ "ipanelVersion": "1.0.533",
5
5
  "description": "",
6
6
  "main": "index.js",
7
7
  "keywords": [