request
This commit is contained in:
parent
69a4ca17e8
commit
7d5a604665
@ -3,12 +3,15 @@ import { authStore } from './auth';
|
|||||||
import { promptAction, router } from '@kit.ArkUI';
|
import { promptAction, router } from '@kit.ArkUI';
|
||||||
import { BusinessError } from '@ohos.base';
|
import { BusinessError } from '@ohos.base';
|
||||||
import { logger } from './logger';
|
import { logger } from './logger';
|
||||||
import { HashMap } from '@kit.ArkTS';
|
import { buffer, HashMap, util } from '@kit.ArkTS';
|
||||||
import { CryptoJS } from '@ohos/crypto-js'
|
import { CryptoJS } from '@ohos/crypto-js'
|
||||||
import { Base64Util } from './Base64Util';
|
import { Base64Util } from './Base64Util';
|
||||||
import { ChangeUtil } from './ChangeUtil'
|
import { ChangeUtil } from './ChangeUtil'
|
||||||
import { bundleManager} from '@kit.AbilityKit';
|
import { bundleManager} from '@kit.AbilityKit';
|
||||||
import { deviceInfo } from '@kit.BasicServicesKit';
|
import { deviceInfo } from '@kit.BasicServicesKit';
|
||||||
|
import { cryptoFramework } from '@kit.CryptoArchitectureKit';
|
||||||
|
import { rcp } from '@kit.RemoteCommunicationKit';
|
||||||
|
|
||||||
interface HdRequestOptions {
|
interface HdRequestOptions {
|
||||||
baseURL?: string
|
baseURL?: string
|
||||||
}
|
}
|
||||||
@ -28,12 +31,14 @@ export interface TimestampBean {
|
|||||||
|
|
||||||
class HdHttp {
|
class HdHttp {
|
||||||
baseURL: string
|
baseURL: string
|
||||||
osFullName: string = deviceInfo.marketName+'/'+ deviceInfo.osFullName;
|
osFullName: string = deviceInfo.marketName + '/' + deviceInfo.osFullName;
|
||||||
|
|
||||||
constructor(options: HdRequestOptions) {
|
constructor(options: HdRequestOptions) {
|
||||||
this.baseURL = options.baseURL || ''
|
this.baseURL = options.baseURL || ''
|
||||||
}
|
}
|
||||||
|
|
||||||
private request<T>(path: string, method: http.RequestMethod = http.RequestMethod.POST, extraDatas :HashMap<string, string>) {
|
private request<T>(path: string, method: http.RequestMethod = http.RequestMethod.POST,
|
||||||
|
extraDatas: HashMap<string, string>) {
|
||||||
const httpInstance = http.createHttp()
|
const httpInstance = http.createHttp()
|
||||||
|
|
||||||
const options: http.HttpRequestOptions = {
|
const options: http.HttpRequestOptions = {
|
||||||
@ -45,56 +50,71 @@ class HdHttp {
|
|||||||
// 开发者根据自身业务需要添加header字段
|
// 开发者根据自身业务需要添加header字段
|
||||||
header: {
|
header: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
'sign':this.getSign(extraDatas),
|
'sign': this.getSign(extraDatas),
|
||||||
'User-Agent':this.osFullName
|
'User-Agent': this.osFullName
|
||||||
},
|
},
|
||||||
extraData:ChangeUtil.map2Json(extraDatas)
|
extraData: ChangeUtil.map2Json(extraDatas)
|
||||||
}
|
}
|
||||||
|
|
||||||
let fullUrl = this.baseURL + path
|
let fullUrl = this.baseURL + path
|
||||||
|
|
||||||
|
|
||||||
return httpInstance.request(fullUrl, options).then((res) => {
|
return httpInstance.request(fullUrl, options).then((res) => {
|
||||||
logger.info('Response param'+JSON.stringify(extraDatas))
|
logger.info('Response param' + JSON.stringify(extraDatas))
|
||||||
logger.info('Response fullUrl:' +fullUrl+ res.result);
|
logger.info('Response fullUrl:' + fullUrl + res.result);
|
||||||
const result = res.result as HdResponse<T>
|
const result = res.result as HdResponse<T>
|
||||||
return result
|
return result
|
||||||
}).catch((err: BusinessError) => {
|
}).catch((err: BusinessError) => {
|
||||||
logger.info(fullUrl+`Response succeeded: ${err}`);
|
logger.info(fullUrl + `Response succeeded: ${err}`);
|
||||||
promptAction.showToast({ message: err.message || '网络错误' })
|
promptAction.showToast({ message: err.message || '网络错误' })
|
||||||
return Promise.reject(err)
|
return Promise.reject(err)
|
||||||
}).finally(() => {
|
}).finally(() => {
|
||||||
httpInstance.destroy()
|
httpInstance.destroy()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
private requestObject<T>(path: string, method: http.RequestMethod = http.RequestMethod.POST, extraDatas :HashMap<string, Object>) {
|
|
||||||
|
private requestObject<T>(path: string, method: http.RequestMethod = http.RequestMethod.POST,
|
||||||
|
extraDatas: HashMap<string, Object>) {
|
||||||
const httpInstance = http.createHttp()
|
const httpInstance = http.createHttp()
|
||||||
|
// 1. 拼接参数
|
||||||
|
let signStr = this.concatParams(extraDatas);
|
||||||
|
console.info('拼接signStr=',signStr)
|
||||||
|
// 2. 字符清理
|
||||||
|
signStr = cleanString(signStr)
|
||||||
|
console.info('异常字符转化后,signStr',signStr)
|
||||||
|
const timestamp = extraDatas.get('timestamp')
|
||||||
|
const timeStampMd5 = CryptoJS.MD5(timestamp.toString()).toString()
|
||||||
|
console.info('时间戳:timeStampStr=',timeStampMd5)
|
||||||
|
signStr += timeStampMd5
|
||||||
|
console.info('时间戳+signStr=',signStr)
|
||||||
|
signStr = String(CryptoJS.MD5(signStr).toString())
|
||||||
|
console.info('时间戳+signStr的MD5后=',signStr)
|
||||||
|
signStr = this.safeUrlBase64Encode(signStr)
|
||||||
|
.replace(/\+/g, '-')
|
||||||
|
.replace(/\//g, '_')
|
||||||
|
.replace(/=+$/, '')
|
||||||
|
console.info('时间戳+signStr的MD5后的base64=',signStr)
|
||||||
|
|
||||||
const options: http.HttpRequestOptions = {
|
const options: http.HttpRequestOptions = {
|
||||||
method: http.RequestMethod.POST,
|
method: http.RequestMethod.POST,
|
||||||
// 可选,默认为60s
|
|
||||||
connectTimeout: 60000,
|
connectTimeout: 60000,
|
||||||
// 可选,默认为60s
|
|
||||||
readTimeout: 60000,
|
readTimeout: 60000,
|
||||||
// 开发者根据自身业务需要添加header字段
|
|
||||||
header: {
|
header: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
'sign':this.getSignO(extraDatas),
|
'sign': signStr,
|
||||||
'User-Agent':this.osFullName
|
'User-Agent': this.osFullName
|
||||||
},
|
},
|
||||||
extraData:ChangeUtil.map2JsonO(extraDatas)
|
extraData: ChangeUtil.map2JsonO(extraDatas)
|
||||||
}
|
}
|
||||||
|
|
||||||
let fullUrl = this.baseURL + path
|
let fullUrl = this.baseURL + path
|
||||||
|
|
||||||
|
|
||||||
return httpInstance.request(fullUrl, options).then((res) => {
|
return httpInstance.request(fullUrl, options).then((res) => {
|
||||||
logger.info('Response param'+JSON.stringify(extraDatas))
|
logger.info('Response param' + JSON.stringify(extraDatas))
|
||||||
logger.info('Response fullUrl:' +fullUrl+ res.result);
|
logger.info('Response fullUrl:' + fullUrl + res.result);
|
||||||
const result = res.result as HdResponse<T>
|
const result = res.result as HdResponse<T>
|
||||||
return result
|
return result
|
||||||
}).catch((err: BusinessError) => {
|
}).catch((err: BusinessError) => {
|
||||||
logger.info(fullUrl+`Response succeeded: ${err}`);
|
logger.info(fullUrl + `Response succeeded: ${err}`);
|
||||||
promptAction.showToast({ message: err.message || '网络错误' })
|
promptAction.showToast({ message: err.message || '网络错误' })
|
||||||
return Promise.reject(err)
|
return Promise.reject(err)
|
||||||
}).finally(() => {
|
}).finally(() => {
|
||||||
@ -129,11 +149,11 @@ class HdHttp {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return httpInstance.request(fullUrl, options).then((res) => {
|
return httpInstance.request(fullUrl, options).then((res) => {
|
||||||
logger.info('Response fullUrl:' +fullUrl+ res.result);
|
logger.info('Response fullUrl:' + fullUrl + res.result);
|
||||||
const result = res.result as HdResponse<T>
|
const result = res.result as HdResponse<T>
|
||||||
return result
|
return result
|
||||||
}).catch((err: BusinessError) => {
|
}).catch((err: BusinessError) => {
|
||||||
logger.info(fullUrl+`Response succeeded: ${err}`);
|
logger.info(fullUrl + `Response succeeded: ${err}`);
|
||||||
promptAction.showToast({ message: err.message || '网络错误' })
|
promptAction.showToast({ message: err.message || '网络错误' })
|
||||||
return Promise.reject(err)
|
return Promise.reject(err)
|
||||||
}).finally(() => {
|
}).finally(() => {
|
||||||
@ -141,9 +161,6 @@ class HdHttp {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
get<T>(url: string, data?: Object): Promise<HdResponse<T>> {
|
get<T>(url: string, data?: Object): Promise<HdResponse<T>> {
|
||||||
return this.requestafter<T>(url, http.RequestMethod.GET, data)
|
return this.requestafter<T>(url, http.RequestMethod.GET, data)
|
||||||
}
|
}
|
||||||
@ -159,12 +176,15 @@ class HdHttp {
|
|||||||
delete<T>(url: string, data?: Object): Promise<HdResponse<T>> {
|
delete<T>(url: string, data?: Object): Promise<HdResponse<T>> {
|
||||||
return this.requestafter<T>(url, http.RequestMethod.DELETE, data)
|
return this.requestafter<T>(url, http.RequestMethod.DELETE, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
posts<T>(url: string, data: HashMap<string, string>): Promise<HdResponse<T>> {
|
posts<T>(url: string, data: HashMap<string, string>): Promise<HdResponse<T>> {
|
||||||
return this.request<T>(url, http.RequestMethod.POST, data)
|
return this.request<T>(url, http.RequestMethod.POST, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
postO<T>(url: string, data: HashMap<string, Object>): Promise<HdResponse<T>> {
|
postO<T>(url: string, data: HashMap<string, Object>): Promise<HdResponse<T>> {
|
||||||
return this.requestObject<T>(url, http.RequestMethod.POST, data)
|
return this.requestObject<T>(url, http.RequestMethod.POST, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
httpReq<T>(url: string, datas: HashMap<string, string>): Promise<HdResponse<T>> {
|
httpReq<T>(url: string, datas: HashMap<string, string>): Promise<HdResponse<T>> {
|
||||||
// 创建httpRequest对象。
|
// 创建httpRequest对象。
|
||||||
let httpRequest = http.createHttp();
|
let httpRequest = http.createHttp();
|
||||||
@ -188,18 +208,18 @@ class HdHttp {
|
|||||||
return promise.then(async (data) => {
|
return promise.then(async (data) => {
|
||||||
if (data.responseCode === http.ResponseCode.OK) {
|
if (data.responseCode === http.ResponseCode.OK) {
|
||||||
logger.info('Response httpReq:' + data.result);
|
logger.info('Response httpReq:' + data.result);
|
||||||
let json:TimestampBean = JSON.parse(data.result.toString()) as TimestampBean;
|
let json: TimestampBean = JSON.parse(data.result.toString()) as TimestampBean;
|
||||||
let tp = json.timestamp;
|
let tp = json.timestamp;
|
||||||
datas.set("user_uuid", authStore.getUser().uuid?authStore.getUser().uuid:'');
|
datas.set("user_uuid", authStore.getUser().uuid ? authStore.getUser().uuid : '');
|
||||||
datas.set("client_type", 'H');
|
datas.set("client_type", 'H');
|
||||||
datas.set("version", await this.getVersion() );
|
datas.set("version", await this.getVersion());
|
||||||
datas.set('timestamp',tp+'');
|
datas.set('timestamp', tp + '');
|
||||||
return this.posts<T>(url, datas);
|
return this.posts<T>(url, datas);
|
||||||
} else {
|
} else {
|
||||||
return this.posts<T>(url, datas);
|
return this.posts<T>(url, datas);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
).catch((err:BusinessError) => {
|
).catch((err: BusinessError) => {
|
||||||
logger.info('Response httpReq error:' + JSON.stringify(err));
|
logger.info('Response httpReq error:' + JSON.stringify(err));
|
||||||
return Promise.reject(err);
|
return Promise.reject(err);
|
||||||
}).finally(() => {
|
}).finally(() => {
|
||||||
@ -230,24 +250,25 @@ class HdHttp {
|
|||||||
return promise.then(async (data) => {
|
return promise.then(async (data) => {
|
||||||
if (data.responseCode === http.ResponseCode.OK) {
|
if (data.responseCode === http.ResponseCode.OK) {
|
||||||
logger.info('Response httpReq:' + data.result);
|
logger.info('Response httpReq:' + data.result);
|
||||||
let json:TimestampBean = JSON.parse(data.result.toString()) as TimestampBean;
|
let json: TimestampBean = JSON.parse(data.result.toString()) as TimestampBean;
|
||||||
let tp = json.timestamp;
|
let tp = json.timestamp;
|
||||||
datas.set("user_uuid", authStore.getUser().uuid?authStore.getUser().uuid:'');
|
datas.set("user_uuid", authStore.getUser().uuid ? authStore.getUser().uuid : '');
|
||||||
datas.set("client_type", 'H');
|
datas.set("client_type", 'H');
|
||||||
datas.set("version", await this.getVersion() );
|
datas.set("version", await this.getVersion());
|
||||||
datas.set('timestamp',tp+'');
|
datas.set('timestamp', tp + '');
|
||||||
return this.postO<T>(url, datas);
|
return this.postO<T>(url, datas );
|
||||||
} else {
|
} else {
|
||||||
return this.postO<T>(url, datas);
|
return this.postO<T>(url, datas);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
).catch((err:BusinessError) => {
|
).catch((err: BusinessError) => {
|
||||||
logger.info('Response httpReq error:' + JSON.stringify(err));
|
logger.info('Response httpReq error:' + JSON.stringify(err));
|
||||||
return Promise.reject(err);
|
return Promise.reject(err);
|
||||||
}).finally(() => {
|
}).finally(() => {
|
||||||
httpRequest.destroy()
|
httpRequest.destroy()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
httpReqSimply<T>(url: string) {
|
httpReqSimply<T>(url: string) {
|
||||||
// 创建httpRequest对象。
|
// 创建httpRequest对象。
|
||||||
let httpRequest = http.createHttp();
|
let httpRequest = http.createHttp();
|
||||||
@ -272,7 +293,7 @@ class HdHttp {
|
|||||||
const result = data.result as HdResponse<T>
|
const result = data.result as HdResponse<T>
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
).catch((err:BusinessError) => {
|
).catch((err: BusinessError) => {
|
||||||
logger.info('Response httpReq error:' + JSON.stringify(err));
|
logger.info('Response httpReq error:' + JSON.stringify(err));
|
||||||
return Promise.reject(err);
|
return Promise.reject(err);
|
||||||
}).finally(() => {
|
}).finally(() => {
|
||||||
@ -280,45 +301,45 @@ class HdHttp {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
getSignO(extraDatas1:HashMap<string, Object>): string {
|
getSignO(extraDatas1: HashMap<string, Object>): string {
|
||||||
let secret= extraDatas1.get("timestamp")+''
|
let secret = extraDatas1.get("timestamp") + ''
|
||||||
if(secret!=null) {
|
if (secret != null) {
|
||||||
let keyValueStr: string = "";
|
let keyValueStr: string = "";
|
||||||
let entriesArray: Array<string> = Array.from(extraDatas1.keys());
|
let entriesArray: Array<string> = Array.from(extraDatas1.keys());
|
||||||
entriesArray.sort();
|
entriesArray.sort();
|
||||||
|
|
||||||
let sortedMap:HashMap<string, Object> = new HashMap();
|
let sortedMap: HashMap<string, Object> = new HashMap();
|
||||||
entriesArray.forEach((value: string, index: number) => {
|
entriesArray.forEach((value: string, index: number) => {
|
||||||
sortedMap.set(value,extraDatas1.get(value));
|
sortedMap.set(value, extraDatas1.get(value));
|
||||||
// keyValueStr +=value+extraDatas1.get(value)
|
// keyValueStr +=value+extraDatas1.get(value)
|
||||||
keyValueStr +=value+JSON.stringify(extraDatas1.get(value))
|
keyValueStr += value + JSON.stringify(extraDatas1.get(value))
|
||||||
});
|
});
|
||||||
keyValueStr = keyValueStr + CryptoJS.MD5(secret).toString();
|
keyValueStr = keyValueStr + CryptoJS.MD5(secret).toString();
|
||||||
keyValueStr = keyValueStr.replaceAll(" ", "").replaceAll("\"", "").replaceAll(":","=");
|
keyValueStr = keyValueStr.replaceAll(" ", "").replaceAll("\"", "").replaceAll(":", "=");
|
||||||
let Md5keyValueStr: string = CryptoJS.MD5(keyValueStr).toString();
|
let Md5keyValueStr: string = CryptoJS.MD5(keyValueStr).toString();
|
||||||
let base64Str:string=Base64Util.encodeToStrSync(Md5keyValueStr);
|
let base64Str: string = Base64Util.encodeToStrSync(Md5keyValueStr);
|
||||||
return base64Str;
|
return base64Str;
|
||||||
} else {
|
} else {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getSign(extraDatas1:HashMap<string, string>): string {
|
getSign(extraDatas1: HashMap<string, string>): string {
|
||||||
let secret= extraDatas1.get("timestamp")
|
let secret = extraDatas1.get("timestamp")
|
||||||
if(secret!=null) {
|
if (secret != null) {
|
||||||
let keyValueStr: string = "";
|
let keyValueStr: string = "";
|
||||||
let entriesArray: Array<string> = Array.from(extraDatas1.keys());
|
let entriesArray: Array<string> = Array.from(extraDatas1.keys());
|
||||||
entriesArray.sort();
|
entriesArray.sort();
|
||||||
|
|
||||||
let sortedMap:HashMap<string, string> = new HashMap();
|
let sortedMap: HashMap<string, string> = new HashMap();
|
||||||
entriesArray.forEach((value: string, index: number) => {
|
entriesArray.forEach((value: string, index: number) => {
|
||||||
sortedMap.set(value,extraDatas1.get(value));
|
sortedMap.set(value, extraDatas1.get(value));
|
||||||
keyValueStr +=value+extraDatas1.get(value)
|
keyValueStr += value + extraDatas1.get(value)
|
||||||
});
|
});
|
||||||
keyValueStr = keyValueStr.replace(" ", "");
|
keyValueStr = keyValueStr.replace(" ", "");
|
||||||
keyValueStr = keyValueStr + CryptoJS.MD5(secret).toString();
|
keyValueStr = keyValueStr + CryptoJS.MD5(secret).toString();
|
||||||
let Md5keyValueStr: string = CryptoJS.MD5(keyValueStr).toString();
|
let Md5keyValueStr: string = CryptoJS.MD5(keyValueStr).toString();
|
||||||
let base64Str:string=Base64Util.encodeToStrSync(Md5keyValueStr);
|
let base64Str: string = Base64Util.encodeToStrSync(Md5keyValueStr);
|
||||||
return base64Str;
|
return base64Str;
|
||||||
} else {
|
} else {
|
||||||
return '';
|
return '';
|
||||||
@ -326,13 +347,98 @@ class HdHttp {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async getVersion() {
|
async getVersion() {
|
||||||
let res=await bundleManager.getBundleInfoForSelf(
|
let res = await bundleManager.getBundleInfoForSelf(
|
||||||
bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_APPLICATION |
|
bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_APPLICATION |
|
||||||
bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_METADATA
|
bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_METADATA
|
||||||
)
|
)
|
||||||
return res.versionName
|
return res.versionName
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 安全Base64编码(URL安全)
|
||||||
|
safeUrlBase64Encode(input: string): string {
|
||||||
|
const base64 = new util.Base64Helper();
|
||||||
|
const encoded = base64.encodeToStringSync(new util.TextEncoder().encode(input));
|
||||||
|
return encoded.replace(/\+/g, '-')
|
||||||
|
.replace(/\//g, '_')
|
||||||
|
.replace(/=/g, '');
|
||||||
|
}
|
||||||
|
|
||||||
|
async md5To32bit(input: string): Promise<string> {
|
||||||
|
// 空值安全处理
|
||||||
|
if (!input || input.length === 0) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
// 1. 创建MD5实例
|
||||||
|
const md = cryptoFramework.createMd('MD5');
|
||||||
|
// 2. 数据转换(严格使用UTF8编码)
|
||||||
|
const dataBlob:DataBlob = {
|
||||||
|
data: new Uint8Array(buffer.from(input, 'utf-8').buffer)
|
||||||
|
}
|
||||||
|
// 3. 更新数据
|
||||||
|
await md.update(dataBlob);
|
||||||
|
// 4. 获取摘要
|
||||||
|
const mdResult = await md.digest();
|
||||||
|
// 5. 转换为16进制小写字符串
|
||||||
|
return Array.from(mdResult.data)
|
||||||
|
.map(byte => byte.toString(16).padStart(2, '0'))
|
||||||
|
.join('');
|
||||||
|
} catch (err) {
|
||||||
|
console.error('MD5加密失败:', err.message);
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
concatParams(params: HashMap<string, Object>): string {
|
||||||
|
const keys = this.iosStyleSort(Array.from(params.keys())); // 使用新排序
|
||||||
|
let result = '';
|
||||||
|
for (const key of keys) {
|
||||||
|
const value = params.get(key);
|
||||||
|
if (value === null || value === undefined) {
|
||||||
|
result += key;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// 严格匹配iOS的JSON处理(保留空格仅删除换行)
|
||||||
|
if (typeof value === 'object') {
|
||||||
|
const jsonStr = JSON.stringify(value)
|
||||||
|
.replace(/\n/g, '') // 仅删除换行符
|
||||||
|
.replace(/\\"/g, '"'); // 处理转义引号
|
||||||
|
result += key + jsonStr;
|
||||||
|
} else {
|
||||||
|
result += key + String(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
iosStyleSort(keys: string[]): string[] {
|
||||||
|
return keys.sort((a, b) => {
|
||||||
|
// 1. 主要排序:忽略大小写和数字值排序
|
||||||
|
let result = a.localeCompare(b, undefined, {
|
||||||
|
sensitivity: 'base',
|
||||||
|
numeric: true
|
||||||
|
});
|
||||||
|
|
||||||
|
// 2. 次要排序:宽度不敏感(全角/半角等效)
|
||||||
|
if (result === 0) {
|
||||||
|
const normalize = (str: string) =>
|
||||||
|
str.normalize('NFKC').replace(/[\uFF00-\uFFEF]/g, '');
|
||||||
|
result = normalize(a).localeCompare(normalize(b));
|
||||||
|
}
|
||||||
|
// 3. 强制确定顺序
|
||||||
|
return result === 0 ? (a < b ? -1 : 1) : result;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface DataBlob {
|
||||||
|
data: Uint8Array;
|
||||||
|
}
|
||||||
|
|
||||||
|
function cleanString(str: string) {
|
||||||
|
const pattern: RegExp = /[\s\\;":]/g
|
||||||
|
return str.replace(pattern, (match) => match === ':' ? '=' : '')
|
||||||
}
|
}
|
||||||
|
|
||||||
export const hdHttp = new HdHttp({ baseURL: '' })
|
export const hdHttp = new HdHttp({ baseURL: '' })
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user