HallwayChat.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354
  1. //导入用户信息类
  2. cc.Class({
  3. extends: cc.BaseClass,
  4. properties: {
  5. //左侧标签按钮
  6. // hallTab: {
  7. // default: null,
  8. // type: cc.Button,
  9. // displayName: '大厅聊天标签'
  10. // },
  11. // privateChatTab: {
  12. // default: null,
  13. // type: cc.Button,
  14. // displayName: '私聊聊天标签'
  15. // },
  16. //聊天滚动区
  17. ScrollView: {
  18. default: null,
  19. type: cc.ScrollView,
  20. displayName: '消息滚动视图'
  21. },
  22. content: {
  23. default: null,
  24. type: cc.Node,
  25. displayName: '消息内容容器'
  26. },
  27. // 消息项预制体
  28. itemOtherPrefab: {
  29. default: null,
  30. type: cc.Prefab,
  31. displayName: '消息项'
  32. },
  33. // 输入区
  34. inputBox: {
  35. default: null,
  36. type: cc.EditBox,
  37. displayName: '输入框'
  38. },
  39. sendBtn: {
  40. default: null,
  41. type: cc.Button,
  42. displayName: '发送按钮'
  43. },
  44. //添加快捷聊天按钮
  45. quickChatBtn: {
  46. default: null,
  47. type: cc.Button,
  48. displayName: '快捷聊天按钮'
  49. },
  50. //快捷聊天消息面板
  51. quickChatPanel: {
  52. default: null,
  53. type: cc.Node,
  54. displayName: '快捷聊天面板'
  55. },
  56. //快捷聊天消息列表
  57. quickChatList: {
  58. default: null,
  59. type: cc.Node,
  60. displayName: '快捷聊天列表'
  61. },
  62. // quickChatMessages: [
  63. // '大家好!',
  64. // '玩得开心!',
  65. // '这把牌不错!',
  66. // '加油!',
  67. // '谢谢!',
  68. // '不好意思,有点事',
  69. // '稍等一下',
  70. // '继续继续',
  71. // '这把运气不错',
  72. // '下次再玩'
  73. // ],
  74. },
  75. SetHook: function (Hook) {
  76. this.m_Hook = Hook;
  77. },
  78. start() {
  79. // 注册聊天消息接收回调
  80. this.registerChatCallback();
  81. },
  82. onLoad() {
  83. },
  84. bindEvents() {
  85. // 绑定发送按钮
  86. if (this.sendBtn) {
  87. this.sendBtn.node.on('click', this.onClickSendMessage, this);
  88. }
  89. // 绑定输入框回车事件
  90. if (this.inputBox) {
  91. this.inputBox.node.on('editing-return', this.onClickSendMessage, this);
  92. }
  93. // 绑定快捷聊天按钮
  94. if (this.quickChatBtn) {
  95. this.quickChatBtn.node.on('click', this.onClickQuickChat, this);
  96. }
  97. // 绑定快捷聊天列表项点击事件
  98. if (this.quickChatList) {
  99. for (let i = 0; i < this.quickChatList.childrenCount; i++) {
  100. this.quickChatList.children[i].on('click', this.onClickQuickChatItem, this);
  101. }
  102. }
  103. },
  104. // 注册聊天消息接收回调
  105. registerChatCallback: function () {
  106. // 保存原始回调函数
  107. var originalChatCallback = window.gClubClientKernel.onSocketChat;
  108. // 重写聊天消息接收回调
  109. window.gClubClientKernel.onSocketChat = function (data, size) {
  110. // 先调用原始回调
  111. var result = originalChatCallback.call(this, data, size);
  112. // 处理聊天消息显示
  113. var chatObj = new CMD_S_UserChat();
  114. gCByte.Bytes2Str(chatObj, data);
  115. // 显示聊天消息
  116. this.onReceiveChatMessage(chatObj.dwSendUserID, chatObj.szChatString);
  117. return result;
  118. }.bind(this);
  119. },
  120. // 接收聊天消息并显示
  121. onReceiveChatMessage: async function (sendUserID, message) {
  122. // 获取发送者信息
  123. let webUrl = window.PHP_HOME + '/UserFunc.php?GetMark=12&dwUserID=' + sendUserID;
  124. WebCenter.GetData(webUrl, null, function (data) {
  125. var senderInfo = JSON.parse(data);
  126. // 获取发送者昵称
  127. var senderName = senderInfo.NickName;
  128. //获取发送者头像URL
  129. var senderHeadUrl = senderInfo.HeadUrl;
  130. // 创建消息项并显示
  131. this.createChatItem(senderName, message, sendUserID, senderHeadUrl);
  132. // var senderInfo = await this.getUserInfo(sendUserID);
  133. }.bind(this));
  134. },
  135. // 创建聊天消息项
  136. createChatItem: function (senderName, message, userID, senderHeadUrl) {
  137. // 克隆消息项模板
  138. var chatItem = cc.instantiate(this.itemOtherPrefab);
  139. // 添加到内容容器
  140. this.content.addChild(chatItem);
  141. //设置消息项的的整体位置
  142. this.updateChatItem(chatItem);
  143. // 设置发送时间
  144. var labelTime = chatItem.getChildByName('LabelTime');
  145. if (labelTime) {
  146. var now = new Date();
  147. var timeString = now.getHours().toString().padStart(2, '0') + ':' +
  148. now.getMinutes().toString().padStart(2, '0');
  149. labelTime.getComponent(cc.Label).string = timeString;
  150. }
  151. // 设置发送者昵称
  152. var Labelname = chatItem.getChildByName('LabelName');
  153. if (Labelname) {
  154. Labelname.getComponent(cc.Label).string = senderName;
  155. }
  156. // 设置发送者头像
  157. var spriteAvater = chatItem.getChildByName('LabelName').getChildByName('SpriteAvater');
  158. // 设置消息内容
  159. var spriteChat = chatItem.getChildByName('SpriteChat');
  160. if (spriteChat) {
  161. // 设置消息内容文本
  162. var chatLabel = spriteChat.getChildByName('LabelChat')
  163. var chatLabelStr = chatLabel.getComponent(cc.Label);
  164. if (chatLabelStr) {
  165. // 设置Label文本内容
  166. chatLabelStr.string = message;
  167. //设置气泡框跟随文字大小变化
  168. this.setChatBubbleSize(chatLabelStr, spriteChat);
  169. }
  170. }
  171. // 更新滚动视图位置,滚动到底部
  172. this.autoScrollToBottom();
  173. },
  174. //更新消息项的子节点的大小和位置(也可以修改样式之类的属性)
  175. updateChatItem(chatItem) {
  176. //获取消息项下的所有子节点
  177. var children = chatItem.children;
  178. //时间文本
  179. //昵称文本 设置文字大小
  180. children[2].getComponent(cc.Label).fontSize = 20;
  181. //气泡文本
  182. //设置文字大小
  183. children[3].getChildByName('LabelChat').getComponent(cc.Label).fontSize = 40;
  184. },
  185. //设置气泡框跟随文字大小变化
  186. setChatBubbleSize(chatLabelStr, spriteChat) {
  187. //等待一帧让Label渲染完成,然后调整气泡框大小
  188. this.scheduleOnce(() => {
  189. // 使用Canvas API精确测量文本尺寸
  190. var textWidth = 0;
  191. var textHeight = 0;
  192. //文本框的最大宽度
  193. var maxWidth = 724;
  194. // 获取Label的字体设置
  195. var fontSize = chatLabelStr.fontSize;
  196. var fontFamily = 'Arial'; // 默认字体
  197. // 创建临时canvas来测量文本
  198. var canvas = document.createElement('canvas');
  199. var ctx = canvas.getContext('2d');
  200. // 设置字体样式
  201. ctx.font = fontSize + 'px ' + fontFamily;
  202. // 分割文本为多行
  203. var lines = chatLabelStr.string.split('\n');
  204. var maxLineWidth = 0;
  205. // 测量每行文本的宽度
  206. for (var i = 0; i < lines.length; i++) {
  207. var metrics = ctx.measureText(lines[i]);
  208. if (metrics.width > maxLineWidth) {
  209. maxLineWidth = metrics.width;
  210. }
  211. }
  212. textWidth = maxLineWidth;
  213. textHeight = lines.length * fontSize + (lines.length - 1) * 10; // 行间距为5px
  214. //获取文本框的大小
  215. var textsize = chatLabelStr.node.getContentSize();
  216. //获取气泡框的大小
  217. var bubbleSize = spriteChat.getContentSize();
  218. //设置气泡框的新大小 和文本框的新大小
  219. if (textWidth > 724) {
  220. //设置气泡框的新大小
  221. spriteChat.setContentSize(maxWidth + 20, textsize.height);
  222. //设置文本框的新大小
  223. chatLabelStr.node.setContentSize(maxWidth, textsize.height + 20);
  224. } else {
  225. //设置气泡框的新大小
  226. spriteChat.setContentSize(textWidth + 20, textHeight + 20);
  227. //设置文本框的新大小
  228. chatLabelStr.node.setContentSize(textWidth, textHeight);
  229. }
  230. // console.log('======================', this.content);
  231. //获取换行之后的行数
  232. var lineCount = this.getLineCount(chatLabelStr.string, maxWidth);
  233. // if (lineCount >= 3) {
  234. // //增加下个消息项之间的上下间距
  235. // var layout = this.content.getComponent(cc.Layout);
  236. // layout.paddingBottom = 20;
  237. // }
  238. }, 0.1); // 延迟0.1秒执行,确保文字渲染完成
  239. },
  240. //计算获取换行之后文本的行数
  241. getLineCount(text, maxWidth) {
  242. var text = text;
  243. var fontSize = 40;
  244. // 创建Canvas进行测量
  245. var canvas = document.createElement('canvas');
  246. var ctx = canvas.getContext('2d');
  247. ctx.font = fontSize + 'px Arial';
  248. var words = text.split('');
  249. var currentLine = '';
  250. var lines = [];
  251. for (var i = 0; i < words.length; i++) {
  252. var testLine = currentLine + words[i];
  253. var metrics = ctx.measureText(testLine);
  254. // 如果超过最大宽度,换行
  255. if (metrics.width > maxWidth && currentLine !== '') {
  256. lines.push(currentLine);
  257. currentLine = words[i];
  258. } else {
  259. currentLine = testLine;
  260. }
  261. }
  262. // 添加最后一行
  263. if (currentLine !== '') {
  264. lines.push(currentLine);
  265. }
  266. return lines.length;
  267. },
  268. // 自动滚动到底部
  269. autoScrollToBottom() {
  270. this.scheduleOnce(() => {
  271. // 设置ScrollView的垂直滚动位置为0(底部)
  272. // Cocos2.4中,ScrollView的verticalScrollOffset:0=底部,最大值=顶部
  273. this.ScrollView.verticalScrollOffset = 0;
  274. // 强制刷新ScrollView
  275. this.ScrollView.scrollToBottom(0.1); // 0.1秒平滑滚动,传0则瞬间到位
  276. }, 0); // 延迟0帧,等待UI布局更新完成
  277. },
  278. // 点击发送聊天消息
  279. onClickSendMessage() {
  280. // console.log('=====发送按钮点击');
  281. const message = this.inputBox ? this.inputBox.string.trim() : '';
  282. if (!message) {
  283. return;
  284. }
  285. //获取用户ID - 从全局用户信息中获取当前登录用户的真实ID
  286. const userID = g_GlobalUserInfo ? g_GlobalUserInfo.GetGlobalUserData().dwUserID : 0;
  287. if (!userID) {
  288. console.error('无法获取当前用户ID,用户可能未登录');
  289. return;
  290. }
  291. // 这里调用发送消息的方法
  292. window.gClubClientKernel.onSendChat(userID, message);
  293. //点击发送按钮时,调用发送消息方法,会将输入框的信息清空
  294. this.clearInput();
  295. },
  296. //点击快捷聊天按钮,
  297. onClickQuickChat(event, customEventData) {
  298. // console.log('=====快捷聊天按钮点击');
  299. // console.log('快捷聊天按钮点击===>', this.quickChatList.childrenCount);
  300. //显示快捷聊天面板
  301. if (this.quickChatPanel) {
  302. this.quickChatPanel.active = true;
  303. }
  304. },
  305. //快速选择聊天文本项点击事件
  306. onClickQuickChatItem(event) {
  307. // console.log('=====快捷聊天文本项点击');
  308. //获取孩子节点
  309. var labelnode = event.target.children[0].children[0];
  310. //获取对应的聊天消息
  311. var message = labelnode.getComponent(cc.Label).string;
  312. if (message) {
  313. //将消息设置到输入框
  314. this.inputBox.string = message;
  315. }
  316. //隐藏快捷聊天面板
  317. if (this.quickChatPanel) {
  318. this.quickChatPanel.active = false;
  319. }
  320. },
  321. clearInput() {
  322. if (this.inputBox) {
  323. this.inputBox.string = '';
  324. }
  325. },
  326. });