Quellcode durchsuchen

增加群聊钩子,及增加WEBSOCKET客户端

齐博 vor 4 Jahren
Ursprung
Commit
cbed1ddb41
32 geänderte Dateien mit 820 neuen und 176 gelöschten Zeilen
  1. 3 0
      application/common/fun/Alilive.php
  2. 22 1
      application/common/fun/Gatewayclient.php
  3. 11 1
      application/common/model/Msg.php
  4. 2 0
      application/common/upgrade/92.sql
  5. 1 0
      application/common/upgrade/log94.txt
  6. 3 0
      application/index/controller/Image.php
  7. 5 1
      application/index/controller/Notify.php
  8. 4 0
      application/install/sql/install.sql
  9. 4 0
      extend/WebSocket/BadOpcodeException.php
  10. 4 0
      extend/WebSocket/BadUriException.php
  11. 287 0
      extend/WebSocket/Base.php
  12. 177 0
      extend/WebSocket/Client.php
  13. 4 0
      extend/WebSocket/ConnectionException.php
  14. 4 0
      extend/WebSocket/Exception.php
  15. 106 0
      extend/WebSocket/Server.php
  16. 2 0
      public/static/libs/amazeui/css/main.css
  17. 1 1
      public/static/libs/amazeui/js/wechat.js
  18. 64 7
      public/static/libs/bui/pages/chat/chat.js
  19. 3 0
      public/static/libs/bui/pages/hack/qqface.js
  20. 18 2
      public/static/libs/bui/pages/hongbao/init.js
  21. 2 0
      public/static/libs/bui/pages/imgzoom/zoom.js
  22. 4 2
      public/static/libs/bui/pages/p2pvideo/init.js
  23. 1 1
      public/static/libs/bui/pages/topic/index.js
  24. 1 1
      public/static/libs/bui/pages/uploadpic/wap_init.js
  25. 8 2
      public/static/libs/bui/pages/wx_share/init.js
  26. 36 1
      public/static/libs/bui/pages/zhibo/dplayer.html
  27. 43 17
      public/static/libs/bui/pages/zhibo/init.js
  28. BIN
      public/static/plugins/hongbao/banner.png
  29. BIN
      public/static/plugins/hongbao/but0.png
  30. BIN
      public/static/plugins/hongbao/but1.png
  31. BIN
      public/static/plugins/hongbao/hb.png
  32. 0 139
      public/static/plugins/hongbao/index.css

+ 3 - 0
application/common/fun/Alilive.php

@@ -21,6 +21,9 @@ class Alilive{
             'flv_url'=>$data['flv_url']?:'',
             'm3u8_url'=>$data['m3u8_url']?:'',
             'rtmp_url'=>$data['rtmp_url']?:'',
+            'picurl'=>$data['picurl']?:'',
+            'title'=>$data['title']?:'',
+            'about'=>$data['about']?:'',
             'create_time'=>time(),
         ];
         $id = Db::name('alilive_log')->insertGetId($array);

+ 22 - 1
application/common/fun/Gatewayclient.php

@@ -2,6 +2,7 @@
 namespace app\common\fun;
 
 use GatewayClient\Gateway;
