支付页面
qrcode生成,剪贴板sdk
@@ -314,6 +314,17 @@ export class SDKManager { //extends Component
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//region 复制到剪贴板
|
||||||
|
/**复制文本到剪贴板 */
|
||||||
|
static copyToClipboard(text: string, cb?: Function) {
|
||||||
|
if (this.sdk.copyToClipboard) {
|
||||||
|
this.sdk.copyToClipboard(text, cb);
|
||||||
|
} else {
|
||||||
|
Utils.Log("当前平台不支持复制功能");
|
||||||
|
cb && cb(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//region 友盟+
|
//region 友盟+
|
||||||
static Uma_Event_TalkRound = "_um.talk.round"; //聊天轮次
|
static Uma_Event_TalkRound = "_um.talk.round"; //聊天轮次
|
||||||
static Uma_Event_LvUnlock = "_um.lv.unlock"; //解锁新关卡
|
static Uma_Event_LvUnlock = "_um.lv.unlock"; //解锁新关卡
|
||||||
|
|||||||
@@ -570,6 +570,23 @@ export class ByteDanceSDK{
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//region 复制到剪贴板
|
||||||
|
/**复制文本到剪贴板 */
|
||||||
|
copyToClipboard(text: string, cb?: Function) {
|
||||||
|
console.log("抖音 复制到剪贴板:", text);
|
||||||
|
window['tt'].setClipboardData({
|
||||||
|
data: text,
|
||||||
|
success: () => {
|
||||||
|
console.log("抖音 复制成功");
|
||||||
|
cb && cb(true);
|
||||||
|
},
|
||||||
|
fail: (err) => {
|
||||||
|
console.log("抖音 复制失败:", err);
|
||||||
|
cb && cb(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
//region 友盟+
|
//region 友盟+
|
||||||
umaInit() {
|
umaInit() {
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -761,6 +761,22 @@ export class KSSDK{
|
|||||||
this.replayBgAudioPause()
|
this.replayBgAudioPause()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//region 复制到剪贴板
|
||||||
|
/**复制文本到剪贴板 */
|
||||||
|
copyToClipboard(text: string, cb?: Function) {
|
||||||
|
console.log("快手 复制到剪贴板:", text);
|
||||||
|
window['ks'].setClipboardData({
|
||||||
|
data: text,
|
||||||
|
success: () => {
|
||||||
|
console.log("快手 复制成功");
|
||||||
|
cb && cb(true);
|
||||||
|
},
|
||||||
|
fail: (err) => {
|
||||||
|
console.log("快手 复制失败:", err);
|
||||||
|
cb && cb(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
//region 友盟+
|
//region 友盟+
|
||||||
umaInit() {
|
umaInit() {
|
||||||
|
|||||||
@@ -7,290 +7,380 @@ import Utils from "../Common/Utils";
|
|||||||
import { InnerMsgCode } from "../Config/InnerMsgCode";
|
import { InnerMsgCode } from "../Config/InnerMsgCode";
|
||||||
import { VideoRoleType } from "../Common/GlobalValue";
|
import { VideoRoleType } from "../Common/GlobalValue";
|
||||||
|
|
||||||
export class WebSDK{
|
export class WebSDK {
|
||||||
|
//初始化
|
||||||
|
init(cb: Function = null) {
|
||||||
|
console.log("init webSDK");
|
||||||
|
cb && cb();
|
||||||
|
}
|
||||||
|
|
||||||
//初始化
|
//检查权限
|
||||||
init(cb: Function = null) {
|
checkAutoSetting(autoKey: string, cb: Function = null) {
|
||||||
console.log("init webSDK");
|
cb && cb(true);
|
||||||
cb && cb();
|
}
|
||||||
}
|
|
||||||
|
|
||||||
//检查权限
|
//获取用户信息
|
||||||
checkAutoSetting(autoKey:string, cb:Function = null) {
|
getUserInfo(cb: Function = null) {
|
||||||
cb && cb(true);
|
let name = HttpUnit.GetNickName();
|
||||||
}
|
cb &&
|
||||||
|
cb({
|
||||||
|
nickName: name,
|
||||||
|
avatarUrl: "https://hxzgame.vip.hnhxzkj.com/lzx/XiangQin/webHead.png",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
//获取用户信息
|
//region 登录
|
||||||
getUserInfo(cb:Function = null) {
|
login(cb: Function = null) {
|
||||||
let name = HttpUnit.GetNickName();
|
cb && cb({ platform: 2, code: null });
|
||||||
cb && cb({ nickName:name, avatarUrl:"https://hxzgame.vip.hnhxzkj.com/lzx/XiangQin/webHead.png" });
|
}
|
||||||
|
|
||||||
|
//显示视频广告
|
||||||
|
show_video(callback: Function, tag: number) {
|
||||||
|
callback && callback({ code: 0, tag: tag });
|
||||||
|
SDKManager.video_ad_back();
|
||||||
|
}
|
||||||
|
|
||||||
|
//显示插屏
|
||||||
|
show_splash() {}
|
||||||
|
|
||||||
|
//显示Banner
|
||||||
|
show_banner(...args) {}
|
||||||
|
|
||||||
|
//隐藏Banner
|
||||||
|
hide_banner(...args) {}
|
||||||
|
|
||||||
|
//主动拉起分享
|
||||||
|
show_share(rewardCB?: Function) {
|
||||||
|
rewardCB && rewardCB();
|
||||||
|
}
|
||||||
|
|
||||||
|
//获取设备分辨率
|
||||||
|
getWindowSize() {
|
||||||
|
return { width: screen.width, height: screen.height };
|
||||||
|
}
|
||||||
|
|
||||||
|
//显示游戏圈
|
||||||
|
show_gameClub(leftRatio, topRatio, widthRatio, heightRatio) {}
|
||||||
|
//隐藏游戏圈
|
||||||
|
hide_gameClub() {}
|
||||||
|
|
||||||
|
//检查是否支持base64音频播放
|
||||||
|
checkSupportBase64Audio() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
//播放base64音频
|
||||||
|
private _audioInst: HTMLAudioElement = null;
|
||||||
|
playBase64Audio(base64: string, loop: boolean) {
|
||||||
|
let substring = base64;
|
||||||
|
let qianzhui = "data:audio/x-wav;base64,";
|
||||||
|
if (base64.startsWith(qianzhui)) {
|
||||||
|
substring = base64.substring(qianzhui.length, base64.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
//region 登录
|
// 解码 Base64 字符串为二进制数据
|
||||||
login(cb: Function = null) {
|
const binaryData = atob(substring);
|
||||||
cb && cb({ platform:2, code: null });
|
|
||||||
|
// 创建一个包含二进制数据的 Uint8Array
|
||||||
|
const byteArray = new Uint8Array(binaryData.length);
|
||||||
|
for (let i = 0; i < binaryData.length; i++) {
|
||||||
|
byteArray[i] = binaryData.charCodeAt(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
//显示视频广告
|
// 创建 Blob 对象,指定 MIME 类型为音频格式(例如 mp3)
|
||||||
show_video(callback:Function, tag:number) {
|
const audioBlob = new Blob([byteArray], { type: "audio/mp3" });
|
||||||
callback && callback({ code: 0, tag: tag });
|
|
||||||
SDKManager.video_ad_back();
|
// 创建音频 URL
|
||||||
|
const audioUrl = URL.createObjectURL(audioBlob);
|
||||||
|
|
||||||
|
console.log("web 播放base64音频", audioUrl);
|
||||||
|
// 创建音频元素并播放
|
||||||
|
if (this._audioInst == null) {
|
||||||
|
this._audioInst = new Audio(audioUrl);
|
||||||
|
} else {
|
||||||
|
this._audioInst.src = audioUrl;
|
||||||
|
}
|
||||||
|
this._audioInst.play();
|
||||||
|
}
|
||||||
|
|
||||||
|
//客服功能是否支持
|
||||||
|
kefuSupport() {
|
||||||
|
console.log("web 不支持联系客服");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
//进入联系客服
|
||||||
|
openKefu() {
|
||||||
|
console.log("web 进入联系客服");
|
||||||
|
}
|
||||||
|
|
||||||
|
//region 播放主背景视频
|
||||||
|
private zhuVideo1: BgVideo | null = null;
|
||||||
|
private zhuExtra1: any = null;
|
||||||
|
playBgAudio(
|
||||||
|
remoteUrl: string,
|
||||||
|
vtype: VideoRoleType,
|
||||||
|
loop: boolean = false,
|
||||||
|
extra: any = {}
|
||||||
|
) {
|
||||||
|
let bgvideo = SceneBgVideoLayer.handle;
|
||||||
|
if (!bgvideo) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//显示插屏
|
this.initBgAudio();
|
||||||
show_splash() {
|
if (this.zhuVideo1 && this.zhuVideo1.isPlaying) {
|
||||||
|
this.playBgAudioNext(remoteUrl, vtype, loop, extra);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//显示Banner
|
if (!this.zhuVideo1) {
|
||||||
show_banner(...args) {
|
this.zhuVideo1 = bgvideo.getVideoClone();
|
||||||
|
}
|
||||||
|
this.zhuExtra1 = extra;
|
||||||
|
this.zhuVideo1.vtype = vtype;
|
||||||
|
this.zhuVideo1.cbReady = this.audioReady.bind(this);
|
||||||
|
this.zhuVideo1.cbEnd = this.audioEnded.bind(this);
|
||||||
|
this.zhuVideo1.playVideo(remoteUrl, loop, false);
|
||||||
|
}
|
||||||
|
initBgAudio() {
|
||||||
|
let bgvideo = SceneBgVideoLayer.handle;
|
||||||
|
if (!bgvideo) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//隐藏Banner
|
console.log("web 初始化主背景视频");
|
||||||
hide_banner(...args) {
|
if (!this.zhuVideo1) {
|
||||||
|
this.zhuVideo1 = bgvideo.getVideoClone();
|
||||||
|
this.zhuVideo1.remoteUrl =
|
||||||
|
"http://hxzgame.vip.hnhxzkj.com/lzx/XiangQin/bginited.mp4";
|
||||||
|
}
|
||||||
|
if (!this.zhuVideo2) {
|
||||||
|
this.zhuVideo2 = bgvideo.getVideoClone();
|
||||||
|
this.zhuVideo2.remoteUrl =
|
||||||
|
"http://hxzgame.vip.hnhxzkj.com/lzx/XiangQin/bginited.mp4";
|
||||||
|
}
|
||||||
|
if (!this.emoVideo1) {
|
||||||
|
this.emoVideo1 = bgvideo.getVideoClone();
|
||||||
|
this.emoVideo1.remoteUrl =
|
||||||
|
"http://hxzgame.vip.hnhxzkj.com/lzx/XiangQin/bginited.mp4";
|
||||||
|
}
|
||||||
|
if (!this.emoVideo2) {
|
||||||
|
this.emoVideo2 = bgvideo.getVideoClone();
|
||||||
|
this.emoVideo2.remoteUrl =
|
||||||
|
"http://hxzgame.vip.hnhxzkj.com/lzx/XiangQin/bginited.mp4";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
audioReady() {
|
||||||
|
this.removeBgAudioNext();
|
||||||
|
this.zhuVideo1.moveIn();
|
||||||
|
Utils.sendInnerMsg(InnerMsgCode.BgVideo_Ready, {
|
||||||
|
compo: this.zhuVideo1,
|
||||||
|
extra: this.zhuExtra1,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
audioEnded() {
|
||||||
|
Utils.sendInnerMsg(InnerMsgCode.BgVideo_End, {
|
||||||
|
compo: this.zhuVideo1,
|
||||||
|
extra: this.zhuExtra1,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
removeBgAudio() {
|
||||||
|
if (this.zhuVideo1 && this.zhuVideo1.isPlaying) {
|
||||||
|
this.zhuVideo1.recycleVideo();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//主背景临时视频
|
||||||
|
private zhuVideo2: BgVideo | null = null;
|
||||||
|
private zhuExtra2: any = null;
|
||||||
|
playBgAudioNext(
|
||||||
|
remoteUrl: string,
|
||||||
|
vtype: VideoRoleType,
|
||||||
|
loop: boolean = false,
|
||||||
|
extra: any = {}
|
||||||
|
) {
|
||||||
|
let bgvideo = SceneBgVideoLayer.handle;
|
||||||
|
if (!bgvideo) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.removeBgAudioNext();
|
||||||
|
if (!this.zhuVideo2) {
|
||||||
|
this.zhuVideo2 = bgvideo.getVideoClone();
|
||||||
|
}
|
||||||
|
this.zhuExtra2 = extra;
|
||||||
|
this.zhuVideo2.vtype = vtype;
|
||||||
|
this.zhuVideo2.cbReady = this.audioNextReady.bind(this);
|
||||||
|
this.zhuVideo2.cbEnd = this.audioNextEnded.bind(this);
|
||||||
|
this.zhuVideo2.playVideo(remoteUrl, loop, false);
|
||||||
|
}
|
||||||
|
audioNextReady() {
|
||||||
|
this.removeBgAudio();
|
||||||
|
this.zhuVideo2.moveIn();
|
||||||
|
Utils.sendInnerMsg(InnerMsgCode.BgVideo_Ready, {
|
||||||
|
compo: this.zhuVideo2,
|
||||||
|
extra: this.zhuExtra2,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
audioNextEnded() {
|
||||||
|
Utils.sendInnerMsg(InnerMsgCode.BgVideo_End, {
|
||||||
|
compo: this.zhuVideo2,
|
||||||
|
extra: this.zhuExtra2,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
removeBgAudioNext() {
|
||||||
|
if (this.zhuVideo2 && this.zhuVideo2.isPlaying) {
|
||||||
|
this.zhuVideo2.recycleVideo();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//region 播放emo视频
|
||||||
|
private emoVideo1: BgVideo | null = null;
|
||||||
|
private emoExtra1: any = {};
|
||||||
|
addEmoAudio(
|
||||||
|
remoteUrl: string,
|
||||||
|
vtype: VideoRoleType,
|
||||||
|
loop: boolean = false,
|
||||||
|
extra: any = {}
|
||||||
|
) {
|
||||||
|
let bgvideo = SceneBgVideoLayer.handle;
|
||||||
|
if (!bgvideo) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//主动拉起分享
|
if (this.emoVideo1 && this.emoVideo1.isPlaying) {
|
||||||
show_share(rewardCB?:Function) {
|
this.playEmoAudioNext(remoteUrl, vtype, loop, extra);
|
||||||
rewardCB && rewardCB();
|
return;
|
||||||
|
// this.emoVideo1.recycleVideo();
|
||||||
}
|
}
|
||||||
|
|
||||||
//获取设备分辨率
|
if (!this.emoVideo1 || !isValid(this.emoVideo1.node)) {
|
||||||
getWindowSize() {
|
this.emoVideo1 = bgvideo.getVideoClone();
|
||||||
return {width:screen.width, height: screen.height};
|
|
||||||
}
|
|
||||||
|
|
||||||
//显示游戏圈
|
|
||||||
show_gameClub(leftRatio, topRatio, widthRatio, heightRatio) {
|
|
||||||
|
|
||||||
}
|
|
||||||
//隐藏游戏圈
|
|
||||||
hide_gameClub() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
//检查是否支持base64音频播放
|
|
||||||
checkSupportBase64Audio() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
//播放base64音频
|
|
||||||
private _audioInst:HTMLAudioElement = null;
|
|
||||||
playBase64Audio(base64:string, loop:boolean) {
|
|
||||||
let substring = base64;
|
|
||||||
let qianzhui = "data:audio/x-wav;base64,"
|
|
||||||
if(base64.startsWith(qianzhui)) {
|
|
||||||
substring = base64.substring(qianzhui.length, base64.length)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 解码 Base64 字符串为二进制数据
|
|
||||||
const binaryData = atob(substring);
|
|
||||||
|
|
||||||
// 创建一个包含二进制数据的 Uint8Array
|
|
||||||
const byteArray = new Uint8Array(binaryData.length);
|
|
||||||
for (let i = 0; i < binaryData.length; i++) {
|
|
||||||
byteArray[i] = binaryData.charCodeAt(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 创建 Blob 对象,指定 MIME 类型为音频格式(例如 mp3)
|
|
||||||
const audioBlob = new Blob([byteArray], { type: 'audio/mp3' });
|
|
||||||
|
|
||||||
// 创建音频 URL
|
|
||||||
const audioUrl = URL.createObjectURL(audioBlob);
|
|
||||||
|
|
||||||
console.log("web 播放base64音频", audioUrl)
|
|
||||||
// 创建音频元素并播放
|
|
||||||
if (this._audioInst == null) {
|
|
||||||
this._audioInst = new Audio(audioUrl);
|
|
||||||
} else {
|
|
||||||
this._audioInst.src = audioUrl;
|
|
||||||
}
|
|
||||||
this._audioInst.play();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
//客服功能是否支持
|
|
||||||
kefuSupport() {
|
|
||||||
console.log("web 不支持联系客服")
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
//进入联系客服
|
this.emoExtra1 = extra;
|
||||||
openKefu() {
|
this.emoVideo1.vtype = vtype;
|
||||||
console.log("web 进入联系客服")
|
this.emoVideo1.cbReady = this.emoReady.bind(this);
|
||||||
|
this.emoVideo1.cbEnd = this.emoEnded.bind(this);
|
||||||
|
this.emoVideo1.playVideo(remoteUrl, loop, false);
|
||||||
|
}
|
||||||
|
emoReady() {
|
||||||
|
this.removeEmoNextAudio();
|
||||||
|
Utils.sendInnerMsg(InnerMsgCode.BgVideo_Ready, {
|
||||||
|
compo: this.emoVideo1,
|
||||||
|
extra: this.emoExtra1,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
emoEnded() {
|
||||||
|
Utils.sendInnerMsg(InnerMsgCode.BgVideo_End, {
|
||||||
|
compo: this.emoVideo1,
|
||||||
|
extra: this.emoExtra1,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
removeEmoAudio() {
|
||||||
|
if (this.emoVideo1 && this.emoVideo1.isPlaying) {
|
||||||
|
this.emoVideo1.recycleVideo();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 播放emo临时视频
|
||||||
|
private emoVideo2: BgVideo | null = null;
|
||||||
|
private emoExtra2: any = {};
|
||||||
|
playEmoAudioNext(
|
||||||
|
remoteUrl: string,
|
||||||
|
vtype: VideoRoleType,
|
||||||
|
loop: boolean = false,
|
||||||
|
extra: any = {}
|
||||||
|
) {
|
||||||
|
let bgvideo = SceneBgVideoLayer.handle;
|
||||||
|
if (!bgvideo) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.removeEmoNextAudio();
|
||||||
|
if (!this.emoVideo2) {
|
||||||
|
this.emoVideo2 = bgvideo.getVideoClone();
|
||||||
|
}
|
||||||
|
this.emoExtra2 = extra;
|
||||||
|
this.emoVideo2.vtype = vtype;
|
||||||
|
this.emoVideo2.cbReady = this.emoNextReady.bind(this);
|
||||||
|
this.emoVideo2.cbEnd = this.emoNextEnded.bind(this);
|
||||||
|
this.emoVideo2.playVideo(remoteUrl, loop, false);
|
||||||
|
}
|
||||||
|
emoNextReady() {
|
||||||
|
this.removeEmoAudio();
|
||||||
|
Utils.sendInnerMsg(InnerMsgCode.BgVideo_Ready, {
|
||||||
|
compo: this.emoVideo2,
|
||||||
|
extra: this.emoExtra2,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
emoNextEnded() {
|
||||||
|
Utils.sendInnerMsg(InnerMsgCode.BgVideo_End, {
|
||||||
|
compo: this.emoVideo2,
|
||||||
|
extra: this.emoExtra2,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
removeEmoNextAudio() {
|
||||||
|
if (this.emoVideo2 && this.emoVideo2.isPlaying) {
|
||||||
|
this.emoVideo2.recycleVideo();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//region 复制到剪贴板
|
||||||
|
/**复制文本到剪贴板 */
|
||||||
|
copyToClipboard(text: string, cb?: Function) {
|
||||||
|
console.log("web 复制到剪贴板:", text);
|
||||||
|
|
||||||
|
if (navigator.clipboard && window.isSecureContext) {
|
||||||
|
// 使用现代的 Clipboard API
|
||||||
|
navigator.clipboard
|
||||||
|
.writeText(text)
|
||||||
|
.then(() => {
|
||||||
|
console.log("web 复制成功 (Clipboard API)");
|
||||||
|
cb && cb(true);
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.log("web 复制失败 (Clipboard API):", err);
|
||||||
|
this.fallbackCopyToClipboard(text, cb);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// 使用兼容性方案
|
||||||
|
this.fallbackCopyToClipboard(text, cb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**兼容性复制方案 */
|
||||||
|
private fallbackCopyToClipboard(text: string, cb?: Function) {
|
||||||
|
const textArea = document.createElement("textarea");
|
||||||
|
textArea.value = text;
|
||||||
|
|
||||||
|
// 避免滚动到底部
|
||||||
|
textArea.style.top = "0";
|
||||||
|
textArea.style.left = "0";
|
||||||
|
textArea.style.position = "fixed";
|
||||||
|
textArea.style.opacity = "0";
|
||||||
|
|
||||||
|
document.body.appendChild(textArea);
|
||||||
|
textArea.focus();
|
||||||
|
textArea.select();
|
||||||
|
|
||||||
|
try {
|
||||||
|
const successful = document.execCommand("copy");
|
||||||
|
if (successful) {
|
||||||
|
console.log("web 复制成功 (fallback)");
|
||||||
|
cb && cb(true);
|
||||||
|
} else {
|
||||||
|
console.log("web 复制失败 (fallback)");
|
||||||
|
cb && cb(false);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.log("web 复制异常 (fallback):", err);
|
||||||
|
cb && cb(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
document.body.removeChild(textArea);
|
||||||
|
}
|
||||||
|
|
||||||
//region 播放主背景视频
|
//region 友盟+
|
||||||
private zhuVideo1: BgVideo | null = null;
|
umaInit() {}
|
||||||
private zhuExtra1: any = null;
|
//友盟统计是否开启
|
||||||
playBgAudio(remoteUrl:string, vtype:VideoRoleType, loop:boolean = false, extra:any = {}) {
|
umaSwt() {
|
||||||
let bgvideo = SceneBgVideoLayer.handle
|
return false;
|
||||||
if (!bgvideo) {
|
}
|
||||||
return
|
//友盟事件统计
|
||||||
}
|
umaEvent(eventName: string, value: any = {}) {}
|
||||||
|
|
||||||
this.initBgAudio()
|
|
||||||
if (this.zhuVideo1 && this.zhuVideo1.isPlaying) {
|
|
||||||
this.playBgAudioNext(remoteUrl, vtype, loop, extra);
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this.zhuVideo1) {
|
|
||||||
this.zhuVideo1 = bgvideo.getVideoClone();
|
|
||||||
}
|
|
||||||
this.zhuExtra1 = extra;
|
|
||||||
this.zhuVideo1.vtype = vtype;
|
|
||||||
this.zhuVideo1.cbReady = this.audioReady.bind(this);
|
|
||||||
this.zhuVideo1.cbEnd = this.audioEnded.bind(this);
|
|
||||||
this.zhuVideo1.playVideo(remoteUrl, loop, false);
|
|
||||||
}
|
|
||||||
initBgAudio() {
|
|
||||||
let bgvideo = SceneBgVideoLayer.handle
|
|
||||||
if (!bgvideo) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log("web 初始化主背景视频")
|
|
||||||
if (!this.zhuVideo1) {
|
|
||||||
this.zhuVideo1 = bgvideo.getVideoClone();
|
|
||||||
this.zhuVideo1.remoteUrl = "http://hxzgame.vip.hnhxzkj.com/lzx/XiangQin/bginited.mp4"
|
|
||||||
}
|
|
||||||
if (!this.zhuVideo2) {
|
|
||||||
this.zhuVideo2 = bgvideo.getVideoClone();
|
|
||||||
this.zhuVideo2.remoteUrl = "http://hxzgame.vip.hnhxzkj.com/lzx/XiangQin/bginited.mp4"
|
|
||||||
}
|
|
||||||
if (!this.emoVideo1) {
|
|
||||||
this.emoVideo1 = bgvideo.getVideoClone();
|
|
||||||
this.emoVideo1.remoteUrl = "http://hxzgame.vip.hnhxzkj.com/lzx/XiangQin/bginited.mp4"
|
|
||||||
}
|
|
||||||
if (!this.emoVideo2) {
|
|
||||||
this.emoVideo2 = bgvideo.getVideoClone();
|
|
||||||
this.emoVideo2.remoteUrl = "http://hxzgame.vip.hnhxzkj.com/lzx/XiangQin/bginited.mp4"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
audioReady() {
|
|
||||||
this.removeBgAudioNext();
|
|
||||||
this.zhuVideo1.moveIn();
|
|
||||||
Utils.sendInnerMsg(InnerMsgCode.BgVideo_Ready, {compo: this.zhuVideo1, extra: this.zhuExtra1});
|
|
||||||
}
|
|
||||||
audioEnded() {
|
|
||||||
Utils.sendInnerMsg(InnerMsgCode.BgVideo_End, {compo: this.zhuVideo1, extra: this.zhuExtra1});
|
|
||||||
}
|
|
||||||
removeBgAudio() {
|
|
||||||
if (this.zhuVideo1 && this.zhuVideo1.isPlaying) {
|
|
||||||
this.zhuVideo1.recycleVideo();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//主背景临时视频
|
|
||||||
private zhuVideo2: BgVideo | null = null;
|
|
||||||
private zhuExtra2: any = null;
|
|
||||||
playBgAudioNext(remoteUrl:string, vtype:VideoRoleType, loop:boolean = false, extra:any = {}) {
|
|
||||||
let bgvideo = SceneBgVideoLayer.handle
|
|
||||||
if (!bgvideo) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
this.removeBgAudioNext();
|
|
||||||
if (!this.zhuVideo2) {
|
|
||||||
this.zhuVideo2 = bgvideo.getVideoClone();
|
|
||||||
}
|
|
||||||
this.zhuExtra2 = extra;
|
|
||||||
this.zhuVideo2.vtype = vtype;
|
|
||||||
this.zhuVideo2.cbReady = this.audioNextReady.bind(this);
|
|
||||||
this.zhuVideo2.cbEnd = this.audioNextEnded.bind(this);
|
|
||||||
this.zhuVideo2.playVideo(remoteUrl, loop, false);
|
|
||||||
}
|
|
||||||
audioNextReady() {
|
|
||||||
this.removeBgAudio();
|
|
||||||
this.zhuVideo2.moveIn();
|
|
||||||
Utils.sendInnerMsg(InnerMsgCode.BgVideo_Ready, {compo: this.zhuVideo2, extra: this.zhuExtra2});
|
|
||||||
}
|
|
||||||
audioNextEnded() {
|
|
||||||
Utils.sendInnerMsg(InnerMsgCode.BgVideo_End, {compo: this.zhuVideo2, extra: this.zhuExtra2});
|
|
||||||
}
|
|
||||||
removeBgAudioNext() {
|
|
||||||
if (this.zhuVideo2 && this.zhuVideo2.isPlaying) {
|
|
||||||
this.zhuVideo2.recycleVideo();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//region 播放emo视频
|
|
||||||
private emoVideo1: BgVideo | null = null;
|
|
||||||
private emoExtra1: any = {}
|
|
||||||
addEmoAudio(remoteUrl:string, vtype:VideoRoleType, loop:boolean = false, extra:any = {}) {
|
|
||||||
let bgvideo = SceneBgVideoLayer.handle
|
|
||||||
if (!bgvideo) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.emoVideo1 && this.emoVideo1.isPlaying) {
|
|
||||||
this.playEmoAudioNext(remoteUrl, vtype, loop, extra);
|
|
||||||
return
|
|
||||||
// this.emoVideo1.recycleVideo();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this.emoVideo1 || !isValid(this.emoVideo1.node)) {
|
|
||||||
this.emoVideo1 = bgvideo.getVideoClone();
|
|
||||||
}
|
|
||||||
this.emoExtra1 = extra;
|
|
||||||
this.emoVideo1.vtype = vtype;
|
|
||||||
this.emoVideo1.cbReady = this.emoReady.bind(this);
|
|
||||||
this.emoVideo1.cbEnd = this.emoEnded.bind(this);
|
|
||||||
this.emoVideo1.playVideo(remoteUrl, loop, false);
|
|
||||||
}
|
|
||||||
emoReady() {
|
|
||||||
this.removeEmoNextAudio();
|
|
||||||
Utils.sendInnerMsg(InnerMsgCode.BgVideo_Ready, {compo: this.emoVideo1, extra: this.emoExtra1});
|
|
||||||
}
|
|
||||||
emoEnded() {
|
|
||||||
Utils.sendInnerMsg(InnerMsgCode.BgVideo_End, {compo: this.emoVideo1, extra: this.emoExtra1});
|
|
||||||
}
|
|
||||||
removeEmoAudio() {
|
|
||||||
if (this.emoVideo1 && this.emoVideo1.isPlaying) {
|
|
||||||
this.emoVideo1.recycleVideo();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// 播放emo临时视频
|
|
||||||
private emoVideo2: BgVideo | null = null;
|
|
||||||
private emoExtra2: any = {}
|
|
||||||
playEmoAudioNext(remoteUrl:string, vtype:VideoRoleType, loop:boolean = false, extra:any = {}) {
|
|
||||||
let bgvideo = SceneBgVideoLayer.handle
|
|
||||||
if (!bgvideo) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
this.removeEmoNextAudio();
|
|
||||||
if (!this.emoVideo2) {
|
|
||||||
this.emoVideo2 = bgvideo.getVideoClone();
|
|
||||||
}
|
|
||||||
this.emoExtra2 = extra;
|
|
||||||
this.emoVideo2.vtype = vtype;
|
|
||||||
this.emoVideo2.cbReady = this.emoNextReady.bind(this);
|
|
||||||
this.emoVideo2.cbEnd = this.emoNextEnded.bind(this);
|
|
||||||
this.emoVideo2.playVideo(remoteUrl, loop, false);
|
|
||||||
}
|
|
||||||
emoNextReady() {
|
|
||||||
this.removeEmoAudio();
|
|
||||||
Utils.sendInnerMsg(InnerMsgCode.BgVideo_Ready, {compo: this.emoVideo2, extra: this.emoExtra2});
|
|
||||||
}
|
|
||||||
emoNextEnded() {
|
|
||||||
Utils.sendInnerMsg(InnerMsgCode.BgVideo_End, {compo: this.emoVideo2, extra: this.emoExtra2});
|
|
||||||
}
|
|
||||||
removeEmoNextAudio() {
|
|
||||||
if (this.emoVideo2 && this.emoVideo2.isPlaying) {
|
|
||||||
this.emoVideo2.recycleVideo();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//region 友盟+
|
|
||||||
umaInit() {
|
|
||||||
}
|
|
||||||
//友盟统计是否开启
|
|
||||||
umaSwt() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
//友盟事件统计
|
|
||||||
umaEvent(eventName: string, value: any = {}) {
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -63,8 +63,9 @@ export class PreloadUI extends Component {
|
|||||||
// 设备号
|
// 设备号
|
||||||
DeviceIdService.I.init();
|
DeviceIdService.I.init();
|
||||||
|
|
||||||
this.preloadFiles();
|
SDKManager.init();
|
||||||
|
|
||||||
|
this.preloadFiles();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected onDestroy(): void {
|
protected onDestroy(): void {
|
||||||
@@ -187,6 +188,4 @@ export class PreloadUI extends Component {
|
|||||||
this.jinduBar.active = false;
|
this.jinduBar.active = false;
|
||||||
ResManager.I.goCustomScene("LoginScene");
|
ResManager.I.goCustomScene("LoginScene");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,8 +53,8 @@ export class PurchasePanel extends li_BaseView {
|
|||||||
Utils.addInnerEL(InnerMsgCode.VipExpireChange, this, () => {
|
Utils.addInnerEL(InnerMsgCode.VipExpireChange, this, () => {
|
||||||
this.onVipExpireChange();
|
this.onVipExpireChange();
|
||||||
});
|
});
|
||||||
Utils.addInnerEL(InnerMsgCode.PayOrderCreateSucc, this, () => {
|
Utils.addInnerEL(InnerMsgCode.PayOrderCreateSucc, this, (data) => {
|
||||||
this.createOrRefreshWeb3PayPanel;
|
this.createOrRefreshWeb3PayPanel(data);
|
||||||
});
|
});
|
||||||
|
|
||||||
for (let index = 0; index < this.items.length; index++) {
|
for (let index = 0; index < this.items.length; index++) {
|
||||||
@@ -75,6 +75,7 @@ export class PurchasePanel extends li_BaseView {
|
|||||||
},
|
},
|
||||||
this
|
this
|
||||||
);
|
);
|
||||||
|
|
||||||
GButton.BandClick(
|
GButton.BandClick(
|
||||||
this._nodeTab.Buy30DayVipBtn,
|
this._nodeTab.Buy30DayVipBtn,
|
||||||
() => {
|
() => {
|
||||||
@@ -85,6 +86,22 @@ export class PurchasePanel extends li_BaseView {
|
|||||||
},
|
},
|
||||||
this
|
this
|
||||||
);
|
);
|
||||||
|
GButton.BandClick(
|
||||||
|
this._nodeTab.cashBtn,
|
||||||
|
() => {
|
||||||
|
// 购买7天会员
|
||||||
|
this.onClickCashBtn();
|
||||||
|
},
|
||||||
|
this
|
||||||
|
);
|
||||||
|
GButton.BandClick(
|
||||||
|
this._nodeTab.web3Btn,
|
||||||
|
() => {
|
||||||
|
// 购买7天会员
|
||||||
|
this.onClickWeb3Btn();
|
||||||
|
},
|
||||||
|
this
|
||||||
|
);
|
||||||
GButton.BandClick(
|
GButton.BandClick(
|
||||||
this._nodeTab.ReturnBtn,
|
this._nodeTab.ReturnBtn,
|
||||||
() => {
|
() => {
|
||||||
@@ -145,6 +162,12 @@ export class PurchasePanel extends li_BaseView {
|
|||||||
// 需要外部支付进行购买
|
// 需要外部支付进行购买
|
||||||
this.startPayment(id, this.currentPayType, networkType);
|
this.startPayment(id, this.currentPayType, networkType);
|
||||||
}
|
}
|
||||||
|
//测试用
|
||||||
|
// Utils.sendInnerMsg(InnerMsgCode.PayOrderCreateSucc, {
|
||||||
|
// orderId: 123,
|
||||||
|
// payType: 1,
|
||||||
|
// goodId: 1001,
|
||||||
|
// });
|
||||||
}
|
}
|
||||||
|
|
||||||
createOrRefreshWeb3PayPanel(param: any) {
|
createOrRefreshWeb3PayPanel(param: any) {
|
||||||
@@ -159,7 +182,7 @@ export class PurchasePanel extends li_BaseView {
|
|||||||
if (
|
if (
|
||||||
NavigationManager.Instance.getCurrentActivePanel() == PanelType.PERSONAL
|
NavigationManager.Instance.getCurrentActivePanel() == PanelType.PERSONAL
|
||||||
)
|
)
|
||||||
if (this.web3PopPanel === null)
|
if (this.web3PopPanel == null)
|
||||||
NavigationManager.Instance.openSubPanel(
|
NavigationManager.Instance.openSubPanel(
|
||||||
"Web3PopPanel",
|
"Web3PopPanel",
|
||||||
this.node,
|
this.node,
|
||||||
|
|||||||
@@ -7,6 +7,9 @@ import { OrderData } from "../../data/OrderData";
|
|||||||
import proto from "db://assets/Scripts/proto/proto.pb.js";
|
import proto from "db://assets/Scripts/proto/proto.pb.js";
|
||||||
import ResManager from "../../../Main/Manager/ResManager";
|
import ResManager from "../../../Main/Manager/ResManager";
|
||||||
import { PurchasePanel } from "./PurchasePanel";
|
import { PurchasePanel } from "./PurchasePanel";
|
||||||
|
import { QRCodeGenerator } from "db://assets/utils/qrcodeGenerator";
|
||||||
|
import { TipsPanel } from "./TipsPanel";
|
||||||
|
import { SDKManager } from "../../../Main/Channel/SDKManager";
|
||||||
|
|
||||||
const { ccclass, property } = _decorator;
|
const { ccclass, property } = _decorator;
|
||||||
|
|
||||||
@@ -21,6 +24,7 @@ export class Web3PopPanel extends li_BaseView {
|
|||||||
private expireTimeText: Label;
|
private expireTimeText: Label;
|
||||||
private selection: Node;
|
private selection: Node;
|
||||||
|
|
||||||
|
private qrCode: Sprite;
|
||||||
private curType: proto.cs.EnmNetworkType;
|
private curType: proto.cs.EnmNetworkType;
|
||||||
|
|
||||||
private orderId;
|
private orderId;
|
||||||
@@ -43,6 +47,7 @@ export class Web3PopPanel extends li_BaseView {
|
|||||||
this.coinText = this._nodeTab.SelectedCoinText.getComponent(Label);
|
this.coinText = this._nodeTab.SelectedCoinText.getComponent(Label);
|
||||||
this.address = this._nodeTab.addressText.getComponent(Label);
|
this.address = this._nodeTab.addressText.getComponent(Label);
|
||||||
this.expireTimeText = this._nodeTab.expireTimeText.getComponent(Label);
|
this.expireTimeText = this._nodeTab.expireTimeText.getComponent(Label);
|
||||||
|
this.qrCode = this._nodeTab.qrCode.getComponent(Sprite);
|
||||||
this.registerListener();
|
this.registerListener();
|
||||||
|
|
||||||
this.selection.setScale(new Vec3(1, 0, 1));
|
this.selection.setScale(new Vec3(1, 0, 1));
|
||||||
@@ -107,6 +112,7 @@ export class Web3PopPanel extends li_BaseView {
|
|||||||
const expireTime = OrderData.getExpireById(this.orderId);
|
const expireTime = OrderData.getExpireById(this.orderId);
|
||||||
const retCode = OrderData.getRetCodeById(this.orderId);
|
const retCode = OrderData.getRetCodeById(this.orderId);
|
||||||
|
|
||||||
|
this.expireTimeText.string = expireTime.toString();
|
||||||
this.amount.string = amount;
|
this.amount.string = amount;
|
||||||
this.address.string = walletUrl;
|
this.address.string = walletUrl;
|
||||||
switch (this.networkType) {
|
switch (this.networkType) {
|
||||||
@@ -139,6 +145,21 @@ export class Web3PopPanel extends li_BaseView {
|
|||||||
this.coinText.string = "ENT_BEP";
|
this.coinText.string = "ENT_BEP";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//this.address.string = "asdasdasd";
|
||||||
|
//refreshQRcode
|
||||||
|
QRCodeGenerator.generateQRCodeSpriteFrame(
|
||||||
|
this.address.string,
|
||||||
|
320,
|
||||||
|
4,
|
||||||
|
(spriteframe) => {
|
||||||
|
if (spriteframe) {
|
||||||
|
this.qrCode.spriteFrame = spriteframe;
|
||||||
|
} else {
|
||||||
|
TipsPanel.show("qrcode generation fail, please copy url");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
updateSelectNetwork() {}
|
updateSelectNetwork() {}
|
||||||
@@ -166,7 +187,15 @@ export class Web3PopPanel extends li_BaseView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onClickCopy() {
|
onClickCopy() {
|
||||||
//todo:copy 功能
|
const stringToCopy = this.address.string;
|
||||||
|
|
||||||
|
SDKManager.copyToClipboard(stringToCopy, (success: boolean) => {
|
||||||
|
if (success) {
|
||||||
|
TipsPanel.show("地址已复制到剪贴板");
|
||||||
|
} else {
|
||||||
|
TipsPanel.show("复制失败,请手动复制地址");
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
onClickClose() {
|
onClickClose() {
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"ver": "1.2.0",
|
||||||
|
"importer": "directory",
|
||||||
|
"imported": true,
|
||||||
|
"uuid": "937d6b90-9aae-4409-b77c-494e10bf1a78",
|
||||||
|
"files": [],
|
||||||
|
"subMetas": {},
|
||||||
|
"userData": {}
|
||||||
|
}
|
||||||
@@ -0,0 +1,126 @@
|
|||||||
|
import { _decorator, Component, Node, Sprite, Label, Button } from 'cc';
|
||||||
|
import { QRCodeGenerator } from '../../utils/qrcodeGenerator';
|
||||||
|
|
||||||
|
const { ccclass, property } = _decorator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 二维码生成器测试演示
|
||||||
|
* 展示如何使用 QRCodeGenerator 工具类
|
||||||
|
*/
|
||||||
|
@ccclass('QRCodeGeneratorTest')
|
||||||
|
export class QRCodeGeneratorTest extends Component {
|
||||||
|
|
||||||
|
@property(Node)
|
||||||
|
qrCodeContainer: Node = null!;
|
||||||
|
|
||||||
|
@property(Button)
|
||||||
|
generateBtn: Button = null!;
|
||||||
|
|
||||||
|
@property(Label)
|
||||||
|
statusLabel: Label = null!;
|
||||||
|
|
||||||
|
private testTexts = [
|
||||||
|
'https://example.com',
|
||||||
|
'Hello World!',
|
||||||
|
'这是一个中文测试',
|
||||||
|
'QR Code Generator Test - 二维码生成器测试',
|
||||||
|
JSON.stringify({ name: 'test', value: 123, timestamp: Date.now() })
|
||||||
|
];
|
||||||
|
|
||||||
|
private currentIndex = 0;
|
||||||
|
|
||||||
|
start() {
|
||||||
|
if (this.generateBtn) {
|
||||||
|
this.generateBtn.node.on(Button.EventType.CLICK, this.onGenerateClick, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 初始生成第一个二维码
|
||||||
|
this.generateQRCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
private onGenerateClick() {
|
||||||
|
this.currentIndex = (this.currentIndex + 1) % this.testTexts.length;
|
||||||
|
this.generateQRCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
private generateQRCode() {
|
||||||
|
if (!this.qrCodeContainer) {
|
||||||
|
this.updateStatus('错误: 二维码容器节点未设置');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 清空容器
|
||||||
|
this.qrCodeContainer.removeAllChildren();
|
||||||
|
|
||||||
|
const testText = this.testTexts[this.currentIndex];
|
||||||
|
this.updateStatus(`正在生成二维码: ${testText.substring(0, 30)}...`);
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 方法1: 生成 Sprite 组件(包含节点)- 异步版本
|
||||||
|
QRCodeGenerator.generateQRCodeSprite(testText, 200, 8, (qrSprite) => {
|
||||||
|
if (qrSprite) {
|
||||||
|
// 将生成的 Sprite 节点添加到容器中
|
||||||
|
qrSprite.node.setParent(this.qrCodeContainer);
|
||||||
|
qrSprite.node.setPosition(0, 0, 0);
|
||||||
|
|
||||||
|
this.updateStatus(`✓ 成功生成二维码 (${this.currentIndex + 1}/${this.testTexts.length})`);
|
||||||
|
|
||||||
|
// 打印一些调试信息
|
||||||
|
console.log('QRCode生成成功:', {
|
||||||
|
text: testText,
|
||||||
|
spriteFrame: qrSprite.spriteFrame,
|
||||||
|
size: qrSprite.spriteFrame?.texture?.width + 'x' + qrSprite.spriteFrame?.texture?.height
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.updateStatus('✗ 生成二维码失败');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 演示方法2: 生成 SpriteFrame 并应用到现有节点(异步版本)
|
||||||
|
// QRCodeGenerator.generateQRCodeSpriteFrame(testText, 200, 8, (spriteFrame) => {
|
||||||
|
// if (spriteFrame && existingSpriteNode) {
|
||||||
|
// const sprite = existingSpriteNode.getComponent(Sprite);
|
||||||
|
// if (sprite) {
|
||||||
|
// sprite.spriteFrame = spriteFrame;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
|
||||||
|
// 演示方法3: 生成 Base64 字符串
|
||||||
|
// const base64 = QRCodeGenerator.generateQRCodeBase64(testText, 200, 8);
|
||||||
|
// console.log('QRCode Base64:', base64.substring(0, 100) + '...');
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('QRCode生成测试失败:', error);
|
||||||
|
this.updateStatus('✗ 生成失败: ' + error.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private updateStatus(message: string) {
|
||||||
|
if (this.statusLabel) {
|
||||||
|
this.statusLabel.string = message;
|
||||||
|
}
|
||||||
|
console.log('QRCodeTest:', message);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 静态方法示例:在其他地方直接调用
|
||||||
|
*/
|
||||||
|
public static createQRCodeExample() {
|
||||||
|
// 示例1: 生成网址二维码(异步)
|
||||||
|
QRCodeGenerator.generateQRCodeSprite('https://www.example.com', 256, 4, (urlQR) => {
|
||||||
|
console.log('URL二维码生成完成:', urlQR);
|
||||||
|
});
|
||||||
|
|
||||||
|
// 示例2: 生成文本二维码,自定义尺寸(异步)
|
||||||
|
QRCodeGenerator.generateQRCodeSpriteFrame('Hello World!', 300, 10, (textQR) => {
|
||||||
|
console.log('文本二维码生成完成:', textQR);
|
||||||
|
});
|
||||||
|
|
||||||
|
// 示例3: 生成Base64格式二维码(同步)
|
||||||
|
const base64QR = QRCodeGenerator.generateQRCodeBase64('测试数据', 150, 5);
|
||||||
|
console.log('Base64二维码生成完成:', base64QR.substring(0, 100) + '...');
|
||||||
|
|
||||||
|
return { message: '二维码生成中,请查看控制台日志' };
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"ver": "4.0.24",
|
||||||
|
"importer": "typescript",
|
||||||
|
"imported": true,
|
||||||
|
"uuid": "8a671ed0-b5e1-46c1-b934-1957736ea00a",
|
||||||
|
"files": [],
|
||||||
|
"subMetas": {},
|
||||||
|
"userData": {}
|
||||||
|
}
|
||||||
|
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 26 KiB |
@@ -11,7 +11,7 @@
|
|||||||
"6c48a": {
|
"6c48a": {
|
||||||
"importer": "texture",
|
"importer": "texture",
|
||||||
"uuid": "6a5c6f1e-d197-4f9c-8113-6732295ebf8e@6c48a",
|
"uuid": "6a5c6f1e-d197-4f9c-8113-6732295ebf8e@6c48a",
|
||||||
"displayName": "2001",
|
"displayName": "1001",
|
||||||
"id": "6c48a",
|
"id": "6c48a",
|
||||||
"name": "texture",
|
"name": "texture",
|
||||||
"userData": {
|
"userData": {
|
||||||
@@ -35,7 +35,7 @@
|
|||||||
"f9941": {
|
"f9941": {
|
||||||
"importer": "sprite-frame",
|
"importer": "sprite-frame",
|
||||||
"uuid": "6a5c6f1e-d197-4f9c-8113-6732295ebf8e@f9941",
|
"uuid": "6a5c6f1e-d197-4f9c-8113-6732295ebf8e@f9941",
|
||||||
"displayName": "2001",
|
"displayName": "1001",
|
||||||
"id": "f9941",
|
"id": "f9941",
|
||||||
"name": "spriteFrame",
|
"name": "spriteFrame",
|
||||||
"userData": {
|
"userData": {
|
||||||
|
Before Width: | Height: | Size: 43 KiB After Width: | Height: | Size: 43 KiB |
@@ -11,7 +11,7 @@
|
|||||||
"6c48a": {
|
"6c48a": {
|
||||||
"importer": "texture",
|
"importer": "texture",
|
||||||
"uuid": "d75397cc-79ea-4678-9387-fec0502ae091@6c48a",
|
"uuid": "d75397cc-79ea-4678-9387-fec0502ae091@6c48a",
|
||||||
"displayName": "2002",
|
"displayName": "1002",
|
||||||
"id": "6c48a",
|
"id": "6c48a",
|
||||||
"name": "texture",
|
"name": "texture",
|
||||||
"userData": {
|
"userData": {
|
||||||
@@ -35,7 +35,7 @@
|
|||||||
"f9941": {
|
"f9941": {
|
||||||
"importer": "sprite-frame",
|
"importer": "sprite-frame",
|
||||||
"uuid": "d75397cc-79ea-4678-9387-fec0502ae091@f9941",
|
"uuid": "d75397cc-79ea-4678-9387-fec0502ae091@f9941",
|
||||||
"displayName": "2002",
|
"displayName": "1002",
|
||||||
"id": "f9941",
|
"id": "f9941",
|
||||||
"name": "spriteFrame",
|
"name": "spriteFrame",
|
||||||
"userData": {
|
"userData": {
|
||||||
|
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 29 KiB |
@@ -11,7 +11,7 @@
|
|||||||
"6c48a": {
|
"6c48a": {
|
||||||
"importer": "texture",
|
"importer": "texture",
|
||||||
"uuid": "f944a7b5-bc82-484f-a5e9-904fcb317707@6c48a",
|
"uuid": "f944a7b5-bc82-484f-a5e9-904fcb317707@6c48a",
|
||||||
"displayName": "2003",
|
"displayName": "1003",
|
||||||
"id": "6c48a",
|
"id": "6c48a",
|
||||||
"name": "texture",
|
"name": "texture",
|
||||||
"userData": {
|
"userData": {
|
||||||
@@ -35,7 +35,7 @@
|
|||||||
"f9941": {
|
"f9941": {
|
||||||
"importer": "sprite-frame",
|
"importer": "sprite-frame",
|
||||||
"uuid": "f944a7b5-bc82-484f-a5e9-904fcb317707@f9941",
|
"uuid": "f944a7b5-bc82-484f-a5e9-904fcb317707@f9941",
|
||||||
"displayName": "2003",
|
"displayName": "1003",
|
||||||
"id": "f9941",
|
"id": "f9941",
|
||||||
"name": "spriteFrame",
|
"name": "spriteFrame",
|
||||||
"userData": {
|
"userData": {
|
||||||
|
Before Width: | Height: | Size: 54 KiB After Width: | Height: | Size: 54 KiB |
@@ -11,7 +11,7 @@
|
|||||||
"6c48a": {
|
"6c48a": {
|
||||||
"importer": "texture",
|
"importer": "texture",
|
||||||
"uuid": "1d7c6978-98a0-47a4-a62b-9f31a7d07617@6c48a",
|
"uuid": "1d7c6978-98a0-47a4-a62b-9f31a7d07617@6c48a",
|
||||||
"displayName": "2004",
|
"displayName": "1004",
|
||||||
"id": "6c48a",
|
"id": "6c48a",
|
||||||
"name": "texture",
|
"name": "texture",
|
||||||
"userData": {
|
"userData": {
|
||||||
@@ -35,7 +35,7 @@
|
|||||||
"f9941": {
|
"f9941": {
|
||||||
"importer": "sprite-frame",
|
"importer": "sprite-frame",
|
||||||
"uuid": "1d7c6978-98a0-47a4-a62b-9f31a7d07617@f9941",
|
"uuid": "1d7c6978-98a0-47a4-a62b-9f31a7d07617@f9941",
|
||||||
"displayName": "2004",
|
"displayName": "1004",
|
||||||
"id": "f9941",
|
"id": "f9941",
|
||||||
"name": "spriteFrame",
|
"name": "spriteFrame",
|
||||||
"userData": {
|
"userData": {
|
||||||
|
Before Width: | Height: | Size: 63 KiB After Width: | Height: | Size: 63 KiB |
@@ -11,7 +11,7 @@
|
|||||||
"6c48a": {
|
"6c48a": {
|
||||||
"importer": "texture",
|
"importer": "texture",
|
||||||
"uuid": "c41d8e92-69ca-4705-a43c-b134a367875e@6c48a",
|
"uuid": "c41d8e92-69ca-4705-a43c-b134a367875e@6c48a",
|
||||||
"displayName": "2005",
|
"displayName": "1005",
|
||||||
"id": "6c48a",
|
"id": "6c48a",
|
||||||
"name": "texture",
|
"name": "texture",
|
||||||
"userData": {
|
"userData": {
|
||||||
@@ -35,7 +35,7 @@
|
|||||||
"f9941": {
|
"f9941": {
|
||||||
"importer": "sprite-frame",
|
"importer": "sprite-frame",
|
||||||
"uuid": "c41d8e92-69ca-4705-a43c-b134a367875e@f9941",
|
"uuid": "c41d8e92-69ca-4705-a43c-b134a367875e@f9941",
|
||||||
"displayName": "2005",
|
"displayName": "1005",
|
||||||
"id": "f9941",
|
"id": "f9941",
|
||||||
"name": "spriteFrame",
|
"name": "spriteFrame",
|
||||||
"userData": {
|
"userData": {
|
||||||
|
Before Width: | Height: | Size: 49 KiB After Width: | Height: | Size: 49 KiB |
@@ -11,7 +11,7 @@
|
|||||||
"6c48a": {
|
"6c48a": {
|
||||||
"importer": "texture",
|
"importer": "texture",
|
||||||
"uuid": "c1263d7c-a965-4ec8-a65a-bf514532b5d0@6c48a",
|
"uuid": "c1263d7c-a965-4ec8-a65a-bf514532b5d0@6c48a",
|
||||||
"displayName": "2006",
|
"displayName": "1006",
|
||||||
"id": "6c48a",
|
"id": "6c48a",
|
||||||
"name": "texture",
|
"name": "texture",
|
||||||
"userData": {
|
"userData": {
|
||||||
@@ -35,7 +35,7 @@
|
|||||||
"f9941": {
|
"f9941": {
|
||||||
"importer": "sprite-frame",
|
"importer": "sprite-frame",
|
||||||
"uuid": "c1263d7c-a965-4ec8-a65a-bf514532b5d0@f9941",
|
"uuid": "c1263d7c-a965-4ec8-a65a-bf514532b5d0@f9941",
|
||||||
"displayName": "2006",
|
"displayName": "1006",
|
||||||
"id": "f9941",
|
"id": "f9941",
|
||||||
"name": "spriteFrame",
|
"name": "spriteFrame",
|
||||||
"userData": {
|
"userData": {
|
||||||
@@ -0,0 +1,208 @@
|
|||||||
|
import { Sprite, SpriteFrame, Texture2D, ImageAsset, Node } from 'cc';
|
||||||
|
import qrcode from 'qrcode-generator';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 二维码生成工具类
|
||||||
|
* 提供生成二维码Sprite的静态方法
|
||||||
|
*/
|
||||||
|
export class QRCodeGenerator {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成二维码 Sprite 组件(异步版本)
|
||||||
|
* @param text 要生成二维码的文本内容
|
||||||
|
* @param size 二维码尺寸,默认256x256
|
||||||
|
* @param margin 二维码边距,默认4
|
||||||
|
* @param callback 完成回调函数
|
||||||
|
*/
|
||||||
|
public static generateQRCodeSprite(text: string, size: number = 256, margin: number = 4, callback?: (sprite: Sprite | null) => void): void {
|
||||||
|
try {
|
||||||
|
if (!text || text.trim().length === 0) {
|
||||||
|
console.error('QRCodeGenerator: 文本内容不能为空');
|
||||||
|
callback && callback(null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.generateQRCodeSpriteFrame(text, size, margin, (spriteFrame) => {
|
||||||
|
if (!spriteFrame) {
|
||||||
|
callback && callback(null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 创建新节点和Sprite组件
|
||||||
|
const node = new Node('QRCode');
|
||||||
|
const sprite = node.addComponent(Sprite);
|
||||||
|
sprite.spriteFrame = spriteFrame;
|
||||||
|
|
||||||
|
callback && callback(sprite);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('QRCodeGenerator: 创建Sprite组件失败', error);
|
||||||
|
callback && callback(null);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error('QRCodeGenerator: 生成二维码Sprite失败', error);
|
||||||
|
callback && callback(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成二维码 SpriteFrame(异步版本)
|
||||||
|
* @param text 要生成二维码的文本内容
|
||||||
|
* @param size 二维码尺寸,默认256x256
|
||||||
|
* @param margin 二维码边距,默认4
|
||||||
|
* @param callback 完成回调函数
|
||||||
|
*/
|
||||||
|
public static generateQRCodeSpriteFrame(text: string, size: number = 256, margin: number = 4, callback?: (spriteFrame: SpriteFrame | null) => void): void {
|
||||||
|
try {
|
||||||
|
if (!text || text.trim().length === 0) {
|
||||||
|
console.error('QRCodeGenerator: 文本内容不能为空');
|
||||||
|
callback && callback(null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (size <= 0 || size > 2048) {
|
||||||
|
console.error('QRCodeGenerator: 尺寸必须在1-2048之间');
|
||||||
|
callback && callback(null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 生成二维码
|
||||||
|
const qr = qrcode(0, 'M'); // 0表示自动类型选择,'M'表示中等纠错级别
|
||||||
|
qr.addData(text);
|
||||||
|
qr.make();
|
||||||
|
|
||||||
|
// 创建Canvas绘制二维码
|
||||||
|
const moduleCount = qr.getModuleCount();
|
||||||
|
const cellSize = Math.floor((size - 2 * margin) / moduleCount);
|
||||||
|
const actualSize = cellSize * moduleCount + 2 * margin;
|
||||||
|
|
||||||
|
const canvas = document.createElement('canvas');
|
||||||
|
canvas.width = actualSize;
|
||||||
|
canvas.height = actualSize;
|
||||||
|
const ctx = canvas.getContext('2d');
|
||||||
|
|
||||||
|
if (!ctx) {
|
||||||
|
console.error('QRCodeGenerator: 无法获取Canvas上下文');
|
||||||
|
callback && callback(null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 绘制白色背景
|
||||||
|
ctx.fillStyle = '#ffffff';
|
||||||
|
ctx.fillRect(0, 0, actualSize, actualSize);
|
||||||
|
|
||||||
|
// 绘制二维码
|
||||||
|
ctx.fillStyle = '#000000';
|
||||||
|
for (let row = 0; row < moduleCount; row++) {
|
||||||
|
for (let col = 0; col < moduleCount; col++) {
|
||||||
|
if (qr.isDark(row, col)) {
|
||||||
|
ctx.fillRect(
|
||||||
|
margin + col * cellSize,
|
||||||
|
margin + row * cellSize,
|
||||||
|
cellSize,
|
||||||
|
cellSize
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 使用异步方式处理图片创建
|
||||||
|
const img = new Image();
|
||||||
|
img.onload = () => {
|
||||||
|
try {
|
||||||
|
// 创建ImageAsset并直接设置图片数据
|
||||||
|
const imageAsset = new ImageAsset(img);
|
||||||
|
|
||||||
|
// 创建Texture2D并设置ImageAsset
|
||||||
|
const texture = new Texture2D();
|
||||||
|
texture.image = imageAsset;
|
||||||
|
|
||||||
|
// 创建SpriteFrame并设置纹理
|
||||||
|
const spriteFrame = new SpriteFrame();
|
||||||
|
spriteFrame.texture = texture;
|
||||||
|
|
||||||
|
callback && callback(spriteFrame);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('QRCodeGenerator: 创建纹理失败', error);
|
||||||
|
callback && callback(null);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
img.onerror = () => {
|
||||||
|
console.error('QRCodeGenerator: 图片加载失败');
|
||||||
|
callback && callback(null);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 设置图片源,触发加载
|
||||||
|
img.src = canvas.toDataURL('image/png');
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('QRCodeGenerator: 生成二维码SpriteFrame失败', error);
|
||||||
|
callback && callback(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成二维码的Base64字符串
|
||||||
|
* @param text 要生成二维码的文本内容
|
||||||
|
* @param size 二维码尺寸,默认256x256
|
||||||
|
* @param margin 二维码边距,默认4
|
||||||
|
* @returns 二维码的Base64字符串,失败时返回空字符串
|
||||||
|
*/
|
||||||
|
public static generateQRCodeBase64(text: string, size: number = 256, margin: number = 4): string {
|
||||||
|
try {
|
||||||
|
if (!text || text.trim().length === 0) {
|
||||||
|
console.error('QRCodeGenerator: 文本内容不能为空');
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
// 生成二维码
|
||||||
|
const qr = qrcode(0, 'M');
|
||||||
|
qr.addData(text);
|
||||||
|
qr.make();
|
||||||
|
|
||||||
|
// 创建Canvas绘制二维码
|
||||||
|
const moduleCount = qr.getModuleCount();
|
||||||
|
const cellSize = Math.floor((size - 2 * margin) / moduleCount);
|
||||||
|
const actualSize = cellSize * moduleCount + 2 * margin;
|
||||||
|
|
||||||
|
const canvas = document.createElement('canvas');
|
||||||
|
canvas.width = actualSize;
|
||||||
|
canvas.height = actualSize;
|
||||||
|
const ctx = canvas.getContext('2d');
|
||||||
|
|
||||||
|
if (!ctx) {
|
||||||
|
console.error('QRCodeGenerator: 无法获取Canvas上下文');
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
// 绘制白色背景
|
||||||
|
ctx.fillStyle = '#ffffff';
|
||||||
|
ctx.fillRect(0, 0, actualSize, actualSize);
|
||||||
|
|
||||||
|
// 绘制二维码
|
||||||
|
ctx.fillStyle = '#000000';
|
||||||
|
for (let row = 0; row < moduleCount; row++) {
|
||||||
|
for (let col = 0; col < moduleCount; col++) {
|
||||||
|
if (qr.isDark(row, col)) {
|
||||||
|
ctx.fillRect(
|
||||||
|
margin + col * cellSize,
|
||||||
|
margin + row * cellSize,
|
||||||
|
cellSize,
|
||||||
|
cellSize
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 返回Base64字符串
|
||||||
|
return canvas.toDataURL('image/png');
|
||||||
|
} catch (error) {
|
||||||
|
console.error('QRCodeGenerator: 生成二维码Base64失败', error);
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"ver": "4.0.24",
|
||||||
|
"importer": "typescript",
|
||||||
|
"imported": true,
|
||||||
|
"uuid": "af3f0b82-68ae-4820-90af-594d57f19dda",
|
||||||
|
"files": [],
|
||||||
|
"subMetas": {},
|
||||||
|
"userData": {}
|
||||||
|
}
|
||||||
@@ -8,7 +8,8 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@google/genai": "^1.13.0",
|
"@google/genai": "^1.13.0",
|
||||||
"buffer": "^6.0.3",
|
"buffer": "^6.0.3",
|
||||||
"protobufjs": "^7.5.3"
|
"protobufjs": "^7.5.3",
|
||||||
|
"qrcode-generator": "^2.0.4"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"fs-extra": "^11.3.1",
|
"fs-extra": "^11.3.1",
|
||||||
@@ -1086,6 +1087,12 @@
|
|||||||
"node": ">=6"
|
"node": ">=6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/qrcode-generator": {
|
||||||
|
"version": "2.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/qrcode-generator/-/qrcode-generator-2.0.4.tgz",
|
||||||
|
"integrity": "sha512-mZSiP6RnbHl4xL2Ap5HfkjLnmxfKcPWpWe/c+5XxCuetEenqmNFf1FH/ftXPCtFG5/TDobjsjz6sSNL0Sr8Z9g==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/requizzle": {
|
"node_modules/requizzle": {
|
||||||
"version": "0.2.4",
|
"version": "0.2.4",
|
||||||
"resolved": "https://registry.npmjs.org/requizzle/-/requizzle-0.2.4.tgz",
|
"resolved": "https://registry.npmjs.org/requizzle/-/requizzle-0.2.4.tgz",
|
||||||
|
|||||||
@@ -11,7 +11,8 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@google/genai": "^1.13.0",
|
"@google/genai": "^1.13.0",
|
||||||
"buffer": "^6.0.3",
|
"buffer": "^6.0.3",
|
||||||
"protobufjs": "^7.5.3"
|
"protobufjs": "^7.5.3",
|
||||||
|
"qrcode-generator": "^2.0.4"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"fs-extra": "^11.3.1",
|
"fs-extra": "^11.3.1",
|
||||||
|
|||||||