diff --git a/assets/resources/common/prefab/window.prefab b/assets/resources/common/prefab/window.prefab index af7c7e45..3cea5464 100644 --- a/assets/resources/common/prefab/window.prefab +++ b/assets/resources/common/prefab/window.prefab @@ -25,32 +25,29 @@ "__id__": 18 }, { - "__id__": 24 + "__id__": 26 }, { - "__id__": 32 + "__id__": 34 }, { "__id__": 40 - }, - { - "__id__": 65 } ], "_active": true, "_components": [ { - "__id__": 90 + "__id__": 96 }, { - "__id__": 92 + "__id__": 98 }, { - "__id__": 94 + "__id__": 100 } ], "_prefab": { - "__id__": 96 + "__id__": 102 }, "_lpos": { "__type__": "cc.Vec3", @@ -287,7 +284,7 @@ }, { "__type__": "cc.Node", - "_name": "Artboard 17", + "_name": "lab_title", "_objFlags": 0, "__editorExtras__": {}, "_parent": { @@ -301,15 +298,18 @@ }, { "__id__": 21 + }, + { + "__id__": 23 } ], "_prefab": { - "__id__": 23 + "__id__": 25 }, "_lpos": { "__type__": "cc.Vec3", "x": 0, - "y": 130.26, + "y": 113.594, "z": 0 }, "_lrot": { @@ -349,8 +349,8 @@ }, "_contentSize": { "__type__": "cc.Size", - "width": 344, - "height": 94 + "width": 84, + "height": 54.4 }, "_anchorPoint": { "__type__": "cc.Vec2", @@ -361,10 +361,10 @@ }, { "__type__": "cc.CompPrefabInfo", - "fileId": "4fLoJ+lN9Jrr78O7XQGMWV" + "fileId": "1c9xohlJtL3bm53voN5DeV" }, { - "__type__": "cc.Sprite", + "__type__": "cc.Label", "_name": "", "_objFlags": 0, "__editorExtras__": {}, @@ -385,147 +385,11 @@ "b": 255, "a": 255 }, - "_spriteFrame": null, - "_type": 0, - "_fillType": 0, - "_sizeMode": 0, - "_fillCenter": { - "__type__": "cc.Vec2", - "x": 0, - "y": 0 - }, - "_fillStart": 0, - "_fillRange": 0, - "_isTrimmedMode": true, - "_useGrayscale": false, - "_atlas": null, - "_id": "" - }, - { - "__type__": "cc.CompPrefabInfo", - "fileId": "6fxJxMkzBA7JMAxKtc/owq" - }, - { - "__type__": "cc.PrefabInfo", - "root": { - "__id__": 1 - }, - "asset": { - "__id__": 0 - }, - "fileId": "60K6iLGSlFhIT/OMCcExCn", - "instance": null, - "targetOverrides": null, - "nestedPrefabInstanceRoots": null - }, - { - "__type__": "cc.Node", - "_name": "lab_title", - "_objFlags": 0, - "__editorExtras__": {}, - "_parent": { - "__id__": 1 - }, - "_children": [], - "_active": true, - "_components": [ - { - "__id__": 25 - }, - { - "__id__": 27 - }, - { - "__id__": 29 - } - ], - "_prefab": { - "__id__": 31 - }, - "_lpos": { - "__type__": "cc.Vec3", - "x": 0, - "y": 127.961, - "z": 0 - }, - "_lrot": { - "__type__": "cc.Quat", - "x": 0, - "y": 0, - "z": 0, - "w": 1 - }, - "_lscale": { - "__type__": "cc.Vec3", - "x": 1, - "y": 1, - "z": 1 - }, - "_mobility": 0, - "_layer": 33554432, - "_euler": { - "__type__": "cc.Vec3", - "x": 0, - "y": 0, - "z": 0 - }, - "_id": "" - }, - { - "__type__": "cc.UITransform", - "_name": "", - "_objFlags": 0, - "__editorExtras__": {}, - "node": { - "__id__": 24 - }, - "_enabled": true, - "__prefab": { - "__id__": 26 - }, - "_contentSize": { - "__type__": "cc.Size", - "width": 64, - "height": 54.4 - }, - "_anchorPoint": { - "__type__": "cc.Vec2", - "x": 0.5, - "y": 0.5 - }, - "_id": "" - }, - { - "__type__": "cc.CompPrefabInfo", - "fileId": "1c9xohlJtL3bm53voN5DeV" - }, - { - "__type__": "cc.Label", - "_name": "", - "_objFlags": 0, - "__editorExtras__": {}, - "node": { - "__id__": 24 - }, - "_enabled": true, - "__prefab": { - "__id__": 28 - }, - "_customMaterial": null, - "_srcBlendFactor": 2, - "_dstBlendFactor": 4, - "_color": { - "__type__": "cc.Color", - "r": 255, - "g": 255, - "b": 255, - "a": 255 - }, "_string": "标题", "_horizontalAlign": 1, "_verticalAlign": 1, - "_actualFontSize": 30, - "_fontSize": 30, + "_actualFontSize": 40, + "_fontSize": 40, "_fontFamily": "Arial", "_lineHeight": 40, "_overflow": 0, @@ -573,11 +437,11 @@ "_objFlags": 0, "__editorExtras__": {}, "node": { - "__id__": 24 + "__id__": 18 }, - "_enabled": true, + "_enabled": false, "__prefab": { - "__id__": 30 + "__id__": 24 }, "_params": [], "_dataID": "", @@ -609,20 +473,20 @@ "__id__": 1 }, "_children": [], - "_active": true, + "_active": false, "_components": [ { - "__id__": 33 + "__id__": 27 }, { - "__id__": 35 + "__id__": 29 }, { - "__id__": 37 + "__id__": 31 } ], "_prefab": { - "__id__": 39 + "__id__": 33 }, "_lpos": { "__type__": "cc.Vec3", @@ -659,11 +523,11 @@ "_objFlags": 0, "__editorExtras__": {}, "node": { - "__id__": 32 + "__id__": 26 }, "_enabled": true, "__prefab": { - "__id__": 34 + "__id__": 28 }, "_contentSize": { "__type__": "cc.Size", @@ -687,11 +551,11 @@ "_objFlags": 0, "__editorExtras__": {}, "node": { - "__id__": 32 + "__id__": 26 }, "_enabled": true, "__prefab": { - "__id__": 36 + "__id__": 30 }, "_customMaterial": null, "_srcBlendFactor": 2, @@ -755,11 +619,11 @@ "_objFlags": 0, "__editorExtras__": {}, "node": { - "__id__": 32 + "__id__": 26 }, - "_enabled": true, + "_enabled": false, "__prefab": { - "__id__": 38 + "__id__": 32 }, "_params": [], "_dataID": "", @@ -784,7 +648,136 @@ }, { "__type__": "cc.Node", - "_name": "btn_ok", + "_name": "RichText", + "_objFlags": 0, + "__editorExtras__": {}, + "_parent": { + "__id__": 1 + }, + "_children": [], + "_active": true, + "_components": [ + { + "__id__": 35 + }, + { + "__id__": 37 + } + ], + "_prefab": { + "__id__": 39 + }, + "_lpos": { + "__type__": "cc.Vec3", + "x": 0, + "y": 12, + "z": 0 + }, + "_lrot": { + "__type__": "cc.Quat", + "x": 0, + "y": 0, + "z": 0, + "w": 1 + }, + "_lscale": { + "__type__": "cc.Vec3", + "x": 1, + "y": 1, + "z": 1 + }, + "_mobility": 0, + "_layer": 33554432, + "_euler": { + "__type__": "cc.Vec3", + "x": 0, + "y": 0, + "z": 0 + }, + "_id": "" + }, + { + "__type__": "cc.UITransform", + "_name": "", + "_objFlags": 0, + "__editorExtras__": {}, + "node": { + "__id__": 34 + }, + "_enabled": true, + "__prefab": { + "__id__": 36 + }, + "_contentSize": { + "__type__": "cc.Size", + "width": 400, + "height": 50.4 + }, + "_anchorPoint": { + "__type__": "cc.Vec2", + "x": 0.5, + "y": 0.5 + }, + "_id": "" + }, + { + "__type__": "cc.CompPrefabInfo", + "fileId": "25SQ94/IJJ3LSvMJUCXt4P" + }, + { + "__type__": "cc.RichText", + "_name": "", + "_objFlags": 0, + "__editorExtras__": {}, + "node": { + "__id__": 34 + }, + "_enabled": true, + "__prefab": { + "__id__": 38 + }, + "_lineHeight": 40, + "_string": "RichText", + "_horizontalAlign": 0, + "_verticalAlign": 0, + "_fontSize": 25, + "_fontColor": { + "__type__": "cc.Color", + "r": 46, + "g": 46, + "b": 46, + "a": 255 + }, + "_maxWidth": 400, + "_fontFamily": "Arial", + "_font": null, + "_isSystemFontUsed": true, + "_userDefinedFont": null, + "_cacheMode": 0, + "_imageAtlas": null, + "_handleTouchEvent": true, + "_id": "" + }, + { + "__type__": "cc.CompPrefabInfo", + "fileId": "5aGowcUTlNQYyiofmn8kEX" + }, + { + "__type__": "cc.PrefabInfo", + "root": { + "__id__": 1 + }, + "asset": { + "__id__": 0 + }, + "fileId": "13fawL78pI2oh31a1ts4i5", + "instance": null, + "targetOverrides": null, + "nestedPrefabInstanceRoots": null + }, + { + "__type__": "cc.Node", + "_name": "Node", "_objFlags": 0, "__editorExtras__": {}, "_parent": { @@ -795,31 +788,88 @@ "__id__": 41 }, { - "__id__": 47 + "__id__": 66 } ], "_active": true, "_components": [ { - "__id__": 55 + "__id__": 91 }, { - "__id__": 57 - }, - { - "__id__": 59 - }, - { - "__id__": 62 + "__id__": 93 } ], "_prefab": { - "__id__": 64 + "__id__": 95 }, "_lpos": { "__type__": "cc.Vec3", - "x": -89, - "y": -100, + "x": 0, + "y": -120.963, + "z": 0 + }, + "_lrot": { + "__type__": "cc.Quat", + "x": 0, + "y": 0, + "z": 0, + "w": 1 + }, + "_lscale": { + "__type__": "cc.Vec3", + "x": 1, + "y": 1, + "z": 1 + }, + "_mobility": 0, + "_layer": 33554432, + "_euler": { + "__type__": "cc.Vec3", + "x": 0, + "y": 0, + "z": 0 + }, + "_id": "" + }, + { + "__type__": "cc.Node", + "_name": "btn_ok", + "_objFlags": 0, + "__editorExtras__": {}, + "_parent": { + "__id__": 40 + }, + "_children": [ + { + "__id__": 42 + }, + { + "__id__": 48 + } + ], + "_active": true, + "_components": [ + { + "__id__": 56 + }, + { + "__id__": 58 + }, + { + "__id__": 60 + }, + { + "__id__": 63 + } + ], + "_prefab": { + "__id__": 65 + }, + "_lpos": { + "__type__": "cc.Vec3", + "x": -80, + "y": 10, "z": 0 }, "_lrot": { @@ -851,20 +901,20 @@ "_objFlags": 0, "__editorExtras__": {}, "_parent": { - "__id__": 40 + "__id__": 41 }, "_children": [], "_active": true, "_components": [ { - "__id__": 42 + "__id__": 43 }, { - "__id__": 44 + "__id__": 45 } ], "_prefab": { - "__id__": 46 + "__id__": 47 }, "_lpos": { "__type__": "cc.Vec3", @@ -901,11 +951,11 @@ "_objFlags": 0, "__editorExtras__": {}, "node": { - "__id__": 41 + "__id__": 42 }, "_enabled": true, "__prefab": { - "__id__": 43 + "__id__": 44 }, "_contentSize": { "__type__": "cc.Size", @@ -929,11 +979,11 @@ "_objFlags": 0, "__editorExtras__": {}, "node": { - "__id__": 41 + "__id__": 42 }, "_enabled": true, "__prefab": { - "__id__": 45 + "__id__": 46 }, "_customMaterial": null, "_srcBlendFactor": 2, @@ -987,23 +1037,23 @@ "_objFlags": 0, "__editorExtras__": {}, "_parent": { - "__id__": 40 + "__id__": 41 }, "_children": [], "_active": true, "_components": [ { - "__id__": 48 + "__id__": 49 }, { - "__id__": 50 + "__id__": 51 }, { - "__id__": 52 + "__id__": 53 } ], "_prefab": { - "__id__": 54 + "__id__": 55 }, "_lpos": { "__type__": "cc.Vec3", @@ -1040,11 +1090,11 @@ "_objFlags": 0, "__editorExtras__": {}, "node": { - "__id__": 47 + "__id__": 48 }, "_enabled": true, "__prefab": { - "__id__": 49 + "__id__": 50 }, "_contentSize": { "__type__": "cc.Size", @@ -1068,11 +1118,11 @@ "_objFlags": 0, "__editorExtras__": {}, "node": { - "__id__": 47 + "__id__": 48 }, "_enabled": true, "__prefab": { - "__id__": 51 + "__id__": 52 }, "_customMaterial": null, "_srcBlendFactor": 2, @@ -1136,11 +1186,11 @@ "_objFlags": 0, "__editorExtras__": {}, "node": { - "__id__": 47 + "__id__": 48 }, - "_enabled": true, + "_enabled": false, "__prefab": { - "__id__": 53 + "__id__": 54 }, "_params": [], "_dataID": "", @@ -1169,11 +1219,11 @@ "_objFlags": 0, "__editorExtras__": {}, "node": { - "__id__": 40 + "__id__": 41 }, "_enabled": true, "__prefab": { - "__id__": 56 + "__id__": 57 }, "_contentSize": { "__type__": "cc.Size", @@ -1197,11 +1247,11 @@ "_objFlags": 0, "__editorExtras__": {}, "node": { - "__id__": 40 + "__id__": 41 }, "_enabled": true, "__prefab": { - "__id__": 58 + "__id__": 59 }, "_customMaterial": null, "_srcBlendFactor": 2, @@ -1239,15 +1289,15 @@ "_objFlags": 0, "__editorExtras__": {}, "node": { - "__id__": 40 + "__id__": 41 }, "_enabled": true, "__prefab": { - "__id__": 60 + "__id__": 61 }, "clickEvents": [ { - "__id__": 61 + "__id__": 62 } ], "_interactable": true, @@ -1287,7 +1337,7 @@ "_duration": 0.1, "_zoomScale": 0.9, "_target": { - "__id__": 40 + "__id__": 41 }, "_id": "" }, @@ -1311,15 +1361,15 @@ "_objFlags": 0, "__editorExtras__": {}, "node": { - "__id__": 40 + "__id__": 41 }, - "_enabled": true, + "_enabled": false, "__prefab": { - "__id__": 63 + "__id__": 64 }, "_alignFlags": 12, "_target": null, - "_left": 100, + "_left": -13.5, "_right": 0, "_top": 0, "_bottom": 40, @@ -1360,38 +1410,38 @@ "_objFlags": 0, "__editorExtras__": {}, "_parent": { - "__id__": 1 + "__id__": 40 }, "_children": [ { - "__id__": 66 + "__id__": 67 }, { - "__id__": 72 + "__id__": 73 } ], "_active": true, "_components": [ { - "__id__": 80 + "__id__": 81 }, { - "__id__": 82 + "__id__": 83 }, { - "__id__": 84 + "__id__": 85 }, { - "__id__": 87 + "__id__": 88 } ], "_prefab": { - "__id__": 89 + "__id__": 90 }, "_lpos": { "__type__": "cc.Vec3", - "x": 89, - "y": -100, + "x": 80, + "y": 10, "z": 0 }, "_lrot": { @@ -1423,20 +1473,20 @@ "_objFlags": 0, "__editorExtras__": {}, "_parent": { - "__id__": 65 + "__id__": 66 }, "_children": [], "_active": true, "_components": [ { - "__id__": 67 + "__id__": 68 }, { - "__id__": 69 + "__id__": 70 } ], "_prefab": { - "__id__": 71 + "__id__": 72 }, "_lpos": { "__type__": "cc.Vec3", @@ -1473,11 +1523,11 @@ "_objFlags": 0, "__editorExtras__": {}, "node": { - "__id__": 66 + "__id__": 67 }, "_enabled": true, "__prefab": { - "__id__": 68 + "__id__": 69 }, "_contentSize": { "__type__": "cc.Size", @@ -1501,11 +1551,11 @@ "_objFlags": 0, "__editorExtras__": {}, "node": { - "__id__": 66 + "__id__": 67 }, "_enabled": true, "__prefab": { - "__id__": 70 + "__id__": 71 }, "_customMaterial": null, "_srcBlendFactor": 2, @@ -1559,23 +1609,23 @@ "_objFlags": 0, "__editorExtras__": {}, "_parent": { - "__id__": 65 + "__id__": 66 }, "_children": [], "_active": true, "_components": [ { - "__id__": 73 + "__id__": 74 }, { - "__id__": 75 + "__id__": 76 }, { - "__id__": 77 + "__id__": 78 } ], "_prefab": { - "__id__": 79 + "__id__": 80 }, "_lpos": { "__type__": "cc.Vec3", @@ -1612,11 +1662,11 @@ "_objFlags": 0, "__editorExtras__": {}, "node": { - "__id__": 72 + "__id__": 73 }, "_enabled": true, "__prefab": { - "__id__": 74 + "__id__": 75 }, "_contentSize": { "__type__": "cc.Size", @@ -1640,11 +1690,11 @@ "_objFlags": 0, "__editorExtras__": {}, "node": { - "__id__": 72 + "__id__": 73 }, "_enabled": true, "__prefab": { - "__id__": 76 + "__id__": 77 }, "_customMaterial": null, "_srcBlendFactor": 2, @@ -1708,11 +1758,11 @@ "_objFlags": 0, "__editorExtras__": {}, "node": { - "__id__": 72 + "__id__": 73 }, - "_enabled": true, + "_enabled": false, "__prefab": { - "__id__": 78 + "__id__": 79 }, "_params": [], "_dataID": "", @@ -1741,11 +1791,11 @@ "_objFlags": 0, "__editorExtras__": {}, "node": { - "__id__": 65 + "__id__": 66 }, "_enabled": true, "__prefab": { - "__id__": 81 + "__id__": 82 }, "_contentSize": { "__type__": "cc.Size", @@ -1769,11 +1819,11 @@ "_objFlags": 0, "__editorExtras__": {}, "node": { - "__id__": 65 + "__id__": 66 }, "_enabled": true, "__prefab": { - "__id__": 83 + "__id__": 84 }, "_customMaterial": null, "_srcBlendFactor": 2, @@ -1811,15 +1861,15 @@ "_objFlags": 0, "__editorExtras__": {}, "node": { - "__id__": 65 + "__id__": 66 }, "_enabled": true, "__prefab": { - "__id__": 85 + "__id__": 86 }, "clickEvents": [ { - "__id__": 86 + "__id__": 87 } ], "_interactable": true, @@ -1859,7 +1909,7 @@ "_duration": 0.1, "_zoomScale": 0.9, "_target": { - "__id__": 65 + "__id__": 66 }, "_id": "" }, @@ -1883,16 +1933,16 @@ "_objFlags": 0, "__editorExtras__": {}, "node": { - "__id__": 65 + "__id__": 66 }, - "_enabled": true, + "_enabled": false, "__prefab": { - "__id__": 88 + "__id__": 89 }, "_alignFlags": 36, "_target": null, "_left": 0, - "_right": 100, + "_right": -13.5, "_top": 0, "_bottom": 40, "_horizontalCenter": 0, @@ -1926,6 +1976,85 @@ "targetOverrides": null, "nestedPrefabInstanceRoots": null }, + { + "__type__": "cc.UITransform", + "_name": "", + "_objFlags": 0, + "__editorExtras__": {}, + "node": { + "__id__": 40 + }, + "_enabled": true, + "__prefab": { + "__id__": 92 + }, + "_contentSize": { + "__type__": "cc.Size", + "width": 260, + "height": 100 + }, + "_anchorPoint": { + "__type__": "cc.Vec2", + "x": 0.5, + "y": 0.5 + }, + "_id": "" + }, + { + "__type__": "cc.CompPrefabInfo", + "fileId": "26SRNQRwZAJoZKE9xRMNp+" + }, + { + "__type__": "cc.Layout", + "_name": "", + "_objFlags": 0, + "__editorExtras__": {}, + "node": { + "__id__": 40 + }, + "_enabled": true, + "__prefab": { + "__id__": 94 + }, + "_resizeMode": 1, + "_layoutType": 1, + "_cellSize": { + "__type__": "cc.Size", + "width": 40, + "height": 40 + }, + "_startAxis": 0, + "_paddingLeft": 0, + "_paddingRight": 0, + "_paddingTop": 0, + "_paddingBottom": 0, + "_spacingX": 60, + "_spacingY": 0, + "_verticalDirection": 1, + "_horizontalDirection": 0, + "_constraint": 0, + "_constraintNum": 2, + "_affectedByScale": false, + "_isAlign": false, + "_id": "" + }, + { + "__type__": "cc.CompPrefabInfo", + "fileId": "daVv83R/FPf66ixTjCR4m7" + }, + { + "__type__": "cc.PrefabInfo", + "root": { + "__id__": 1 + }, + "asset": { + "__id__": 0 + }, + "fileId": "4cQc5j6SxEfqIZHoPnjEPN", + "instance": null, + "targetOverrides": null, + "nestedPrefabInstanceRoots": null + }, { "__type__": "cc.UITransform", "_name": "", @@ -1936,7 +2065,7 @@ }, "_enabled": true, "__prefab": { - "__id__": 91 + "__id__": 97 }, "_contentSize": { "__type__": "cc.Size", @@ -1964,7 +2093,7 @@ }, "_enabled": true, "__prefab": { - "__id__": 93 + "__id__": 99 }, "_customMaterial": null, "_srcBlendFactor": 2, @@ -1997,7 +2126,7 @@ "fileId": "a0vC/W2QdFb7e69t18Gf21" }, { - "__type__": "653bf8VPC5Fn49zFJFqXVgx", + "__type__": "8c571eVD/lHZa1+Hefxzcs8", "_name": "", "_objFlags": 0, "__editorExtras__": {}, @@ -2006,25 +2135,25 @@ }, "_enabled": true, "__prefab": { - "__id__": 95 + "__id__": 101 }, "lab_title": { - "__id__": 29 + "__id__": 21 }, "lab_content": { "__id__": 37 }, "lab_ok": { - "__id__": 52 + "__id__": 51 }, "lab_cancel": { - "__id__": 77 + "__id__": 76 }, "_id": "" }, { "__type__": "cc.CompPrefabInfo", - "fileId": "e0auVYS4NJEJyKsqISdog5" + "fileId": "77iyThOpFEQp0+W7mtNN5D" }, { "__type__": "cc.PrefabInfo", diff --git a/assets/script/game/common/CommonPrompt.ts b/assets/script/game/common/CommonPrompt.ts new file mode 100644 index 00000000..5d15f46e --- /dev/null +++ b/assets/script/game/common/CommonPrompt.ts @@ -0,0 +1,226 @@ +/** + * @file CommonPrompt.ts + * @description 自定义公共确认窗口组件(UI 视图层) + * + * 职责: + * 1. 替换框架插件 CommonPrompt(extensions/oops-plugin-framework/.../CommonPrompt.ts), + * 脚本类名、onTouchEnd 处理器与 4 个属性名保持同名,window.prefab 无需改动即可自动重链。 + * 2. 内容区由 cc.Label 升级为 cc.RichText,支持 // 等富文本标签。 + * 3. 扩展标题样式、窗体缩放动画、遮罩点击关闭等自定义能力。 + * + * 使用(oops.gui 模块): + * oops.gui.open(UIID.Window, { + * title: "标题", + * content: "支持 富文本", + * okWord: "确定", cancelWord: "取消", needCancel: true, + * okFunc: () => {}, cancelFunc: () => {}, + * titleColor: "#FF0000", // 可选:标题颜色 + * maskClose: true, // 可选:点击空白遮罩关闭(等同取消) + * closeFunc: () => {} // 可选:任意方式关闭后的统一回调 + * }); + */ +import { _decorator, Button, Color, Component, EventTouch, Label, Node, NodeEventType, RichText, Tween, tween, Vec3 } from "cc"; +import { oops } from "db://oops-framework/core/Oops"; + +const { ccclass, property } = _decorator; + +/** 确认窗口参数 */ +export interface WindowPromptParams { + /** 标题(普通文本) */ + title?: string; + /** 内容(RichText 富文本,支持 //// 等标签) */ + content?: string; + /** 确定按钮文字 */ + okWord?: string; + /** 确定回调 */ + okFunc?: () => void; + /** 取消按钮文字 */ + cancelWord?: string; + /** 取消回调 */ + cancelFunc?: () => void; + /** 是否显示取消按钮 */ + needCancel?: boolean; + /** 标题颜色(如 "#FF0000",不传用默认色) */ + titleColor?: string; + /** 点击窗体外空白遮罩是否关闭(等同取消,默认 false) */ + maskClose?: boolean; + /** 任意方式关闭后的统一回调(在 okFunc/cancelFunc 之后触发) */ + closeFunc?: () => void; +} + +/** + * CommonPrompt —— 自定义公共确认窗口 + * + * 与 window.prefab 的绑定约定: + * - 根节点按钮事件 handler:onTouchEnd(btn_ok / btn_cancel 已绑定) + * - 属性名:lab_title / lab_content / lab_ok / lab_cancel + * - lab_content 需将 prefab 中的 cc.Label 替换为 cc.RichText 后拖入 + */ +@ccclass("CommonPrompt") +export class CommonPrompt extends Component { + /** 窗口标题 */ + @property(Label) + private lab_title: Label | null = null; + + /** 窗口内容(富文本,需在 prefab 中将 Label 换为 RichText 后重新拖入) */ + @property(RichText) + private lab_content: RichText | null = null; + + /** 确定按钮文本 */ + @property(Label) + private lab_ok: Label | null = null; + + /** 取消按钮文本 */ + @property(Label) + private lab_cancel: Label | null = null; + + /** 运行时参数 */ + private config: WindowPromptParams = {}; + + /** 弹窗打开动画已播放标记(防止 onAdded 重复触发) */ + private animPlayed: boolean = false; + + /** 代码动态绑定的确定按钮(prefab clickEvents 失效时的兜底) */ + private btnOk: Node | null = null; + /** 代码动态绑定的取消按钮 */ + private btnCancel: Node | null = null; + + onLoad() { + // 兜底:prefab 中 clickEvents 引用的旧插件脚本被移除后,代码动态绑定保证按钮可用 + this.btnOk = this.node.getChildByName("Node")?.getChildByName("btn_ok") ?? null; + this.btnCancel = this.node.getChildByName("Node")?.getChildByName("btn_cancel") ?? null; + this.btnOk?.on(Button.EventType.CLICK, this.onOk, this); + this.btnCancel?.on(Button.EventType.CLICK, this.onCancel, this); + // 遮罩点击关闭(btn_sky 为 btn_ok 内嵌子节点,无 Button 组件,直接监听触摸事件) + this.btnOk?.getChildByName("btn_sky")?.on(NodeEventType.TOUCH_END, this.onMaskClick, this); + + // 序列化属性槽引用的是旧插件 LanguageLabel 组件实例,脚本替换后已失效; + // 这里按节点名查找 Label/RichText 作为兜底,保证文字一定写入 + if (!this.lab_title) { + this.lab_title = this.node.getChildByName("lab_title")?.getComponent(Label) ?? null; + } + if (!this.lab_ok) { + this.lab_ok = this.btnOk?.getChildByName("lab_ok")?.getComponent(Label) ?? null; + } + if (!this.lab_cancel) { + this.lab_cancel = this.btnCancel?.getChildByName("lab_cancel")?.getComponent(Label) ?? null; + } + if (!this.lab_content) { + this.lab_content = this.node.getChildByName("lab_content")?.getComponent(RichText) ?? null; + } + + // 禁用旧插件残留的 LanguageLabel 组件:其 update 会用空 dataID 每帧覆盖 Label 文本 + this.disableLegacyLanguageLabels(this.lab_title?.node); + this.disableLegacyLanguageLabels(this.lab_ok?.node); + this.disableLegacyLanguageLabels(this.lab_cancel?.node); + this.disableLegacyLanguageLabels(this.lab_content?.node); + } + + /** 禁用节点上残留的 LanguageLabel(旧插件组件,类名带 LanguageLabel 后缀) */ + private disableLegacyLanguageLabels(node: Node | null | undefined) { + if (!node || !node.isValid) return; + for (const comp of node.components) { + if (comp.constructor.name === "LanguageLabel") { + comp.enabled = false; + } + } + } + + onDestroy() { + this.btnOk?.off(Button.EventType.CLICK, this.onOk, this); + this.btnCancel?.off(Button.EventType.CLICK, this.onCancel, this); + Tween.stopAllByTarget(this.node); + this.config = {}; + } + + /** + * oops.gui 添加到舞台回调(框架约定入口) + * @param params 见 WindowPromptParams + */ + onAdded(params: WindowPromptParams = {}) { + this.config = params || {}; + this.setTitle(); + this.setContent(); + this.setBtnOkLabel(); + this.setBtnCancelLabel(); + this.node.active = true; + this.playOpenAnim(); + } + + /** 按钮点击处理器(window.prefab 中 btn_ok / btn_cancel 的 clickEvents 绑定此方法) */ + private onTouchEnd(event: EventTouch) { + switch (event.target.name) { + case "btn_ok": + this.onOk(); + break; + case "btn_cancel": + this.onCancel(); + break; + default: + break; + } + } + + /** 遮罩(btn_sky)点击:仅当 maskClose 开启时按取消处理 */ + private onMaskClick() { + if (this.config.maskClose) { + this.onCancel(); + } + } + + private setTitle() { + if (!this.lab_title || !this.lab_title.isValid) return; + this.lab_title.string = this.config.title ?? ""; + if (this.config.titleColor) { + this.lab_title.color = new Color().fromHEX(this.config.titleColor); + } + } + + private setContent() { + if (!this.lab_content || !this.lab_content.isValid) return; + this.lab_content.string = this.config.content ?? ""; + } + + private setBtnOkLabel() { + if (!this.lab_ok || !this.lab_ok.isValid) return; + this.lab_ok.string = this.config.okWord ?? "确定"; + } + + private setBtnCancelLabel() { + if (!this.lab_cancel || !this.lab_cancel.isValid) return; + this.lab_cancel.string = this.config.cancelWord ?? "取消"; + // 取消按钮挂在 lab_cancel 的父节点上 + const cancelBtn = this.lab_cancel.node?.parent; + if (cancelBtn && cancelBtn.isValid) { + cancelBtn.active = this.config.needCancel || false; + } + } + + /** 打开动画:缩放 0.8 → 1 回弹 */ + private playOpenAnim() { + if (this.animPlayed) return; + this.animPlayed = true; + Tween.stopAllByTarget(this.node); + this.node.setScale(0.8, 0.8, 1); + tween(this.node) + .to(0.15, { scale: new Vec3(1, 1, 1) }, { easing: "backOut" }) + .start(); + } + + private onOk() { + oops.audio.playEffect("music/button"); + this.config.okFunc?.(); + this.close(); + } + + private onCancel() { + oops.audio.playEffect("music/button"); + this.config.cancelFunc?.(); + this.close(); + } + + private close() { + this.config.closeFunc?.(); + oops.gui.removeByNode(this.node); + } +} diff --git a/assets/script/game/common/CommonPrompt.ts.meta b/assets/script/game/common/CommonPrompt.ts.meta new file mode 100644 index 00000000..409735bf --- /dev/null +++ b/assets/script/game/common/CommonPrompt.ts.meta @@ -0,0 +1,9 @@ +{ + "ver": "4.0.24", + "importer": "typescript", + "imported": true, + "uuid": "8c571795-0ff9-4765-ad7e-1de7f1cdcb3c", + "files": [], + "subMetas": {}, + "userData": {} +} diff --git a/assets/script/game/common/config/GameUIConfig.ts b/assets/script/game/common/config/GameUIConfig.ts index 61d79742..6f19940a 100644 --- a/assets/script/game/common/config/GameUIConfig.ts +++ b/assets/script/game/common/config/GameUIConfig.ts @@ -12,6 +12,8 @@ export enum UIID { Loading = 1, /** 加载与延时提示界面 */ Netinstable, + /** 公共确认窗口(标题 + 内容 + 确定/取消) */ + Window, /** 角色控制 */ Role_Controller, Victory, @@ -34,6 +36,7 @@ export enum UIID { export var UIConfigData: { [key: number]: UIConfig } = { [UIID.Loading]: { layer: LayerType.UI, prefab: "loading/prefab/loading", bundle: "resources" }, [UIID.Netinstable]: { layer: LayerType.PopUp, prefab: "common/prefab/netinstable" }, + [UIID.Window]: { layer: LayerType.Dialog, prefab: "common/prefab/window" }, [UIID.Role_Controller]: { layer: LayerType.UI, prefab: "gui/role_controller" }, [UIID.Victory]: { layer: LayerType.UI, prefab: "gui/element/victory" }, [UIID.IBox]: { layer: LayerType.PopUp, prefab: "gui/element/ibox" }, diff --git a/assets/script/game/map/HeroBoxComp.ts b/assets/script/game/map/HeroBoxComp.ts index 1b24cafe..31eeb902 100644 --- a/assets/script/game/map/HeroBoxComp.ts +++ b/assets/script/game/map/HeroBoxComp.ts @@ -23,6 +23,7 @@ import { Hero } from "../hero/Hero"; import { getLvColor } from "../common/config/GameSet"; import { buildSkillDescRich } from "../common/config/HeroSkillDesc"; import { MissionEconomy } from "./MissionEconomy"; +import { UIID } from "../common/config/GameUIConfig"; const { ccclass, property } = _decorator; @@ -183,19 +184,42 @@ export class HeroBoxComp extends CCComp { } /** - * 出售按钮点击:移除英雄实体、按等级结算金币并派发 HeroSell 事件。 - * MissionCardComp 监听该事件后会刷新槽位,本盒自动切为空状态。 + * 出售按钮点击:弹出公共确认窗口,确认后再执行出售。 + * Why: 出售不可逆,需二次确认防止误触。 */ private onSellHeroClick() { + if (!this.eid || !this.model) return; + oops.audio.playEffect("music/button"); + + const heroName = this.model.hero_name ?? ""; + const heroLv = Math.max(1, Math.floor(this.model.lv ?? 1)); + const gold = MissionEconomy.getSellGold(heroLv); + + // oops.gui 公共确认窗口(自定义 CommonPrompt:内容支持富文本高亮) + oops.gui.open(UIID.Window, { + title: "出售英雄", + content: `确定出售 ${heroName}(Lv.${heroLv})吗?\n出售后获得 ${gold} 金币`, + okWord: "出售", + cancelWord: "取消", + needCancel: true, + okFunc: () => this.executeSellHero() + }); + } + + /** + * 执行出售:移除英雄实体、按等级结算金币并派发 HeroSell 事件。 + * MissionCardComp 监听该事件后会刷新槽位,本盒自动切为空状态。 + */ + private executeSellHero() { + // 确认窗口打开期间英雄可能已死亡/被移除,需二次校验 if (!this.eid || !this.model) return; const heroLv = Math.max(1, Math.floor(this.model.lv ?? 1)); // 移除 ECS 实体失败(实体已失效)则不做后续结算 if (!Hero.removeByEid(this.eid)) return; - oops.audio.playEffect("music/button"); // 统一经济管理入口:按等级计算卖价并加金币 const gold = MissionEconomy.executeSellHero(heroLv); - mLogger.log(this.debugMode, "HeroBoxComp", "onSellHeroClick", { eid: this.eid, heroLv, gold }); + mLogger.log(this.debugMode, "HeroBoxComp", "executeSellHero", { eid: this.eid, heroLv, gold }); // 通知 MissionCardComp 更新场上英雄数量并刷新英雄盒槽位 oops.message.dispatchEvent(GameEvent.HeroSell, { eid: this.eid });