+use WebSocket\Client;
 
 class Gatewayclient{
     
@@ -21,7 +22,27 @@ class Gatewayclient{
     }
     
     /**
-     * 给当前用户群群发信息
+     * 模拟浏览器请求websocket服务器
+     * @param array $array
+     */
+    public function ask_ws($array=[]){
+        if (is_array($array)) {
+            $array['url'] = $array['url']?:request()->domain();
+            $array['my_uid'] = $array['my_uid']?:login_user('uid');
+            $array = json_encode($array);
+        }
+        $client = new Client($this->client_url());
+        $string = $client->receive();
+        //$info = json_decode($string,true);
+        //$client_id = $info['client_id'];
+        $client->send($array);
+        $string = $client->receive();die($string);
+        $info = json_decode($string,true);
+        return is_array($info)?$info:$string;
+    }
+    
+    /**
+     * 给当前圈子群发信息
      * @param number $my_uid 当前用户自己的ID
      * @param number $uid 负数是圈子ID,正数是私人聊天对方的UID
      * @param string $json_msg 消息内容,必须是json格式的数据

+ 11 - 1
application/common/model/Msg.php

@@ -36,8 +36,13 @@ class Msg extends Model
             if (cache('pm_msg_'.$data['uid'])) {
                 return ['errmsg'=>'请不要那么频繁的发送消息'];
             }
-            cache('pm_msg_'.$data['uid'],time(),5);
+            cache('pm_msg_'.$data['uid'],time(),3);
         }
+        
+        //钩子接口
+        get_hook('add_msg_begin',$data,[],['admin'=>$admin,'push'=>$push],true);
+        hook_listen('add_msg_begin',$data,['admin'=>$admin,'push'=>$push]);
+        
         $result = parent::create($data);
         if($data['uid']>0 && $data['touid']>0){
             if (empty($info)) {
@@ -57,6 +62,11 @@ class Msg extends Model
             }            
         }
         if ($result) {
+            
+            //钩子接口
+            get_hook('add_msg_end',$data,[],['admin'=>$admin,'push'=>$push,'id'=>$result->id],true);
+            hook_listen('add_msg_end',$data,['admin'=>$admin,'push'=>$push,'id'=>$result->id]);
+            
             if ($push) {
                 self::push_msg($result->id);
             }

+ 2 - 0
application/common/upgrade/92.sql

@@ -0,0 +1,2 @@
+INSERT INTO `qb_hook` (`id`, `name`, `about`, `ifopen`, `list`) VALUES(0, 'add_msg_begin', '短消息(群聊)发布接口(入库前)', 1, 0);
+INSERT INTO `qb_hook` (`id`, `name`, `about`, `ifopen`, `list`) VALUES(0, 'add_msg_end', '短消息(群聊)发布接口(入库后)', 1, 0);

+ 1 - 0
application/common/upgrade/log94.txt

@@ -0,0 +1 @@
+增加发送短消息的钩子接口

+ 3 - 0
application/index/controller/Image.php

@@ -25,6 +25,9 @@ class Image extends IndexBase
 		if($url==''){
 			return ;
 		}
+		if(preg_match("/^\//",$url)){
+			$url = get_url(tempdir($url));
+		}
 		$img = http_curl($url);
 		if($img==''){
 			return ;

+ 5 - 1
application/index/controller/Notify.php

@@ -9,7 +9,11 @@ class Notify extends IndexBase
 {
     public function index($type='')
     {
-        $data = input();
+        $data = $this->request->post();
+        if (empty($data['type'])&&$type) {
+            $this->request->post(['type'=>$type]);
+			$data['type'] = $type;
+        }
         
         //钩子扩展
         $this->get_hook('user_leave',$data);

+ 4 - 0
application/install/sql/install.sql

@@ -1714,3 +1714,7 @@ INSERT INTO `qb_chatmod` (`id`, `uid`, `aid`, `type`, `name`, `about`, `icon`, `
 
 INSERT INTO `qb_chatmod` (`id`, `uid`, `aid`, `type`, `name`, `about`, `icon`, `pcwap`, `keywords`, `init_jsfile`, `init_iframe`, `init_jscode`, `status`, `list`, `allowgroup`) VALUES(0, 0, 0, 1, '微信分享', '', '', 1, 'wx_share', '/public/static/libs/bui/pages/wx_share/init.js', '', '', 1, 0, '');
 INSERT INTO `qb_chatmod` (`id`, `uid`, `aid`, `type`, `name`, `about`, `icon`, `pcwap`, `keywords`, `init_jsfile`, `init_iframe`, `init_jscode`, `status`, `list`, `allowgroup`) VALUES(0, 0, 0, 1, '微信分享', '', 'fa fa-share-square-o', 3, 'wx_share', '/public/static/libs/bui/pages/wx_share/init.js', '', '', 1, 0, '');
+
+
+INSERT INTO `qb_hook` (`id`, `name`, `about`, `ifopen`, `list`) VALUES(0, 'add_msg_begin', '短消息(群聊)发布接口(入库前)', 1, 0);
+INSERT INTO `qb_hook` (`id`, `name`, `about`, `ifopen`, `list`) VALUES(0, 'add_msg_end', '短消息(群聊)发布接口(入库后)', 1, 0);

+ 4 - 0
extend/WebSocket/BadOpcodeException.php

@@ -0,0 +1,4 @@
+<?php
+
+namespace WebSocket;
+class BadOpcodeException extends Exception {}

+ 4 - 0
extend/WebSocket/BadUriException.php

@@ -0,0 +1,4 @@
+<?php
+
+namespace WebSocket;
+class BadUriException extends Exception {}

+ 287 - 0
extend/WebSocket/Base.php

@@ -0,0 +1,287 @@
+<?php
+
+/**
+ * Copyright (C) 2014, 2015 Textalk
+ * Copyright (C) 2015 Patrick McCarren - added payload fragmentation for huge payloads
+ *
+ * This file is part of Websocket PHP and is free software under the ISC License.
+ * License text: https://raw.githubusercontent.com/Textalk/websocket-php/master/COPYING
+ */
+
+namespace WebSocket;
+
+class Base {
+  protected $socket, $is_connected = false, $is_closing = false, $last_opcode = null,
+    $close_status = null, $huge_payload = null;
+
+  protected static $opcodes = array(
+    'continuation' => 0,
+    'text'         => 1,
+    'binary'       => 2,
+    'close'        => 8,
+    'ping'         => 9,
+    'pong'         => 10,
+  );
+
+  public function getLastOpcode()  { return $this->last_opcode;  }
+  public function getCloseStatus() { return $this->close_status; }
+  public function isConnected()    { return $this->is_connected; }
+
+  public function setTimeout($timeout) {
+    $this->options['timeout'] = $timeout;
+
+    if ($this->socket && get_resource_type($this->socket) === 'stream') {
+      stream_set_timeout($this->socket, $timeout);
+    }
+  }
+
+  public function setFragmentSize($fragment_size) {
+    $this->options['fragment_size'] = $fragment_size;
+    return $this;
+  }
+
+  public function getFragmentSize() {
+    return $this->options['fragment_size'];
+  }
+
+  public function send($payload, $opcode = 'text', $masked = true) {
+    if (!$this->is_connected) $this->connect(); /// @todo This is a client function, fixme!
+
+    if (!in_array($opcode, array_keys(self::$opcodes))) {
+      throw new BadOpcodeException("Bad opcode '$opcode'.  Try 'text' or 'binary'.");
+    }
+
+    // record the length of the payload
+    $payload_length = strlen($payload);
+
+    $fragment_cursor = 0;
+    // while we have data to send
+    while ($payload_length > $fragment_cursor) {
+      // get a fragment of the payload
+      $sub_payload = substr($payload, $fragment_cursor, $this->options['fragment_size']);
+
+      // advance the cursor
+      $fragment_cursor += $this->options['fragment_size'];
+
+      // is this the final fragment to send?
+      $final = $payload_length <= $fragment_cursor;
+
+      // send the fragment
+      $this->send_fragment($final, $sub_payload, $opcode, $masked);
+
+      // all fragments after the first will be marked a continuation
+      $opcode = 'continuation';
+    }
+
+  }
+
+  protected function send_fragment($final, $payload, $opcode, $masked) {
+    // Binary string for header.
+    $frame_head_binstr = '';
+
+    // Write FIN, final fragment bit.
+    $frame_head_binstr .= (bool) $final ? '1' : '0';
+
+    // RSV 1, 2, & 3 false and unused.
+    $frame_head_binstr .= '000';
+
+    // Opcode rest of the byte.
+    $frame_head_binstr .= sprintf('%04b', self::$opcodes[$opcode]);
+
+    // Use masking?
+    $frame_head_binstr .= $masked ? '1' : '0';
+
+    // 7 bits of payload length...
+    $payload_length = strlen($payload);
+    if ($payload_length > 65535) {
+      $frame_head_binstr .= decbin(127);
+      $frame_head_binstr .= sprintf('%064b', $payload_length);
+    }
+    elseif ($payload_length > 125) {
+      $frame_head_binstr .= decbin(126);
+      $frame_head_binstr .= sprintf('%016b', $payload_length);
+    }
+    else {
+      $frame_head_binstr .= sprintf('%07b', $payload_length);
+    }
+
+    $frame = '';
+
+    // Write frame head to frame.
+    foreach (str_split($frame_head_binstr, 8) as $binstr) $frame .= chr(bindec($binstr));
+
+    // Handle masking
+    if ($masked) {
+      // generate a random mask:
+      $mask = '';
+      for ($i = 0; $i < 4; $i++) $mask .= chr(rand(0, 255));
+      $frame .= $mask;
+    }
+
+    // Append payload to frame:
+    for ($i = 0; $i < $payload_length; $i++) {
+      $frame .= ($masked === true) ? $payload[$i] ^ $mask[$i % 4] : $payload[$i];
+    }
+
+    $this->write($frame);
+  }
+
+  public function receive() {
+    if (!$this->is_connected) $this->connect(); /// @todo This is a client function, fixme!
+
+    $this->huge_payload = '';
+
+    $response = null;
+    while (is_null($response)) $response = $this->receive_fragment();
+
+    return $response;
+  }
+
+  protected function receive_fragment() {
+
+    // Just read the main fragment information first.
+    $data = $this->read(2);
+
+    // Is this the final fragment?  // Bit 0 in byte 0
+    /// @todo Handle huge payloads with multiple fragments.
+    $final = (boolean) (ord($data[0]) & 1 << 7);
+
+    // Should be unused, and must be false…  // Bits 1, 2, & 3
+    $rsv1  = (boolean) (ord($data[0]) & 1 << 6);
+    $rsv2  = (boolean) (ord($data[0]) & 1 << 5);
+    $rsv3  = (boolean) (ord($data[0]) & 1 << 4);
+
+    // Parse opcode
+    $opcode_int = ord($data[0]) & 31; // Bits 4-7
+    $opcode_ints = array_flip(self::$opcodes);
+    if (!array_key_exists($opcode_int, $opcode_ints)) {
+      throw new ConnectionException("Bad opcode in websocket frame: $opcode_int");
+    }
+    $opcode = $opcode_ints[$opcode_int];
+
+    // record the opcode if we are not receiving a continutation fragment
+    if ($opcode !== 'continuation') {
+      $this->last_opcode = $opcode;
+    }
+
+    // Masking?
+    $mask = (boolean) (ord($data[1]) >> 7);  // Bit 0 in byte 1
+
+    $payload = '';
+
+    // Payload length
+    $payload_length = (integer) ord($data[1]) & 127; // Bits 1-7 in byte 1
+    if ($payload_length > 125) {
+      if ($payload_length === 126) $data = $this->read(2); // 126: Payload is a 16-bit unsigned int
+      else                         $data = $this->read(8); // 127: Payload is a 64-bit unsigned int
+      $payload_length = bindec(self::sprintB($data));
+    }
+
+    // Get masking key.
+    if ($mask) $masking_key = $this->read(4);
+
+    // Get the actual payload, if any (might not be for e.g. close frames.
+    if ($payload_length > 0) {
+      $data = $this->read($payload_length);
+
+      if ($mask) {
+        // Unmask payload.
+        for ($i = 0; $i < $payload_length; $i++) $payload .= ($data[$i] ^ $masking_key[$i % 4]);
+      }
+      else $payload = $data;
+    }
+
+    if ($opcode === 'close') {
+      // Get the close status.
+      if ($payload_length >= 2) {
+        $status_bin = $payload[0] . $payload[1];
+        $status = bindec(sprintf("%08b%08b", ord($payload[0]), ord($payload[1])));
+        $this->close_status = $status;
+        $payload = substr($payload, 2);
+
+        if (!$this->is_closing) $this->send($status_bin . 'Close acknowledged: ' . $status, 'close', true); // Respond.
+      }
+
+      if ($this->is_closing) $this->is_closing = false; // A close response, all done.
+
+      // And close the socket.
+      fclose($this->socket);
+      $this->is_connected = false;
+    }
+
+    // if this is not the last fragment, then we need to save the payload
+    if (!$final) {
+      $this->huge_payload .= $payload;
+      return null;
+    }
+    // this is the last fragment, and we are processing a huge_payload
+    else if ($this->huge_payload) {
+      // sp we need to retreive the whole payload
+      $payload = $this->huge_payload .= $payload;
+      $this->huge_payload = null;
+    }
+
+    return $payload;
+  }
+
+  /**
+   * Tell the socket to close.
+   *
+   * @param integer $status  http://tools.ietf.org/html/rfc6455#section-7.4
+   * @param string  $message A closing message, max 125 bytes.
+   */
+  public function close($status = 1000, $message = 'ttfn') {
+    $status_binstr = sprintf('%016b', $status);
+    $status_str = '';
+    foreach (str_split($status_binstr, 8) as $binstr) $status_str .= chr(bindec($binstr));
+    $this->send($status_str . $message, 'close', true);
+
+    $this->is_closing = true;
+    $response = $this->receive(); // Receiving a close frame will close the socket now.
+
+    return $response;
+  }
+
+  protected function write($data) {
+    $written = fwrite($this->socket, $data);
+
+    if ($written < strlen($data)) {
+      throw new ConnectionException(
+        "Could only write $written out of " . strlen($data) . " bytes."
+      );
+    }
+  }
+
+  protected function read($length) {
+    $data = '';
+    while (strlen($data) < $length) {
+      $buffer = fread($this->socket, $length - strlen($data));
+      if ($buffer === false) {
+        $metadata = stream_get_meta_data($this->socket);
+        throw new ConnectionException(
+          'Broken frame, read ' . strlen($data) . ' of stated '
+          . $length . ' bytes.  Stream state: '
+          . json_encode($metadata)
+        );
+      }
+      if ($buffer === '') {
+        $metadata = stream_get_meta_data($this->socket);
+        throw new ConnectionException(
+          'Empty read; connection dead?  Stream state: ' . json_encode($metadata)
+        );
+      }
+      $data .= $buffer;
+    }
+    return $data;
+  }
+
+
+  /**
+   * Helper to convert a binary to a string of '0' and '1'.
+   */
+  protected static function sprintB($string) {
+    $return = '';
+    for ($i = 0; $i < strlen($string); $i++) $return .= sprintf("%08b", ord($string[$i]));
+    return $return;
+  }
+}

+ 177 - 0
extend/WebSocket/Client.php

@@ -0,0 +1,177 @@
+<?php
+
+/**
+ * Copyright (C) 2014, 2015 Textalk
+ * Copyright (C) 2015 Ignas Bernotas - added context options and handling
+ *
+ * This file is part of Websocket PHP and is free software under the ISC License.
+ * License text: https://raw.githubusercontent.com/Textalk/websocket-php/master/COPYING
+ */
+
+namespace WebSocket;
+
+class Client extends Base {
+  protected $socket_uri;
+
+  /**
+   * @param string  $uri      A ws/wss-URI
+   * @param array   $options
+   *   Associative array containing:
+   *   - context:      Set the stream context. Default: empty context
+   *   - timeout:      Set the socket timeout in seconds.  Default: 5
+   *   - headers:      Associative array of headers to set/override.
+   */
+  public function __construct($uri, $options = array()) {
+    $this->options = $options;
+
+    if (!array_key_exists('timeout', $this->options)) $this->options['timeout'] = 30;
+
+    // the fragment size
+    if (!array_key_exists('fragment_size', $this->options)) $this->options['fragment_size'] = 4096;
+
+    $this->socket_uri = $uri;
+  }
+
+  public function __destruct() {
+    if ($this->socket) {
+      if (get_resource_type($this->socket) === 'stream') fclose($this->socket);
+      $this->socket = null;
+    }
+  }
+
+  /**
+   * Perform WebSocket handshake
+   */
+  protected function connect() {
+    $url_parts = parse_url($this->socket_uri);
+    $scheme    = $url_parts['scheme'];
+    $host      = $url_parts['host'];
+    $user      = isset($url_parts['user']) ? $url_parts['user'] : '';
+    $pass      = isset($url_parts['pass']) ? $url_parts['pass'] : '';
+    $port      = isset($url_parts['port']) ? $url_parts['port'] : ($scheme === 'wss' ? 443 : 80);
+    $path      = isset($url_parts['path']) ? $url_parts['path'] : '/';
+    $query     = isset($url_parts['query'])    ? $url_parts['query'] : '';
+    $fragment  = isset($url_parts['fragment']) ? $url_parts['fragment'] : '';
+
+    $path_with_query = $path;
+    if (!empty($query))    $path_with_query .= '?' . $query;
+    if (!empty($fragment)) $path_with_query .= '#' . $fragment;
+
+    if (!in_array($scheme, array('ws', 'wss'))) {
+      throw new BadUriException(
+        "Url should have scheme ws or wss, not '$scheme' from URI '$this->socket_uri' ."
+      );
+    }
+
+    $host_uri = ($scheme === 'wss' ? 'ssl' : 'tcp') . '://' . $host;
+
+    // Set the stream context options if they're already set in the config
+    if (isset($this->options['context'])) {
+      // Suppress the error since we'll catch it below
+      if (@get_resource_type($this->options['context']) === 'stream-context') {
+        $context = $this->options['context'];
+      }
+      else {
+        throw new \InvalidArgumentException(
+          "Stream context in \$options['context'] isn't a valid context"
+        );
+      }
+    }
+    else {
+      $context = stream_context_create();
+    }
+
+    // Open the socket.  @ is there to supress warning that we will catch in check below instead.
+    $this->socket = @stream_socket_client(
+      $host_uri . ':' . $port,
+      $errno,
+      $errstr,
+      $this->options['timeout'],
+      STREAM_CLIENT_CONNECT,
+      $context
+    );
+
+    if ($this->socket === false) {
+      throw new ConnectionException(
+        "Could not open socket to \"$host:$port\": $errstr ($errno)."
+      );
+    }
+
+    // Set timeout on the stream as well.
+    stream_set_timeout($this->socket, $this->options['timeout']);
+
+    // Generate the WebSocket key.
+    $key = self::generateKey();
+
+    // Default headers (using lowercase for simpler array_merge below).
+    $headers = array(
+      'host'                  => $host . ":" . $port,
+      'user-agent'            => 'websocket-client-php',
+      'connection'            => 'Upgrade',
+      'upgrade'               => 'websocket',
+      'sec-websocket-key'     => $key,
+      'sec-websocket-version' => '13',
+    );
+
+    // Handle basic authentication.
+    if ($user || $pass) {
+      $headers['authorization'] = 'Basic ' . base64_encode($user . ':' . $pass) . "\r\n";
+    }
+
+    // Deprecated way of adding origin (use headers instead).
+    if (isset($this->options['origin'])) $headers['origin'] = $this->options['origin'];
+
+    // Add and override with headers from options.
+    if (isset($this->options['headers'])) {
+      $headers = array_merge($headers, array_change_key_case($this->options['headers']));
+    }
+
+    $header =
+      "GET " . $path_with_query . " HTTP/1.1\r\n"
+      . implode(
+        "\r\n", array_map(
+          function($key, $value) { return "$key: $value"; }, array_keys($headers), $headers
+        )
+      )
+      . "\r\n\r\n";
+
+    // Send headers.
+    $this->write($header);
+
+    // Get server response header (terminated with double CR+LF).
+    $response = stream_get_line($this->socket, 1024, "\r\n\r\n");
+
+    /// @todo Handle version switching
+
+    // Validate response.
+    if (!preg_match('#Sec-WebSocket-Accept:\s(.*)$#mUi', $response, $matches)) {
+      $address = $scheme . '://' . $host . $path_with_query;
+      throw new ConnectionException(
+        "Connection to '{$address}' failed: Server sent invalid upgrade response:\n"
+        . $response
+      );
+    }
+
+    $keyAccept = trim($matches[1]);
+    $expectedResonse
+      = base64_encode(pack('H*', sha1($key . '258EAFA5-E914-47DA-95CA-C5AB0DC85B11')));
+
+    if ($keyAccept !== $expectedResonse) {
+      throw new ConnectionException('Server sent bad upgrade response.');
+    }
+
+    $this->is_connected = true;
+  }
+
+  /**
+   * Generate a random string for WebSocket key.
+   * @return string Random string
+   */
+  protected static function generateKey() {
+    $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"$&/()=[]{}0123456789';
+    $key = '';
+    $chars_length = strlen($chars);
+    for ($i = 0; $i < 16; $i++) $key .= $chars[mt_rand(0, $chars_length-1)];
+    return base64_encode($key);
+  }
+}

+ 4 - 0
extend/WebSocket/ConnectionException.php

@@ -0,0 +1,4 @@
+<?php
+
+namespace WebSocket;
+class ConnectionException extends Exception {}

+ 4 - 0
extend/WebSocket/Exception.php

@@ -0,0 +1,4 @@
+<?php
+
+namespace WebSocket;
+class Exception extends \Exception {}

+ 106 - 0
extend/WebSocket/Server.php

@@ -0,0 +1,106 @@
+<?php
+
+/**
+ * Copyright (C) 2014, 2015 Textalk
+ *
+ * This file is part of Websocket PHP and is free software under the ISC License.
+ * License text: https://raw.githubusercontent.com/Textalk/websocket-php/master/COPYING
+ */
+
+namespace WebSocket;
+
+/**
+ * This is just a simple stub for testing the Client.  It could be made useful…
+ */
+class Server extends Base {
+  protected $addr, $port, $listening, $request;
+
+  /**
+   * @param array   $options
+   *   Associative array containing:
+   *   - timeout:  Set the socket timeout in seconds.  Default: 5
+   *   - port:     Chose port for listening.
+   */
+  public function __construct(array $options = array()) {
+
+    // the fragment size
+    if (!array_key_exists('fragment_size', $options)) $options['fragment_size'] = 4096;
+
+
+    $this->port = isset($options['port']) ? $options['port'] : 8000;
+    $this->options = $options;
+
+    do {
+      $this->listening = @stream_socket_server("tcp://0.0.0.0:$this->port", $errno, $errstr);
+    } while ($this->listening === false && $this->port++ < 10000);
+
+    if (!$this->listening) {
+      throw new ConnectionException("Could not open listening socket.");
+    }
+  }
+
+  public function getPort()    { return $this->port;         }
+  public function getPath()    { return $this->request_path; }
+  public function getRequest() { return $this->request;      }
+
+  public function getHeader($header) {
+    foreach ($this->request as $row) {
+      if (stripos($row, $header) !== false) {
+        list($headername, $headervalue) = explode(":", $row);
+        return trim($headervalue);
+      }
+    }
+    return null;
+  }
+
+  public function accept() {
+    if (empty($this->options['timeout'])) {
+      $this->socket = stream_socket_accept($this->listening);
+    }
+    else {
+      $this->socket = stream_socket_accept($this->listening, $this->options['timeout']);
+      stream_set_timeout($this->socket, $this->options['timeout']);
+    }
+
+    $this->performHandshake();
+
+    return $this->socket;
+  }
+
+  protected function performHandshake() {
+    $request = '';
+    do {
+      $buffer = stream_get_line($this->socket, 1024, "\r\n");
+      $request .= $buffer . "\n";
+      $metadata = stream_get_meta_data($this->socket);
+    } while (!feof($this->socket) && $metadata['unread_bytes'] > 0);
+
+    if (!preg_match('/GET (.*) HTTP\//mUi', $request, $matches)) {
+      throw new ConnectionException("No GET in request:\n" . $request);
+    }
+    $get_uri = trim($matches[1]);
+    $uri_parts = parse_url($get_uri);
+
+    $this->request = explode("\n", $request);
+    $this->request_path = $uri_parts['path'];
+    /// @todo Get query and fragment as well.
+
+    if (!preg_match('#Sec-WebSocket-Key:\s(.*)$#mUi', $request, $matches)) {
+      throw new ConnectionException("Client had no Key in upgrade request:\n" . $request);
+    }
+
+    $key = trim($matches[1]);
+
+    /// @todo Validate key length and base 64...
+    $response_key = base64_encode(pack('H*', sha1($key . '258EAFA5-E914-47DA-95CA-C5AB0DC85B11')));
+
+    $header = "HTTP/1.1 101 Switching Protocols\r\n"
+      . "Upgrade: websocket\r\n"
+      . "Connection: Upgrade\r\n"
+      . "Sec-WebSocket-Accept: $response_key\r\n"
+      . "\r\n";
+
+    $this->write($header);
+    $this->is_connected = true;
+  }
+}

+ 2 - 0
public/static/libs/amazeui/css/main.css

@@ -721,6 +721,7 @@ font-size:18px;
 .me span { 
     float: right;
     background: #9eea6a;
+	word-break: break-all; white-space: normal;
 }
 
 .me{
@@ -780,6 +781,7 @@ font-size:18px;
 }
 
 .other span { 
+	word-break: break-all; white-space: normal;
     float: right;
 	width: auto;
     background: #9eea6a;

+ 1 - 1
public/static/libs/amazeui/js/wechat.js

@@ -1003,7 +1003,7 @@ function postmsg(cnt,callback){
 			$("#hack_wrap").hide(100);
 		}else{
 			//$(".msgcontent").val(content);
-			layer.alert('本条信息已发出,但并没有入库,原因:'+res.msg);
+			layer.msg('本条信息已发出,在线会员都能看,但后面来的人看不到,因为没有入库,原因:'+res.msg);
 		}
 		if(typeof(callback)=='function'){
 			callback(res);

+ 64 - 7
public/static/libs/bui/pages/chat/chat.js

@@ -1,3 +1,55 @@
+/**
+ * 聊天对话模板
+ */
+
+/*****这个IF语句里边的代码是APP专用***/
+if(typeof(web_url)!='undefined'){
+var ReWrite={};	//重写JQ与BUI的一些方法
+
+ReWrite.get = $.get;
+$.get = function(url,callback){
+	url = Qibo.check_url(url);
+	return  ReWrite.get(url,callback);//$.post(url,{},callback);	
+}
+
+ReWrite.post = $.post;
+$.post = function(url,obj,callback){
+	url = Qibo.check_url(url);
+	return  ReWrite.post(url,obj,callback);
+}
+
+ReWrite.buiload = bui.load;
+bui.load = function(obj){
+	if(typeof(obj.url)!='undefined' && (obj.url).indexOf('/public/static/')==0 ){
+		obj.url = obj.url.substring(1);		
+	}
+	ReWrite.buiload(obj);
+}
+
+ReWrite.loader = loader.import;
+loader.import = function(arr,callback){
+	var o = typeof(arr)=='string' ? [arr] : arr;
+	console.log(o);
+	o.forEach((url,i)=>{
+		if( url.indexOf('/public/static/')==0 ){
+			o[i] = url.substring(1);
+		}
+	});
+	console.log(o);
+	ReWrite.loader(o,callback);
+}
+
+ReWrite.layeropen = layer.open;
+layer.open = function(obj){
+	if(obj.type==2){
+		obj.content = Qibo.check_url(obj.content);
+	}
+	ReWrite.layeropen(obj);
+}
+
+}
+/*****上面的IF语句代码是APP专用***/
+
 layer.closeAll = function(){console.log('不允许使用把全部层一次关闭,不然会影响到其它插件');};
 
 var refresh_i,refresh_timenum;//这几个已弃用
@@ -9,6 +61,7 @@ var load_data = {};	//接口
 var first_page_data;	//初始数据,给后加载的框架使用
 var in_pc = false;
 var format_content ={}; //接口
+var format_content_have_run ={};
 
 //加载聊天窗口框架
 function load_chat_iframe(url,callback){
@@ -456,7 +509,7 @@ loader.define(function(require,exports,module) {
 			if( typeof(load_data[keywords])=='function' ){
 				load_data[keywords](res);
 			}
-			if(typeof(format_content[keywords])=='function'){
+			if(typeof(format_content[keywords])=='function' && format_content_have_run[keywords]!=true){
 				format_content[keywords](res);
 			}
 		}
@@ -784,11 +837,10 @@ loader.define(function(require,exports,module) {
 		format_nickname();	//设置圈子昵称
 
 
-		if(show_msg_page>1 || is_repeat>1 || type=='cknew'){	//第一页不一定能执行得到,所以就放在加载脚本那里单独处理
-			for(var index in format_content){
-				if(typeof(format_content[index])=='function'){
-					format_content[index](res,type);
-				}
+		for(var index in format_content){
+			if(typeof(format_content[index])=='function'){
+				format_content[index](res,type);
+				format_content_have_run[index] = true;
 			}
 		}
 
@@ -885,7 +937,7 @@ loader.define(function(require,exports,module) {
 				content_add_btn(res,type);
 			}
 			//console.log('userinfo=',userinfo);
-		},500);	//定时器,为了反复刷新用户登录数据
+		},500);	//定时器,为了反复刷新用户登录数据 ,用户数据登录数据如果加载不了, 可能会白屏
 	}
 
 	function format_msgdata_tohtml(array , myid , type){
@@ -904,6 +956,11 @@ loader.define(function(require,exports,module) {
 			if(userdb.uid>0 && (rs.uid==userdb.uid || rs.touid==userdb.uid) ){
 				del_str = `<i data-id="${rs.id}" class="del glyphicon glyphicon-remove-circle"></i>`;
 			}
+			
+			if(typeof(web_url)!='undefined'){
+				rs.content = (rs.content).replace(/ src=('|")\/public\/static\//g," src=$1public/static/");
+				rs.content = (rs.content).replace(/ src=('|")\/public\/uploads\//g," src=$1"+web_url+"/public/uploads/");
+			}			
 
 			user_str = `<div class="chat-icon" data-uid="${rs.uid}" data-name="${rs.from_username}"><img src="${rs.from_icon}" onerror="this.src='${d_url}public/static/images/noface.png'" title="${rs.from_username}"></div>`;
 			if(rs.uid!=myid){

+ 3 - 0
public/static/libs/bui/pages/hack/qqface.js

@@ -77,6 +77,8 @@ mod_class.qqface = {
 
 //类接口,加载到聊天会话数据时执行的  刷新数据的时候也会有到.不仅仅是初次加载
 format_content.qqface = function(res,type){
+	//rs.content = (rs.content).replace(/ src=('|")\/public\/static\//g," src=$1"+web_url+"/public/static/");
+	/*
 	if( typeof(api)=='object' ){
 		$("#chat_win").find("img").each(function(){
 			var url = $(this).attr('src');
@@ -86,4 +88,5 @@ format_content.qqface = function(res,type){
 			}
 		});
 	}
+	*/
 }

+ 18 - 2
public/static/libs/bui/pages/hongbao/init.js

@@ -43,11 +43,12 @@ mod_class.hongbao = {
 
 //对聊天内容进行重新转义显示
 format_content.hongbao = function(res,type){
+	var w_url = typeof(api) == 'object' ? '' : '/';
 	if(in_pc==true){
 		$(".office_text .hack-hongbao").each(function(){
 			var id = $(this).data("id");
 			var title = $(this).data("title");
-			var str = `<a href="#" title="${title}" onclick="layer.open({type: 2,title: '${title}',shadeClose: true,shade: 0.3,area: ['600px', '600px'],content: '/index.php/p/hongbao-content-show/id/${id}.html'});"><img src="/public/static/plugins/voicehb/hongbao.png"></a>`;
+			var str = `<a href="#" title="${title}" onclick="layer.open({type: 2,title: '${title}',shadeClose: true,shade: 0.3,area: ['600px', '600px'],content: '/index.php/p/hongbao-content-show/id/${id}.html'});"><img src="${w_url}public/static/plugins/hongbao/bongbao.png"></a>`;
 			$(this).html(str);
 		});
 	}else{
@@ -56,8 +57,23 @@ format_content.hongbao = function(res,type){
 		router.$(".chat-panel .hack-hongbao").each(function(){
 			var id = $(this).data("id");
 			var title = $(this).data("title");
-			var str = `<div onclick="layer.open({type: 2,title: '${title}',shadeClose: true,shade: 0.3,area: ['95%', '80%'],content: '${d_url}/index.php/p/hongbao-content-show/id/${id}.html'});"><img src="/public/static/plugins/voicehb/hongbao.png"></div>`;
+			var str = `<div onclick="layer.open({type: 2,title: '${title}',shadeClose: true,shade: 0.3,area: ['95%', '80%'],content: '${d_url}/index.php/p/hongbao-content-show/id/${id}.html'});"><img src="${w_url}public/static/plugins/hongbao/bongbao.png"></div>`;
 			$(this).html(str);
 		});
 	}
+}
+
+
+ws_onmsg.hongbao = function(obj) {
+    var d_url = typeof(api) == 'object' ? '' : '/';
+    if (obj.type == 'rob_hongbao') {
+		var str = "<div class='new-gift-msg'><div> <img style='width:20px' src='"+d_url+"public/static/plugins/hongbao/bongbao.png' style='margin:0;'> <span>" + obj.data.username + "  </span> 抢了 <span class='buyname'>" + obj.data.from_username + "</span> 的红包 <span class='buyname'>" + obj.data.money + "</span> 元 </div></div>";
+        if (in_pc == true) {
+            $(".pc_show_all_msg").prepend(str);
+            goto_bottom(500)
+        } else {
+            $("#chat_win").prepend(str);
+            $('#chat_win').parent().scrollTop(20000);
+        }
+    }
 }

+ 2 - 0
public/static/libs/bui/pages/imgzoom/zoom.js

@@ -47,6 +47,8 @@
 			for(var len=imgList.length,i=0; i<len; i++){
 				if(imgList[i].onclick){
 					continue ;//有点击事件的图片,就不处理
+				}else if(imgList[i].parentNode.onclick||imgList[i].parentNode.href){
+					continue ;//父节点有点击事件的图片,就不处理
 				}
 				imgList[i].addEventListener("click", function(){
 					imgSrc = this.getAttribute("src");

+ 4 - 2
public/static/libs/bui/pages/p2pvideo/init.js

@@ -11,8 +11,10 @@ mod_class.p2pvideo = {
 		layer.open({
 						type: 2,
 						title:'视频电话',
-						shadeClose: true,
-						shade: 0.3,
+						//shadeClose: true,
+						shade: 0,
+						maxmin: true,
+						shadeClose: false,  
 						area: (in_pc?['500px', '350px']:['90%', '60%']),
 						content: d_url+'public/static/libs/bui/pages/p2pvideo/index.html',
 						success: function(layero, index){  

+ 1 - 1
public/static/libs/bui/pages/topic/index.js

@@ -189,7 +189,7 @@ loader.define(function(require,exports,module) {
 			if(result.uid==undefined){
 				layer.alert('uid参数不存在');
 			}else if(result.type==undefined){
-				layer.alert('type参数不存在');
+				//layer.alert('type参数不存在');
 			}
 			uid = result.uid;
 			if(result.type!=undefined)type = result.type;

+ 1 - 1
public/static/libs/bui/pages/uploadpic/wap_init.js

@@ -19,6 +19,7 @@ mod_class.uploadpic = {
 		//}).fail(function() {
 		//	console.log('/public/static/js/base64uppic.js加载失败');
 		//});
+		loader.import(["/public/static/js/exif.js"],function(){});	//上传图片要获取图片信息
 	},
 	finish:function(res){  //所有模块加载完才执行
 		//jQuery.getScript("/public/static/js/exif.js").done(function() {
@@ -26,7 +27,6 @@ mod_class.uploadpic = {
 		//}).fail(function() {
 		//	console.log('/public/static/js/exif.js加载失败');
 		//});
-		loader.import(["/public/static/js/exif.js"],function(){});	//上传图片要获取图片信息
 	},
 	logic_init:function(res){  //init()只做界面渲染与页面元素的事件绑定,若做逻辑的话,更换圈子时PC端不执行,执行的话,会导致界面重复渲染。logic_init()做逻辑处理,满足更换圈子房间的需要
 	},

+ 8 - 2
public/static/libs/bui/pages/wx_share/init.js

@@ -2,15 +2,21 @@
 mod_class.wx_share = {
 	init:function(res){	//init()只做界面渲染与页面元素的事件绑定,若做逻辑的话,更换圈子时PC端不执行,执行的话,会导致界面重复渲染。logic_init()做逻辑处理,满足更换圈子房间的需要
 		
+		if(uid>=0){	//只有圈子才有分享功能
+			return ;
+		}
+
 		var title = quninfo.title!=''?quninfo.title:'欢迎加入圈子群聊';
+		var about = quninfo.content!=''?quninfo.content.replace('&nbsp;',''):'欢迎加入圈子群聊,不错过每一个精彩的直播!';
 		if( typeof(res.ext)=='object' && typeof(res.ext.live)=='object' && typeof(res.ext.live.live_video)=='object' ){
-			title += ' 欢迎你过来看直播!';
+			title = res.ext.live.live_video.title;
+			about = res.ext.live.live_video.about;
 		}
 		var info = {
 				url:(typeof(web_url)!='undefined'?web_url:'')+"/index.php/index/msg/index.html?uid="+uid,
 				picurl:quninfo.picurl!=''?quninfo.picurl:'',
 				title:title,
-				about:quninfo.content!=''?quninfo.content.replace('&nbsp;',''):'欢迎加入圈子群聊,不错过每一个精彩的直播!',
+				about:about,
 		}
 		if(typeof(web_url)!='undefined'){	//APP中使用的
 			var dialog;			

+ 36 - 1
public/static/libs/bui/pages/zhibo/dplayer.html

@@ -19,12 +19,15 @@ body {
 <script type="text/javascript" src="./dplayer/flv.min.js"></script> 
 <script type="text/javascript" src="./dplayer/hls.min.js"></script>
 <script type="text/javascript" src="./dplayer/DPlayer.min.js?v=f32"></script>
+<link rel="stylesheet" href="./dplayer/DPlayer.min.css">
 </head>
 <body>
 <script type="text/javascript">
 var weburl = window.location.href;	//var weburl = window.location.href.indexOf("http")==0 ? '' : '../../../../../..';
 weburl = weburl.substring(0,weburl.indexOf('/public/static/')); //方便手机获取真实路径
-document.write('<link rel="stylesheet" href="'+weburl+'/public/static/libs/bui/pages/zhibo/dplayer/DPlayer.min.css">');
+document.write('<link rel="stylesheet" href="'+weburl+'/public/static/icon/icon.css">');
+document.write('<script type="text/javascript" src="'+weburl+'/public/static/js/core/jquery.min.js"><\/script>');
+//document.write('<script type="text/javascript" src="'+weburl+'/public/static/layer/layer.js"><\/script>');
 </script>
 
 
@@ -68,5 +71,37 @@ function palyer(video_url, height, only_sound, in_pc) {
     }
 }   
 </script>
+<style type="text/css">
+.about{
+	padding:5px;
+	font-size:14px;
+	color:#888;
+}
+.tt{
+	color:orange;
+}
+.more{
+	color:blue;
+}
+
+</style>
+<div class="about"><span class="tt fa fa-bullhorn">直播介绍:</span><span class="cnt">传奇 夫代工夫工地会要地仍城大规模地魂牵梦萦城魂牵梦萦城魂牵梦萦地魂牵梦萦地械左夺 </span><span class="more">[详情]</span></div>
+<script type="text/javascript">
+$(function(){
+	$(".about .cnt").html(parent.mod_class.zhibo.dataUrls.title);
+	$(".about .more").click(function(){
+		var about = parent.mod_class.zhibo.dataUrls.about;
+		about = about.replace(/\r\n/g,"<br>");
+		//about = about.replace(/ /g,"&nbsp;");
+		parent.layer.open({
+			type: 1,
+			title:false,
+			shift: 1,
+			area:['98%','300px'],
+			content: '<style type="text/css">.layui-layer-setwin{ top:250px !important;}</style><div style="padding:10px;">' + about + '</content>',
+		});
+	});
+});
+</script>
 </body>
 </html>

+ 43 - 17
public/static/libs/bui/pages/zhibo/init.js

@@ -1,7 +1,7 @@
 //init() logic_init() once() finish() 的使用教程网址 http://help.php168.com/1435153 
 mod_class.zhibo = {
 	zhibo_obj:null,	
-	urls:{},
+	dataUrls:{},			//这个变量里边包含了直播地址与直播介绍等信息
 	zhibo_status:false,		//是否在直播进行中
 	finish:function(res){  //所有模块加载完才执行
 	},
@@ -88,11 +88,36 @@ mod_class.zhibo = {
 			}else if(quninfo.uid!=my_uid){
 				layer.alert('只有圈主才能直播,你如果没有圈子的话,可以创建一个!');
 				return ;
-			}else if(typeof(api)=='object'){	//在APP中执行,打开直播			
-				that.app_start_zhibo();
+			}
+			
+			var show_str = `<div class="live_video_warp">
+							分享标题:<input class="zhibo_share_title" type="text" style="width:80%;" value="${quninfo.title}"><br>
+							分享描述:<textarea class="zhibo_share_about"  style="width:80%;height:100px;" value="${quninfo.content}"></textarea><br>
+							</div>`;
+			layer.open({
+					type: 1,
+					title:'请输入本次直播介绍,有利于微信转发推广',
+					shift: 1,
+					btn:["确认","取消"],
+					area:in_pc?['500px','250px']:['98%','300px'],
+					content: show_str,
+					btn1:function(index){
+						layer.close(index);
+						var postdata = {
+							title:$(".live_video_warp").last().find(".zhibo_share_title").val(),
+							about:$(".live_video_warp").last().find(".zhibo_share_about").val(),
+						};
+						zhibo_choose(postdata);
+					}
+			});
+		});
+
+		function zhibo_choose(postdata){
+			if(typeof(api)=='object'){	//在APP中执行,打开直播			
+				that.app_start_zhibo(postdata);
 				return ;
 			}
-			$.get("/index.php/p/alilive-api-url.html?id="+Math.abs(uid),function(res){
+			$.post("/index.php/p/alilive-api-url.html?id="+Math.abs(uid),postdata,function(res){
 					if(res.code==0){
 						that.notify_selfsever(res.data.self_server_api);	//自建服务器的话要做通知开播处理
 						var play_url = '';
@@ -139,17 +164,17 @@ mod_class.zhibo = {
 						layer.alert(res.msg);
 					}
 			});
-		});
+		}
 	},
-	app_start_zhibo:function(){	//在APP中直播		
+	app_start_zhibo:function(postdata){	//在APP中直播		
 		if(this.zhibo_obj!=null){
-			this.zhibo_obj.start();
+			this.zhibo_obj.start(postdata);
 		}else{
 			this.add_btn();		//添加菜单元素
 			var that = this; //变量引用			
 			loader.require("public/static/libs/bui/pages/zhibo/bo",function (o) {
 				that.zhibo_obj = o;				
-				that.zhibo_obj.start();
+				that.zhibo_obj.start(postdata);
 				that.zhibo_obj.add_btn_fun();			//直播菜单加点击事件
 				//that.zhibo_obj.showbtn();
 			});
@@ -212,7 +237,7 @@ mod_class.zhibo = {
 				  }
 			});
 		}else{			
-			load_chat_iframe("/public/static/libs/bui/pages/zhibo/dplayer.html",function(win,body){
+			load_chat_iframe("/public/static/libs/bui/pages/zhibo/dplayer.html?gf",function(win,body){
 				win.palyer(m3u8_url,only_sound==true?'40px':'200px',only_sound);
 			});
 		}
@@ -349,7 +374,7 @@ mod_class.zhibo = {
 		}
 	},
 	ask_play:function(urls){
-		this.urls = urls;
+		this.dataUrls = urls;
 		//请求圈主当前播放状态是不是纯音频 请求成功后,再播放,要保证WS服务器正常连上.否则3秒后自动播放
 		ws_send({type:"user_ask_quner",tag:"ask_live_state"},'user_cid');
 		var that = this;
@@ -368,7 +393,8 @@ mod_class.zhibo = {
 			this.waitTime = null;
 		}
 		if(this.haveLoadPlayer == false){
-			this.player(urls.length==0?this.urls:urls,only_sound);
+			this.player(urls.length==0?this.dataUrls:urls,	//urls就是圈主提供的最新播放信息
+				only_sound);
 		}		
 	},
 }
@@ -376,14 +402,14 @@ mod_class.zhibo = {
 
 //类接口,WebSocket下发消息的回调接口
 ws_onmsg.zhibo = function(obj){
-	if(obj.type=='ask_live_state'){	//访客请求播放状态 ,圈主进行上传回馈.
+	if(obj.type=='ask_live_state'){		//访客请求播放状态 ,圈主进行上传回馈.  特别要注意, 这里只是圈主才会执行
 
 		var msgarray = {
 			type: "quner_to_user",		//群主发给指定会员的指令 这个是固定标志
 			user_cid: obj.user_cid,		//某个会员的ID标志			
 			tag: 'give_live_state' ,	//访客接收标志 ,不同插件,这个标志不能雷同,避免冲突
 			data: {
-				urls:mod_class.zhibo.urls,	//这个值有可能不存在,因为圈主发起推流的时候没设置
+				urls:mod_class.zhibo.dataUrls,
 				only_sound:mod_class.zhibo.only_sound(),
 			},
 		}
@@ -396,10 +422,10 @@ ws_onmsg.zhibo = function(obj){
 
 	}else if(obj.type=='error#give_live_state'){  //圈主不在,或者是圈主首次访问 就 直接播放 , 用第三方推流工具的时候,才用到的.
 
-		if( my_uid!=quninfo.uid && typeof(mod_class.zhibo.limit_time)=='number' ){
+		if( my_uid!=quninfo.uid && typeof(mod_class.zhibo.limit_time)=='number' ){  //收费课堂,圈主必须要在线才行.
 			layer.alert('圈主掉线,直播暂停了!');
 		}else{
-			mod_class.zhibo.sync_play(mod_class.zhibo.urls);
+			mod_class.zhibo.sync_play(mod_class.zhibo.dataUrls);
 		}
 		
 	}else if(obj.type=='zhibo_server_stop'){	//推流服务器发过来的通知,推流断开了,就自动关闭,推流断开有可能是网络的问题,所以不一定是圈主 人为主动关闭直播
@@ -415,14 +441,14 @@ ws_onmsg.zhibo = function(obj){
 			mod_class.zhibo.notify_selfsever('reconnect');
 		}
 		
-	}else if(obj.type=='zhibo_server_start'){  //聊天过程中,圈主中途打开直播,通知所有用户打开直播
+	}else if(obj.type=='zhibo_server_start'){  //聊天过程中,圈主中途打开直播,通知所有用户打开直播 , 重要提醒,这条信息是服务器发过来的
 
 		if(mod_class.zhibo.connect_timer!=null){	//这里处理圈主直播断线重连,这里是圈主才执行的
 			layer.msg('重连成功');
 			clearInterval( mod_class.zhibo.connect_timer );
 			mod_class.zhibo.connect_timer = null;
 		}
-		mod_class.zhibo.urls = obj.data;
+		mod_class.zhibo.dataUrls = obj.data;	//这个赋值给圈主使用的,其实可以删除,因为prepare_play函数里同样赋值了
 		mod_class.zhibo.prepare_play(obj.data);
 
 	}else if(obj.type=='count' || obj.type=='leave'){	//用户进来或者离开

BIN
public/static/plugins/hongbao/banner.png


BIN
public/static/plugins/hongbao/but0.png


BIN
public/static/plugins/hongbao/but1.png


BIN
public/static/plugins/hongbao/hb.png


+ 0 - 139
public/static/plugins/hongbao/index.css

@@ -1,139 +0,0 @@
-.HongbaoBox{
-	max-width: 640px;
-	background: #F5F5F5;
-	margin: auto;
-}
-.Banner img{
-	width:100%;
-}
-.addHongbao{
-	padding: 15px 10px;
-	background: #FFF;
-}
-.addHongbao a{
-	display: block;
-	background: #F9D806;
-	text-align: center;
-	line-height: 45px;
-	color: #F30;
-	border-radius: 5px;
-	font-weight: bold;
-}
-.addHongbao a span{
-	display: inline-block;
-	margin-right: 5px;
-}
-.ShowTypes{	
-	background: #FFF;
-	margin-top: 10px;
-	height: 50px;
-	line-height: 50px;
-	position: relative;
-	overflow: hidden;
-	display: flex;
-	flex-direction: row;
-}
-.ShowTypes:before{
-	content: '';
-	display: block;
-	width: 100%;
-	height:1px;
-	background: #EEE;
-	position: absolute;
-	left: 0;
-	bottom: 0px;
-}
-.ShowTypes a{
-	display: flex;
-	width:33.33%;
-	position:relative;
-	justify-content:center; 
-	align-items:center;
-}
-.ShowTypes a.ck{
-	color: #F30;
-}
-.ShowTypes a.ck:before{
-	content: '';
-	display: block;
-	width: 100%;
-	height:2px;
-	background: #F30;
-	position: absolute;
-	left: 0;
-	bottom: 0px;
-}
-.ListHongbao{
-	padding: 0 10px;
-	background: #FFF;
-}
-.ListHongbao .list{
-	padding: 15px 0px;
-	border-bottom: #EEE solid 1px;
-}
-.ListHongbao .list ul{
-	padding-left:90px;
-	height: 100px;
-	position: relative;
-	overflow: hidden;
-}
-.ListHongbao .list ul .hb{
-	position: absolute;
-	width:80px;
-	height: 100px;
-	overflow: hidden;
-	left:0;
-	top:0;
-}
-.ListHongbao .list ul .hb img{
-	position: absolute;
-	width:100%;
-	height: 100%;
-	left: 0;
-	top:0px;
-}
-.ListHongbao .list ul .but{
-	position: absolute;
-	width:70px;
-	right:0;
-	bottom: 0px;
-}
-.ListHongbao .list ul .but img{
-	width:100%;
-}
-.ListHongbao .list ul .info div{
-	height:33px;
-	line-height: 33px;
-	overflow: hidden;
-}
-.ListHongbao .list ul .info div.cnt{
-	font-size:14px;
-	color: #666;
-}
-.ListHongbao .list ul .info div.cnt span{
-	color: #F30;
-}
-.ListHongbao .list ul .info div.cnt em{
-	color: #AAA;
-}
-.ListHongbao .list ul .info div.more,.ListHongbao .list ul .info div.more a{
-	display: flex;
-	flex-direction: row;
-	font-size:14px;
-	color: #888;
-}
-.ListHongbao .list ul .info div.more a span{
-	display: flex;
-	width:25px;
-	overflow: hidden;
-	justify-content:center; 
-	align-items:center;
-}
-.ListHongbao .list ul .info div.more a span img{
-	height: 25px;
-	width: 25px;
-	border-radius: 50%;
-}
-.ListHongbao .list ul .info div.more a em{
-	padding: 0 15px 0 5px;
-}