SendMessage和PostMessage 的区别

本文详细阐述了Windows消息处理机制中的两种关键函数:SendMessage与PostMessage的区别。包括它们的返回值含义、同步与异步特性、同一及不同线程间的处理方式、消息队列限制等内容。
 

1、首先是返回值意义的区别,我们先看一下 MSDN 里的声明:

LRESULT SendMessage(
        HWND hWnd,
        UINT Msg,
        WPARAM wParam,
        LPARAM lParam
);
BOOL PostMessage(
        HWND hWnd,
        UINT Msg,
        WPARAM wParam,
        LPARAM lParam
);

  其中 个参数的意义是一样的,返回值类型不同(其实从数据上看他们一样是一个 32 位的数,只是意义不一样),LRESULT 表示的是消息被处理后的返回值,BOOL 表示的是消息是不是 Post 成功。

2、PostMessage 是异步的,SendMessage 是同步的。
  PostMessage 只把消息放入队列,不管消息是否被处理就返回,消息可能不被处理;而 SendMessage 等待消息被处理完了之后才返回,如果消息不被处理,发送消息的线程将一直被阻塞。

3、如果在同一个线程内,SendMessage 发送消息时,由 USER32.DLL 模块调用目标窗口的消息处理程序,并将结果返回。SendMessage 在同一线程中发送消息并不入线程消息队列。PostMessage 发送消息时,消息要先放入线程的消息队列,然后通过消息循环分派到目标窗口(DispatchMessage)。

  如果在不同线程内,SendMessage 发送消息到目标窗口所属线程的消息队列,然后发送消息的线程在 USER32.DLL 模块内监视和等待消息处理,直到目标窗口处理完返回。SendMessage 在返回前还做了很多工作,比如,响应别的线程向它 SendMessage。Post 到别的线程时,最好用 PostThreadMessage 代替 PostMessage,PostMessage 的 hWnd 参数可以是 NULL,等效于 PostThreadMessage GetCurrentThreadId。Post WM_QUIT 时,应使用 PostQuitMessage 代替。

4、系统只整编(marshal)系统消息(0 到 WM_USER 之间的消息),发送用户消息(WM_USER 以上)到别的进程时,需要自己做整编。

  用 PostMessage、SendNotifyMessage、SendMessageCallback 等异步函数发送系统消息时,参数里不可以使用指针,因为发送者并不等待消息的处理就返回,接受者还没处理指针就已经被释放了。

5、在 Windows 2000/XP 里,每个消息队列最多只能存放 10,000 个 Post 的消息,超过的还没被处理的将不会被处理,直接丢掉。这个值可以改得更大:[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows] USERPostMessageLimit,最小可以是 4000。

