程序使用PHP+MySQL,jQuery实现Ajax,页面布局用的DIV+CSS,并有一个VB写的客户端程序。原演示地址:http://ask.n9sky.com/MagicMirror/ (现在不能访问了)现在贴出部分代码:server.php 主要的操作处理都在这个文件<?php
$do = @$_GET['do'];
if ('' == $do)
{
exit('Missing Action');
}
require 'config.php';
require 'dll.php';
session_start();
// check session
if ('' == $_SESSION['sid']) exit('登录超时,请关闭重试!');
switch ($do)
{
case 'init':
// check user && update
dll::import('mysql');
$db = new mysql();
$db->connect($dbs['server'], $dbs['user'], $dbs['password']);
$db->database($dbs['database']);
// update
$rs = $db->update(DBPrefix.'user', 'sid="'.$_SESSION['sid'].'"');
$rs->set('client_to', '');
$rs->set('role', RoleOnline);
$rs->set('last_access_time', time());
$rs->setfunc('login_count', 'login_count+1');
$rs->set('last_login_time', time());
$ip = $_SERVER['REMOTE_ADDR'];
$ipx = explode('.', $ip);
$iplong = 
$ipx[0] * 16777216 +
$ipx[1] * 65536 +
$ipx[2] * 256 +
$ipx[3];
$rs->set('last_login_ip', $iplong);
if (!$rs->update())
{
// add new
$rs = $db->insert(DBPrefix.'user');
$rs->set('sid', $_SESSION['sid']);
$rs->set('client_to', '');
$rs->set('role', RoleOnline);
$rs->set('last_access_time', time());
$rs->set('login_count', 1);
$rs->set('last_login_time', time());
$rs->set('last_login_ip', $iplong);
$rs->insert();
}
$db->close();
// display init page
display('init.html');
break;
case 'status':
dll::import('mysql');
// access $dbs
global $dbs;
$db = new mysql();
$db->connect($dbs['server'], $dbs['user'], $dbs['password']);
$db->database($dbs['database']);
// update access
update_access($db);
// import mysql.class
display('server.status.html');
$db->close();
break;
case 'work':
$mode = $_GET['mode'];
// update work mode
dll::import('mysql');
$db = new mysql();
$db->connect($dbs['server'], $dbs['user'], $dbs['password']);
$db->database($dbs['database']);
// update
$rs = $db->update(DBPrefix.'user', 'sid="'.$_SESSION['sid'].'"');
switch ($mode)
{
case 'answer':
$rs->set('role', RoleAnswer);
break;
case 'asker':
$rs->set('role', RoleAsker);
break;
case 'chater':
$rs->set('role', RoleChater);
break;
case 'offline':
$rs->set('role', RoleOffline);
$rs->set('client_to', '');
// delete input status cache
@unlink(dirname('.').'/cache/'.$_SESSION['sid'].'.input.status');
// clear session
unset($_SESSION);
break;
}
$rs->set('last_access_time', time());
$rs->update();
$db->close();
// display mode page
if ($mode != 'offline')
{
display('work.'.$mode.'.html');
}
else
{
echo 'logout';
}
break;
case 'looking':
$mode = $_GET['mode'];
// finding target
dll::import('mysql');
$db = new mysql();
$db->connect($dbs['server'], $dbs['user'], $dbs['password']);
$db->database($dbs['database']);
// check my client
$result = $db->getRow('select client_to from '.DBPrefix.'user where sid="'.$_SESSION['sid'].'"');
$findout = false;
$passive_client = false;
if ($result[0] == "")
{
// finding new
switch ($mode)
{
case 'answer':
// looking for asker
$result = $db->getRow('select sid from '.DBPrefix.'user where client_to="" and sid<>"'.$_SESSION['sid'].'" and role='.RoleAsker);
if (!$result)
{
echo 'notfind';
}
else
{
$_SESSION['target'] = $result[0];
$findout = true;
echo 'findout';
}
break;
case 'asker':
// looking for answer
$result = $db->getRow('select sid from '.DBPrefix.'user where client_to="" and sid<>"'.$_SESSION['sid'].'" and role='.RoleAnswer);
if (!$result)
{
echo 'notfind';
}
else
{
$_SESSION['target'] = $result[0];
$findout = true;
echo 'findout';
}
break;
case 'chater':
// looking for chater
$result = $db->getRow('select sid from '.DBPrefix.'user where client_to="" and sid<>"'.$_SESSION['sid'].'" and role='.RoleChater);
if (!$result)
{
echo 'notfind';
}
else
{
$_SESSION['target'] = $result[0];
$findout = true;
echo 'findout';
}
break;
}
}
else
{
// return findout
$_SESSION['target'] = $result[0];
$findout = true;
$passive_client = true;
echo 'findout';
}
if ($findout)
{
// update client
$db->exec('update '.DBPrefix.'user set client_to="'.$_SESSION['target'].'" where sid="'.$_SESSION['sid'].'"');
// update target client
$db->exec('update '.DBPrefix.'user set client_to="'.$_SESSION['sid'].'" where sid="'.$_SESSION['target'].'"');
// delete my last message
$db->delete(DBPrefix.'message', 'sid="'.$_SESSION['sid'].'"');
if (!$passive_client)
{
// delete target last message
$db->delete(DBPrefix.'message', 'sid="'.$_SESSION['target'].'"');
}
}
$db->close();
break;
case 'input':
$status = $_GET['status'];
@file_put_contents(dirname('.').'/cache/'.$_SESSION['sid'].'.input.status', $status);
break;
case 'sender':
$channel = $_GET['channel'];
// looking target
dll::import('mysql');
$db = new mysql();
$db->connect($dbs['server'], $dbs['user'], $dbs['password']);
$db->database($dbs['database']);
if ('upload' == $channel)
{
$_POST['content'] = htmlspecialchars(urldecode($_POST['content']));
$rs = $db->insert(DBPrefix.'message');
$rs->set('sid', $_SESSION['sid']);
$rs->set('content', $_POST['content']);
$rs->set('submit_time', time());
$rs->insert();
echo 'ok';
}
elseif ('download' == $channel)
{
// check target client
$result = $db->getRow('select * from '.DBPrefix.'user where sid="'.$_SESSION['target'].'"');
if ($result['client_to'] != $_SESSION['sid'])
{
$db->exec('update '.DBPrefix.'user set client_to="" where sid="'.$_SESSION['sid'].'"');
json_message_echo('offline','From ['.$_SESSION['target'].']');
}
else
{
$lastMsgTime = (int)$_GET['lastMsgTime'];
if ($lastMsgTime == 0)
{
$rs = $db->query('select * from '.DBPrefix.'message where sid="'.$_SESSION['target'].'"');
}
else
{
$rs = $db->query('select * from '.DBPrefix.'message where sid="'.$_SESSION['target'].'" and submit_time>'.$lastMsgTime.'');
}
if ($rs->count == 0)
{
json_message_echo('input', @file_get_contents(dirname('.').'/cache/'.$_SESSION['target'].'.input.status'));
}
else
{
echo '[';
for ($i=0; $i<$rs->count; $i++)
{
json_message_echo('message', $rs->row['submit_time'].':'.$rs->row['content']);
if (($i+1) < $rs->count) echo ',';
$rs->moveNext();
}
echo ']';
}
}
}
$db->close();
break;
default:
exit('UnSupport Action');
break;
}
?>
VB 的客户端代码:Option ExplicitPrivate Server As StringPrivate confirmQuit As BooleanPrivate Declare Function GetVolumeInformation Lib "kernel32" Alias "GetVolumeInformationA" (ByVal lpRootPathName As String, ByVal lpVolumeNameBuffer As String, ByVal nVolumeNameSize As Long, lpVolumeSerialNumber As Long, lpMaximumComponentLength As Long, lpFileSystemFlags As Long, ByVal lpFileSystemNameBuffer As String, ByVal nFileSystemNameSize As Long) As LongPrivate Sub Form_Load()
    '服务器地址
    Server = "ask.n9sky.com"
    '获取序列号
    Dim ComID As String
        ComID = Disk_Info("D") '获取D盘序列号
    If ComID = "" Then
        ComID = Disk_Info("C") 'D盘错误,继续获取C盘序列号
    End If
    '跳转地址
    Web.Navigate "http://" & Server & "/MagicMirror/load.php?me=" & ComID
