first
This commit is contained in:
5
assets/res-native/.res-native.md
Normal file
5
assets/res-native/.res-native.md
Normal file
@@ -0,0 +1,5 @@
|
||||
存储静态资源的文件夹
|
||||
1、非公共脚本资源,尽量不放到主包内
|
||||
3、图片、字体等非脚本类公共资源,尽量不放到主包内(因为构建后这些资源会被拷贝到其它Bundle中)
|
||||
2、如果公共脚本资源体积较大,可以考虑放到Bundle内,保证首屏体积尽量小
|
||||
4、如不再需要,可以直接删除此文件夹
|
||||
9
assets/res-native/animation.meta
Normal file
9
assets/res-native/animation.meta
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "1.2.0",
|
||||
"importer": "directory",
|
||||
"imported": true,
|
||||
"uuid": "769a05ac-21c9-496a-8982-371919a27245",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
9
assets/res-native/com.meta
Normal file
9
assets/res-native/com.meta
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "1.2.0",
|
||||
"importer": "directory",
|
||||
"imported": true,
|
||||
"uuid": "7b91c9e2-ac91-4eb5-9033-3e2b1dd991cd",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
BIN
assets/res-native/com/com_loading.png
Normal file
BIN
assets/res-native/com/com_loading.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 623 KiB |
138
assets/res-native/com/com_loading.png.meta
Normal file
138
assets/res-native/com/com_loading.png.meta
Normal file
@@ -0,0 +1,138 @@
|
||||
{
|
||||
"ver": "1.0.27",
|
||||
"importer": "image",
|
||||
"imported": true,
|
||||
"uuid": "17f7634b-b629-4c04-8183-8c680b6151ad",
|
||||
"files": [
|
||||
".json",
|
||||
".png"
|
||||
],
|
||||
"subMetas": {
|
||||
"6c48a": {
|
||||
"importer": "texture",
|
||||
"uuid": "17f7634b-b629-4c04-8183-8c680b6151ad@6c48a",
|
||||
"displayName": "com_loading",
|
||||
"id": "6c48a",
|
||||
"name": "texture",
|
||||
"userData": {
|
||||
"wrapModeS": "clamp-to-edge",
|
||||
"wrapModeT": "clamp-to-edge",
|
||||
"imageUuidOrDatabaseUri": "17f7634b-b629-4c04-8183-8c680b6151ad",
|
||||
"isUuid": true,
|
||||
"visible": false,
|
||||
"minfilter": "linear",
|
||||
"magfilter": "linear",
|
||||
"mipfilter": "none",
|
||||
"anisotropy": 0
|
||||
},
|
||||
"ver": "1.0.22",
|
||||
"imported": true,
|
||||
"files": [
|
||||
".json"
|
||||
],
|
||||
"subMetas": {}
|
||||
},
|
||||
"f9941": {
|
||||
"importer": "sprite-frame",
|
||||
"uuid": "17f7634b-b629-4c04-8183-8c680b6151ad@f9941",
|
||||
"displayName": "com_loading",
|
||||
"id": "f9941",
|
||||
"name": "spriteFrame",
|
||||
"userData": {
|
||||
"trimType": "auto",
|
||||
"trimThreshold": 1,
|
||||
"rotated": false,
|
||||
"offsetX": 0,
|
||||
"offsetY": 0,
|
||||
"trimX": 0,
|
||||
"trimY": 0,
|
||||
"width": 1080,
|
||||
"height": 1920,
|
||||
"rawWidth": 1080,
|
||||
"rawHeight": 1920,
|
||||
"borderTop": 0,
|
||||
"borderBottom": 0,
|
||||
"borderLeft": 0,
|
||||
"borderRight": 0,
|
||||
"packable": true,
|
||||
"pixelsToUnit": 100,
|
||||
"pivotX": 0.5,
|
||||
"pivotY": 0.5,
|
||||
"meshType": 0,
|
||||
"vertices": {
|
||||
"rawPosition": [
|
||||
-540,
|
||||
-960,
|
||||
0,
|
||||
540,
|
||||
-960,
|
||||
0,
|
||||
-540,
|
||||
960,
|
||||
0,
|
||||
540,
|
||||
960,
|
||||
0
|
||||
],
|
||||
"indexes": [
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
2,
|
||||
1,
|
||||
3
|
||||
],
|
||||
"uv": [
|
||||
0,
|
||||
1920,
|
||||
1080,
|
||||
1920,
|
||||
0,
|
||||
0,
|
||||
1080,
|
||||
0
|
||||
],
|
||||
"nuv": [
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
1,
|
||||
1
|
||||
],
|
||||
"minPos": [
|
||||
-540,
|
||||
-960,
|
||||
0
|
||||
],
|
||||
"maxPos": [
|
||||
540,
|
||||
960,
|
||||
0
|
||||
]
|
||||
},
|
||||
"isUuid": true,
|
||||
"imageUuidOrDatabaseUri": "17f7634b-b629-4c04-8183-8c680b6151ad@6c48a",
|
||||
"atlasUuid": ""
|
||||
},
|
||||
"ver": "1.0.12",
|
||||
"imported": true,
|
||||
"files": [
|
||||
".json"
|
||||
],
|
||||
"subMetas": {}
|
||||
}
|
||||
},
|
||||
"userData": {
|
||||
"type": "sprite-frame",
|
||||
"hasAlpha": false,
|
||||
"fixAlphaTransparencyArtifacts": false,
|
||||
"redirect": "17f7634b-b629-4c04-8183-8c680b6151ad@6c48a",
|
||||
"compressSettings": {
|
||||
"useCompressTexture": true,
|
||||
"presetId": "b1rRMHaV9Gz5HhQd3Z8obg"
|
||||
}
|
||||
}
|
||||
}
|
||||
9
assets/res-native/data.meta
Normal file
9
assets/res-native/data.meta
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "1.2.0",
|
||||
"importer": "directory",
|
||||
"imported": true,
|
||||
"uuid": "da6dc13a-ba14-40ce-a8ee-791a814c21d7",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
81
assets/res-native/data/ChannelData.ts
Normal file
81
assets/res-native/data/ChannelData.ts
Normal file
@@ -0,0 +1,81 @@
|
||||
import { _decorator } from 'cc';
|
||||
const { ccclass } = _decorator;
|
||||
|
||||
/** 玩家数据类 */
|
||||
@ccclass('ChannelData')
|
||||
class ChannelData {
|
||||
public static instance: ChannelData | null = null;
|
||||
|
||||
/** 获取渠道数据状态 */
|
||||
public get_success: boolean = false;
|
||||
|
||||
/** 活动开关(0:关闭,1:开启) */
|
||||
public activity_open : number = 0;
|
||||
/** 币商功能(0:禁用,1:启用) */
|
||||
public coin_status : boolean = true;
|
||||
/** 币别代码 */
|
||||
public currency : string = "";
|
||||
/** 讨论组功能(0:禁用,1:启用) */
|
||||
public discussion_group_status : boolean = true;
|
||||
/** 渠道域名 */
|
||||
public domain : string = "";
|
||||
/** 下载地址 */
|
||||
public download_url : string = "";
|
||||
/** 渠道ID */
|
||||
public id : number = 0;
|
||||
/** 语言 */
|
||||
public lang : string = "";
|
||||
/** line client id */
|
||||
public line_client_id : string = "";
|
||||
/** line 登录功能(0:禁用,1:启用) */
|
||||
public line_login_status : boolean = true;
|
||||
/** 机台线路 */
|
||||
public machine_media_line : number = 0;
|
||||
/** 渠道名称 */
|
||||
public name : string = "";
|
||||
/** 全民代理功能(0:禁用,1:启用) */
|
||||
public national_promoter_status : boolean = true;
|
||||
/** 代理开启状态 */
|
||||
public promotion_status : boolean = true;
|
||||
/** Q币转入(0:禁用,1:启用) */
|
||||
public q_talk_point_status : boolean = true;
|
||||
/** Q币充值(0:禁用,1:启用) */
|
||||
public q_talk_recharge_status : boolean = true;
|
||||
/** Q币转出(0:禁用,1:启用) */
|
||||
public q_talk_withdraw_status : boolean = true;
|
||||
/** 排行榜功能(0:禁用,1:启用) */
|
||||
public ranking_status : boolean = true;
|
||||
/** 充值开启状态 */
|
||||
public recharge_status : boolean = true;
|
||||
/** 反水开启状态 */
|
||||
public reverse_water_status : boolean = true;
|
||||
/** 实体机台开关 0关闭1-开启 */
|
||||
public status_machine : boolean = true;
|
||||
/** web登录状态(0:禁用,1:启用) */
|
||||
public web_login_status : boolean = true;
|
||||
/** 人工提现(0:禁用,1:启用) */
|
||||
public withdraw_status : boolean = true;
|
||||
|
||||
private constructor(){}
|
||||
static get Instance(){
|
||||
if(ChannelData.instance == null){
|
||||
ChannelData.instance = new ChannelData();
|
||||
}
|
||||
return ChannelData.instance;
|
||||
}
|
||||
|
||||
public setChannelData(data:any){
|
||||
for (let key in data){
|
||||
if (this.hasOwnProperty(key)){
|
||||
(this as any)[key] = data[key];
|
||||
}
|
||||
}
|
||||
|
||||
this.get_success = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 游戏配置数据
|
||||
*/
|
||||
export const CHANNELDATA = ChannelData.Instance;
|
||||
9
assets/res-native/data/ChannelData.ts.meta
Normal file
9
assets/res-native/data/ChannelData.ts.meta
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.24",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "c2e6b946-cc1f-4b8a-b626-42968399e30d",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
39
assets/res-native/data/UserData.ts
Normal file
39
assets/res-native/data/UserData.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
import { _decorator } from 'cc';
|
||||
const { ccclass } = _decorator;
|
||||
|
||||
/** 玩家数据类 */
|
||||
@ccclass('UserData')
|
||||
class UserData {
|
||||
public static instance: UserData | null = null;
|
||||
|
||||
/** 剩余抽奖次数 */
|
||||
public point : number = 0;
|
||||
/** 奖品列表 */
|
||||
public prize_list : any[] = [];
|
||||
/** 游戏描述 */
|
||||
public description : string = "";
|
||||
/* 游戏logo */
|
||||
public logo : string = "";
|
||||
public logo_back : string = "";
|
||||
|
||||
private constructor(){}
|
||||
static get Instance(){
|
||||
if(UserData.instance == null){
|
||||
UserData.instance = new UserData();
|
||||
}
|
||||
return UserData.instance;
|
||||
}
|
||||
|
||||
public setUserData(data:any){
|
||||
for (let key in data){
|
||||
if (this.hasOwnProperty(key)){
|
||||
(this as any)[key] = data[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 玩家数据
|
||||
*/
|
||||
export const USERDATA = UserData.Instance;
|
||||
9
assets/res-native/data/UserData.ts.meta
Normal file
9
assets/res-native/data/UserData.ts.meta
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.24",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "29d17a77-7796-4df7-a0ed-7e0ececeae54",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
9
assets/res-native/network.meta
Normal file
9
assets/res-native/network.meta
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "1.2.0",
|
||||
"importer": "directory",
|
||||
"imported": true,
|
||||
"uuid": "baf2ef12-30f7-46ec-af55-620c096bef72",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
295
assets/res-native/network/HttpRequest.ts
Normal file
295
assets/res-native/network/HttpRequest.ts
Normal file
@@ -0,0 +1,295 @@
|
||||
import { game } from "cc";
|
||||
import { HTTP_SITE_ID, SERVER_LIST, GAME_VER } from "../setting/ServerConfig";
|
||||
import { Tools } from "../tools/Tools";
|
||||
import { app } from "../../app/app";
|
||||
import { CHANNELDATA } from "../data/ChannelData";
|
||||
|
||||
var urls: any = {}; // 当前请求地址集合
|
||||
var reqparams: any = {}; // 请求参数
|
||||
|
||||
/**
|
||||
* 登录token类,全局唯一
|
||||
*/
|
||||
export class LoginToken{
|
||||
private static instance: LoginToken | null = null;
|
||||
public access_token: string = "";
|
||||
public refresh_token: string = "";
|
||||
public appId: string = "";
|
||||
public appKey: string = "";
|
||||
private constructor(){}
|
||||
|
||||
static get Instance(){
|
||||
if(LoginToken.instance == null){
|
||||
LoginToken.instance = new LoginToken();
|
||||
}
|
||||
return LoginToken.instance;
|
||||
}
|
||||
|
||||
public setToken(access_token: string, refresh_token: string, appID: string, appKey: string){
|
||||
this.access_token = access_token;
|
||||
this.refresh_token = refresh_token;
|
||||
this.appId = appID
|
||||
this.appKey = appKey
|
||||
}
|
||||
}
|
||||
|
||||
/** 当前保存的token */
|
||||
export const LOGIN_TOKEN : LoginToken = LoginToken.Instance;
|
||||
|
||||
export enum HttpEvent {
|
||||
NO_NETWORK = "http_request_no_network", // 断网
|
||||
UNKNOWN_ERROR = "http_request_unknown_error", // 未知错误
|
||||
TIMEOUT = "http_request_timout" // 请求超时
|
||||
}
|
||||
|
||||
|
||||
export class HttpRequest {
|
||||
/** 服务器地址 */
|
||||
public server: string = SERVER_LIST
|
||||
/** 请求超时时间 */
|
||||
public timeout: number = 10000;
|
||||
|
||||
public lobbyUrl = ""
|
||||
|
||||
public setUrl (url:string) {
|
||||
this.server = "http://" + url + "/"
|
||||
}
|
||||
|
||||
/**
|
||||
* HTTP GET请求
|
||||
* 例:
|
||||
*
|
||||
* Get
|
||||
var complete = function(response){
|
||||
LogWrap.log(response);
|
||||
}
|
||||
var error = function(response){
|
||||
LogWrap.log(response);
|
||||
}
|
||||
this.get(name, complete, error);
|
||||
*/
|
||||
public get(name: string, completeCallback: Function, errorCallback?: Function) {
|
||||
this.sendRequest(name, null, false, completeCallback, errorCallback)
|
||||
}
|
||||
public getWithParams(name: string, params: any, completeCallback: Function, errorCallback?: Function) {
|
||||
this.sendRequest(name, params, false, completeCallback, errorCallback)
|
||||
}
|
||||
|
||||
public getByArraybuffer(name: string, completeCallback: Function, errorCallback?: Function) {
|
||||
this.sendRequest(name, null, false, completeCallback, errorCallback, 'arraybuffer', false);
|
||||
}
|
||||
public getWithParamsByArraybuffer(name: string, params: any, completeCallback: Function, errorCallback?: Function) {
|
||||
this.sendRequest(name, params, false, completeCallback, errorCallback, 'arraybuffer', false);
|
||||
}
|
||||
|
||||
/**
|
||||
* HTTP POST请求
|
||||
* 例:
|
||||
*
|
||||
* Post
|
||||
var param = '{"LoginCode":"donggang_dev","Password":"e10adc3949ba59abbe56e057f20f883e"}'
|
||||
var complete = function(response){
|
||||
var jsonData = JSON.parse(response);
|
||||
var data = JSON.parse(jsonData.Data);
|
||||
LogWrap.log(data.Id);
|
||||
}
|
||||
var error = function(response){
|
||||
LogWrap.log(response);
|
||||
}
|
||||
this.post(name, param, complete, error);
|
||||
*/
|
||||
public post(name: string, params: any, completeCallback?: Function, errorCallback?: Function) {
|
||||
this.sendRequest(name, params, true, completeCallback, errorCallback);
|
||||
}
|
||||
|
||||
/** 取消请求中的请求 */
|
||||
public abort(name: string) {
|
||||
var xhr = urls[this.server + name];
|
||||
if (xhr) {
|
||||
xhr.abort();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得字符串形式的参数
|
||||
*/
|
||||
private getParamString(params: any) {
|
||||
var result = "";
|
||||
for (var name in params) {
|
||||
let data = params[name];
|
||||
if (data instanceof Object) {
|
||||
for (var key in data)
|
||||
result += `${key}=${data[key]}&`;
|
||||
}
|
||||
else {
|
||||
result += `${name}=${data}&`;
|
||||
}
|
||||
}
|
||||
|
||||
return result.substring(0, result.length - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Http请求
|
||||
* @param name(string) 请求地址
|
||||
* @param params(JSON) 请求参数
|
||||
* @param isPost(boolen) 是否为POST方式
|
||||
* @param callback(function) 请求成功回调
|
||||
* @param errorCallback(function) 请求失败回调
|
||||
* @param responseType(string) 响应类型
|
||||
*/
|
||||
private async sendRequest(
|
||||
name: string,
|
||||
params: any,
|
||||
isPost: boolean,
|
||||
completeCallback?: Function,
|
||||
errorCallback?: Function,
|
||||
responseType?: string,
|
||||
isOpenTimeout = true,
|
||||
timeout: number = this.timeout
|
||||
) {
|
||||
if (!name) {
|
||||
console.log("请求地址不能为空");
|
||||
return;
|
||||
}
|
||||
|
||||
let url: string, newUrl: string, paramsStr: string;
|
||||
if (name.toLocaleLowerCase().indexOf("http") === 0) {
|
||||
url = name;
|
||||
} else {
|
||||
url = this.server + name;
|
||||
}
|
||||
|
||||
if (params) {
|
||||
paramsStr = this.getParamString(params);
|
||||
if (url.indexOf("?") > -1)
|
||||
newUrl = url + "&" + encodeURIComponent(paramsStr);
|
||||
else
|
||||
newUrl = url + "?" + paramsStr;
|
||||
} else {
|
||||
newUrl = url;
|
||||
}
|
||||
|
||||
if (urls[newUrl] != null && reqparams[newUrl] === paramsStr!) {
|
||||
console.log(`地址【${url}】已正在请求中,不能重复请求`);
|
||||
return;
|
||||
}
|
||||
|
||||
const xhr = new XMLHttpRequest();
|
||||
urls[newUrl] = xhr;
|
||||
reqparams[newUrl] = paramsStr!;
|
||||
|
||||
if (isPost) {
|
||||
xhr.open("POST", url);
|
||||
} else {
|
||||
xhr.open("GET", newUrl);
|
||||
}
|
||||
|
||||
if (LOGIN_TOKEN.access_token !== "") {
|
||||
xhr.setRequestHeader("Authorization", "Bearer " + LOGIN_TOKEN.access_token);
|
||||
}
|
||||
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded;charset=utf-8");
|
||||
|
||||
// 加密设置
|
||||
const time = Math.floor(Date.now() / 1000);
|
||||
xhr.setRequestHeader("Lang", CHANNELDATA.lang);
|
||||
|
||||
if (!params) params = {};
|
||||
let _params = params;
|
||||
_params.appId = LOGIN_TOKEN.appId;
|
||||
_params.nonceStr = Tools.getRandomStr(6);
|
||||
_params.timestamp = time;
|
||||
|
||||
let sha256DDD: string;
|
||||
try {
|
||||
sha256DDD = await Tools.generateSignNative(_params, LOGIN_TOKEN.appKey);
|
||||
} catch (err) {
|
||||
console.error("生成签名失败:", err);
|
||||
this.deleteCache(newUrl);
|
||||
const data: any = { url, params, event: HttpEvent.UNKNOWN_ERROR };
|
||||
if (errorCallback) errorCallback(data);
|
||||
return; // 出错直接返回,避免继续执行
|
||||
}
|
||||
|
||||
xhr.setRequestHeader("appId", LOGIN_TOKEN.appId);
|
||||
xhr.setRequestHeader("timestamp", _params.timestamp.toString());
|
||||
xhr.setRequestHeader("signature", sha256DDD);
|
||||
xhr.setRequestHeader("nonceStr", _params.nonceStr);
|
||||
xhr.setRequestHeader("Site-Id", HTTP_SITE_ID);
|
||||
const v = app.lib.storage.get("CURR_VERSION") || "100";
|
||||
xhr.setRequestHeader("app-version-key", v.toString());
|
||||
xhr.setRequestHeader("system-key", "android");
|
||||
xhr.setRequestHeader("Client-Version", GAME_VER);
|
||||
|
||||
const data: any = { url, params };
|
||||
|
||||
// 请求超时
|
||||
if (isOpenTimeout) {
|
||||
xhr.timeout = timeout;
|
||||
xhr.ontimeout = () => {
|
||||
this.deleteCache(newUrl);
|
||||
data.event = HttpEvent.TIMEOUT;
|
||||
if (errorCallback) errorCallback(data);
|
||||
};
|
||||
}
|
||||
|
||||
xhr.onloadend = () => {
|
||||
if (xhr.status === 500) {
|
||||
this.deleteCache(newUrl);
|
||||
data.event = HttpEvent.NO_NETWORK;
|
||||
if (errorCallback) errorCallback(data);
|
||||
}
|
||||
};
|
||||
|
||||
xhr.onerror = () => {
|
||||
this.deleteCache(newUrl);
|
||||
if (!errorCallback) return;
|
||||
if (xhr.readyState === 0 || xhr.readyState === 1 || xhr.status === 0) {
|
||||
data.event = HttpEvent.NO_NETWORK;
|
||||
} else {
|
||||
data.event = HttpEvent.UNKNOWN_ERROR;
|
||||
}
|
||||
errorCallback(data);
|
||||
};
|
||||
|
||||
xhr.onreadystatechange = () => {
|
||||
if (xhr.readyState !== 4) return;
|
||||
this.deleteCache(newUrl);
|
||||
if (xhr.status === 200) {
|
||||
if (completeCallback) {
|
||||
if (responseType === "arraybuffer") {
|
||||
xhr.responseType = responseType;
|
||||
completeCallback(xhr.response);
|
||||
} else {
|
||||
try {
|
||||
const resp: any = JSON.parse(xhr.response);
|
||||
console.log("---" + newUrl + "---", resp);
|
||||
if (Number(resp.code) === 200 || Number(resp.code) === 406) {
|
||||
completeCallback(resp.data);
|
||||
} else {
|
||||
app.manager.ui.showToast(Tools.GetLocalized(resp.msg));
|
||||
if (errorCallback) errorCallback(resp.data);
|
||||
}
|
||||
} catch (error) {
|
||||
console.log("解析响应失败:", error);
|
||||
if (errorCallback) errorCallback({ event: HttpEvent.UNKNOWN_ERROR });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (!paramsStr) {
|
||||
xhr.send();
|
||||
} else {
|
||||
xhr.send(paramsStr!);
|
||||
}
|
||||
}
|
||||
|
||||
private deleteCache(url: string) {
|
||||
delete urls[url];
|
||||
delete reqparams[url];
|
||||
}
|
||||
}
|
||||
|
||||
export let httpRequest = new HttpRequest()
|
||||
9
assets/res-native/network/HttpRequest.ts.meta
Normal file
9
assets/res-native/network/HttpRequest.ts.meta
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.24",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "58832863-cdb2-4696-85ed-027e9449985d",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
9
assets/res-native/setting.meta
Normal file
9
assets/res-native/setting.meta
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "1.2.0",
|
||||
"importer": "directory",
|
||||
"imported": true,
|
||||
"uuid": "c3f3b179-7966-4963-a10d-f690739ee781",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
34
assets/res-native/setting/ServerConfig.ts
Normal file
34
assets/res-native/setting/ServerConfig.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
/** 服务区域 */
|
||||
export const enum SERVER_EREA {
|
||||
// 一级棒横版
|
||||
ZP = 0,
|
||||
}
|
||||
/** 当前服务区域配置(根据打包修改) */
|
||||
export const NOW_SERVER_EREA : SERVER_EREA = SERVER_EREA.ZP;
|
||||
|
||||
// 默认地址
|
||||
const DEFAULT_URL = "https://xyxapi.yuliao666.top"
|
||||
/** 通用版本 */
|
||||
const DEFAULT_VERSION = "1.0.5"
|
||||
/** 测试服版本号 */
|
||||
const DEFAULT_TEST_VERSION = "1.0.0"
|
||||
|
||||
/** 区域打包配置文件 */
|
||||
const SERVER_CONFIG = {
|
||||
// 横版一级棒
|
||||
[0] : {
|
||||
"server" : DEFAULT_URL,
|
||||
"site_id" : "ba5ea4dc-75bb-438d-8a3a-b8031ef89426",
|
||||
"ver" : DEFAULT_TEST_VERSION,
|
||||
"area" : "86",
|
||||
}
|
||||
}
|
||||
|
||||
/** 服务器地址 */
|
||||
export const SERVER_LIST = SERVER_CONFIG[NOW_SERVER_EREA]["server"];
|
||||
/** Site ID */
|
||||
export const HTTP_SITE_ID = SERVER_CONFIG[NOW_SERVER_EREA]["site_id"];
|
||||
/** 当前版本号 */
|
||||
export const GAME_VER = SERVER_CONFIG[NOW_SERVER_EREA]["ver"];
|
||||
/** 国家电话区号 */
|
||||
export const COUNTRY_CODE = SERVER_CONFIG[NOW_SERVER_EREA]["area"];
|
||||
9
assets/res-native/setting/ServerConfig.ts.meta
Normal file
9
assets/res-native/setting/ServerConfig.ts.meta
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.24",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "29ef329c-fd90-4d8a-a91a-95ab0b17eace",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
9
assets/res-native/spine.meta
Normal file
9
assets/res-native/spine.meta
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "1.2.0",
|
||||
"importer": "directory",
|
||||
"imported": true,
|
||||
"uuid": "a2199cad-9ebc-415d-97ce-29c44b5628df",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
9
assets/res-native/tools.meta
Normal file
9
assets/res-native/tools.meta
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "1.2.0",
|
||||
"importer": "directory",
|
||||
"imported": true,
|
||||
"uuid": "c1e551ce-e4da-42b1-b6e7-60cf4cf1f45c",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
627
assets/res-native/tools/Tools.ts
Normal file
627
assets/res-native/tools/Tools.ts
Normal file
@@ -0,0 +1,627 @@
|
||||
import { _decorator, SpriteFrame, Node, Sprite, instantiate, Label, Prefab, Color, Size, UITransform, RichText, Component, Texture2D, ImageAsset } from 'cc';
|
||||
import { httpRequest } from '../network/HttpRequest';
|
||||
import { app } from '../../app/app';
|
||||
const { ccclass } = _decorator;
|
||||
|
||||
//@ts-ignore
|
||||
import CryptoJS from "crypto-js";
|
||||
|
||||
type ConstructorOf<T> = new (...args: any[]) => T;
|
||||
|
||||
// 定义数据接口
|
||||
interface DataObject {
|
||||
[key: string]: string | number | boolean;
|
||||
}
|
||||
|
||||
/** 事件名称 */
|
||||
export enum EventType {
|
||||
/** 刷新玩家数据 */
|
||||
RefreshUserInfo = "RefreshUserInfo",
|
||||
/** 刷新玩家数据成功 */
|
||||
RefreshUserInfoSuccess = "RefreshUserInfoSuccess",
|
||||
}
|
||||
|
||||
|
||||
// 定义阈值和对应的num值
|
||||
const sizeThresholds = [
|
||||
{ size: 20000000, num: 100 },
|
||||
{ size: 19000000, num: 95 },
|
||||
{ size: 18000000, num: 90 },
|
||||
{ size: 17000000, num: 85 },
|
||||
{ size: 16000000, num: 80 },
|
||||
{ size: 15000000, num: 75 },
|
||||
{ size: 14000000, num: 70 },
|
||||
{ size: 13000000, num: 65 },
|
||||
{ size: 12000000, num: 60 },
|
||||
{ size: 11000000, num: 55 },
|
||||
{ size: 10000000, num: 50 },
|
||||
{ size: 9000000, num: 45 },
|
||||
{ size: 8000000, num: 40 },
|
||||
{ size: 7000000, num: 35 },
|
||||
{ size: 6000000, num: 30 },
|
||||
{ size: 5000000, num: 25 },
|
||||
{ size: 4000000, num: 20 },
|
||||
{ size: 3000000, num: 15 },
|
||||
{ size: 2000000, num: 10 },
|
||||
{ size: 1000000, num: 5 },
|
||||
{ size: 500000, num: 2.5 },
|
||||
{ size: 250000, num: 1.5 }
|
||||
];
|
||||
|
||||
/** 用户代理等级和图片对照表 */
|
||||
const AGENT_LV_TO_PIC = {
|
||||
["等级青铜"] : "a",
|
||||
["等级白银"] : "b",
|
||||
["等级黄金"] : "c",
|
||||
["等级VIP"] : "d",
|
||||
["等级超级VIP"] : "e"
|
||||
}
|
||||
|
||||
/** 通用工具类 */
|
||||
@ccclass('Tools')
|
||||
export class Tools
|
||||
{
|
||||
//#region Sprite相关操作
|
||||
/** 设置节点的SpriteFrame, 默认从resource/ui下面找 */
|
||||
static SetSpriteFrame(node:Node, uiname:string, uipath:string, fuc:Function = null) {
|
||||
app.manager.loader.load({
|
||||
bundle: "", // 不传入bundle,默认为resources
|
||||
path: 'xxx/xxxx',
|
||||
type: SpriteFrame,
|
||||
onComplete(asset){
|
||||
if (node){
|
||||
let c = node.getComponent(Sprite)
|
||||
if (c) c.spriteFrame = asset
|
||||
if (fuc) fuc()
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/** 加载远程图片 */
|
||||
static remoteLoadSprite(url: string, node: Sprite, fuc?: Function) {
|
||||
app.manager.loader.loadRemote( {
|
||||
url: url,
|
||||
ext: null,
|
||||
onComplete: (result: ImageAsset | null) => {
|
||||
if (result) {
|
||||
if(node) {
|
||||
let sp = new SpriteFrame()
|
||||
let tex = new Texture2D();
|
||||
tex.image = result;
|
||||
sp.texture = tex
|
||||
node.spriteFrame = sp
|
||||
if (fuc) fuc()
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/** 设置子节点uisprite */
|
||||
static SetChildSprite(node:Node, path:string, uiname:string, uipath:string, fuc:Function = null) {
|
||||
let n = node.getChildByPath(path)
|
||||
if (n) this.SetSpriteFrame(n, uiname, uipath, fuc)
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置艺术字
|
||||
* itemPath:字体预制件位置, numPath:字体图片位置, pre:图片名前缀
|
||||
*/
|
||||
// static SetArtNums(str:any, item:Node, itemPath:string = "ui/numbers/num_Item", numPath:string = "ui/numbers", pre:string = "numbers_0") {
|
||||
// str = String(str)
|
||||
// item.destroyAllChildren()
|
||||
// let m_resLoader = new ResLoader();
|
||||
// m_resLoader.loadPrefabNode(itemPath, (prefab:Node) => {
|
||||
// console.log(itemPath, prefab)
|
||||
// // 根据字符串长度,显示对应数量的数字图片
|
||||
// for (let i = 0; i < str.length; i++) {
|
||||
// let n = Tools.AddChild(item, prefab, "num_" + i)
|
||||
// n.active = true
|
||||
// this.SetSpriteFrame(n, pre + (str[i] == "." ? "dot" : str[i]), numPath)
|
||||
// }
|
||||
// })
|
||||
// }
|
||||
//#endregion
|
||||
|
||||
|
||||
//#region http相关
|
||||
/** 发送http请求 */
|
||||
static httpReq(str:string, param:any, callback:Function, failCallBack:Function = null) {
|
||||
httpRequest.post("/agent/api/" + str, param, callback, failCallBack)
|
||||
}
|
||||
//#endregion
|
||||
|
||||
|
||||
//#region Node 相关
|
||||
/** 添加子节点 */
|
||||
static AddChild(node:Node, prefab:Node|Prefab, name:string = null):Node {
|
||||
var n = instantiate(prefab as Node)
|
||||
node.addChild(n)
|
||||
if (name) n.name = name
|
||||
return n
|
||||
}
|
||||
|
||||
/** 设置子节点显示 */
|
||||
static ActChild(node:Node, path:string, act:boolean)
|
||||
{
|
||||
let n = node.getChildByPath(path)
|
||||
if (n) n.active = act
|
||||
}
|
||||
|
||||
/** 获取子节点组件 */
|
||||
static GetChildComp<T extends Component>(node: Node, path: string, compClass: ConstructorOf<T>): T {
|
||||
return node.getChildByPath(path)?.getComponent(compClass);
|
||||
}
|
||||
|
||||
//#endregion
|
||||
|
||||
|
||||
//#region Text 相关
|
||||
/** 设置子节点文字 */
|
||||
static SetText(node:Node, str:string) {
|
||||
str = String(str)
|
||||
node.getComponent(Label).string = str
|
||||
}
|
||||
/** 设置子节点文字 */
|
||||
static SetChildText(node:Node, path:string, str:string) {
|
||||
str = String(str)
|
||||
let n = node.getChildByPath(path)
|
||||
n.getComponent(Label).string = str
|
||||
}
|
||||
/** 设置子节点文字 */
|
||||
static SetChildRichText(node:Node, path:string, str:string) {
|
||||
str = String(str)
|
||||
let n = node.getChildByPath(path)
|
||||
n.getComponent(RichText).string = str
|
||||
}
|
||||
/** 设置节点文字颜色 */
|
||||
static SetLabColor(node:Node, str:string) {
|
||||
node.getComponent(Label).color = Color.fromHEX(new Color(), str)
|
||||
}
|
||||
/** 设置子节点字体颜色 */
|
||||
static SetChildLabColor(node:Node, path:string, str:string) {
|
||||
let n = node.getChildByPath(path)
|
||||
n.getComponent(Label).color = Color.fromHEX(new Color(), str)
|
||||
}
|
||||
|
||||
/** 设置节点大小 */
|
||||
static SetSize(node:Node, size:Size) {
|
||||
node.getComponent(UITransform).setContentSize(size);
|
||||
}
|
||||
|
||||
/** 设置节点触摸事件 */
|
||||
static SetTouchEndEvt(node:Node, func:Function) {
|
||||
node.off(Node.EventType.TOUCH_END)
|
||||
node.on(Node.EventType.TOUCH_END, func)
|
||||
}
|
||||
|
||||
/** 设置子节点触摸事件 */
|
||||
static SetChildTouchEndEvt(node:Node, path:string, func:Function) {
|
||||
let n = node.getChildByPath(path)
|
||||
if (n) this.SetTouchEndEvt(n, func)
|
||||
}
|
||||
//#endregion
|
||||
|
||||
|
||||
//#region 字符串操作
|
||||
/**
|
||||
** 替换占位符{0},{1}....
|
||||
** 例子: const message = Tools.stringFormat("My name is {0} and I am {1} years old.", name, age);
|
||||
*/
|
||||
static StringFormat(format: string, ...args: any[]): string {
|
||||
return format.replace(/{(\d+)}/g, (match, index) => {
|
||||
return typeof args[index] !== "undefined" ? args[index] : match;
|
||||
});
|
||||
}
|
||||
|
||||
static StringLFormat(format: string, ...args: any[]): string {
|
||||
format = this.GetLocalized(format)
|
||||
return this.StringFormat(format, ...args)
|
||||
}
|
||||
//#endregion
|
||||
|
||||
|
||||
//#region 其他
|
||||
/** 本地化 */
|
||||
static GetLocalized(str : string) {
|
||||
return str
|
||||
//return LabelConfig[str] ? LabelConfig[str][LocalizadManager.getInstance().getLanauge()-1] : str
|
||||
}
|
||||
/** 压缩上传图片成base64 */
|
||||
static CompressImageToBase64(param:any, callback:Function = null){
|
||||
var fileList = param.files[0];
|
||||
var reader = new FileReader();
|
||||
reader.readAsDataURL(fileList);
|
||||
reader.onload = (event) => {
|
||||
let image = new Image() //新建一个img标签(还没嵌入DOM节点)
|
||||
var dataImg = event.target.result;
|
||||
var num = 1;
|
||||
//@ts-ignore
|
||||
image.src = event.target.result
|
||||
image.onload = () => {
|
||||
//由于不能将太多Base64字符给服务端发过于,咱们压缩一下
|
||||
//如果想支持更大图片,请继续加判断,增加除数
|
||||
// 检查文件大小是否超过20M
|
||||
if (fileList.size > 20000000) {
|
||||
console.log("文件大小不能大于20M!");
|
||||
param.value = '';
|
||||
return;
|
||||
}
|
||||
// 根据文件大小设置num值
|
||||
for (const threshold of sizeThresholds) {
|
||||
if (fileList.size > threshold.size) {
|
||||
num = threshold.num;
|
||||
break;
|
||||
}
|
||||
}
|
||||
let canvas = document.createElement('canvas');
|
||||
let context = canvas.getContext('2d');
|
||||
let imageWidth = image.width / num; //压缩后图片的大小
|
||||
let imageHeight = image.height / num;
|
||||
const minSize = 640; // 设置最小尺寸
|
||||
if (imageWidth < minSize || imageHeight < minSize) {
|
||||
const scaleFactor = Math.max(minSize / imageWidth, minSize / imageHeight);
|
||||
imageWidth *= scaleFactor;
|
||||
imageHeight *= scaleFactor;
|
||||
}
|
||||
canvas.width = imageWidth;
|
||||
canvas.height = imageHeight;
|
||||
context.drawImage(image, 0, 0, imageWidth, imageHeight);
|
||||
dataImg = canvas.toDataURL('image/png');
|
||||
//此时的dataImg就是你要上传给服务器的字符
|
||||
param.value = '';
|
||||
if (callback) callback(dataImg)
|
||||
return dataImg;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/** 生成二维码 */
|
||||
// static SetQRCode(text: string, item : Node){
|
||||
// const qr = QRCode(0, 'M');
|
||||
// qr.addData(text);
|
||||
// qr.make();
|
||||
// const dataUrl = qr.createDataURL(4, 4);
|
||||
// const img = new Image();
|
||||
// img.src = dataUrl;
|
||||
|
||||
// assetManager.loadRemote(dataUrl, {ext : '.png'}, (err, imgAsset: ImageAsset) => {
|
||||
// if (err) {
|
||||
// console.error(err.message || err);
|
||||
// return;
|
||||
// }
|
||||
// const sp = new SpriteFrame()
|
||||
// const tx = new Texture2D()
|
||||
// tx.image = imgAsset
|
||||
// sp.texture = tx
|
||||
// item.getComponent(Sprite).spriteFrame = sp
|
||||
// })
|
||||
// }
|
||||
|
||||
/** 通过base64字符串设置图片 */
|
||||
static SetBase64Pic(src: string, node: Node): void {
|
||||
let image = new Image()
|
||||
image.src = src // base 64是string,看后端返回是二进制,是否带头data:image/png;base64, 不带要手动添加
|
||||
image.onload = () => {
|
||||
let texture = new Texture2D()
|
||||
texture.image = new ImageAsset(image)
|
||||
let _frame = new SpriteFrame()
|
||||
_frame.texture = texture
|
||||
// 获取节点的容器
|
||||
let c = node.getComponent(Sprite)
|
||||
if (c) c.spriteFrame = _frame
|
||||
}
|
||||
}
|
||||
|
||||
/** 复制到剪切板 */
|
||||
static CopyToClipboard(str:string) {
|
||||
var input = str + '';
|
||||
const el = document.createElement('textarea');
|
||||
el.value = input;
|
||||
el.setAttribute('readonly', '');
|
||||
el.style.contain = 'strict';
|
||||
el.style.position = 'absolute';
|
||||
el.style.left = '-9999px';
|
||||
el.style.fontSize = '12pt'; // Prevent zooming on iOS
|
||||
|
||||
const selection = getSelection();
|
||||
var originalRange = null;
|
||||
if (selection.rangeCount > 0) {
|
||||
originalRange = selection.getRangeAt(0);
|
||||
}
|
||||
document.body.appendChild(el);
|
||||
el.select();
|
||||
el.selectionStart = 0;
|
||||
el.selectionEnd = input.length;
|
||||
|
||||
var success = false;
|
||||
try {
|
||||
success = document.execCommand('copy');
|
||||
} catch (err) {}
|
||||
|
||||
document.body.removeChild(el);
|
||||
|
||||
if (originalRange) {
|
||||
selection.removeAllRanges();
|
||||
selection.addRange(originalRange);
|
||||
}
|
||||
app.manager.ui.showToast("复制成功")
|
||||
return success;
|
||||
}
|
||||
|
||||
/** 获取代理等级本地化 */
|
||||
static GetAgentLvLocalized(agentLv:string, lv :number) {
|
||||
return this.StringFormat(this.GetLocalized(agentLv), lv)
|
||||
}
|
||||
|
||||
/** 设置代理等级图标 */
|
||||
// static SetAgentLvIcon(item:Node, agentLv:string, lv :number) {
|
||||
// if (!AGENT_LV_TO_PIC[agentLv]) return
|
||||
// var icon = "icon" + AGENT_LV_TO_PIC[agentLv] + this.Return2LengthNumber(lv)
|
||||
// this.SetSpriteFrame(item, icon, "Lobby/ui/allagent/icon")
|
||||
// }
|
||||
|
||||
/** 设置子节点代理等级图标 */
|
||||
// static SetChildAgentLvIcon(item:Node, path :string, agentLv:string, lv :number) {
|
||||
// let n = item.getChildByPath(path)
|
||||
// this.SetAgentLvIcon(n, agentLv, lv)
|
||||
// }
|
||||
|
||||
/** 返回两位数 */
|
||||
static Return2LengthNumber(n : number) {
|
||||
return n < 10 ? "0" + n : n.toString()
|
||||
}
|
||||
|
||||
//#endregion
|
||||
|
||||
|
||||
//#region 数学算法
|
||||
static MathClampZeroToOne(value: number): number {
|
||||
return Math.max(0, Math.min(1, value));
|
||||
}
|
||||
|
||||
static MathClamp(value: number, min: number, max: number): number {
|
||||
return Math.max(min, Math.min(max, value));
|
||||
}
|
||||
//#endregion
|
||||
|
||||
|
||||
static OpenWeb(url:string) {
|
||||
const link = document.createElement('a');
|
||||
link.href = url;
|
||||
link.target = '_blank';
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
document.body.removeChild(link);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取指定长度随机字符串
|
||||
*/
|
||||
public static getRandomStr (len:number) {
|
||||
let chars =
|
||||
'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz'
|
||||
let maxPos = chars.length
|
||||
let pwd = ''
|
||||
for (let i = 0; i < len; i++) {
|
||||
pwd += chars.charAt(Math.floor(Math.random() * maxPos))
|
||||
}
|
||||
return pwd
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用 crypto-js 生成签名
|
||||
* @param data - 要签名的数据
|
||||
* @param key - 签名密钥
|
||||
* @param encrypt - 加密算法 (sha1, sha256)
|
||||
* @returns Promise<string> 签名结果
|
||||
*/
|
||||
public static generateSignNative(
|
||||
data: Record<string, string>,
|
||||
key: string,
|
||||
encrypt: string = 'sha256'
|
||||
): Promise<string> {
|
||||
// 1. 对数据进行排序
|
||||
const sortedData = Tools.sortData(data);
|
||||
|
||||
// 2. 构建查询字符串(自定义实现)
|
||||
const queryString = Object.keys(sortedData)
|
||||
.map(k => encodeURIComponent(k) + "=" + encodeURIComponent(sortedData[k]))
|
||||
.join("&");
|
||||
|
||||
// 3. URL解码并拼接密钥
|
||||
const decodedString = decodeURIComponent(queryString);
|
||||
const str = decodedString + key;
|
||||
|
||||
// 4. 根据算法生成签名
|
||||
let hash;
|
||||
switch (encrypt.toLowerCase()) {
|
||||
case 'sha1':
|
||||
hash = CryptoJS.SHA1(str);
|
||||
break;
|
||||
case 'sha256':
|
||||
default:
|
||||
hash = CryptoJS.SHA256(str);
|
||||
break;
|
||||
}
|
||||
|
||||
// 5. 返回十六进制字符串
|
||||
return Promise.resolve(hash.toString(CryptoJS.enc.Hex));
|
||||
}
|
||||
|
||||
// 示例排序函数(你已有的话可以直接用)
|
||||
public static sortData(data: Record<string, string>): Record<string, string> {
|
||||
return Object.keys(data)
|
||||
.sort()
|
||||
.reduce((acc, key) => {
|
||||
acc[key] = data[key];
|
||||
return acc;
|
||||
}, {} as Record<string, string>);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//#region 加密解密
|
||||
/** 解析JWT令牌 */
|
||||
public static parseJWT(token: string) {
|
||||
try {
|
||||
const parts = token.split('.');
|
||||
if (parts.length !== 3) {
|
||||
throw new Error('Invalid JWT token');
|
||||
}
|
||||
|
||||
// 解码 payload 部分(第二部分)
|
||||
const payload = JSON.parse(atob(parts[1]));
|
||||
return payload;
|
||||
} catch (error) {
|
||||
console.error('Failed to parse JWT token:', error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 解密 DES-ECB 模式加密的数据
|
||||
* @param encryptedData base64编码的加密数据
|
||||
* @param secretKey 8位密钥
|
||||
* @returns 解密后的字符串
|
||||
*/
|
||||
static desEcbDecrypt(encryptedData: string, secretKey: string): string {
|
||||
try {
|
||||
// 确保密钥为8位 (PHP的openssl_encrypt会自动截取前8位)
|
||||
const key = secretKey.length > 8 ? secretKey.substring(0, 8) : this.padKey(secretKey, 8);
|
||||
|
||||
// 创建CryptoJS格式的密钥
|
||||
const keyWordArray = CryptoJS.enc.Utf8.parse(key);
|
||||
|
||||
// 解密
|
||||
const decrypted = CryptoJS.DES.decrypt(
|
||||
encryptedData,
|
||||
keyWordArray,
|
||||
{
|
||||
mode: CryptoJS.mode.ECB,
|
||||
padding: CryptoJS.pad.Pkcs7
|
||||
}
|
||||
);
|
||||
|
||||
return decrypted.toString(CryptoJS.enc.Utf8);
|
||||
} catch (error) {
|
||||
console.error('DES-ECB decryption failed:', error);
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 加密 DES-ECB 模式数据
|
||||
* @param data 待加密的数据
|
||||
* @param secretKey 8位密钥
|
||||
* @returns base64编码的加密数据
|
||||
*/
|
||||
static desEcbEncrypt(data: string, secretKey: string): string {
|
||||
try {
|
||||
// 确保密钥为8位
|
||||
const key = secretKey.length > 8 ? secretKey.substring(0, 8) : this.padKey(secretKey, 8);
|
||||
|
||||
// 创建CryptoJS格式的密钥
|
||||
const keyWordArray = CryptoJS.enc.Utf8.parse(key);
|
||||
|
||||
// 加密
|
||||
const encrypted = CryptoJS.DES.encrypt(
|
||||
data,
|
||||
keyWordArray,
|
||||
{
|
||||
mode: CryptoJS.mode.ECB,
|
||||
padding: CryptoJS.pad.Pkcs7
|
||||
}
|
||||
);
|
||||
|
||||
return encrypted.toString();
|
||||
} catch (error) {
|
||||
console.error('DES-ECB encryption failed:', error);
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 补齐或截断密钥到指定长度
|
||||
* @param key 原始密钥
|
||||
* @param length 目标长度
|
||||
*/
|
||||
private static padKey(key: string, length: number): string {
|
||||
if (key.length > length) {
|
||||
return key.substring(0, length);
|
||||
} else if (key.length < length) {
|
||||
while (key.length < length) {
|
||||
key += '\0'; // 用null字符补齐
|
||||
}
|
||||
return key;
|
||||
}
|
||||
return key;
|
||||
}
|
||||
|
||||
/**
|
||||
* 3DES-ECB 解密 (Triple DES)
|
||||
* @param encryptedData base64编码的加密数据
|
||||
* @param secretKey 24位密钥 (3DES需要24字节密钥)
|
||||
* @returns 解密后的字符串
|
||||
*/
|
||||
static tripleDesEcbDecrypt(encryptedData: string, secretKey: string): string {
|
||||
try {
|
||||
// 确保密钥为24位
|
||||
const key = this.padKey(secretKey, 24);
|
||||
|
||||
// 创建CryptoJS格式的密钥
|
||||
const keyWordArray = CryptoJS.enc.Utf8.parse(key);
|
||||
|
||||
// 解密
|
||||
const decrypted = CryptoJS.TripleDES.decrypt(
|
||||
encryptedData,
|
||||
keyWordArray,
|
||||
{
|
||||
mode: CryptoJS.mode.ECB,
|
||||
padding: CryptoJS.pad.Pkcs7
|
||||
}
|
||||
);
|
||||
|
||||
return decrypted.toString(CryptoJS.enc.Utf8);
|
||||
} catch (error) {
|
||||
console.error('3DES-ECB decryption failed:', error);
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 3DES-ECB 加密 (Triple DES)
|
||||
* @param data 待加密的数据
|
||||
* @param secretKey 24位密钥
|
||||
* @returns base64编码的加密数据
|
||||
*/
|
||||
static tripleDesEcbEncrypt(data: string, secretKey: string): string {
|
||||
try {
|
||||
// 确保密钥为24位
|
||||
const key = this.padKey(secretKey, 24);
|
||||
|
||||
// 创建CryptoJS格式的密钥
|
||||
const keyWordArray = CryptoJS.enc.Utf8.parse(key);
|
||||
|
||||
// 加密
|
||||
const encrypted = CryptoJS.TripleDES.encrypt(
|
||||
data,
|
||||
keyWordArray,
|
||||
{
|
||||
mode: CryptoJS.mode.ECB,
|
||||
padding: CryptoJS.pad.Pkcs7
|
||||
}
|
||||
);
|
||||
|
||||
return encrypted.toString();
|
||||
} catch (error) {
|
||||
console.error('3DES-ECB encryption failed:', error);
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
//#endregion
|
||||
}
|
||||
9
assets/res-native/tools/Tools.ts.meta
Normal file
9
assets/res-native/tools/Tools.ts.meta
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.24",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "20f5e370-8629-444b-85bb-ebe2ee037cff",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
Reference in New Issue
Block a user