import { _decorator, assetManager, AssetManager, Button, Color, Component, instantiate, JsonAsset, Label, Layout, Node, resources, ScrollView, sp, Sprite, SpriteAtlas, SpriteFrame, tween, UITransform, Vec3 } from 'cc'; import { ScrollControl } from './ScrollControl'; import { fixNum, getTimezoneOffsetString, getTranslate, hideAllChildren, isBrahmic, updateLang, waitNextFrame } from './Tools'; const { ccclass, property } = _decorator; @ccclass('HistoryDetail') export class HistoryDetail extends Component { @property(JsonAsset) langJson: JsonAsset | null = null; /**loading 动画节点*/ @property(Node) loading: Node = null @property(Node) pnl_title: Node = null; @property(Node) item_round_winning: Node = null; @property(ScrollView) list_round_winning: ScrollView = null; @property(Node) item_detail: Node = null; @property(ScrollView) list_detail: ScrollView = null; @property(Node) item_symbol: Node = null; @property(Node) item_win_kind: Node = null; @property(Node) flip: Node = null; @property(ScrollControl) scrollControl: ScrollControl = null @property(SpriteAtlas) symbolsAtlas: SpriteAtlas = null!; @property([SpriteFrame]) multiFrame = new Array; dict = null data: any = null protected onLoad(): void { this.node.on("show_history_formula_detail", this.showFormulaDetail, this) this.node.on("hide_history_formula_detail", this.hideFormulaDetail, this) this.node.on("remark_round_winning_list", this.remarkRoundWinningList, this) this.list_round_winning.node.active = false this.item_round_winning.active = false this.item_symbol.active = false this.item_win_kind.active = false this.item_detail.active = false } protected start(): void { } protected onDisable(): void { this.node.off("show_history_formula_detail", this.showFormulaDetail, this) this.node.off("hide_history_formula_detail", this.hideFormulaDetail, this) this.node.off("remark_round_winning_list", this.remarkRoundWinningList, this) } setDetailData(data, lang: string) { this.data = null this.data = JSON.parse(JSON.stringify(data)); this.dict = this.langJson.json[lang] ?? this.langJson.json["en"]; updateLang(this.node, this.dict, lang) // console.error(`0 this.data.panDetails.length, ${this.data.panDetails.length}`) // for (let i = 0; i < 100; i++) { // let one = JSON.parse(JSON.stringify(data.panDetails[0])) // this.data.panDetails.push(one) // } // console.error(`0 this.data.panDetails.length, ${this.data.panDetails.length}`) } loadRoundWinningList(scoreInfos) { this.data.scoreInfos = scoreInfos const content = this.list_round_winning.content content.destroyAllChildren() const currencySymbol = this.data.currencySymbol const yellowColor = new Color(0xFF, 0xAE, 0x00) scoreInfos.forEach((v, i) => { const item = instantiate(this.item_round_winning) const txt_round = item.getChildByName("txt_round").getComponent(Label) const txt_score = item.getChildByName("txt_score").getComponent(Label) if (i == 0) { txt_round.string = getTranslate(this.dict, "Normal Spin") txt_round.color = yellowColor txt_score.color = yellowColor } else { txt_round.string = getTranslate(this.dict, "Free Spin:") + ` ${i}/${scoreInfos.length - 1}` txt_round.color = Color.WHITE txt_score.color = Color.WHITE } txt_score.string = `${currencySymbol}${fixNum(v.Score)}` item.name = v.StartIndex.toString() item.position = new Vec3() content.addChild(item) }); } jumpToPage(event) { const item = event.target as any as Node const page = item.name this.scrollControl.jumpToPage(Number(page)) this.hideRoundWinningList() } remarkRoundWinningList(page) { const txt_spin = this.pnl_title.getChildByName("txt_spin").getComponent(Label) if (!this.data) { return } if (!this.data.scoreInfos) { txt_spin.string = getTranslate(this.dict, "Normal Spin") return } let maxIdx = this.data.scoreInfos.length - 1 let findIndex = maxIdx for (let i = maxIdx; i >= 0; i--) { let scoreInfo = this.data.scoreInfos[i] if (page >= scoreInfo.StartIndex) { findIndex = i break } } // console.log(`findIndex, ${findIndex}`) if (findIndex == 0) { txt_spin.string = getTranslate(this.dict, "Normal Spin") } else { txt_spin.string = getTranslate(this.dict, "Free Spin:") + `${findIndex}/${maxIdx}` } const yellowColor = new Color(0xFF, 0xAE, 0x00) this.list_round_winning.content.children.forEach((item, i) => { const txt_round = item.getChildByName("txt_round").getComponent(Label) const txt_score = item.getChildByName("txt_score").getComponent(Label) if (i == findIndex) { txt_round.color = yellowColor txt_score.color = yellowColor } else { txt_round.color = Color.WHITE txt_score.color = Color.WHITE } }) } showRoundWinningList() { let isActive = this.list_round_winning.node.active if (isActive) { this.hideRoundWinningList() return } const node = this.list_round_winning.node const content = this.list_round_winning.content content.children.forEach(v => { v.active = true }) node.active = true let startVec = new Vec3(0, 3000) let endVec = new Vec3(0, 800) node.position = startVec tween(node).to(0.2, { position: endVec }).call(() => { let sp = this.pnl_title.getChildByName("txt_spin").getChildByName("sp") sp.scale = new Vec3(1, -1) }).start() } hideRoundWinningList() { const node = this.list_round_winning.node const content = this.list_round_winning.content let startVec = new Vec3(0, 3000) tween(this.list_round_winning.node).to(0.2, { position: startVec }) .call(() => { content.children.forEach(v => { v.active = false }) node.active = false let sp = this.pnl_title.getChildByName("txt_spin").getChildByName("sp") sp.scale = new Vec3(1, 1) }).start() } // 加载一盘数据 loadOne(item: Node, pan, idx) { item.position = new Vec3() this.list_detail.content.addChild(item) const currencySymbol = this.data.currencySymbol const currency = this.data.currency const info = item.getChildByName("info"); info.getChildByName("txt_transaction").getComponent(Label).string = this.data.roundId; let bet = idx == 0 ? fixNum(pan.Bet) : fixNum(0) info.getChildByName("txt_bet").getComponent(Label).string = bet; info.getChildByName("Label_Bet").getComponent(Label).string = getTranslate(this.dict, "Bet") + `(${currencySymbol})`; info.getChildByName("txt_profit").getComponent(Label).string = fixNum(pan.AllScore - pan.Bet); info.getChildByName("Label_Profit").getComponent(Label).string = getTranslate(this.dict, "Profit") + `(${currencySymbol})`; info.getChildByName("txt_balance_before").getComponent(Label).string = fixNum(pan.Balance - pan.AllScore + pan.Bet) + "➡️"; info.getChildByName("txt_balance_after").getComponent(Label).string = fixNum(pan.Balance); info.getChildByName("Label_Balance").getComponent(Label).string = getTranslate(this.dict, "Balance") + `(${currencySymbol})`; const content = item.getComponent(ScrollView).content; const bet_info = content.getChildByName("bet_info") if (pan.RoundInfo) { const txt_round = bet_info.getChildByName("txt_round").getComponent(Label) txt_round.string = getTranslate(this.dict, "Round:") + ` ${pan.RoundInfo.Current}/${pan.RoundInfo.Total}` } else { bet_info.getChildByName("txt_round").active = false } // 顶上四个横着摆的 // const hor_symbols = content.getChildByName("hor_symbols") // hor_symbols.destroyAllChildren() // pan.PanColor.Top.forEach((v, i) => { // const item_symbol = instantiate(this.item_symbol) // const bg = item_symbol.getChildByName("bg").getComponent(Sprite) // const path_bg = `symbol_bg_${v}` // bg.spriteFrame = this.symbolsAtlas.getSpriteFrame(path_bg) // const symbol = item_symbol.getChildByName("symbol").getComponent(Sprite) // const path_symbol = `symbol_${v}_x1` // symbol.spriteFrame = this.symbolsAtlas.getSpriteFrame(path_symbol) // //顶部横着的一排全是铁框 // const frame = item_symbol.getChildByName("frame").getComponent(Sprite) // const path_frame = `frame_0` // frame.spriteFrame = this.symbolsAtlas.getSpriteFrame(path_frame) // // scatter 和 wild symbol没有金/银/铁框 // frame.node.active = !this.isScatterOrWild(v) // item_symbol.position = new Vec3() // item_symbol.active = true // hor_symbols.addChild(item_symbol) // }) // 下面几列竖着摆的 // 5行6列 的网格,固定有6个竖列, 每一列2~5个symbol const vert_symbols = content.getChildByName("vert_symbols") vert_symbols.children.forEach(vert => { vert.destroyAllChildren() }); // 每一竖列最多有5个symbol const EACH_LINE_MAX_SYMBOL = 5 const sortArr = []; const CroSymbolsKeys = Object.keys(pan.CroSymbols) CroSymbolsKeys.forEach(v => { sortArr.push(pan.CroSymbols[Number(v)]) }) sortArr.sort((a, b) => { return a.PosFirst - b.PosFirst }) let curCross = sortArr.shift() let curSymbolIdx = curCross?.PosFirst for (let i = 0; i < pan.Symbol.Middle.length;) { // 如果i不等于当前需要处理的连体符号,正常生成一个symbol if (i != curSymbolIdx) { const item_symbol = instantiate(this.item_symbol) let v = pan.Symbol.Middle[i] const bg = item_symbol.getChildByName("bg").getComponent(Sprite) const path_bg = `${v > 8 ? 8 : v}_1` bg.spriteFrame = this.symbolsAtlas.getSpriteFrame(path_bg) const symbol = item_symbol.getChildByName("symbol").getComponent(Sprite) const path_symbol = `${v}` symbol.spriteFrame = this.symbolsAtlas.getSpriteFrame(path_symbol) //单个symbol 无框 const frame = item_symbol.getChildByName("frame").getComponent(Sprite) // const path_frame = `frame_0` // frame.spriteFrame = this.symbolsAtlas.getSpriteFrame(path_frame) frame.node.active = false item_symbol.position = new Vec3() item_symbol.active = true // 通过 i 计算在第几行第几列 let row = i % EACH_LINE_MAX_SYMBOL let line = Math.floor(i / EACH_LINE_MAX_SYMBOL) // console.log(`第${i}个元素在,第${row}横行,第${line}竖列`) vert_symbols.children[line].addChild(item_symbol) i++ } else { // console.log(`当前处理到CroSymbols ,curCrossIdx=${curCrossIdx}`) // console.log(`遇到了连体元素i=${i},curSymbolIdx = ${curSymbolIdx}`) const item_symbol = instantiate(this.item_symbol) let v = pan.Symbol.Middle[i] let length = curCross.PosLast - curCross.PosFirst + 1 // console.log(`${length}连框`) // 组件长度拉长 item_symbol.getComponent(UITransform).height = item_symbol.getComponent(UITransform).height * length; // 背景拉长 const bg = item_symbol.getChildByName("bg").getComponent(Sprite) const path_bg = `${v > 8 ? 8 : v}_${length}` bg.spriteFrame = this.symbolsAtlas.getSpriteFrame(path_bg); bg.node.getComponent(UITransform).height = bg.node.getComponent(UITransform).height * length; const symbol = item_symbol.getChildByName("symbol").getComponent(Sprite) const path_symbol = `${v}` symbol.spriteFrame = this.symbolsAtlas.getSpriteFrame(path_symbol) const frame = item_symbol.getChildByName("frame").getComponent(Sprite) if (curCross?.Type != 0) { let height = frame.node.getComponent(UITransform).height * length; const path_frame = `13_${length}` frame.spriteFrame = this.symbolsAtlas.getSpriteFrame(path_frame) frame.node.getComponent(UITransform).height = height; frame.node.active = true } else { frame.node.active = false } item_symbol.position = new Vec3() item_symbol.active = true // 通过 i 计算在第几行第几列 let tmp = i let row = tmp % EACH_LINE_MAX_SYMBOL let line = Math.floor(tmp / EACH_LINE_MAX_SYMBOL) // console.log(`第${i}个元素在,第${line}竖列,第${row}横行`) vert_symbols.children[line].addChild(item_symbol) curCross = sortArr.shift() curSymbolIdx = curCross?.PosFirst // 连体symbol的数据视为一个 i = i + length } } // No Winning Combination const node_no_winning = content.getChildByName("node_no_winning") node_no_winning.active = !pan.WinInfo // feature_buy const node_feature_buy = content.getChildByName("node_feature_buy") const isActive = this.data.isBuy && idx == 0 node_feature_buy.active = isActive //showMulti const showMultiNode = content.getChildByName('showMulti') let multiValue = pan.Symbol.MultiValue multiValue.push(multiValue[3] + 2) for (let i = 0; i < multiValue.length; i++) { showMultiNode.getChildByName('bg').children[i].getChildByName('multi').getComponent(Label).string = 'x' + multiValue[i] showMultiNode.getChildByName('bg').children[i].getChildByName('multi').setPosition(0, 0, 0) switch (true) { case multiValue[i] <= 4: showMultiNode.getChildByName('bg').children[i].getComponent(Sprite).spriteFrame = this.multiFrame[0] break case multiValue[i] <= 8 && multiValue[i] > 4: showMultiNode.getChildByName('bg').children[i].getComponent(Sprite).spriteFrame = this.multiFrame[1] break case multiValue[i] <= 16 && multiValue[i] > 8: showMultiNode.getChildByName('bg').children[i].getComponent(Sprite).spriteFrame = this.multiFrame[2] break case multiValue[i] > 16: showMultiNode.getChildByName('bg').children[i].getComponent(Sprite).spriteFrame = this.multiFrame[3] break } } if (pan.WinInfo && pan.WinInfo.MultPos) { for (let key in pan.WinInfo.MultPos) { showMultiNode.getChildByName('bg').children[key].getChildByName('multi').setPosition(0, 110, 0) } } // Win Multiplier x ? const node_win_multiplier = content.getChildByName("node_win_multiplier") const txt_win_multiplier = node_win_multiplier.getChildByName("txt_win_multiplier") if (pan.WinInfo && pan.WinInfo.Multi > 0) { let multi = pan.WinInfo.Multi == 0 ? 1 : pan.WinInfo.Multi txt_win_multiplier.getComponent(Label).string = getTranslate(this.dict, "Win Multiplier") + " x " + multi node_win_multiplier.active = true } else { node_win_multiplier.active = false } // scatter 数量统计 node_scatter if (pan.ScNum >= 4 && pan.GetGamesTimes >= 10) { const node_scatter = content.getChildByName("node_scatter") const txt_scatter_num = node_scatter.getChildByName("txt_scatter_num").getComponent(Label) txt_scatter_num.string = "x " + pan.ScNum const txt_free_spin = node_scatter.getChildByName("txt_free_spin").getComponent(Label) txt_free_spin.string = pan.GetGamesTimes + " " + getTranslate(this.dict, "Free Spins") node_scatter.active = true } else { const node_scatter = content.getChildByName("node_scatter") node_scatter.removeFromParent() node_scatter.destroy() } const symbolWinInfosKeys = pan.WinInfo ? Object.keys(pan.WinInfo.Desc) : [] // 赢分符号统计 if (symbolWinInfosKeys.length > 0) { const node_formula = content.getChildByName("node_formula") symbolWinInfosKeys.forEach((v) => { // console.log("symbol:", v, " = ", pan.SymbolWinInfos[v]) const symbolWinInfo = pan.WinInfo.Desc[v] const item_win_kind = instantiate(this.item_win_kind) item_win_kind.name = `item_win_kind_${v}` const sp = item_win_kind.getChildByName("sp").getComponent(Sprite) const path_symbol = `${v}` sp.spriteFrame = this.symbolsAtlas.getSpriteFrame(path_symbol) const txt_kind = item_win_kind.getChildByName("txt_kind").getComponent(Label) txt_kind.string = symbolWinInfo.WinAxisNum.toString() + " " + getTranslate(this.dict, "of a Kind") const txt_ways = item_win_kind.getChildByName("txt_ways").getComponent(Label) txt_ways.string = symbolWinInfo.Ways.toString() + " " + getTranslate(this.dict, "way(s)") const txt_win = item_win_kind.getChildByName("txt_win").getComponent(Label) txt_win.string = currencySymbol + fixNum(symbolWinInfo.Score) const txt_formula = item_win_kind.getChildByName("txt_formula").getComponent(Label) txt_formula.string = symbolWinInfo.Formula const formula_detail = item_win_kind.getChildByName("formula_detail") const txt_formual_detail = formula_detail.getChildByName("txt_formual_detail").getComponent(Label) txt_formual_detail.string = symbolWinInfo.FormulaDetail formula_detail.active = false item_win_kind.position = new Vec3() item_win_kind.active = true node_formula.addChild(item_win_kind) }) // 每一条 item_win_kind 可以点开 自己的 formula_detail // 要求列表前面的item_win_kind弹出来formula_detail ,盖住后面的 item_win_kind // 但 addChild的顺序决定后 后面会盖住前面,所以这里要反转一下 // 而且一定要关掉 Layout ,因为它会把 SiblingIndex最小的放到最上面 const lyt = node_formula.getComponent(Layout) lyt.updateLayout() lyt.enabled = false const children = node_formula.children.slice().reverse(); children.forEach((child, i) => { child.active = true child.setSiblingIndex(i); }); const contentlyt = content.getComponent(Layout) contentlyt.updateLayout() contentlyt.enabled = false // 多给一截滑动空间 content.getComponent(UITransform).height = content.getComponent(UITransform).height + 160 } hideAllChildren(item) } async loadDetailList() { // 时间 let pnl_title = this.node.getChildByName("pnl_title") let txt_time = pnl_title.getChildByName("txt_time").getComponent(Label) const timestamp = this.data.startTime; const date = new Date(timestamp * 1000); // JS 使用毫秒,所以要 *1000 const pad = (n: number) => (n < 10 ? '0' + n : String(n)); const formatted = `${date.getFullYear()}/${pad(date.getMonth() + 1)}/${pad(date.getDate())} ${pad(date.getHours())}:${pad(date.getMinutes())}`; let str = formatted + getTimezoneOffsetString() txt_time.string = str const currencySymbol = this.data.currencySymbol const currency = this.data.currency const scoreInfos = this.data.panDetails[0].ScoreInfos const btn_winning_list = this.pnl_title.getChildByName("txt_spin").getChildByName("btn_winning_list").getComponent(Button) const sp = this.pnl_title.getChildByName("txt_spin").getChildByName("sp") if (scoreInfos) { this.loadRoundWinningList(scoreInfos) btn_winning_list.interactable = true sp.active = true } else { btn_winning_list.interactable = false sp.active = false } this.data.panDetails.forEach(async (pan, idx) => { const item = instantiate(this.item_detail); item.active = true this.loadOne(item, pan, idx) if (idx == this.data.panDetails.length - 1) { // console.log("已全部生成完") this.hideLoading() this.scrollControl.jumpToPage(0) } // 等待下一帧再生成下一个 await waitNextFrame(); }) this.scrollControl.vert_scrollView = this.list_detail.content.children[0].getComponent(ScrollView) this.list_detail.node.active = true } // wild 是0, scatter 是1 isScatterOrWild(v) { return v == 0 || v == 1 } clickPageUp() { this.scrollControl.pageUp() } clickPageDown() { this.scrollControl.pageDown() } async entryFinish() { // this.node.children.forEach((node, i) => { // node.active = true // }) this.showLoading() await this.loadDetailList() } removeReturnBtn() { let btn_return = this.node.getChildByName("btn_return") btn_return.destroy() } clickReturn() { const self = this tween(this.node).to(0.2, { position: new Vec3(2000, 0) }) .call(() => { self.node.destroy() }) .start() } // 传过来的是 item_win_kind showFormulaDetail(item_win_kind) { // 隐藏其他的formula_detail item_win_kind.parent.children.forEach(child => { if (child != item_win_kind) child.getChildByName("formula_detail").active = false }) // 显示就隐藏,隐藏就显示 let isActive = item_win_kind.getChildByName("formula_detail").active item_win_kind.getChildByName("formula_detail").active = !isActive } // 传过来的是 item_win_kind showFormulaDetail2(event) { const btn = event.target as Node as any const item_win_kind = btn.parent // 隐藏其他的formula_detail item_win_kind.parent.children.forEach(child => { if (child != item_win_kind) child.getChildByName("formula_detail").active = false }) // 显示就隐藏,隐藏就显示 let isActive = item_win_kind.getChildByName("formula_detail").active item_win_kind.getChildByName("formula_detail").active = !isActive } hideFormulaDetail(scrollVeiw: ScrollView) { const node_formula = scrollVeiw.content.getChildByName("node_formula") node_formula.children.forEach(node => { node.getChildByName("formula_detail").active = false }) } showLoading() { this.loading.active = true let sk = this.loading.getComponent(sp.Skeleton) sk.paused = false sk.loop = true } hideLoading() { let sk = this.loading.getComponent(sp.Skeleton) sk.paused = true sk.loop = false this.loading.active = false } }