End SubPrivate Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
    If confirmQuit Then
        End
    End If    Dim Click As Integer
    If UnloadMode = 0 Then
        Click = MsgBox("您确认要退出魔镜吗?点击取消强制关闭程序", vbYesNoCancel)
    Else
        Click = 6
    End If
    If Click = 6 Then
        Cancel = 1
        Web.Navigate "javascript:session_logout();"
    ElseIf Click = 7 Then
        Cancel = 1
    ElseIf Click = 2 Then
        End
    End If
End SubPrivate Sub Web_TitleChange(ByVal Text As String)
    If Text = "MMI_EXIT" Then
        confirmQuit = True
        Unload Me
    End If
    If Left(Text, 7) <> "http://" Then
        Me.Caption = Text
    End If
End SubPrivate Function Disk_Info(ByVal iDriver As String) As String
    Dim Driver, VolName, FSys As String
    Dim volNumber, MCM, FSF As Long
    Dim Res As Long
    Driver = iDriver & ":\"
    Res = GetVolumeInformation(Driver, VolName, 127, volNumber, MCM, FSF, FSys, 127)
    If Res = 1 Then
        Disk_Info = Hex(MCM) & Hex(FSF) & Hex(volNumber)
    Else
        Disk_Info = ""
    End If
End Function

解决方案 »

  1.   

    MySQL 数据库操作类:<?php
    class mysql
    {
    //设置:
    var $errorReport = true;
    var $querytimes = 0;
    function __construct(){}
    function __destruct(){}
    //连接数据库
    function connect($host, $user, $pass)
    {
    if (!mysql_connect($host, $user, $pass))
    {
    $this->alert('连接服务器['.$host.']时出错');
    }
    }
    //选择数据库
    function database($database)
    {
    if (!mysql_select_db($database))
    {
    $this->alert('选择数据库['.$database.']时出错');
    }
    }
    //设置数据库语言编码
    function charset($charset)
    {
    if (!mysql_query('SET NAMES "'.$charset.'"'))
    {
    $this->alert('设置数据库语言['.$charset.']时错误') ;
    }
    }
    //查询并返回结果集
    function query($sql, $result_type = 1)
    {
    /*   
    $result_type   
    0: 数字下标   
    1: 文字下标   
    2: 包含数字与文字下标   
    */   
    $this->querytimes++;
    if (!($result = mysql_query($sql)))
    {
    $this->alert('数据库查询错误:<br/> <b>[ '.$sql.' ]</b>');
    return false;
    }
    return new mysql_db_queryResult($result, $result_type);
    }
    //查询,返回一条记录
    function getRow($sql)
    {
    $this->querytimes++;
    if (!($result = mysql_query($sql)))
    {
    $this->alert('数据库查询错误:<br/>[ '.$sql.' ]');
    return false;
    }
    return mysql_fetch_array($result);
    }
    //执行SQL,不返回查询对象
    function exec($sql)
    {
    if (!mysql_query($sql))
    {
    $this->alert('数据库查询错误:<br/>[ '.$sql.' ]');
    return false;
    }
    }
    //数据操作:插入记录
    function insert($column)
    {
    return new mysql_db_record_insert($column);
    }
    //数据操作:修改记录
    function update($column, $condition)
    {
    return new mysql_db_record_update($column, $condition);
    }
    //数据操作:删除记录
    function delete($column, $condition)
    {
    $sql = 'delete from '.$column.' where '.$condition;
    if (!mysql_query($sql))
    {
    $this->alert('删除记录时出错:<br/>[ '.$sql.' ]');
    return false;
    }
    return mysql_affected_rows();
    }
    //断开数据库连接
    function close()
    {
    mysql_close();
    }
    //警示信息
    function alert($tip)
    {
    if ($this->errorReport)
    {
    exit( '<fieldset style="border:1px solid #000;z-index:109;"><legend style="font-weight:bold;"><div style="border:1px solid #000;padding:3px;">数据库错误:</div></legend><div style="padding:6px;">'.$tip.'<br/><br/><div style="border:1px solid #000;padding:6px;">Mysql Server<br/>No: '.mysql_errno().'<br/>Message: '.mysql_error().'</div></fieldset>' );
    }
    }
    }
    //查询结果集
    class mysql_db_queryResult extends mysql
    {
    var $queryhandle;
    var $result_type = 1;
    var $current_row_num = -1;
    var $count = 0;
    var $row = array();
    function __construct($result, $result_type = 1)
    {
    $this->queryhandle = $result;
    $this->result_type = $result_type;
    $this->count = mysql_num_rows($this->queryhandle);
    $this->getRow();
    }
    function getRow()
    {
    if ($this->result_type == 1)
    {
    $this->row = mysql_fetch_assoc($this->queryhandle) ;
    }
    else if ($this->result_type == 0)
    {
    $this->row = mysql_fetch_row($this->queryhandle) ;
    }
    else
    {
    $this->row = mysql_fetch_array($this->queryhandle) ;
    }
    }
    function moveFirst()
    {
    mysql_data_seek($this->queryhandle, 0);
    $this->getRow();
    }
    function movePrevious()
    {
    mysql_data_seek($this->queryhandle, $this->current_row_num--);
    $this->getRow();
    }
    function moveNext()
    {
    $this->current_row_num++;
    $this->getRow();
    }
    function moveLast()
    {
    mysql_data_seek($this->queryhandle, $this->count-1);
    $this->getRow();
    }
    }
    //插入新的记录
    class mysql_db_record_insert extends mysql
    {
    var $column;
    var $db_rs_array = array();
    function __construct($column)
    {
    $this->column = $column;
    }
    function set($key, $val)
    {
    if (is_numeric($val))
    {
    $this->db_rs_array[$key] = $val;
    }
    else   
    {
    $this->db_rs_array[$key] = '"'.$val.'"';
    }
    }
    //设置SQL内置函数
    function setfunc($key, $val)
    {
    $this->db_rs_array[$key] = $val;
    }
    function insert()
    {
    $sql = 'insert into '.$this->column.' (';
    $keys = '';
    $vals = '';
    foreach ($this->db_rs_array as $key => $val)
    {
    $keys .= $key.',';
    $vals .= $val.',';
    }
    $sql = $sql.substr($keys, 0, -1).')values('.substr($vals, 0, -1).')';
    if (!mysql_query($sql))
    {
    $this->alert('插入新记录时出错:<br/>[ '.$sql.' ]');
    return false;
    }
    return mysql_affected_rows();
    }
    }
    //编辑记录
    class mysql_db_record_update extends mysql
    {
    var $column;
    var $condition;
    var $db_rs_array = array();
    function __construct($column, $condition)
    {
    $this->column = $column;
    $this->condition = $condition;
    }
    function set($key, $val)
    {
    if (is_numeric($val))
    {
    $this->db_rs_array[$key] = $val;
    }
    else
    {
    $this->db_rs_array[$key] = '"'.$val.'"';
    }
    }
    //设置SQL内置函数
    function setfunc($key, $val)
    {
    $this->db_rs_array[$key] = $val;
    }
    function update()
    {
    $sql = 'update '.$this->column.' set ';
    $items = '';
    foreach ($this->db_rs_array as $key => $val)
    {
    $items .= $key.'='.$val.',';
    }
    $sql = $sql.substr($items, 0, -1).' where '.$this->condition;
    if (!mysql_query($sql))
    {
    $this->alert('编辑记录时出错:<br/>[ '.$sql.' ]');
    return false;
    }
    return mysql_affected_rows();
    }
    }
    ?>
      

  2.   

    console.js  主要的Ajax操作$global = new Object();
    // global vars
    $global.server = './server.php';
    $global.mode = '';
    $global.iWhere = '';
    $global.lastMsgTime = 0;
    $global.lastSendTime = 0;
    // app limit
    $global.ASLimitTalks = 3;
    $global.SendInvLimit = 1;
    // timer demons
    $global.demonsSender = new Object();
    $global.demonsWork = new Object();
    $global.demonsInput = new Object();
    $global.TimerOfHideSS = new Object();
    $global.TimerOfHideMM = new Object();
    // input count
    $global.sender_focus = false;
    $global.iTalks = 0;
    // load
    $(window).load(
    function()
    {
    // bind
    $('body').bind('keydown', function(input)
    {
    //disble Backspace, F5
    if (input.keyCode == 116)
    {
    window.event.keyCode = 0;
    window.event.returnValue = false;
    }
    if (input.keyCode == 8 && !$global.sender_focus)
    {
    window.event.keyCode = 0;
    window.event.returnValue = false;
    }
    }
    );
    $('#sender_content').bind('focus', sender_status_input);
    $('#sender_content').bind('blur', sender_status_free);
    $('#sender_content').bind('keyup', sender_key_check);
    // load
    server_status_refresh();
    init();
    }
    );
    // function for console.html
    function init()
    {
    if ($global.iWhere == 'init')
    {
    return;
    }
    $global.iWhere = 'init';
    loading(true, '正在请求服务器调度');
    // free timer
    if ($global.demonsInput != null) clearTimeout($global.demonsInput);
    if ($global.demonsSender != null) clearTimeout($global.demonsSender);
    if ($global.demonsWork != null) clearTimeout($global.demonsWork);
    // init global vars
    $global.mode = '';
    $global.lastMsgTime = 0;
    $global.iTalks = 0;
    // disable sender
    $('#sender_content').attr('disabled', 'true');
    $('#sender_status').slideDown('normal');
    // do init
    $.get($global.server+'?do=init',
    function(data)
    {
    $('#main').html(data);
    loading(false);
    }
    );
    }
    function server_status_refresh()
    {
    $.get($global.server+'?do=status',
    function(data)
    {
    $('#server_status').html(data);
    // every 3 sec
    setTimeout(server_status_refresh, 3000);
    }
    );
    }
    function sender_status_input()
    {
    $global.sender_focus = true;
    $.get($global.server+'?do=input&status=input',
    function(data)
    {

    }
    );
    }
    function sender_status_free()
    {
    $global.sender_focus = false;
    $.get($global.server+'?do=input&status=free',
    function(data)
    {

    }
    );
    }
    function sender_key_check(input)
    {
    if (input.keyCode == 13)
    {
    // enter
    sender_client();
    }
    else if(input.altKey && input.keyCode == 83)
    {
    // ALT+S
    sender_client();
    }
    }
    function sender_client()
    {
    $('#sender_status').slideDown('normal');
    // replace enter.key
    var str = $('#sender_content').val();
    var strLen = $('#sender_content').val().length;
    if (str.substr(strLen-1, 1) == "\n")
    {
    $('#sender_content').val(str.substr(0, strLen-1));
    }
    // check if empty
    if ('' == $('#sender_content').val())
    {
    $('#sender_status').text('内容不能为空!');
    return false;
    }
    // check last send time
    var nowTime = (new Date()).getTime();
    if (nowTime-$global.lastSendTime <= ($global.SendInvLimit*1000))
    {
    $('#sender_status').text('您发送的太快了!');
    sender_status_later_hide();
    $global.lastSendTime = nowTime;
    return false;
    }
    $global.lastSendTime = nowTime;
    $('#sender_status').text('正在发送...');
    $.post($global.server+'?do=sender&channel=upload',
    {'content': encodeURIComponent($('#sender_content').val())},
    function(data)
    {
    if ('ok' != data)
    {
    $('#sender_status').text('发送失败,正在重试...'+data);
    // retry @ 3sec later
    $global.demonsSender = setTimeout(sender_client, 3000);
    }
    else
    {
    append_msg(true, $('#sender_content').val());
    $('#sender_content').val('');
    $('#sender_status').text('发送成功!');
    sender_status_later_hide();
    // check for MMI
    if ($global.mode == 'answer' && $global.iTalks >= $global.ASLimitTalks)
    {
    loading(true, '你已经回答了对方的['+$global.ASLimitTalks+']个问题<br/><br/><br/>希望你的答案能够帮到他吧...<br/><br/><a class="MMTipClick" href="javascript:hide_MMTips();init();">[ 确定 ]</a>');
    $global.TimerOfHideMM = setTimeout(function(){loading(false);init();}, 10000);
    }
    // MMI status update
    if ($global.mode == 'answer' || $global.mode == 'asker')
    {
    $('#sender_content').attr('disabled', 'true');
    $('#target_limit_status').text('对方没有回复之前不可以说话哦');
    }
    }
    }
    );
    }
    // function for init.html
    function select_mode(mode)
    {
    $global.mode = mode;
    init_work_space();
    }
    function init_work_space()
    {
    $global.iWhere = 'workspace';
    loading(true, '正在构建环境');
    $.get($global.server+'?do=work&mode='+$global.mode,
    function(data)
    {
    $('#main').html(data);
    loading(false);
    }
    );
    }
    // function for work.*.html
    function work_demons()
    {
    // demons for work.*
    $.get($global.server+'?do=looking&mode='+$global.mode,
    function(data)
    {
    if ('findout' == data)
    {
    $('#target_finding').fadeOut('normal');
    $('#target_status').text('已经建立连接,您可以发送信息了');
    $('#sender_status').text('和对方说句话吧');
    // check for MMI
    // asker
    if ($global.mode == 'asker')
    {
    $('#target_limit_status').text('您可以向对方提问了');
    loading(true, '作为求助者,您只可以向魔镜回答['+$global.ASLimitTalks+']个问题,超出后魔镜会自动消失<br/><br/><a class="MMTipClick" href="javascript:hide_MMTips();">[ 确定 ]</a>');
    $global.TimerOfHideMM = setTimeout(function(){loading(false);}, 10000);
    }
    // answer
    if ($global.mode == 'answer')
    {
    $('#target_limit_status').text('对方没有提问的时候不可以说话哦');
    loading(true, '作为魔镜,您只可以回答求助者['+$global.ASLimitTalks+']个问题,超出后会自动断开<br/><br/><a class="MMTipClick" href="javascript:hide_MMTips();">[ 确定 ]</a>');
    $global.TimerOfHideMM = setTimeout(function(){loading(false);}, 10000);
    }
    else
    {
    // mode that can send message at first
    // enable sender
    $('#sender_content').attr('disabled', '');
    }
    // show limit status
    if ($global.mode == 'chater')
    {
    $('#target_limit_status').slideUp('normal');
    }
    else
    {
    $('#target_limit_status').slideDown('normal');
    }
    // active input demons
    input_demons();
    }
    else
    {
    // refind @ 3sec later
    $global.demonsWork = setTimeout(work_demons, 3000);
    }
    }
    );
    }
    function input_demons()
    {
    $.get($global.server+'?do=sender&channel=download&lastMsgTime='+$global.lastMsgTime,
    function(data)
    {
    try
    {
    var msg = eval('('+data+')');
    }
    catch(e)
    {
    alert('Err.DownMessage:'+e.message+'\n\nData = '+data);
    }
    var msgType = '';
    if ($.isArray(msg))
    {
    // message
    msgType = 'message';
    var lastMsg = '';
    for (var i=0; i<msg.length; i++)
    {
    $global.lastMsgTime = msg[i].content.substr(0, 10);
    lastMsg = msg[i].content.substr(11);
    append_msg(false, lastMsg);
    }
    // input count
    $global.iTalks ++ ;
    // check for MMI limit
    if ($global.mode == 'asker' && $global.iTalks >= $global.ASLimitTalks)
    {
    loading(true, '魔镜回答了你的['+$global.ASLimitTalks+']个问题,已经消失了<br/>留下了最后一个答案给你:<br/><br/><b>'+lastMsg+'</b><br/><br/><a class="MMTipClick" href="javascript:hide_MMTips();init();">[ 确定 ]</a>');
    $global.TimerOfHideMM = setTimeout(function(){loading(false);init();}, 10000);
    // set target is offline that disconnect from MagicMirror
    msgType = 'offline';
    }
    // MMI status update
    if ($global.mode == 'answer' || $global.mode == 'asker')
    {
    $('#sender_content').attr('disabled', '');
    $('#target_limit_status').text('您可以继续回复了');
    }
    }
    else
    {
    // input status
    msgType = msg.type;
    switch (msg.type)
    {
    case 'input':
    if (msg.content == 'input')
    {
    $('#target_status').text('对方正在输入...');
    }
    else if (msg.content == 'free')
    {
    $('#target_status').text('对方正在发呆...');
    }
    break;
    case 'offline':
    $('#sender_status').text('对方已断开连接,请重新选择');
    init();
    break;
    }
    }
    if (msgType != 'offline')
    {
    // check every 3sec
    $global.demonsInput = setTimeout(input_demons, 3000);
    }
    }
    );
    }
    // common function
    function hide_MMTips()
    {
    if ($global.TimerOfHideMM != null) clearTimeout($global.TimerOfHideMM);
    loading(false);
    }
    // CSDN 提示内容过长  !!- -
      

  3.   

    项目打包下载地址:
        http://download.csdn.net/source/2448828
      

  4.   

    park,收藏了,肯能以后会用到