Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1895830907 | ||
|
|
bbc4dce0b6 |
@@ -0,0 +1,99 @@
|
|||||||
|
# B-225 双端验收包无法联网
|
||||||
|
|
||||||
|
分支:`agent/agent/a4ad7eed`(基于问题基线 `18d890ae7fdf66fa4df67360469f0f143641666a`)
|
||||||
|
施工依据:B-148 第13阶段返工;对照旧包 `v1.0.6-internal-test`、故障预发布 `v3.8.3-internal-acceptance`、本卡新源码与新产物。
|
||||||
|
本卡只修客户端/构建配置并重打候选包,不改现网服务、不覆盖 Gitea 预发布 tag、不把构建成功当成真机联网通过。
|
||||||
|
|
||||||
|
**结论:Windows 根因是 Vite 未注入 `VITE_*`,登录打到 `undefined`;Android 根因是默认 host 为官方占位域名,且回退端口 10008/10009 已关闭。候选包产物级已写入公司内网地址。真机登录未测。**
|
||||||
|
|
||||||
|
## 根因(产物对照,不是猜)
|
||||||
|
|
||||||
|
公司内网现况(构建机只读探测 `192.168.200.11`):10001 / 10002 / 10010 / 17880 开;官方 chat 默认口 10008 / 10009 关。账号服务 `POST /api/login` 有业务响应。
|
||||||
|
|
||||||
|
| 对照项 | 旧可用包 `v1.0.6-internal-test` | 故障预发布 `v3.8.3-internal-acceptance` | 本卡源码 + 候选包 |
|
||||||
|
|---|---|---|---|
|
||||||
|
| Windows 登录 | asar 字面量 `http://192.168.200.11:10010/api/login` | asar 为 `` `${{}.VITE_ACCOUNT_URL}/api/login` ``(Vite 空对象) | asar 字面量 `http://192.168.200.11:10010` 等四条地址 |
|
||||||
|
| Windows IM / LiveKit | `:10002` / `:10001` / `:17880` 字面量 | 同样未注入 | 同上,四条均字面量 |
|
||||||
|
| Android `libapp.so` | 仅公司地址 | 公司地址 + `your-server-ip or your-domain` + `:10008` | 公司四条地址;`your-server-ip` / `:10008` / `:10009` 为 0 |
|
||||||
|
|
||||||
|
Windows 直接原因:仓库根 `.gitignore` 忽略 `.env`,B-213 打包时没有 `.env` / `.env.production`,`vite build` 把 `import.meta.env.VITE_*` 编成空对象属性。
|
||||||
|
|
||||||
|
Android 直接原因:`Config._host` 不是 IP,启动默认走 HTTPS 假域名;`HttpUtil.init()` 在 `CompanyBootstrap` 之前拍死 `dio.baseUrl`;`ApiService.setBaseUrl` 曾只写 host 不带 `http://` 和端口;`Urls` 的 `static final` 第一次读取会冻结错误 URL;官方 chat 口已关,公司账号口是 10010。
|
||||||
|
|
||||||
|
## 最小修复
|
||||||
|
|
||||||
|
| 端 | 改动 | 作用 |
|
||||||
|
|---|---|---|
|
||||||
|
| PC | 新增 `pc-client/.env.production`(可入库) | `vite build` 默认 production 能注入内网地址 |
|
||||||
|
| PC | 新增 `pc-client/src/config/endpoints.ts`,登录/目录/RTC/IM 改走兜底常量 | 即使漏加载 env,也不会变成 `undefined` |
|
||||||
|
| Android | `Config._host = 192.168.200.11`;auth/chatToken 回退 10008/10009 → 10010 | 默认不再走假域名和已关闭端口 |
|
||||||
|
| Android | `HttpUtil.setBaseUrl`;bootstrap 写入完整 `AppEndpoints.apiAddr` | 启动后 Dio / ApiService 指向 `http://192.168.200.11:10002` |
|
||||||
|
| Android | `Urls` 改为 getter | DataSp 写入后 URL 会跟着更新 |
|
||||||
|
|
||||||
|
未改:`account-service/`、docker、端口、现网数据、`mobile/` 旧工程。
|
||||||
|
|
||||||
|
## 提交与回退
|
||||||
|
|
||||||
|
从新到旧回退:先本验收记录,再联网修复。
|
||||||
|
|
||||||
|
| 主题 | SHA | 文件 |
|
||||||
|
|---|---|---|
|
||||||
|
| 本验收记录 | 本文件当次提交 | `docs/acceptance/b225-network-fix.md` |
|
||||||
|
| 联网修复 | `bbc4dce0b61b44447f84732d841b8a66e3a2f4be` | `pc-client/.env.production`、`pc-client/src/config/endpoints.ts`、PC 调用点、Android Config/Urls/HttpUtil/bootstrap |
|
||||||
|
|
||||||
|
回退示例(新到旧):
|
||||||
|
|
||||||
|
```
|
||||||
|
git revert <本验收提交>
|
||||||
|
git revert bbc4dce0b61b44447f84732d841b8a66e3a2f4be
|
||||||
|
```
|
||||||
|
|
||||||
|
用户侧继续用旧包 `v1.0.6-internal-test`。不要回退到故障预发布 `v3.8.3-internal-acceptance`。
|
||||||
|
|
||||||
|
代码侧也可把分支重置回 `18d890ae7fdf66fa4df67360469f0f143641666a`。回退不影响现网服务与已发布旧包。
|
||||||
|
|
||||||
|
## 环境
|
||||||
|
|
||||||
|
- Flutter 3.24.5 / Dart 3.5.4(`C:\devtools\flutter_3.24.5`)
|
||||||
|
- Temurin JDK 17.0.20
|
||||||
|
- Android SDK:platform-tools、platforms;android-34、build-tools;34.0.0
|
||||||
|
- Node v24.5.0;`pc-client` `npm install --ignore-scripts` 后 `npm run build` + `npx electron-builder --win --x64`
|
||||||
|
- `GRADLE_OPTS=-Xmx4096M`
|
||||||
|
|
||||||
|
## 候选包(未发布,未覆盖 `v3.8.3-internal-acceptance`)
|
||||||
|
|
||||||
|
构建基线 HEAD:`18d890ae7fdf66fa4df67360469f0f143641666a` + 本卡两提交。
|
||||||
|
|
||||||
|
| 产物 | 版本 | 大小 | SHA256 | 路径 |
|
||||||
|
|---|---|---|---|---|
|
||||||
|
| Android release APK | 3.8.3 | 53,288,459 B | `3709E9B24F2F8B12B9BD931D6633DC101C186367B5C3E704DD91D67DCB791B86` | `mobile-next/build/app/outputs/flutter-apk/app-release.apk` |
|
||||||
|
| Windows NSIS EXE | 1.0.2 | 105,893,401 B | `F16B421857C341016E4375A869C53FF80B1028E49F84A59FE43C93D50FCC866C` | `pc-client/release/Base/1.0.2/畅联_1.0.2.exe` |
|
||||||
|
|
||||||
|
故障预发布对照(不要当候选):
|
||||||
|
|
||||||
|
| 产物 | SHA256 |
|
||||||
|
|---|---|
|
||||||
|
| APK `v3.8.3-internal-acceptance` | `41261A1BEBD00597D16B50A0D01A261AF592129C5F28014B423A1AAE07AE7C73` |
|
||||||
|
| EXE `v3.8.3-internal-acceptance` | `25491BA9A19E181144602F81991993DBF3350A3981BD1CC82354949A83B0E645` |
|
||||||
|
|
||||||
|
产物抽检:
|
||||||
|
|
||||||
|
- 新 EXE `app.asar`:`http://192.168.200.11:10010` / `:10002` / `ws://...:10001` / `:17880` 各 1 次;`VITE_ACCOUNT_URL`、`{}.VITE_`、`undefined/api/login` 为 0。
|
||||||
|
- 新 APK `lib/arm64-v8a/libapp.so`:上述四条公司地址各 1 次;`your-server-ip`、`:10008`、`:10009` 为 0。
|
||||||
|
|
||||||
|
APK 内嵌时间戳,哈希不可位级复现。构建期告警同前:Flutter Gradle apply-script 弃用;部分依赖 Kotlin metadata 1.8.0 vs 工程预期 1.6.0。均属上游,release 通过。
|
||||||
|
|
||||||
|
## 已测 / 未测
|
||||||
|
|
||||||
|
已测:
|
||||||
|
|
||||||
|
- 构建机到 `192.168.200.11` 的 10001/10002/10010/17880 端口开,10008/10009 关
|
||||||
|
- 账号服务对错误工号返回业务 JSON(服务本身在)
|
||||||
|
- `npm run build`、`electron-builder --win --x64`、`flutter build apk --release` 成功
|
||||||
|
- 新旧产物字符串对照如上
|
||||||
|
|
||||||
|
未测(不得写成已通过):
|
||||||
|
|
||||||
|
- 公司内网真机 / 真 PC 用工号登录
|
||||||
|
- 登录后会话列表、发消息、音视频
|
||||||
|
- 本候选包安装覆盖旧包后的升级路径
|
||||||
@@ -10,6 +10,7 @@ class CompanyBootstrap {
|
|||||||
static Future<void> install() async {
|
static Future<void> install() async {
|
||||||
applyOfficialStylesFromTokens();
|
applyOfficialStylesFromTokens();
|
||||||
await DataSp.putServerConfig(AppEndpoints.toServerConfig());
|
await DataSp.putServerConfig(AppEndpoints.toServerConfig());
|
||||||
ApiService().setBaseUrl(AppEndpoints.host);
|
HttpUtil.setBaseUrl(AppEndpoints.apiAddr);
|
||||||
|
ApiService().setBaseUrl(AppEndpoints.apiAddr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ class Config {
|
|||||||
await Hive.initFlutter(path);
|
await Hive.initFlutter(path);
|
||||||
MediaKit.ensureInitialized();
|
MediaKit.ensureInitialized();
|
||||||
HttpUtil.init();
|
HttpUtil.init();
|
||||||
ApiService().setBaseUrl(serverIp);
|
ApiService().setBaseUrl(imApiUrl);
|
||||||
} catch (_) {}
|
} catch (_) {}
|
||||||
|
|
||||||
runApp();
|
runApp();
|
||||||
@@ -65,9 +65,10 @@ class Config {
|
|||||||
static const friendScheme = "io.openim.app/addFriend/";
|
static const friendScheme = "io.openim.app/addFriend/";
|
||||||
static const groupScheme = "io.openim.app/joinGroup/";
|
static const groupScheme = "io.openim.app/joinGroup/";
|
||||||
|
|
||||||
static const _host = "your-server-ip or your-domain";
|
static const _host = "192.168.200.11";
|
||||||
|
|
||||||
static const _ipRegex = '((2[0-4]\\d|25[0-5]|[01]?\\d\\d?)\\.){3}(2[0-4]\\d|25[0-5]|[01]?\\d\\d?)';
|
static const _ipRegex =
|
||||||
|
'((2[0-4]\\d|25[0-5]|[01]?\\d\\d?)\\.){3}(2[0-4]\\d|25[0-5]|[01]?\\d\\d?)';
|
||||||
|
|
||||||
static bool get _isIP => RegExp(_ipRegex).hasMatch(_host);
|
static bool get _isIP => RegExp(_ipRegex).hasMatch(_host);
|
||||||
|
|
||||||
@@ -86,7 +87,7 @@ class Config {
|
|||||||
if (null != server) {
|
if (null != server) {
|
||||||
url = server['chatTokenUrl'];
|
url = server['chatTokenUrl'];
|
||||||
}
|
}
|
||||||
return url ?? (_isIP ? "http://$_host:10009" : "https://$_host/chat");
|
return url ?? (_isIP ? "http://$_host:10010" : "https://$_host/chat");
|
||||||
}
|
}
|
||||||
|
|
||||||
static String get appAuthUrl {
|
static String get appAuthUrl {
|
||||||
@@ -95,7 +96,7 @@ class Config {
|
|||||||
if (null != server) {
|
if (null != server) {
|
||||||
url = server['authUrl'];
|
url = server['authUrl'];
|
||||||
}
|
}
|
||||||
return url ?? (_isIP ? "http://$_host:10008" : "https://$_host/chat");
|
return url ?? (_isIP ? "http://$_host:10010" : "https://$_host/chat");
|
||||||
}
|
}
|
||||||
|
|
||||||
static String get imApiUrl {
|
static String get imApiUrl {
|
||||||
|
|||||||
@@ -1,22 +1,27 @@
|
|||||||
import 'config.dart';
|
import 'config.dart';
|
||||||
|
|
||||||
class Urls {
|
class Urls {
|
||||||
static final onlineStatus = "${Config.imApiUrl}/manager/get_users_online_status";
|
static String get onlineStatus =>
|
||||||
static final queryAllUsers = "${Config.imApiUrl}/manager/get_all_users_uid";
|
"${Config.imApiUrl}/manager/get_users_online_status";
|
||||||
static final updateUserInfo = "${Config.appAuthUrl}/user/update";
|
static String get queryAllUsers =>
|
||||||
static final searchFriendInfo = "${Config.appAuthUrl}/friend/search";
|
"${Config.imApiUrl}/manager/get_all_users_uid";
|
||||||
static final getUsersFullInfo = "${Config.appAuthUrl}/user/find/full";
|
static String get updateUserInfo => "${Config.appAuthUrl}/user/update";
|
||||||
static final searchUserFullInfo = "${Config.appAuthUrl}/user/search/full";
|
static String get searchFriendInfo => "${Config.appAuthUrl}/friend/search";
|
||||||
|
static String get getUsersFullInfo => "${Config.appAuthUrl}/user/find/full";
|
||||||
|
static String get searchUserFullInfo =>
|
||||||
|
"${Config.appAuthUrl}/user/search/full";
|
||||||
|
|
||||||
static final getVerificationCode = "${Config.appAuthUrl}/account/code/send";
|
static String get getVerificationCode =>
|
||||||
static final checkVerificationCode = "${Config.appAuthUrl}/account/code/verify";
|
"${Config.appAuthUrl}/account/code/send";
|
||||||
static final register = "${Config.appAuthUrl}/account/register";
|
static String get checkVerificationCode =>
|
||||||
|
"${Config.appAuthUrl}/account/code/verify";
|
||||||
|
static String get register => "${Config.appAuthUrl}/account/register";
|
||||||
|
|
||||||
static final resetPwd = "${Config.appAuthUrl}/account/password/reset";
|
static String get resetPwd => "${Config.appAuthUrl}/account/password/reset";
|
||||||
static final changePwd = "${Config.appAuthUrl}/account/password/change";
|
static String get changePwd => "${Config.appAuthUrl}/account/password/change";
|
||||||
static final login = "${Config.appAuthUrl}/account/login";
|
static String get login => "${Config.appAuthUrl}/account/login";
|
||||||
|
|
||||||
static final upgrade = "${Config.appAuthUrl}/app/check";
|
static String get upgrade => "${Config.appAuthUrl}/app/check";
|
||||||
static final getClientConfig = '${Config.appAuthUrl}/client_config/get';
|
static String get getClientConfig => '${Config.appAuthUrl}/client_config/get';
|
||||||
static final getTokenForRTC = "${Config.appAuthUrl}/user/rtc/get_token";
|
static String get getTokenForRTC => "${Config.appAuthUrl}/user/rtc/get_token";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,7 +39,12 @@ class HttpUtil {
|
|||||||
dio.options.receiveTimeout = const Duration(seconds: 30);
|
dio.options.receiveTimeout = const Duration(seconds: 30);
|
||||||
}
|
}
|
||||||
|
|
||||||
static String get operationID => DateTime.now().millisecondsSinceEpoch.toString();
|
static void setBaseUrl(String url) {
|
||||||
|
dio.options.baseUrl = url;
|
||||||
|
}
|
||||||
|
|
||||||
|
static String get operationID =>
|
||||||
|
DateTime.now().millisecondsSinceEpoch.toString();
|
||||||
|
|
||||||
static Future post(
|
static Future post(
|
||||||
String path, {
|
String path, {
|
||||||
@@ -103,8 +108,11 @@ class HttpUtil {
|
|||||||
final bytes = await File(compressPath ?? path).readAsBytes();
|
final bytes = await File(compressPath ?? path).readAsBytes();
|
||||||
final mf = MultipartFile.fromBytes(bytes, filename: fileName);
|
final mf = MultipartFile.fromBytes(bytes, filename: fileName);
|
||||||
|
|
||||||
var formData =
|
var formData = FormData.fromMap({
|
||||||
FormData.fromMap({'operationID': '${DateTime.now().millisecondsSinceEpoch}', 'fileType': 1, 'file': mf});
|
'operationID': '${DateTime.now().millisecondsSinceEpoch}',
|
||||||
|
'fileType': 1,
|
||||||
|
'file': mf
|
||||||
|
});
|
||||||
|
|
||||||
var resp = await dio.post<Map<String, dynamic>>(
|
var resp = await dio.post<Map<String, dynamic>>(
|
||||||
"${Config.imApiUrl}/third/minio_upload",
|
"${Config.imApiUrl}/third/minio_upload",
|
||||||
@@ -151,12 +159,14 @@ class HttpUtil {
|
|||||||
onCompletion?.call();
|
onCompletion?.call();
|
||||||
intervalDo.drop(
|
intervalDo.drop(
|
||||||
fun: () async {
|
fun: () async {
|
||||||
saveFileToGallerySaver(File(cachePath), showTaost: EasyLoading.isShow);
|
saveFileToGallerySaver(File(cachePath),
|
||||||
|
showTaost: EasyLoading.isShow);
|
||||||
},
|
},
|
||||||
milliseconds: 1500);
|
milliseconds: 1500);
|
||||||
}
|
}
|
||||||
if (count == total) {
|
if (count == total) {
|
||||||
saveFileToGallerySaver(File(cachePath), showTaost: EasyLoading.isShow);
|
saveFileToGallerySaver(File(cachePath),
|
||||||
|
showTaost: EasyLoading.isShow);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@@ -166,7 +176,8 @@ class HttpUtil {
|
|||||||
var byteData = await image.toByteData(format: ImageByteFormat.png);
|
var byteData = await image.toByteData(format: ImageByteFormat.png);
|
||||||
if (byteData != null) {
|
if (byteData != null) {
|
||||||
Uint8List uint8list = byteData.buffer.asUint8List();
|
Uint8List uint8list = byteData.buffer.asUint8List();
|
||||||
var result = await ImageGallerySaverPlus.saveImage(Uint8List.fromList(uint8list));
|
var result =
|
||||||
|
await ImageGallerySaverPlus.saveImage(Uint8List.fromList(uint8list));
|
||||||
if (result != null) {
|
if (result != null) {
|
||||||
var tips = StrRes.saveSuccessfully;
|
var tips = StrRes.saveSuccessfully;
|
||||||
if (Platform.isAndroid) {
|
if (Platform.isAndroid) {
|
||||||
@@ -214,13 +225,15 @@ class HttpUtil {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future saveFileToGallerySaver(File file, {String? name, bool showTaost = true}) async {
|
static Future saveFileToGallerySaver(File file,
|
||||||
|
{String? name, bool showTaost = true}) async {
|
||||||
Permissions.storage(() async {
|
Permissions.storage(() async {
|
||||||
var tips = StrRes.saveSuccessfully;
|
var tips = StrRes.saveSuccessfully;
|
||||||
Logger.print('saveFileToGallerySaver: ${file.path}');
|
Logger.print('saveFileToGallerySaver: ${file.path}');
|
||||||
final imageBytes = await file.readAsBytes();
|
final imageBytes = await file.readAsBytes();
|
||||||
|
|
||||||
final result = await ImageGallerySaverPlus.saveImage(imageBytes, name: name);
|
final result =
|
||||||
|
await ImageGallerySaverPlus.saveImage(imageBytes, name: name);
|
||||||
if (result != null && showTaost) {
|
if (result != null && showTaost) {
|
||||||
if (Platform.isAndroid) {
|
if (Platform.isAndroid) {
|
||||||
final filePath = result['filePath'].split('//').last;
|
final filePath = result['filePath'].split('//').last;
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
# 生产/验收包写入的公司内网地址。vite build 默认 mode=production 会加载本文件。
|
||||||
|
# 不要依赖本机未入库的 .env:缺文件时 VITE_* 会变成 undefined,登录会变成网络失败。
|
||||||
|
VITE_WS_URL=ws://192.168.200.11:10001
|
||||||
|
VITE_API_URL=http://192.168.200.11:10002
|
||||||
|
VITE_ACCOUNT_URL=http://192.168.200.11:10010
|
||||||
|
VITE_LIVEKIT_URL=ws://192.168.200.11:17880
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
|
|
||||||
|
import { ACCOUNT_URL, LIVEKIT_URL } from "@/config/endpoints";
|
||||||
import { getIMToken } from "@/utils/storage";
|
import { getIMToken } from "@/utils/storage";
|
||||||
|
|
||||||
// RTC(音视频通话)令牌改由自研账号服务签发(原 OpenIM chat 服务 :10008 已下线)。
|
// RTC(音视频通话)令牌改由自研账号服务签发(原 OpenIM chat 服务 :10008 已下线)。
|
||||||
@@ -15,7 +16,7 @@ export const getRtcConnectData = async (room: string, identity: string) => {
|
|||||||
msg: string;
|
msg: string;
|
||||||
data: { token: string };
|
data: { token: string };
|
||||||
}>(
|
}>(
|
||||||
`${import.meta.env.VITE_ACCOUNT_URL}/api/rtc_token`,
|
`${ACCOUNT_URL}/api/rtc_token`,
|
||||||
{ room, identity },
|
{ room, identity },
|
||||||
{ headers: { Authorization: `Bearer ${imToken}` } },
|
{ headers: { Authorization: `Bearer ${imToken}` } },
|
||||||
);
|
);
|
||||||
@@ -24,7 +25,7 @@ export const getRtcConnectData = async (room: string, identity: string) => {
|
|||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
data: {
|
data: {
|
||||||
serverUrl: import.meta.env.VITE_LIVEKIT_URL as string,
|
serverUrl: LIVEKIT_URL,
|
||||||
token: res.data.token,
|
token: res.data.token,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
/** 公司内网接口。Vite 未注入 VITE_* 时不得变成 undefined。 */
|
||||||
|
const COMPANY_HOST = "192.168.200.11";
|
||||||
|
|
||||||
|
export const API_URL =
|
||||||
|
import.meta.env.VITE_API_URL || `http://${COMPANY_HOST}:10002`;
|
||||||
|
export const WS_URL =
|
||||||
|
import.meta.env.VITE_WS_URL || `ws://${COMPANY_HOST}:10001`;
|
||||||
|
export const ACCOUNT_URL =
|
||||||
|
import.meta.env.VITE_ACCOUNT_URL || `http://${COMPANY_HOST}:10010`;
|
||||||
|
export const LIVEKIT_URL =
|
||||||
|
import.meta.env.VITE_LIVEKIT_URL || `ws://${COMPANY_HOST}:17880`;
|
||||||
@@ -19,6 +19,7 @@ import { useEffect, useRef } from "react";
|
|||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
|
|
||||||
import { CustomType } from "@/constants";
|
import { CustomType } from "@/constants";
|
||||||
|
import { API_URL, WS_URL } from "@/config/endpoints";
|
||||||
import {
|
import {
|
||||||
pushNewMessage,
|
pushNewMessage,
|
||||||
updateOneMessage,
|
updateOneMessage,
|
||||||
@@ -123,8 +124,8 @@ export function useGlobalEvent() {
|
|||||||
const IMToken = (await getIMToken()) as string;
|
const IMToken = (await getIMToken()) as string;
|
||||||
const IMUserID = (await getIMUserID()) as string;
|
const IMUserID = (await getIMUserID()) as string;
|
||||||
try {
|
try {
|
||||||
const apiAddr = import.meta.env.VITE_API_URL;
|
const apiAddr = API_URL;
|
||||||
const wsAddr = import.meta.env.VITE_WS_URL;
|
const wsAddr = WS_URL;
|
||||||
if (window.electronAPI) {
|
if (window.electronAPI) {
|
||||||
await IMSDK.initSDK({
|
await IMSDK.initSDK({
|
||||||
platformID: window.electronAPI?.getPlatform() ?? 5,
|
platformID: window.electronAPI?.getPlatform() ?? 5,
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { useCallback, useEffect, useMemo, useState } from "react";
|
|||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { GroupedVirtuoso } from "react-virtuoso";
|
import { GroupedVirtuoso } from "react-virtuoso";
|
||||||
|
|
||||||
|
import { ACCOUNT_URL } from "@/config/endpoints";
|
||||||
import { useContactStore } from "@/store";
|
import { useContactStore } from "@/store";
|
||||||
import { emit } from "@/utils/events";
|
import { emit } from "@/utils/events";
|
||||||
import { getIMToken } from "@/utils/storage";
|
import { getIMToken } from "@/utils/storage";
|
||||||
@@ -29,7 +30,7 @@ export const MyFriends = () => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const { data } = await axios.get(
|
const { data } = await axios.get(
|
||||||
`${import.meta.env.VITE_ACCOUNT_URL}/api/directory`,
|
`${ACCOUNT_URL}/api/directory`,
|
||||||
{
|
{
|
||||||
params: { keyword: "", limit: 100 },
|
params: { keyword: "", limit: 100 },
|
||||||
headers: { Authorization: `Bearer ${token}` },
|
headers: { Authorization: `Bearer ${token}` },
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { t } from "i18next";
|
|||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
|
|
||||||
|
import { ACCOUNT_URL } from "@/config/endpoints";
|
||||||
import { setIMProfile } from "@/utils/storage";
|
import { setIMProfile } from "@/utils/storage";
|
||||||
|
|
||||||
interface LoginResult {
|
interface LoginResult {
|
||||||
@@ -29,7 +30,7 @@ const LoginForm = ({ onBanner }: LoginFormProps) => {
|
|||||||
setLoading(true);
|
setLoading(true);
|
||||||
try {
|
try {
|
||||||
const { data: res } = await axios.post<LoginResult>(
|
const { data: res } = await axios.post<LoginResult>(
|
||||||
`${import.meta.env.VITE_ACCOUNT_URL}/api/login`,
|
`${ACCOUNT_URL}/api/login`,
|
||||||
{
|
{
|
||||||
staffNo: values.staffNo.trim(),
|
staffNo: values.staffNo.trim(),
|
||||||
password: values.password,
|
password: values.password,
|
||||||
|
|||||||
Reference in New Issue
Block a user