fix: 验收包写入公司内网地址,避免 Windows 空 VITE 与 Android 假域名
Windows 补 .env.production 与 endpoints 兜底;Android 默认 host/端口改为内网,启动后重写 HttpUtil/ApiService,Urls 改为 getter。 Co-authored-by: Cursor <cursoragent@cursor.com> Co-authored-by: multica-agent <github@multica.ai>
This commit is contained in:
co-authored by
Cursor
multica-agent
parent
18d890ae7f
commit
bbc4dce0b6
@@ -10,6 +10,7 @@ class CompanyBootstrap {
|
||||
static Future<void> install() async {
|
||||
applyOfficialStylesFromTokens();
|
||||
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);
|
||||
MediaKit.ensureInitialized();
|
||||
HttpUtil.init();
|
||||
ApiService().setBaseUrl(serverIp);
|
||||
ApiService().setBaseUrl(imApiUrl);
|
||||
} catch (_) {}
|
||||
|
||||
runApp();
|
||||
@@ -65,9 +65,10 @@ class Config {
|
||||
static const friendScheme = "io.openim.app/addFriend/";
|
||||
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);
|
||||
|
||||
@@ -86,7 +87,7 @@ class Config {
|
||||
if (null != server) {
|
||||
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 {
|
||||
@@ -95,7 +96,7 @@ class Config {
|
||||
if (null != server) {
|
||||
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 {
|
||||
|
||||
@@ -1,22 +1,27 @@
|
||||
import 'config.dart';
|
||||
|
||||
class Urls {
|
||||
static final onlineStatus = "${Config.imApiUrl}/manager/get_users_online_status";
|
||||
static final queryAllUsers = "${Config.imApiUrl}/manager/get_all_users_uid";
|
||||
static final updateUserInfo = "${Config.appAuthUrl}/user/update";
|
||||
static final searchFriendInfo = "${Config.appAuthUrl}/friend/search";
|
||||
static final getUsersFullInfo = "${Config.appAuthUrl}/user/find/full";
|
||||
static final searchUserFullInfo = "${Config.appAuthUrl}/user/search/full";
|
||||
static String get onlineStatus =>
|
||||
"${Config.imApiUrl}/manager/get_users_online_status";
|
||||
static String get queryAllUsers =>
|
||||
"${Config.imApiUrl}/manager/get_all_users_uid";
|
||||
static String get updateUserInfo => "${Config.appAuthUrl}/user/update";
|
||||
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 final checkVerificationCode = "${Config.appAuthUrl}/account/code/verify";
|
||||
static final register = "${Config.appAuthUrl}/account/register";
|
||||
static String get getVerificationCode =>
|
||||
"${Config.appAuthUrl}/account/code/send";
|
||||
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 final changePwd = "${Config.appAuthUrl}/account/password/change";
|
||||
static final login = "${Config.appAuthUrl}/account/login";
|
||||
static String get resetPwd => "${Config.appAuthUrl}/account/password/reset";
|
||||
static String get changePwd => "${Config.appAuthUrl}/account/password/change";
|
||||
static String get login => "${Config.appAuthUrl}/account/login";
|
||||
|
||||
static final upgrade = "${Config.appAuthUrl}/app/check";
|
||||
static final getClientConfig = '${Config.appAuthUrl}/client_config/get';
|
||||
static final getTokenForRTC = "${Config.appAuthUrl}/user/rtc/get_token";
|
||||
static String get upgrade => "${Config.appAuthUrl}/app/check";
|
||||
static String get getClientConfig => '${Config.appAuthUrl}/client_config/get';
|
||||
static String get getTokenForRTC => "${Config.appAuthUrl}/user/rtc/get_token";
|
||||
}
|
||||
|
||||
@@ -39,7 +39,12 @@ class HttpUtil {
|
||||
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(
|
||||
String path, {
|
||||
@@ -103,8 +108,11 @@ class HttpUtil {
|
||||
final bytes = await File(compressPath ?? path).readAsBytes();
|
||||
final mf = MultipartFile.fromBytes(bytes, filename: fileName);
|
||||
|
||||
var formData =
|
||||
FormData.fromMap({'operationID': '${DateTime.now().millisecondsSinceEpoch}', 'fileType': 1, 'file': mf});
|
||||
var formData = FormData.fromMap({
|
||||
'operationID': '${DateTime.now().millisecondsSinceEpoch}',
|
||||
'fileType': 1,
|
||||
'file': mf
|
||||
});
|
||||
|
||||
var resp = await dio.post<Map<String, dynamic>>(
|
||||
"${Config.imApiUrl}/third/minio_upload",
|
||||
@@ -151,12 +159,14 @@ class HttpUtil {
|
||||
onCompletion?.call();
|
||||
intervalDo.drop(
|
||||
fun: () async {
|
||||
saveFileToGallerySaver(File(cachePath), showTaost: EasyLoading.isShow);
|
||||
saveFileToGallerySaver(File(cachePath),
|
||||
showTaost: EasyLoading.isShow);
|
||||
},
|
||||
milliseconds: 1500);
|
||||
}
|
||||
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);
|
||||
if (byteData != null) {
|
||||
Uint8List uint8list = byteData.buffer.asUint8List();
|
||||
var result = await ImageGallerySaverPlus.saveImage(Uint8List.fromList(uint8list));
|
||||
var result =
|
||||
await ImageGallerySaverPlus.saveImage(Uint8List.fromList(uint8list));
|
||||
if (result != null) {
|
||||
var tips = StrRes.saveSuccessfully;
|
||||
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 {
|
||||
var tips = StrRes.saveSuccessfully;
|
||||
Logger.print('saveFileToGallerySaver: ${file.path}');
|
||||
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 (Platform.isAndroid) {
|
||||
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 { ACCOUNT_URL, LIVEKIT_URL } from "@/config/endpoints";
|
||||
import { getIMToken } from "@/utils/storage";
|
||||
|
||||
// RTC(音视频通话)令牌改由自研账号服务签发(原 OpenIM chat 服务 :10008 已下线)。
|
||||
@@ -15,7 +16,7 @@ export const getRtcConnectData = async (room: string, identity: string) => {
|
||||
msg: string;
|
||||
data: { token: string };
|
||||
}>(
|
||||
`${import.meta.env.VITE_ACCOUNT_URL}/api/rtc_token`,
|
||||
`${ACCOUNT_URL}/api/rtc_token`,
|
||||
{ room, identity },
|
||||
{ headers: { Authorization: `Bearer ${imToken}` } },
|
||||
);
|
||||
@@ -24,7 +25,7 @@ export const getRtcConnectData = async (room: string, identity: string) => {
|
||||
}
|
||||
return {
|
||||
data: {
|
||||
serverUrl: import.meta.env.VITE_LIVEKIT_URL as string,
|
||||
serverUrl: LIVEKIT_URL,
|
||||
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 { CustomType } from "@/constants";
|
||||
import { API_URL, WS_URL } from "@/config/endpoints";
|
||||
import {
|
||||
pushNewMessage,
|
||||
updateOneMessage,
|
||||
@@ -123,8 +124,8 @@ export function useGlobalEvent() {
|
||||
const IMToken = (await getIMToken()) as string;
|
||||
const IMUserID = (await getIMUserID()) as string;
|
||||
try {
|
||||
const apiAddr = import.meta.env.VITE_API_URL;
|
||||
const wsAddr = import.meta.env.VITE_WS_URL;
|
||||
const apiAddr = API_URL;
|
||||
const wsAddr = WS_URL;
|
||||
if (window.electronAPI) {
|
||||
await IMSDK.initSDK({
|
||||
platformID: window.electronAPI?.getPlatform() ?? 5,
|
||||
|
||||
@@ -5,6 +5,7 @@ import { useCallback, useEffect, useMemo, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { GroupedVirtuoso } from "react-virtuoso";
|
||||
|
||||
import { ACCOUNT_URL } from "@/config/endpoints";
|
||||
import { useContactStore } from "@/store";
|
||||
import { emit } from "@/utils/events";
|
||||
import { getIMToken } from "@/utils/storage";
|
||||
@@ -29,7 +30,7 @@ export const MyFriends = () => {
|
||||
return;
|
||||
}
|
||||
const { data } = await axios.get(
|
||||
`${import.meta.env.VITE_ACCOUNT_URL}/api/directory`,
|
||||
`${ACCOUNT_URL}/api/directory`,
|
||||
{
|
||||
params: { keyword: "", limit: 100 },
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
|
||||
@@ -4,6 +4,7 @@ import { t } from "i18next";
|
||||
import { useState } from "react";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
|
||||
import { ACCOUNT_URL } from "@/config/endpoints";
|
||||
import { setIMProfile } from "@/utils/storage";
|
||||
|
||||
interface LoginResult {
|
||||
@@ -29,7 +30,7 @@ const LoginForm = ({ onBanner }: LoginFormProps) => {
|
||||
setLoading(true);
|
||||
try {
|
||||
const { data: res } = await axios.post<LoginResult>(
|
||||
`${import.meta.env.VITE_ACCOUNT_URL}/api/login`,
|
||||
`${ACCOUNT_URL}/api/login`,
|
||||
{
|
||||
staffNo: values.staffNo.trim(),
|
||||
password: values.password,
|
||||
|
||||
Reference in New Issue
Block a user