打印 上一主题 下一主题

微信扫描登录

[复制链接]
跳转到指定楼层
楼主
发表于 2014-2-2 21:55:19 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
楼主
用户通过扫描网页提供的二维码实现登陆信息获取
0 a5 D& i7 n% Q* f- C& Z
  1. <?php1 `3 w% D; P1 @! G
  2. /**9 d5 z( `. u- a3 z+ U* V# B
  3. *  微信公众平台PHP-SDK) K2 I8 G7 V, g. i/ R$ K
  4. *  Wechatauth为非官方微信登陆API
    % E, f  p4 o+ `' d+ p7 C
  5. *  用户通过扫描网页提供的二维码实现登陆信息获取
    7 E; i! E& G6 G4 D0 X0 Z# w" Q
  6. *  主要实现如下功能:( d, p/ @2 I2 L# H0 K! I
  7. *  get_login_code() 获取登陆授权码, 通过授权码才能获取二维码7 P1 Y2 w$ Y2 [' }* O, a
  8. *  get_code_image($code='') 将上面获取的授权码转换为图片二维码
    7 X% J3 i) j( F. Z0 a
  9. *  verify_code() 鉴定是否登陆成功,返回200为最终授权成功.
    ' y/ m4 p+ o! A
  10. *  get_login_cookie() 鉴定成功后调用此方法即可获取用户基本信息- x/ m+ u5 y" ]" _2 `, n
  11. *  sendNews($account,$title,$summary,$content,$pic,$srcurl='') 向一个微信账户发送图文信息
    / B- z. O. a% [- |1 V" x: r
  12. *  get_avatar($url) 获取用户头像图片数据
    6 @( K8 o2 d1 n4 Q8 r- t
  13. *  @author dodge <dodgepudding@gmail.com>* s) z" ?9 }' n* Q9 z  i) t
  14. *  @link https://github.com/dodgepudding/wechat-php-sdk7 V- U' ]( Y+ y) x; w: C) P
  15. *  @version 1.1* d, t9 ?5 x: {2 w8 n  O
  16. *  3 h6 R# y& j& W: c2 o7 l
  17. */7 T1 g+ m) b3 l& P, ?
  18. include "snoopy.class.php";
    9 s  X3 z' [$ e; V1 |- E
  19. class Wechatauth1 K& s6 S6 j* n9 \" ~% l1 R
  20. {/ w% N6 @( o! G- r0 W  ~
  21.         private $cookie;
      C) L  t) s4 s) C
  22.         private $_cookiename;
    : x) n8 Y6 d. c* A9 m/ T& v' K- a
  23.         private $_cookieexpired = 3600;
    6 _. y" Y* X" v, T* ]; m7 M8 Y
  24.         private $_account = 'test';
    7 b  N4 c! Q# |
  25.         private $_datapath = './data/cookie_';# b7 l* B  j0 y: @6 T
  26.         private $debug;' G) p7 X3 U1 M# w
  27.         private $_logcallback;! c0 y# R- l9 r; z) m
  28.         public $login_user; //当前登陆用户, 调用get_login_info后获取# P8 Y+ M$ K8 t3 ^
  29.         
    . p- M2 e& i" A6 Q% B- Y
  30.         public function __construct($options)8 \/ E- w  p; J/ g/ D; K# Y
  31.         {
    / g; n" ^; D# R! l# a2 K/ H
  32.                 $this->_account = isset($options['account'])?$options['account']:'';6 G2 N( O% L& a/ r
  33.                 $this->_datapath = isset($options['datapath'])?$options['datapath']:$this->_datapath;
    & V$ L& T0 u$ @# H: r: b" E$ H  @# u
  34.                 $this->debug = isset($options['debug'])?$options['debug']:false;+ F$ j' a6 C# b- |* E. q9 @, W: X
  35.                 $this->_logcallback = isset($options['logcallback'])?$options['logcallback']:false;9 s+ Z& \  W4 s$ ^
  36.                 $this->_cookiename = $this->_datapath.$this->_account;. G$ ?  D0 Y: v9 E' ]
  37.                 $this->getCookie($this->_cookiename);  K2 ~& q( k! n/ I' n
  38.         }
    1 t0 Y  a, ^" i0 j
  39.         /**4 Y' R( i# G8 S* B7 Z+ ]
  40.          * 把cookie写入缓存
    : P& O+ Q7 m/ B
  41.          * @param  string $filename 缓存文件名7 g- H8 ^: n9 n+ B; R  ^9 w: d" P
  42.          * @param  string $content  文件内容
    # G: L# t9 `3 t5 U
  43.          * @return bool) \5 [9 [# C& v0 D
  44.          */. O, C. M7 g# u8 j% t
  45.         public function saveCookie($filename,$content){
    ) ]* @7 q+ D/ U! \1 H+ M8 m! w: ?
  46.                 return file_put_contents($filename,$content);
    6 \/ w9 p* c" Y  j2 m4 W
  47.         }9 ?7 G* s- m, a6 G% U% Z
  48. 0 n0 u" J, o) `
  49.         /**
    9 C2 |' f; c" K6 J5 ~! K0 \
  50.          * 读取cookie缓存内容
    $ u9 P$ u! Y; P, T) m
  51.          * @param  string $filename 缓存文件名- S( }/ O$ h& \! _9 k
  52.          * @return string cookie# P& F( E$ s) f  y% k. o
  53.          */4 [9 w+ f2 `; ~  a4 z) |
  54.         public function getCookie($filename){
    ' I0 `: k' H2 N* }$ r
  55.                 if (file_exists($filename)) {" _; @* ~9 Z4 |. R3 J' L
  56.                         $mtime = filemtime($filename);1 v8 P4 n7 c4 O" O; L3 k) s( v2 K
  57.                         if ($mtime<time()-$this->_cookieexpired) return false;& @) x2 i! X1 _. p' m
  58.                         $data = file_get_contents($filename);* t5 b  o$ X9 e% S2 k
  59.                         if ($data) $this->cookie = $data;
    3 N/ j- M; w" Y" ~
  60.                 }
    : _, M1 y" L5 u1 g7 U# q' {
  61.                 return $this->cookie;
    & M- w0 s3 P+ x* `9 ]5 }2 h# }
  62.         }4 X* y( _" U( e2 }
  63.         / b: V1 C7 L" y
  64.         /*
    & x# M. _, B1 Y  o' W0 |! H" K
  65.          * 删除cookie6 ]) E1 r1 v1 I9 R3 Z1 w4 [2 [
  66.          */
      W/ X2 ^9 G6 s! \9 |1 a& h
  67.         public function deleteCookie($filename) {
    ! y, c+ o8 x( ^* |
  68.                 $this->cookie = '';3 x- I' o' E4 {
  69.                 @unlink($filename);- [1 e% l* H) ?% F0 Y
  70.                 return true;: B/ p9 Q  e+ r1 W
  71.         }, ?  y: t# }+ _. s
  72.         
    : H: ?% S6 a5 [5 g8 L  R
  73.         private function log($log){
    . n$ j" a) f; j  R5 [
  74.                 if ($this->debug && function_exists($this->_logcallback)) {
    ( t$ ?. r: p& F- l1 c' W
  75.                         if (is_array($log)) $log = print_r($log,true);
    : Z8 m7 U. k) l$ F: m
  76.                         return call_user_func($this->_logcallback,$log);
    $ l& v$ O) a- P, j# U; Y3 X
  77.                 }
    % ~$ \  ~5 V% u5 K
  78.         }0 {1 U) s, s  d
  79.         1 W" N; D0 F$ G; p. c; i; A) d
  80.         /**/ q( ^* W5 t. G7 o1 l
  81.          * 获取登陆二维码对应的授权码  j, }# N/ f5 o3 W% D+ G
  82.          */
    . M) e& p. J* _2 }4 s) Y7 M$ y
  83.         public function get_login_code(){) |, R1 `! r- `, m8 O" M, {2 y* V0 E" I
  84.                 if ($this->_logincode) return $this->_logincode;
    9 h6 E& R: l8 T  O
  85.                 $t = time().strval(mt_rand(100,999));5 ?) K6 Y, ~* N
  86.                 $codeurl = 'https://login.weixin.qq.com/jslogin?appid=wx782c26e4c19acffb&redirect_uri=https%3A%2F%2Fwx.qq.com%2Fcgi-bin%2Fmmwebwx-bin%2Fwebwxnewloginpage&fun=new&lang=zh_CN&_='.$t;3 ?9 p( V! r9 d3 K
  87.                 $send_snoopy = new Snoopy;
    2 \0 W1 p; b6 M) {3 ^  h
  88.                 $send_snoopy->fetch($codeurl);( T/ O! m6 q3 k1 o! ~
  89.                 $result = $send_snoopy->results;
    0 F  V9 X2 u+ B
  90.                 if ($result) {$ ]( N( P0 C$ I7 C4 S- R6 C2 j
  91.                         preg_match("/window.QRLogin.uuid\s+=\s+"([^"]+)"/",$result,$matches);
    2 I0 ]+ x2 n+ O) R9 O. k  n
  92.                         if(count($matches)>1) {
    7 l6 B8 s- w' P- r4 d( n; {& V
  93.                                 $this->_logincode = $matches[1];! m2 V; e& ?) v  w
  94.                                 $_SESSION['login_step'] = 0;5 m2 s* r3 |, X6 w8 h: y
  95.                                 return $this->_logincode;/ L# C. b' i% g8 Y
  96.                         }1 _! z) r" ]! V- Z
  97.                 }
    # q7 ^9 Q- c$ A" i. @
  98.                 return $result;, D% V4 J1 R% Y) _9 V& p- s( Z
  99.         }
    2 Q- G8 K/ ~8 M7 a$ s# U- I! V
  100. % I  U1 F& t) K# V) h3 a
  101.         /**- l$ S) t# ?2 ~
  102.          * 通过授权码获取对应的二维码图片地址. k- s; Q8 m2 \; O% s8 L7 s
  103.          * @param string $code& C" D+ ]! g# f9 i: q
  104.          * @return string image url
    ! D* i4 m; i2 d& G3 A
  105.          */' p$ ~" V1 z; G$ ]; G
  106.         public function get_code_image($code=''){
    7 d8 j" u; I+ A& E9 e, {% e: P
  107.                 if ($code=='') $code = $this->_logincode;
    1 J! A) K5 X9 p+ V2 `
  108.                 if (!$code) return false;6 d! l( d7 l3 @" {, W
  109.                 return 'http://login.weixin.qq.com/qrcode/'.$this->_logincode.'?t=webwx';
    $ O9 z7 g( l) @$ K5 O! g5 l7 H3 b( U
  110.         }
    8 b& D4 f) n* i9 s
  111.         7 ~5 }+ s  g. I% v4 Z
  112.         /**0 L# Z- }7 ~# [5 n/ ^+ [$ S; s, t0 T6 g3 R
  113.          * 设置二维码对应的授权码+ @$ P' ~4 k% r$ q( y6 T/ n
  114.          * @param string $code% T5 C8 H6 z0 n4 I6 S5 Y, E
  115.          * @return class $this% M2 r8 d; ?1 `
  116.          */. t- u2 k  ]$ K/ ~  Y% B) P
  117.         public  function set_login_code($code) {
    6 v- Y% v& ^0 M: f. k+ {) k5 ^
  118.                 $this->_logincode = $code;
    5 p. `5 j  L( Z) Y, c7 o
  119.                 return $this;* r- s6 g% D" \+ H
  120.         }
    2 g, F' [3 T# O3 q
  121.         4 b4 y1 P. W! V0 J' S+ E. T
  122.         /**
    % B- X' P3 l1 F
  123.          * 二维码登陆验证, _# c1 T. X# `7 N
  124.          *
    3 W# e  F! K) B, u1 t) _
  125.          * @return status:
    . B! `# i  I3 C6 g* Z
  126.          * >=400: invaild code; 408: not auth and wait, 400,401: not valid or expired8 i' F+ |! W0 R, Y% M
  127.          * 201: just scaned but not confirm
    # G+ w3 _+ J; j5 J
  128.          * 200: confirm then you can get user info0 j) I0 c  E+ d, E, @7 w8 [
  129.          */$ D# h: C: _0 ?1 J* Q
  130.         public function verify_code() {
    ) A8 Q; a& L- |" f: r1 U
  131.                 if (!$this->_logincode) return false;
    1 |+ Y/ H5 L0 y
  132.                 $t = time().strval(mt_rand(100,999));  }+ f  n+ A! d9 _" e& j5 x
  133. ! M8 \7 A( S8 `& E  n9 T
  134.                         $url = 'https://login.weixin.qq.com/cgi-bin/mmwebwx-bin/login?uuid='.$this->_logincode.'&tip=1&_='.$t;
    / a% ~+ @5 s  T3 m" O/ N
  135.                         $send_snoopy = new Snoopy;
    : y) z: e5 D' }2 V9 S0 O+ Q1 s. v
  136.                         $send_snoopy->referer = "https://wx.qq.com/";
    + G0 W5 \7 O3 E( u' `, V- ?  U
  137.                         $send_snoopy->fetch($url);
    $ U* _$ D4 @: @$ q% T. @
  138.                         $result = $send_snoopy->results;
    1 |' K" m( `. |( v& j" w1 h0 G) K
  139.                         $this->log('step1:'.$result);
    $ W/ W) b' L& F$ d* o
  140.                         if ($result) {
    , K% I+ W) l; k3 c# j/ ^
  141.                                 preg_match("/window\.code=(\d+)/",$result,$matches);( }5 m8 p5 E, r/ \
  142.                                 if(count($matches)>1) {- N$ x+ W0 h  E
  143.                                         $status = intval($matches[1]);
    6 l5 D4 {! ^9 h
  144.                                         if ($status==201) $_SESSION['login_step'] = 1;
    * f6 `! }0 `8 j$ u+ W6 m7 u; j
  145.                                         if ($status==200) {
    ) E0 f6 r. Z& n5 ^7 w4 k+ S; a7 S: z
  146.                                                 preg_match("/ticket=([0-9a-z-_]+)&lang=zh_CN&scan=(\d+)/",$result,$matches);/ o7 \( d0 X4 {) i+ C7 {9 q
  147.                                                 $this->log('step2:'.print_r($matches,true));; X. ?* u# t2 Y8 S* W; d/ \
  148.                                                 if (count($matches)>1) {2 G/ N, t& c5 M
  149.                                                         $ticket = $matches[1];
    : y+ z: ~- J% `5 V* _
  150.                                                         $scan = $matches[2];
    2 \$ @/ n$ O  i4 S/ G+ e
  151.                                                         $loginurl = 'https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxnewloginpage?ticket='.$ticket.'&lang=zh_CN&scan='.$scan.'&fun=new';
    2 k9 G% F# M9 W8 o
  152.                                                         $send_snoopy = new Snoopy; . v9 z9 k) w9 J6 ~
  153.                                                         $send_snoopy->referer = "https://wx.qq.com/";" R3 K% m$ R. M7 |8 }8 R: j! n
  154.                                                         $send_snoopy->fetch($loginurl);* D6 ?3 w% @* A$ Q2 i
  155.                                                         $this->log('step3:'.print_r($send_snoopy->headers,true));% ~8 o5 U7 ~* H1 W+ x0 h
  156.                                                         foreach ($send_snoopy->headers as $key => $value) {2 s5 F! i" n$ T# a9 K( }' v
  157.                                                                 $value = trim($value);7 }& N0 x" e. f! L/ c
  158.                                                                 if(strpos($value,'Set-Cookie: ') !== false){
    1 A2 c8 p6 _# u) b3 _4 |7 t# _* E9 ~
  159.                                                                         $tmp = str_replace("Set-Cookie: ","",$value);
    0 {+ y8 M% r- n% i
  160.                                                                         $tmp = str_replace("Path=/","",$tmp);
    3 }$ N/ Z; d( |: Z5 M' D2 o
  161.                                                                         $tmp = str_replace("Domain=.qq.com; ","",$tmp);
    ! _4 g& P) q" t# s
  162.                                                                         $cookie.=$tmp;6 W! I2 S; n: K1 Q# s" a# [
  163.                                                                 }
    8 v1 d' O! d7 F# \
  164.                                                         }
    4 \- d: D5 V' y
  165.                                                         $cookie .="Domain=.qq.com;";8 S7 `7 o* C5 B1 O& k0 P
  166.                                                         $this->cookie = $cookie;4 }) ^  L# b  d  h6 g
  167.                                                         $this->saveCookie($this->_cookiename,$this->cookie);
    9 ~2 F! Z0 j( y
  168.                                                 }: m. c4 _9 e0 T9 @9 h9 t
  169.                                         }/ a7 |8 b) L. N
  170.                                         return $status;# |6 ^( d  n9 Z. S3 {7 u, m4 q& Y
  171.                                 }
    5 [+ K# \& G- o
  172.                         }
      k- g/ D* f. J% M, e
  173.                 return false;  Q9 ~" |+ P, \4 Y% ]3 v
  174.         }1 A/ h* p; _! r: J
  175.         2 B- W3 Z# o% N8 f( T3 }+ w
  176.         /**
    ( T5 L/ ^6 X7 w
  177.          * 获取登陆的cookie
    * @2 S/ X- V8 e: f% j; L$ f
  178.          *8 U. c) x; C. Z2 X+ v6 x( z
  179.          * @param bool $is_array 是否以数值方式返回,默认否,返回字符串
    ; ]- e+ s0 }6 Z
  180.          * @return string|array
    7 q$ x+ s0 {8 W1 ]( A
  181.          */
    + u1 I3 |% p' Z9 q' U
  182.         public function get_login_cookie($is_array = false){
    6 G- N1 h! K9 v7 E3 j/ X: n
  183.                 if (!$is_array)        return $this->cookie;
    % l0 F7 p* }& H" d$ B' R
  184.                 $c_arr = explode(';',$this->cookie);
    " c8 l) \" @% L1 ^. h
  185.                 $cookie = array();
    & E& F9 @7 `; Y. ~1 A3 \' Q* n8 h
  186.                 foreach($c_arr as $item) {
    9 c% L0 C. V, g- [( c- Y
  187.                         $kitem = explode('=',trim($item));* c9 U( ^' b1 T" e4 O4 V
  188.                         if (count($kitem)>1) {
    & A' z" I1 S/ H: n
  189.                                 $key = trim($kitem[0]);
    ! F. t2 n3 B  n7 F' F- U& t
  190.                                 $val = trim($kitem[1]);
    ; v& v1 `. Z  [. z. L8 s4 g0 N
  191.                                 if (!empty($val)) $cookie[$key] = $val;
    / D1 S! D4 r. j4 E
  192.                         }
    % ~5 [* f2 u3 h! I
  193.                 }
    8 z0 v2 S, `  T
  194.                 return $cookie;
    , D9 x2 o& |$ g
  195.         }  R! g! l2 U8 o: I: B! Y
  196.         ; s$ x0 O1 o4 j1 L9 K
  197.         /**; I# m) i7 @7 e1 e  P4 S
  198.          *          授权登陆后获取用户登陆信息
    6 I) c  M! N9 s
  199.          */
    5 Y2 [" j2 R( M( A' |
  200.         public function get_login_info(){; y- N! _4 V" i, z# [- `2 v
  201.                 if (!$this->cookie) return false;
    3 z0 O4 [3 W4 ^0 v- j# ~* D0 G0 P
  202.                 $t = time().strval(mt_rand(100,999));
      s) T8 \8 l3 M8 o( Q& Q
  203.                 $send_snoopy = new Snoopy; 3 p& Q" i7 |' e8 W  }9 {
  204.                 $submit = 'https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxinit?r='.$t;8 ~1 |! m: g# ]% E( @0 Y* f# Y$ [- k
  205.                 $send_snoopy->rawheaders['Cookie']= $this->cookie;( t" j1 |/ J" o) P
  206.                 $send_snoopy->referer = "https://wx.qq.com/";
    ( Q  V' J. j% e/ ]9 m$ t, k
  207.                 $send_snoopy->submit($submit,array());
    / f. h& D+ m1 p! I
  208.                 $this->log('login_info:'.$send_snoopy->results);
    ' x: P# V7 F/ f; w  s6 R
  209.                 $result = json_decode($send_snoopy->results,true);
    # I2 Q7 J9 x, E' S2 a
  210.                 if ($result['BaseResponse']['Ret']<0) return false;) D8 V' ~- C0 O, H% q
  211.                 $this->_login_user = $result['User'];
    6 z, V  j2 B' W& V) n  C& G
  212.                 return $result;8 m# E* W" Y. w7 E( h
  213.         }
      _7 n: i* q( m
  214.         
    " c7 N, B, Q* g$ \
  215.         /**
    0 G5 F' a9 H- M# U# F
  216.          *  获取头像4 a4 A! ~( Y) j* o
  217.          *  @param string $url 传入从用户信息接口获取到的头像地址2 S- V0 s2 j( q2 Z8 F
  218.          */
    ; i: F5 r$ P6 r& }7 g) T
  219.         public function get_avatar($url) {
    4 k+ w0 w( ^& m( X
  220.                 if (!$this->cookie) return false;
    ) W0 e, P8 Q/ H7 T2 Q
  221.                 if (strpos($url, 'http')===false) {
    - a) t  H( @2 {" B3 ]8 y$ p( ~
  222.                         $url = 'http://wx.qq.com'.$url;
    0 u8 f7 J/ A% }* J# T4 G1 C' L. l
  223.                 }
    4 W/ ^+ o6 \% a
  224.                 $send_snoopy = new Snoopy;
      K4 D# _% R( a0 S
  225.                 $send_snoopy->rawheaders['Cookie']= $this->cookie;9 D8 u5 U- v  x! q0 p
  226.                 $send_snoopy->referer = "https://wx.qq.com/";
    7 Q5 H4 x  M' Z, o8 S6 N! U
  227.                 $send_snoopy->fetch($url);5 d2 Y2 M4 y2 L! W! f
  228.                 $result = $send_snoopy->results;( D+ U+ t/ u6 ]( Y! q
  229.                 if ($result)
    $ t6 o% z6 ]. p6 M
  230.                         return $result;
    ; a0 ?  U+ E$ k, i% \/ i" l
  231.                 else* }( U( f4 E% T! F- u
  232.                         return false;1 n9 B5 A/ _" O0 @: e4 C5 N: H+ Y
  233.         }
    ' s8 a1 F. g1 S* o- v0 u( w
  234.         : v  ]6 }: t  n, [) W6 z
  235.         /**9 G: J& X- X- g1 m$ ~
  236.          * 登出当前登陆用户- T% {; X% W7 D- G/ @$ {" u1 z4 ?
  237.          */
    * G5 v9 z% u) \1 ~* l1 E! R
  238.         public function logout(){: s$ Q( n# t/ R4 P" a1 j2 ~. q0 I
  239.                 if (!$this->cookie) return false;
    , a' v5 W5 l7 ?5 Z3 g5 L* J6 E% A7 v
  240.                 preg_match("/wxuin=(\w+);/",$this->cookie,$matches);
    9 v$ g. m* A4 R7 {8 {
  241.                 if (count($matches)>1) $uid = $matches[1];1 L$ ^5 @( k: m" g
  242.                 preg_match("/wxsid=(\w+);/",$this->cookie,$matches);: P! J+ t) U/ s5 }" p
  243.                 if (count($matches)>1) $sid = $matches[1];
    & v- @. W0 h: z5 F: {  k3 H; I1 \! ^
  244.                 $this->log('logout: uid='.$uid.';sid='.$sid);) m8 p7 p6 u- d6 n5 U5 \
  245.                 $send_snoopy = new Snoopy; * u5 z+ p1 }4 d# w9 \- C9 l
  246.                 $submit = 'https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxlogout?redirect=1&type=1';
    1 g# }/ o' s- S+ Q
  247.                 $send_snoopy->rawheaders['Cookie']= $this->cookie;2 D1 G+ {, O& i  d! D
  248.                 $send_snoopy->referer = "https://wx.qq.com/";
    7 o) P& g& @- r* G: L
  249.                 $send_snoopy->submit($submit,array('uin'=>$uid,'sid'=>$sid));
    ; M1 D- z( P% X2 l
  250.                 $this->deleteCookie($this->_cookiename);( R3 c  T- F/ R4 i( U
  251.                 return true;
    ) y' U) Q& ^* Q: P% y
  252.         }
    / t$ G2 k- Q5 y3 m+ [
  253. }
复制代码

1 ^& k* b- M: _+ h* j4 t7 e




上一篇:[Discuz插件] Discuz!微信登录插件配置前提
下一篇:Emacs逆袭:开发微信公众平台小游戏
回复

使用道具 举报

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏

快速回复 返回顶部 返回列表