/ -- 在线客服聊天 --> 认证失败,重新设置聊天系统的用户密码 // 聊天窗口右侧默认展示最近订单,如果想要展示商品、订单、店铺则需要在当前页面中设置隐藏域,name必须为 chat_goods_id, // chat_order_id, chat_supp_id /* ------------------------------------------------------ */ function action_authfail () { $user_id = $_SESSION['user_id']; $sql = "select user_name, password, email from " . $GLOBALS['ecs']->table('users') . " where user_id = '$user_id'"; $row = $db->getRow($sql); $success = create_of_user($user_id, $row['password'], $row['user_name'], $row['email'], 10, - 1); if($success) { $result = array( 'error' => 1,'message' => '可能由于网络原因,发生错误!请点击 <a href="chat.php?act=chat"><strong>重试</strong></a> ,重新连接...','content' => '' ); } else { $result = array( 'error' => 1,'message' => '由于网络原因,发生错误!请点击 <a href="chat.php?act=chat"><strong>重试</strong></a> ,重新连接...','content' => '' ); } $result = json_encode($result); exit($result); } /** * 用户离线 */ function action_off_line() { // 用户超过5分钟未发言则视为自动离线,更新客服状态 } function is_telephone ($phone) { $chars = "/^13[0-9]{1}[0-9]{8}$|15[0-9]{1}[0-9]{8}$|18[0-9]{1}[0-9]{8}$/"; if(preg_match($chars, $phone)) { return true; } } /** * 获取db对象 * * @return unknown */ function get_database () { return $GLOBALS['db']; } /** * 获取smarty对象 * * @return unknown */ function get_smarty () { return $GLOBALS[smarty]; } /** * 获取ecs对象 * * @return unknown */ function get_ecs () { return $GLOBALS['ecs']; } /* * 获取商品所对应店铺的店铺基本信息 * @param int $suppid 店铺id * @param int $suppinfo 入驻商的信息 */ function get_dianpu_baseinfo ($suppid = 0) { if(intval($suppid) <= 0) { return; } $sql_supplier = "SELECT s.supplier_id,s.supplier_name,s.add_time,sr.rank_name FROM " . $GLOBALS['ecs']->table("supplier") . " as s left join " . $GLOBALS['ecs']->table("supplier_rank") . " as sr ON s.rank_id=sr.rank_id WHERE s.supplier_id=" . $suppid . " AND s.status=1"; $supp_info = $GLOBALS['db']->getRow($sql_supplier); $sql = "SELECT * FROM " . $GLOBALS['ecs']->table('supplier_shop_config') . " WHERE supplier_id = " . $suppid; $shopinfo = $GLOBALS['db']->getAll($sql); $config = array(); foreach($shopinfo as $value) { $config[$value['code']] = $value['value']; } $shop_info = array(); $shop_info['ghs_css_path'] = 'themes/' . $config['template'] . '/images/ghs/css/ghs_style.css'; // 入驻商所选模板样式路径 $shoplogo = empty($config['shop_logo']) ? 'themes/' . $config['template'] . '/images/dianpu.jpg' : $config['shop_logo']; $shop_info['shoplogo'] = $shoplogo; // 商家logo $shop_info['shopname'] = htmlspecialchars($config['shop_name']); // 店铺名称 $shop_info['suppid'] = $suppid; // 商家名称 $shop_info['suppliername'] = htmlspecialchars($supp_info['supplier_name']); // 商家名称 $shop_info['userrank'] = htmlspecialchars($supp_info['rank_name']); // 商家等级 $shop_info['region'] = get_province_city($config['shop_province'], $config['shop_city']); $shop_info['address'] = $config['shop_address']; $shop_info['serviceqq'] = $config['qq']; $shop_info['serviceww'] = $config['ww']; $shop_info['serviceemail'] = $config['service_email']; $shop_info['servicephone'] = $config['service_phone']; $shop_info['createtime'] = gmdate('Y-m-d', $config['add_time']); // 商家创建时间 $suppid = (intval($suppid) > 0) ? intval($suppid) : intval($_GET['suppId']); return $shop_info; } 构建多商户人工客服系统
07-16
<?php /** * 鸿宇多用户商城 在线客服聊天系统-前台 * ============================================================================ * 版权所有 2015-2018 鸿宇多用户商城科技有限公司,并保留所有权利。 * 网站地址: http://bbs.hongyuvip.com; * ---------------------------------------------------------------------------- * 仅供学习交流使用,如需商用请购买正版版权。鸿宇不承担任何法律责任。 * 踏踏实实做事,堂堂正正做人。 * ============================================================================ * $Author: 鸿宇多用户商城 $ * $Id: category.php 17217 2015-02-10 06:29:08Z 鸿宇多用户商城 $ */ define('IN_ECS', true); require ('includes/init.php'); require ('includes/lib_chat.php'); /* 载入语言文件 */ require_once (ROOT_PATH . 'languages/' . $_CFG['lang'] . '/user.php'); $action = isset($_REQUEST['act']) ? trim($_REQUEST['act']) : 'chat'; /* 检查用户是否已登录 */ if(empty($_SESSION['user_id']) && $action != 'act_login' && $action != 'check_login') { // $captcha = intval($_CFG['captcha']); // if(($captcha & CAPTCHA_LOGIN) && (! ($captcha & CAPTCHA_LOGIN_FAIL) || (($captcha & CAPTCHA_LOGIN_FAIL) && $_SESSION['login_fail'] > 2)) && gd_version() > 0) // { // $GLOBALS['smarty']->assign('enabled_captcha', 1); // $GLOBALS['smarty']->assign('rand', mt_rand()); // } // 如果未登录跳转到登录页面 /** $smarty->assign('lang', $_LANG); $smarty->assign('back_act', ''); $smarty->assign('action', 'login'); $smarty->display('chat_passport.dwt'); **/ show_message('您还未登录系统,请先登录!', array('登录', '返回上一页'), array('user.php?act=login', 'index.php'), 'info'); return; } //路由 $function_name = 'action_' . $action; if(function_exists($function_name)) { call_user_func($function_name); } else { exit('函数' . $function_name . '不存在'); } /** * 检查用户是否登录 */ function action_check_login() { $is_login = empty($_SESSION['user_id']) ? 'false' : 'true'; exit($is_login); } /** * 处理会员登录 */ function action_act_login () { $user_id = $_SESSION['user_id']; $smarty = get_smarty(); $ecs = get_ecs(); $db = get_database(); /* 处理会员的登录 */ $username = isset($_POST['username']) ? trim($_POST['username']) : ''; $password = isset($_POST['password']) ? trim($_POST['password']) : ''; $back_act = isset($_POST['back_act']) ? trim($_POST['back_act']) : ''; $captcha = intval($_CFG['captcha']); if(($captcha & CAPTCHA_LOGIN) && (! ($captcha & CAPTCHA_LOGIN_FAIL) || (($captcha & CAPTCHA_LOGIN_FAIL) && $_SESSION['login_fail'] > 2)) && gd_version() > 0) { if(empty($_POST['captcha'])) { $smarty->assign('lang', $_LANG); $smarty->assign('action', 'login'); $smarty->assign('error', $_LANG['invalid_captcha']); $smarty->display('chat_passport.dwt'); return; } /* 检查验证码 */ include_once ('includes/cls_captcha.php'); $validator = new captcha(); $validator->session_word = 'captcha_login'; if(! $validator->check_word($_POST['captcha'])) { $smarty->assign('lang', $_LANG); $smarty->assign('action', 'login'); $smarty->assign('error', $_LANG['invalid_captcha']); $smarty->display('chat_passport.dwt'); return; } } if(is_email($username)) { $sql = "select user_name from " . $ecs->table('users') . " where email='" . $username . "'"; $username_e = $db->getOne($sql); if($username_e) $username = $username_e; } if(is_telephone($username)) { $sql = "select user_name from " . $ecs->table('users') . " where mobile_phone='" . $username . "'"; $username_res = $db->query($sql); $kkk = 0; while($username_row = $db->fetchRow($username_res)) { $username_e = $username_row['user_name']; $kkk = $kkk + 1; } if($kkk > 1) { $smarty->assign('lang', $_LANG); $smarty->assign('action', 'login'); $smarty->assign('error', '本网站有多个会员ID绑定了您相同的手机号,请使用其他登录方式,如:邮箱或用户名。'); $smarty->display('chat_passport.dwt'); return; } if($username_e) { $username = $username_e; } } if($GLOBALS['user']->login($username, $password, isset($_POST['remember']))) { update_user_info(); recalculate_price(); // 登录成功 $ucdata = isset($user->ucdata) ? $user->ucdata : ''; // show_message($_LANG['login_success'] . $ucdata , // array($_LANG['back_up_page'], $_LANG['profile_lnk']), // array($back_act,'user.php'), 'info'); // 刷新user_id $user_id = $_SESSION['user_id']; header('Location: chat.php?act=chat'); } else { $_SESSION['login_fail'] ++; $smarty->assign('lang', $_LANG); $smarty->assign('action', 'login'); $smarty->assign('error', $_LANG['login_failure']); $smarty->display('chat_passport.dwt'); return; } } /* ------------------------------------------------------ */ // -- 在线客服聊天 --> 请求聊天 // 聊天窗口右侧默认展示最近订单,如果想要展示商品、订单、店铺则需要在当前页面中设置隐藏域,name必须为 chat_goods_id, // chat_order_id, chat_supp_id /* ------------------------------------------------------ */ function action_chat () { $user_id = $_SESSION['user_id']; $smarty = get_smarty(); $ecs = get_ecs(); $db = get_database(); /** * 判断当前用户是为聊天系统的注册用户 */ $exist = check_of_username_exist($user_id); // 获取用户头像 if(! empty($user_id)) { $sql = "select password, headimg from " . $ecs->table('users') . " where user_id = '$user_id'"; $row = $db->getRow($sql); $headimg = $row['headimg']; $password = $row['password']; $smarty->assign('headimg', $headimg); } if(! $exist) { // 查询ECShop内用户信息 $sql = 'select a.user_id, a.password, a.email, a.user_name from ' . $ecs->table('users') . ' AS a where a.user_id = "' . $user_id . '"'; $user = $GLOBALS['db']->getRow($sql); if(empty($user)) { // 根据user_id未查找到任何用户信息 } // 用户不存在,创建用户信息 $username = $user_id; $password = $user['password']; $name = $user['user_name']; $email = $user['email']; $type = 10; $shop_id = - 1; $result = create_of_user($username, $password, $name, $email, $type, $shop_id); if($result) { // 创建成功 } else { // 创建失败 } } // 获取前端传来的商品编号、订单编号、店铺编号等 // 商品编号则显示商品信息 // 订单编号则显示订单信息 // 店铺编号则显示店铺信息 $goods_id = null; $supp_id = - 1; $order_id = null; $customers = null; // 获取客服信息 $tab_items = array(); // 客服类型 $cus_types = CUSTOMER_SERVICE; // 记录需要发给客服的URL if(! empty($_REQUEST['chat_goods_id'])) { /* 咨询商品信息 */ $goods_id = $_REQUEST['chat_goods_id']; $goods = goods_info($goods_id); $smarty->assign('chat_goods', $goods); $smarty->assign('chat_goods_id', $goods_id); $tab_items[] = array( "id" => "chat_goods","name" => "咨询商品" ); // 客服+售前 $cus_types = CUSTOMER_SERVICE . ',' . CUSTOMER_PRE; } if(! empty($_REQUEST['chat_order_id'])) { /* 咨询订单信息 */ require ('includes/lib_order.php'); $order_id = $_REQUEST['chat_order_id']; // 获取商品店铺信息 $goods_id = null; $order = order_info($order_id); $supp_id = $order['supplier_id']; $order['order_status_text'] = $GLOBALS['_LANG']['os'][$order['order_status']] . ',' . $GLOBALS['_LANG']['ps'][$order['pay_status']] . ',' . $GLOBALS['_LANG']['ss'][$order['shipping_status']]; $order['goods_list'] = order_goods($order_id); $smarty->assign('chat_order', $order); $smarty->assign('chat_order_id', $order_id); $smarty->assign('chat_order_sn', $order['order_sn']); $tab_items[] = array( "id" => "chat_order","name" => "咨询订单" ); // 客服+售后 $cus_types = CUSTOMER_SERVICE . ',' . CUSTOMER_AFTER; } if(! empty($_REQUEST['chat_supp_id']) && $_REQUEST['chat_supp_id'] != 0) { /* 店铺信息 */ $supp_id = $_REQUEST['chat_supp_id']; $supp_info = get_dianpu_baseinfo($supp_id); $smarty->assign('supp_info', $supp_info); $smarty->assign('chat_supp_id', $supp_id); $tab_items[] = array( "id" => "chat_supp", "name" => "店铺信息" ); // 客服+售前 $cus_types = CUSTOMER_SERVICE . ',' . CUSTOMER_PRE; } if(true) { /* 最近订单列表 */ require ('includes/lib_transaction_1.php'); // 获取用户最近的5条订单列表 $order_list = get_user_orders_1($user_id, 5, 0); // 所有客服忙碌状态,提示web端 $smarty->assign('order_list', $order_list); $smarty->assign('order_count', count($order_list)); $tab_items[] = array( "id" => "chat_order_list","name" => "最近订单" ); // 客服 $cus_types = CUSTOMER_SERVICE; } // 获取客服信息 $customers = get_customers($cus_types, $supp_id); // 转换为JSON数据 $smarty->assign('tab_items', json_encode($tab_items)); $to = null; // 客服获取策略:0-顺序、1-随机、2-竞争 if(! empty($customers)) { // 暂时采用随机策略 $poliy = 1; if($poliy == 0) { foreach($customers as $customer) { $status = $customer['status']; if($status == '在线' || $status == '空闲') { $to = $customer; break; // if(isset($customer['cus_status']) && count($customers) > 1) // { // if(time() - $customer['chat_time'] > 5*60) // { // set_customer_status($customer['cus_id'], 0); // $customer['cus_status'] = 0; // } // if($customer['cus_status'] == 0) // { // $to = $customer; // break; // } // } // else // { // $to = $customer; // break; // } } } } else if($poliy == 1) { /* 随进策略 */ $onlines = array(); foreach($customers as $customer) { $status = $customer['status']; if($status == '在线' || $status == '空闲') { $onlines[] = $customer; } } if(count($onlines) > 0) { $min = 1; $max = count($onlines); $i = mt_rand($min, $max); $to = $onlines[$i - 1]; } } else { } if(empty($to)) { if($supp_id == -1){ // 所有客服忙碌状态,提示web端 $smarty->assign('system_notice', '当前客服忙碌,请稍后联系!'); }else{ // 所有客服忙碌状态,提示web端 $smarty->assign('system_notice', '当前店铺客服忙碌,请稍后联系!'); } } else { $xmpp_domain = get_xmpp_domain(); $_SESSION['OF_FROM'] = $user_id . '@' . $xmpp_domain; $_SESSION['OF_TO'] = $to['of_username'] . '@' . $xmpp_domain; $smarty->assign('from', $_SESSION['OF_FROM']); $smarty->assign('password', $password); // $smarty->assign('password', "123456"); $smarty->assign('to', '==to=='); $smarty->assign('username', $_SESSION['user_name']); $smarty->assign('customername', $to['cus_name']); // 存储在Session中方便其他地方使用 // 所有客服忙碌状态,提示web端 $smarty->assign('system_notice', '客服<span class="kf_name">' . $to['cus_name'] . '</span>已加入会话!'); } } else { // 所有客服忙碌状态,提示web端 $smarty->assign('system_notice', '当前客服忙碌,请稍后联系!'); } // 打开聊天页面 $smarty->display('chat.dwt'); } /* ------------------------------------------------------ */ // -- 在线客服聊天 --> 认证失败,重新设置聊天系统的用户密码 // 聊天窗口右侧默认展示最近订单,如果想要展示商品、订单、店铺则需要在当前页面中设置隐藏域,name必须为 chat_goods_id, // chat_order_id, chat_supp_id /* ------------------------------------------------------ */ function action_authfail () { $user_id = $_SESSION['user_id']; $sql = "select user_name, password, email from " . $GLOBALS['ecs']->table('users') . " where user_id = '$user_id'"; $row = $db->getRow($sql); $success = create_of_user($user_id, $row['password'], $row['user_name'], $row['email'], 10, - 1); if($success) { $result = array( 'error' => 1,'message' => '可能由于网络原因,发生错误!请点击 <a href="chat.php?act=chat"><strong>重试</strong></a> ,重新连接...','content' => '' ); } else { $result = array( 'error' => 1,'message' => '由于网络原因,发生错误!请点击 <a href="chat.php?act=chat"><strong>重试</strong></a> ,重新连接...','content' => '' ); } $result = json_encode($result); exit($result); } /** * 用户离线 */ function action_off_line() { // 用户超过5分钟未发言则视为自动离线,更新客服状态 } function is_telephone ($phone) { $chars = "/^13[0-9]{1}[0-9]{8}$|15[0-9]{1}[0-9]{8}$|18[0-9]{1}[0-9]{8}$/"; if(preg_match($chars, $phone)) { return true; } } /** * 获取db对象 * * @return unknown */ function get_database () { return $GLOBALS['db']; } /** * 获取smarty对象 * * @return unknown */ function get_smarty () { return $GLOBALS[smarty]; } /** * 获取ecs对象 * * @return unknown */ function get_ecs () { return $GLOBALS['ecs']; } /* * 获取商品所对应店铺的店铺基本信息 * @param int $suppid 店铺id * @param int $suppinfo 入驻商的信息 */ function get_dianpu_baseinfo ($suppid = 0) { if(intval($suppid) <= 0) { return; } $sql_supplier = "SELECT s.supplier_id,s.supplier_name,s.add_time,sr.rank_name FROM " . $GLOBALS['ecs']->table("supplier") . " as s left join " . $GLOBALS['ecs']->table("supplier_rank") . " as sr ON s.rank_id=sr.rank_id WHERE s.supplier_id=" . $suppid . " AND s.status=1"; $supp_info = $GLOBALS['db']->getRow($sql_supplier); $sql = "SELECT * FROM " . $GLOBALS['ecs']->table('supplier_shop_config') . " WHERE supplier_id = " . $suppid; $shopinfo = $GLOBALS['db']->getAll($sql); $config = array(); foreach($shopinfo as $value) { $config[$value['code']] = $value['value']; } $shop_info = array(); $shop_info['ghs_css_path'] = 'themes/' . $config['template'] . '/images/ghs/css/ghs_style.css'; // 入驻商所选模板样式路径 $shoplogo = empty($config['shop_logo']) ? 'themes/' . $config['template'] . '/images/dianpu.jpg' : $config['shop_logo']; $shop_info['shoplogo'] = $shoplogo; // 商家logo $shop_info['shopname'] = htmlspecialchars($config['shop_name']); // 店铺名称 $shop_info['suppid'] = $suppid; // 商家名称 $shop_info['suppliername'] = htmlspecialchars($supp_info['supplier_name']); // 商家名称 $shop_info['userrank'] = htmlspecialchars($supp_info['rank_name']); // 商家等级 $shop_info['region'] = get_province_city($config['shop_province'], $config['shop_city']); $shop_info['address'] = $config['shop_address']; $shop_info['serviceqq'] = $config['qq']; $shop_info['serviceww'] = $config['ww']; $shop_info['serviceemail'] = $config['service_email']; $shop_info['servicephone'] = $config['service_phone']; $shop_info['createtime'] = gmdate('Y-m-d', $config['add_time']); // 商家创建时间 $suppid = (intval($suppid) > 0) ? intval($suppid) : intval($_GET['suppId']); return $shop_info; } ?>插件 A plugin has loaded admin console authentication bypass patterns that includes a wildcard, but the System Property 'adminConsole.access.allow-wildcards-in-excludes' is disabled. 插件为服务器添加了新功能。当前安装的插件列表如下。要下载新插件,请访问可用插件页面。 插件 描述 版本 作者 重启 删除 Plugin Client Control README changelog Controls clients allowed to connect and available features 2.1.10 Jive Software 刷新 Client Control 删除 Client Control Plugin Content Filter README changelog Scans message packets for defined patterns 1.9.0 Conor Hayes 刷新 Content Filter 删除 Content Filter Plugin Fastpath Service README changelog Support for managed queued chat requests, such as a support team might use. 4.5.1 Ignite Realtime 刷新 Fastpath Service 删除 Fastpath Service Plugin Jabber Browsing README changelog This plugin implements the (obsolete!) XEP-0011 'Jabber Browsing' specification for service discovery using the jabber:iq:browse namespace. 1.0.1 Guus der Kinderen 刷新 Jabber Browsing 删除 Jabber Browsing Plugin Just married README changelog Allows admins to rename or copy users 1.3.0 Holger Bergunde 刷新 Just married 删除 Just married Plugin MUC Service Discovery Extensions README changelog Allows an admin to configure Extended Service Discovery information to Multi User Chat entities. 1.0.0 Guus der Kinderen 刷新 MUC Service Discovery Extensions 删除 MUC Service Discovery Extensions Plugin Pade README changelog Web-based chat, groupchat, telephones, audio and video conferencing solution using ConverseJS, Jitsi and FreeSWITCH 1.8.4 Ignite Realtime 刷新 Pade 删除 Pade Plugin Presence Service README changelog Exposes presence information through HTTP. 1.7.4 Jive Software 刷新 Presence Service 删除 Presence Service Plugin Push Notification README changelog Adds Push Notification (XEP-0357) support to Openfire. 1.0.1 Guus der Kinderen 刷新 Push Notification 删除 Push Notification Plugin REST API README changelog Allows administration over a RESTful API. 1.8.0 Roman Soldatow 刷新 REST API 删除 REST API Plugin Search README changelog Provides support for Jabber Search (XEP-0055) 1.7.5 Ryan Graham 刷新 Search 删除 Search Plugin User Creation changelog Creates users and populates rosters. 1.4.1 Jive Software 刷新 User Creation 删除 User Creation Plugin User Import Export README changelog Enables import and export of user data 2.8.0 Ryan Graham 刷新 User Import Export 删除 User Import Export Plugin User Service README changelog (Deprecated) Please use the REST API Plugin. Allows administration of users via HTTP requests. 2.1.3 Roman Soldatow, Justin Hunt 刷新 User Service 删除 User Service Plugin User Status Plugin README changelog Openfire plugin to save the user status to the database. 1.3.0 Stefan Reuter 刷新 User Status Plugin 删除 User Status Plugin Plugin Openfire WebSocket README changelog Provides WebSocket support for Openfire. 1.2.1 Tom Evans 删除 Openfire WebSocket Plugin xmppweb README changelog Adds the (third-party) xmpp-web client to Openfire. 0.10.3 Release 1 Guus der Kinderen 刷新 xmppweb 删除 xmppweb 如何完整配置 在线客服与网站用户聊天
10-03
<?php date_default_timezone_set('Asia/Shanghai'); // 强制使用北京时间 require_once './include/conn.php'; // 获取当前用户历史消息并按时间排序 $h_user = getUserIP(); $rs = $db->get_one("select count(*) as tj from `h_kefu` where h_user = '{$h_user}' and h_who = 2 and h_isread = 0"); if($rs['tj'] > 0){ $query = "select * from `h_kefu` where h_user = '{$h_user}' and h_isread = 1 order by h_addTime asc,id asc"; }else{ $query = "select * from `h_kefu` where h_user = '{$h_user}' order by h_addTime asc,id asc"; } $result = $db->query($query); $messages = []; while($rs_list = $db->fetch_array($result)){ $messages[] = $rs_list; } ?> <!DOCTYPE html> <html lang="en"> <head> <!-- 头部样式保持不变 --> <!-- ... 原有样式代码 ... --> </head> <body class="m-mobile-frame" id="auto-id-1691801730040" style="font-size:14px"> <div class="service"> <div class="chat_show_loading u-errtip j-loading f-hide" id="jz"><img src="https://qiyukf.nosdn.127.net/sdk/res/default/loading_3782900ab9d04a1465e574a7d50af408.gif"> <span class="j-loading-txt">正在连接,请稍等...</span></div> <div class="service"> <div class="chat_show_loading u-errtip j-loading f-hide" id="ljcg" style="margin-left: -50px;"><span class="j-loading-txt">连接成功</span></div> <div class="bd_title"> <div class="left"> <div class="icon"> <a href="javascript:;" onclick="history.go(-1);"><img src="https://qiyukf.nosdn.127.net/sdk/res/img/prev_fb1146ba7f3ea25f1bbb8db373fb710f.png" alt></a> </div> <div class="text"> <span class="name">闲鱼官方在线客服中心</span> </div> </div> </div> <div class="msg-box"> <div class="PullToRefresh-content PullToRefresh-transition" style="transform: translate3d(0px, 0px, 0px);"> <div class="PullToRefresh-indicator"></div> <div class="Message left" data-id="167012827668700566" data-type="card"> <div class="Message-main"> <div class="Message-inner"> <div class="Message-content" role="alert" aria-live="assertive" aria-atomic="false"> <div class="ComponentMessage" data-spm-anchor-id="a311a.7996332.0.i0.7f0e3f5dNPC0Mt"> </div> </div> </div> </div> </div> <div class="kf_box"> <h3>闲鱼人工客服 为您服务</h3> </div> <!-- 初始客服消息 --> <div class="Message left" data-id="169177542802256502" data-type="text"> <div class="Message-main"> <span class="Avatar Avatar--md Avatar--circle"> <img src="/img/xy1.png"></span> <div class="Message-inner"> <div class="Message-content" role="alert" aria-live="assertive" aria-atomic="false"> <div class="Bubble text" data-type="text"><p><span style="color:red;">闲鱼网在线授权客服工号10788号很高兴为您服务,请简单描述您需要咨询的问题!您好请问有什么可以帮到您呢?</span></p> </div> </div> </div> </div> </div> </div> <!-- 历史消息(带时间间隔判断) --> <?php $lastTime = 0; // 上一条消息时间戳 foreach($messages as $rs_list){ $currentTime = strtotime($rs_list['h_addTime']); $sendTimeText = date('H:i', $currentTime); // 时间间隔超过60秒则显示时间分隔符 if($lastTime == 0 || ($currentTime - $lastTime) > 60){ echo '<div class="time-separator">' . $sendTimeText . '</div>'; } // 输出消息内容 if($rs_list['h_who'] == 2){ // 客服消息 echo ' <div class="msg clearfix"> <div class="img1"> <img src="/img/xy1.png" alt=""> </div> <div class="content"> <span>' . $rs_list['h_content'] . '</span> </div> </div> '; } else { // 客户消息 echo ' <div class="msg clearfix on"> <div class="img2"> <img src="http://tc.chuzhong.icu/i/2025/11/10/wei91.png" alt=""> </div> <div class="content"> <span>' . $rs_list['h_content'] . '</span> </div> </div> '; } $lastTime = $currentTime; // 更新上一条消息时间戳 } ?> <p id="msgzone"></p> </div> <div class="msg-post"> <textarea enterkeyhint="send" rows="1" placeholder="输入消息..." type="text" class="Input Input--outline Composer-input" id="cont"></textarea> <svg id="bd" onclick="bd5()" style="width: 33px; height: 33px; margin: 5px 0px 5px 5px; display: block;" t="1687901693741" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="8335" width="200" height="200"> <path d="M696 480H544V328c0-4.4-3.6-8-8-8h-48c-4.4 0-8 3.6-8 8v152H328c-4.4 0-8 3.6-8 8v48c0 4.4 3.6 8 8 8h152v152c0 4.4 3.6 8 8 8h48c4.4 0 8-3.6 8-8V544h152c4.4 0 8-3.6 8-8v-48c0-4.4-3.6-8-8-8z" p-id="8336"></path> <path d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64z m0 820c-205.4 0-372-166.6-372-372s166.6-372 372-372 372 166.6 372 372-166.6 372-372 372z" p-id="8337"></path> </svg> <svg t="1687903493556" id="bd999" onclick="bd6()" style="width: 33px; height: 33px; margin: 5px 0px 5px 5px; display: none;" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2305" width="200" height="200"> <path d="M512 42.666667c259.2 0 469.333333 210.133333 469.333333 469.333333s-210.133333 469.333333-469.333333 469.333333S42.666667 771.2 42.666667 512 252.8 42.666667 512 42.666667z m0 64C288.149333 106.666667 106.666667 288.149333 106.666667 512s181.482667 405.333333 405.333333 405.333333 405.333333-181.482667 405.333333-405.333333S735.850667 106.666667 512 106.666667z m-104.746667 256a8.533333 8.533333 0 0 1 6.037334 2.496L512 463.850667l98.688-98.688a8.533333 8.533333 0 0 1 6.037333-2.496h66.346667a8.533333 8.533333 0 0 1 6.037333 14.570666l-131.84 131.861334 137.642667 137.664a8.533333 8.533333 0 0 1-6.037333 14.570666h-66.346667a8.533333 8.533333 0 0 1-6.037333-2.496L512 554.346667l-104.512 104.490666a8.533333 8.533333 0 0 1-6.037333 2.496h-66.346667a8.533333 8.533333 0 0 1-6.016-14.570666l137.664-137.664-131.861333-131.861334A8.533333 8.533333 0 0 1 340.906667 362.666667h66.346666z" fill="#333333" p-id="2306"></path> </svg> <input class="Btn Btn--primary Composer-sendBtn" type="button" onclick="sendMessage();" value="发送"> </div> <div style="display: none;" id="bd777"> <div class="Toolbar"> <div class="Toolbar-item" data-type="album"> <button class="Btn Toolbar-btn" type="button"> <span class="Toolbar-btnIcon"> <label for="file"> <img src="/img/kjs.png"> </label> </span> <span class="Toolbar-btnText">相册</span> <input type="file" accept="image/*" id="file" onchange="upload()" style="width:0;height:0"> </button> </div> </div> </div> </div> <!-- 只保留一个jQuery版本 --> <script src="https://cdn.staticfile.org/jquery/3.5.1/jquery.min.js"></script> <script src="https://g.alicdn.com/chatui/icons/2.1.0/index.js"></script> <script src="layer/layer.js"></script> <script> // 记录最后一条消息的时间戳 let lastMessageTime = <?php echo empty($messages) ? 0 : strtotime(end($messages)['h_addTime']); ?>; // 修复:添加消息发送功能 function sendMessage() { const cont = $('#cont').val().trim(); if (!cont) return alert('请输入消息内容'); // 获取当前时间 const now = new Date(); const sendTimeText = now.getHours().toString().padStart(2, '0') + ':' + now.getMinutes().toString().padStart(2, '0'); // 间隔超过60秒显示时间分隔符 if (lastMessageTime === 0 || (Math.floor(now.getTime()/1000) - lastMessageTime) > 60) { $('#msgzone').before(`<div class="time-separator">${sendTimeText}</div>`); } // 添加消息到页面 $('#msgzone').before(` <div class="msg clearfix on"> <div class="img2"> <img src="http://tc.chuzhong.icu/i/2025/11/10/wei91.png" alt=""> </div> <div class="content"> <span>${cont}</span> </div> </div> `); // 清空输入框 $('#cont').val(''); // 更新最后一条消息时间 lastMessageTime = Math.floor(now.getTime()/1000); // 滚动到底部 const msgContainer = $('.PullToRefresh-content'); msgContainer.scrollTop(msgContainer[0].scrollHeight); // 发送到后端(模拟示例) console.log('发送消息:', cont); // 实际项目中应使用AJAX发送到服务器 // $.post('ajax.php?act=send', {content: cont}, function(data) { // if (data.code !== 1) { // alert('发送失败: ' + data.msg); // } // }, 'json'); } // 修复:支持回车键发送 $('#cont').keypress(function(e) { if (e.which === 13 && !e.shiftKey) { e.preventDefault(); sendMessage(); } }); // 底部工具栏切换函数 function bd5() { $('#bd').hide(); $('#bd999').show(); $('#bd777').show(); } function bd6() { $('#bd').show(); $('#bd999').hide(); $('#bd777').hide(); } // 页面加载后滚动到底部 $(document).ready(function() { const msgContainer = $('.PullToRefresh-content'); msgContainer.scrollTop(msgContainer[0].scrollHeight); }); </script> </body> </html> 点击发送没反应
最新发布
11-11
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值