zoukankan      html  css  js  c++  java
  • EasyUI的增删查改(后台ASP.NET)

    某某人曾经跟我说,你们做系统不就是增删查改吗。

    是啊,很多时候我们就是把用户的数据同后台数据库进行增删查改的沟通。

    但是,把CRUD(增删查改)做得好,可能也不是一件很简单的事,

    这里要展现的是我现在能写出来最好的Demo了,水平有限,小弟在校学生一枚,还请各位看客多多指教。

    Demo前台使用JQuery EasyUI 请求一般处理程序,一般处理程序调用BLL层方法,BLL==>DAL,一个简单三层的效果。

    项目结构如图:

    一、数据库表结构

        这里只创建一个UserInfo表,表中字段有:UserID,CardID,UPwd,UName,UAge,IsDel,AddDate

    二、后台处理CRUD

        后台处理添加、删除(软删除)、编辑、查询(分页)。其中查询包括:分页和搜索处理所有有点麻烦,

        1、先介绍数据访问层(DAL)中的方法

            这里是,添加、删除、编辑、分页查询的方法。

            前台查询的参数存储在NameValueCollection中,然后在DAL层中的PreSearchParameter方法中把查询参数装配到sql语句和SqlParameter中,

            在DAL层中获取的数据是DataTable,然后在BLL层中转换成JSON格式的数据传给EasyUI展示。

            

    View Code
      1 using System;
      2 using System.Text;
      3 using System.Data;
      4 using System.Data.SqlClient;
      5 using Dedeyi.Common;
      6 using System.Collections;
      7 using System.Collections.Generic;
      8 using System.Collections.Specialized;
      9 
     10 namespace Dedeyi.ZSF.DAL
     11 {
     12    public class UserInfoDAL
     13     {
     14          /// <summary>
     15         /// 增加一条数据
     16         /// </summary>
     17         public int Add(Dedeyi.ZSF.Model.UserInfo model)
     18         {
     19             StringBuilder strSql=new StringBuilder();
     20             strSql.Append("insert into UserInfo(");
     21             strSql.Append("CardID,UPwd,UName,UAge,IsDel,AddDate)");
     22             strSql.Append(" values (");
     23             strSql.Append("@CardID,@UPwd,@UName,@UAge,@IsDel,@AddDate)");
     24             strSql.Append(";select @@IDENTITY");
     25             SqlParameter[] parameters = {
     26                     new SqlParameter("@CardID", SqlDbType.VarChar,16),
     27                     new SqlParameter("@UPwd", SqlDbType.VarChar,64),
     28                     new SqlParameter("@UName", SqlDbType.NVarChar,16),
     29                     new SqlParameter("@UAge", SqlDbType.Int,4),
     30                     new SqlParameter("@IsDel", SqlDbType.Bit,1),
     31                     new SqlParameter("@AddDate", SqlDbType.SmallDateTime)};
     32             parameters[0].Value = model.CardID;
     33             parameters[1].Value = model.UPwd;
     34             parameters[2].Value = model.UName;
     35             parameters[3].Value = model.UAge;
     36             parameters[4].Value = model.IsDel;
     37             parameters[5].Value = model.AddDate;
     38 
     39             object obj = SQLHelper.ExecuteScalar(strSql.ToString(),parameters);
     40             if (obj == null)
     41             {
     42                 return 0;
     43             }
     44             else
     45             {
     46                 return Convert.ToInt32(obj);
     47             }
     48         
     49        }
     50 
     51        /// <summary>
     52        /// 删除用户
     53        /// </summary>
     54        /// <param name="keyid"></param>
     55         public void Del(int keyid) 
     56         {
     57             //此处软删除
     58             string s = "update UserInfo set IsDel=1 where UserID="+keyid;
     59             SQLHelper.ExecuteNoneQuery(s,null);
     60         }
     61 
     62             ///<summary>
     63         ///更新一条数据
     64         ///</summary>
     65         public bool Update(Dedeyi.ZSF.Model.UserInfo model)
     66         {
     67             StringBuilder strSql = new StringBuilder();
     68 
     69             strSql.Append("update [UserInfo] set ");
     70             strSql.Append(" CardID=@CardID,");
     71             strSql.Append(" UPwd=@UPwd,");
     72             strSql.Append(" UName=@UName,");
     73             strSql.Append(" UAge=@UAge ");
     74             //strSql.Append(" IsDel=@IsDel,");
     75             //strSql.Append("AddDate=@AddDate");
     76             strSql.Append(" where UserID=@UserID");
     77 
     78             SqlParameter[] parameters = {
     79                 new SqlParameter("@UserID", SqlDbType.Int,4),
     80                 new SqlParameter("@CardID", SqlDbType.VarChar,16),
     81                 new SqlParameter("@UPwd", SqlDbType.VarChar,64),
     82                 new SqlParameter("@UName", SqlDbType.NVarChar,16),
     83                 new SqlParameter("@UAge", SqlDbType.Int,4),
     84                 //new SqlParameter("@IsDel", SqlDbType.Bit,1),
     85                 //new SqlParameter("@AddDate", SqlDbType.DateTime),
     86             };
     87             parameters[0].Value = model.UserID;
     88             parameters[1].Value = model.CardID;
     89             parameters[2].Value = model.UPwd;
     90             parameters[3].Value = model.UName;
     91             parameters[4].Value = model.UAge;
     92             //parameters[5].Value = model.IsDel;
     93             //parameters[6].Value = model.AddDate;
     94 
     95             int rows = SQLHelper.ExecuteNoneQuery(strSql.ToString(),parameters);
     96             if (rows > 0)
     97             {
     98                 return true;
     99             }
    100             else
    101             {
    102                 return false;
    103             }
    104         }
    105 
    106 
    107         //分页相关的
    108         #region 
    109         /// <summary>
    110         /// 获取条件查询数据行数
    111         /// </summary>
    112         /// <param name="nv">关键字,UName,UAge,在前台请求形成Hashtable作为参数时候要用到这个</param>
    113         /// <returns>数据行数</returns>
    114         public int GetSearchCount(NameValueCollection nv) 
    115         {
    116             string sc;
    117             SqlParameter[] ps;
    118             PreSearchParameter(nv, out sc, out ps);
    119 
    120             string sql = "select count(0) from UserInfo where " + sc;
    121 
    122             return Convert.ToInt32(SQLHelper.ExecuteScalar(sql, ps));
    123         } 
    124 
    125        /// <summary>
    126        /// 获取条件查询的分页数据
    127        /// </summary>
    128        /// <param name="index"></param>
    129        /// <param name="size"></param>
    130         /// <param name="nv">关键字,UName,UAge,在前台请求形成Hashtable作为参数时候要用到这个</param>
    131        /// <returns></returns>
    132         public DataTable GetSearchPage(int index, int size,NameValueCollection nv)
    133         {
    134             string f = "UserID,CardID,UPwd,UName,UAge,AddDate";
    135             string o = "AddDate DESC";
    136             return GetSearchePage(index,size,nv,f,o);
    137         }
    138        /// <summary>
    139        /// 获取分页数据
    140        /// </summary>
    141        /// <param name="index">当前页</param>
    142        /// <param name="size">每一页数据行数</param>
    143        /// <param name="ht">查询条件key是字段,value是对应的值</param>
    144        /// <param name="fieldList">要返回的字段</param>
    145        /// <param name="orderby">排序规则不要order by ,如 AddDate desc,userid asc</param>
    146        /// <returns></returns>
    147         private DataTable GetSearchePage(int index, int size, NameValueCollection nv, string fieldList,string orderby) 
    148         {
    149             string sc ; //过滤条件
    150             SqlParameter[] ps;
    151             PreSearchParameter(nv,out sc,out ps);
    152 
    153             string sql = "select * from (select {0},ROW_NUMBER() over(order by {1}) as num from UserInfo where {2}) as tb";
    154             sql += " where num between {3} and {4}";
    155 
    156             sql = string.Format(sql, fieldList, orderby, sc, (index - 1) * size + 1, index * size);
    157 
    158             return SQLHelper.GetDataTable(sql, ps);
    159         }
    160 
    161        /// <summary>
    162        /// 把查询参数转换为sql,和SqlParameter
    163        /// </summary>
    164         /// <param name="ht">关键字,UName,UAge,在前台请求形成Hashtable作为参数时候要用到这个</param>
    165        /// <param name="sql"></param>
    166        /// <param name="paras"></param>
    167         private void PreSearchParameter(NameValueCollection nv, out string sql, out SqlParameter[] paras)
    168         {
    169             sql = " '1'='1' and IsDel=0";
    170             List<SqlParameter> list = new List<SqlParameter>();
    171             if (!string.IsNullOrEmpty(nv["UName"]))
    172             {
    173                 sql += " and UName like @UName";
    174                 list.Add(new SqlParameter("@UName", "%" + nv["UName"] + "%"));
    175             }
    176 
    177             int tAge;
    178             if (int.TryParse(nv["UAge"],out tAge))
    179             {
    180                 sql += " and UAge=" + nv["UAge"];
    181             }
    182             paras = list.ToArray();
    183         }
    184 
    185         #endregion
    186     }
    187 }

        2、然后在业务逻辑层,做一些逻辑处理(JSON格式转换、添加预设值)

          

    View Code
     1 using Dedeyi.ZSF.DAL;
     2 using Dedeyi.ZSF.Model;
     3 using Dedeyi.Common;
     4 using System;
     5 using System.Collections.Specialized;
     6 
     7 namespace Dedeyi.ZSF.BLL
     8 {
     9    public class UserInfoBLL
    10     {
    11         UserInfoDAL dal=new UserInfoDAL();
    12 
    13        /// <summary>
    14        /// 添加
    15        /// </summary>
    16        /// <param name="user"></param>
    17        /// <returns></returns>
    18        public int Add(UserInfo user) 
    19        {
    20            user.AddDate = DateTime.Now;
    21            user.IsDel = false;
    22            
    23            return dal.Add(user);
    24        }
    25 
    26         /// <summary>
    27        /// 删除用户
    28        /// </summary>
    29        /// <param name="keyid"></param>
    30        public void Del(int keyid) 
    31        {
    32             dal.Del(keyid);
    33        }
    34 
    35           ///<summary>
    36         ///更新一条数据
    37         ///</summary>
    38        public bool Update(Dedeyi.ZSF.Model.UserInfo model) 
    39        {
    40            return dal.Update(model);
    41        }
    42 
    43        //分页相关的
    44         #region 
    45         /// <summary>
    46         /// 获取条件查询数据行数
    47         /// </summary>
    48         /// <param name="ht">关键字,UName,UAge,在前台请求形成Hashtable作为参数时候要用到这个</param>
    49         /// <returns>数据行数</returns>
    50        public int GetSearchCount(NameValueCollection ht) 
    51        {
    52            return dal.GetSearchCount(ht);
    53        }
    54 
    55        /// <summary>
    56        /// 获取条件查询的分页数据
    57        /// </summary>
    58        /// <param name="index"></param>
    59        /// <param name="size"></param>
    60         /// <param name="ht">关键字,UName,UAge,在前台请求形成Hashtable作为参数时候要用到这个</param>
    61        /// <returns>json格式的数据集</returns>
    62        public string GetSearchPage(int index, int size,NameValueCollection ht)
    63        {
    64            return JSONHelper.DataTableToJson(dal.GetSearchPage(index,size,ht));
    65        }
    66 
    67         #endregion
    68 
    69     }
    70 }

        

        3、界面层的一般处理程序,处理一般请求

    View Code
      1 using System.Web;
      2 using Dedeyi.Common;
      3 using Dedeyi.ZSF.Model;
      4 using Dedeyi.ZSF.BLL;
      5 using System;
      6 
      7 namespace WebApp.Handler
      8 {
      9     /// <summary>
     10     /// UserHandler 的摘要说明
     11     /// </summary>
     12     public class UserHandler : IHttpHandler,System.Web.SessionState.IRequiresSessionState
     13     {
     14         private HttpContext context;
     15         private UserInfoBLL bll =new UserInfoBLL();
     16 
     17         public void ProcessRequest(HttpContext context)
     18         {
     19             context.Response.ContentType = "text/plain";
     20 
     21             //权限检查
     22             //
     23             try
     24             {
     25                 string sType = context.Request["reqTypes"];
     26                 if (string.IsNullOrEmpty(sType))
     27                 {
     28                     context.Response.Write("参数错误");
     29                     return;
     30                 }
     31                 this.context = context;
     32 
     33                 switch (sType.ToLower())
     34                 {
     35                     case "add":
     36                         Add();
     37                         break;
     38                     case "del":
     39                         Del();
     40                         break;
     41                     case "update":
     42                         Update();
     43                         break;
     44                     case "search":
     45                         Search();
     46                         break;
     47 
     48                 }
     49             }
     50             catch (Exception ex) 
     51             {
     52                 context.Response.Write(new ReqMsg(false,ex.Message.ToString()));
     53             }
     54         }
     55         /// <summary>
     56         /// 获取用户ID
     57         /// </summary>
     58         /// <returns></returns>
     59         private int GetUserID() 
     60         {
     61             string s = context.Request["uid"];
     62             return StringHelper.GetInt(s);
     63         }
     64 
     65         /// <summary>
     66         /// 添加方法
     67         /// </summary>
     68         private void Add() 
     69         {
     70             UserInfo user=new UserInfo();
     71             int n= RequestHelper.FormToModel<UserInfo>(user,context.Request.Form);
     72             ReqMsg msg = new ReqMsg();
     73             
     74             msg.Success=n>2?bll.Add(user)>0:false;
     75 
     76             context.Response.Write(msg.ToString());
     77 
     78         }
     79 
     80         /// <summary>
     81         /// 更新
     82         /// </summary>
     83         private void Update() 
     84         {
     85             UserInfo user = new UserInfo();
     86             int n = RequestHelper.FormToModel<UserInfo>(user, context.Request.Form);
     87             ReqMsg msg = new ReqMsg();
     88 
     89             msg.Success = n > 2 ? bll.Update(user) : false;
     90 
     91             context.Response.Write(msg.ToString());
     92         }
     93 
     94         /// <summary>
     95         /// 删除
     96         /// </summary>
     97         private void Del() 
     98         {
     99             int i = GetUserID();
    100             bll.Del(i);
    101             ReqMsg msg = new ReqMsg(true, "ok");
    102             context.Response.Write(msg.ToString());
    103         }
    104         /// <summary>
    105         /// 查询
    106         /// </summary>
    107         private void Search() 
    108         {
    109             int index = StringHelper.GetInt(context.Request["page"], 1);
    110             int page = StringHelper.GetInt(context.Request["rows"], 10);
    111 
    112             string s = bll.GetSearchPage(index,page,context.Request.Form);
    113             int t = bll.GetSearchCount(context.Request.Form);
    114 
    115             context.Response.Write(RequestHelper.ResponseGridJSON(s,t));
    116         }
    117 
    118         public bool IsReusable
    119         {
    120             get
    121             {
    122                 return false;
    123             }
    124         }
    125     }
    126 }

    三、EasyUI前台展示

        前台方法主要是AJAX处理增删查改请求,创建工具菜单(可能工具权限显示部分但此次不考虑),

      

    View Code
      1 <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="WebApp.Default" %>
      2 
      3 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
      4 
      5 <html xmlns="http://www.w3.org/1999/xhtml">
      6 <head runat="server">
      7     <title></title>
      8     <link href="Scripts/EasyUI/themes/icon.css" rel="stylesheet" type="text/css" />
      9     <link href="Scripts/EasyUI/themes/default/easyui.css" rel="stylesheet" type="text/css" />
     10     <script src="Scripts/EasyUI/jquery-1.8.0.min.js" type="text/javascript"></script>
     11     <script src="Scripts/EasyUI/jquery.easyui.min.js" type="text/javascript"></script>
     12     <script src="Scripts/EasyUI/easyui-lang-zh_CN.js" type="text/javascript"></script>
     13     <script src="Scripts/Common.js" type="text/javascript"></script>
     14 
     15     <script type="text/javascript">
     16         var actionURL="handler/UserHandler.ashx";
     17         var CRUD =
     18         {
     19             Init: function () {
     20                 $('#dataTB').datagrid(
     21                  {
     22                      title: '用户列表',
     23                      iconCls: 'icon-reload',
     24                       800,
     25                      //height: size.height,
     26                      nowrap: false,
     27                      collapsible: false,
     28                      url: actionURL,
     29                      loadMsg: '正在加载……',
     30                      singleSelect: true,
     31                      striped: true,
     32                      pagesize: 10,
     33                      pagination: true,
     34                      queryParams: convertArray($('#fmSearch').serializeArray()),
     35                      toolbar: CreateToolBar(),
     36 
     37                      columns: [[
     38                         { title: '编号', field: 'UserID',  80, align: 'center' },
     39                         { title: '卡号', field: 'CardID',  100, align: 'center' },
     40                         { title: '姓名', field: 'UName',  160, align: 'center' },
     41                         { title: '密码', field: 'UPwd',  160, align: 'center' },
     42                         { title: '年龄', field: 'UAge',  50, align: 'center' },
     43                         { title: '添加时间', field: 'AddDate',  150,
     44                             formatter: function (val, rec) {
     45                                 return ChangeDateFormat(val);
     46                             }
     47 
     48                         }
     49                      ]]
     50                  });
     51             },
     52             Add: function () {
     53                 $('#dialogAdd').dialog('open');
     54                 $('#txt_editType').val('add'); //标示为添加
     55             },
     56             Del: function () {
     57                 var r = $('#dataTB').datagrid('getSelected');
     58                 if (r) {
     59                     $.messager.confirm('删除提示', '你确认删除这一条数据吗?', function (d) {
     60                         if (d) {
     61                             $.post(actionURL, { "reqTypes": "del", "uid": r["UserID"] }, function (d) {
     62                                 var res = $.parseJSON(d);
     63                                 if (res.Success) {
     64                                     $.messager.show(
     65                                     {
     66                                         title: '系统提示',
     67                                         msg: '删除成功!',
     68                                         timeout: 1500
     69                                     });
     70                                     $('#dataTB').datagrid('reload', convertArray($('#fmSearch').serializeArray()));
     71                                 } else {
     72                                     $.messager.alert('错误', res.Msg);
     73                                 }
     74                             });
     75                         }
     76                     });
     77                 } else {
     78                     $.messager.alert('提示', '请选择一行数据!');
     79                 }
     80 
     81             },
     82             Update: function () {
     83                 var r = $('#dataTB').datagrid('getSelected');
     84                 if (r == null) { $.messager.alert('提示', '请选择一行数据'); return; };
     85                 $('#dialogAdd').dialog('open');
     86                 $('#fmAdd').form('load', r);
     87                 $('#txt_editType').val('update');
     88             }
     89         };
     90 
     91         function InitForm() {
     92             $('#dialogAdd').dialog(
     93             {
     94                 closed: true,
     95                 title:'添加用户',
     96                 300,
     97                 height:300
     98             });
     99          }
    100 
    101         function CreateToolBar() {
    102             var a = [];
    103             var isReflesh = true;
    104             var isAdd = true;
    105             var isDel = true;
    106             var isUpdate = true;
    107             if (isReflesh) {
    108                 a.push({
    109                     text: '刷新',
    110                     iconCls: 'icon-reload',
    111                     handler: function () {
    112 
    113                         CRUD.Init();
    114                     }
    115                 });
    116 
    117                 a.push('-');
    118 
    119             }
    120 
    121             if (isAdd) {
    122                 a.push({
    123                     text: '添加',
    124                     iconCls: 'icon-add',
    125                     handler: function () {
    126                         CRUD.Add();
    127                     }
    128                 });
    129 
    130                 a.push('-');
    131             }
    132 
    133             if (isUpdate) {
    134                 a.push({
    135                     text: '编辑',
    136                     iconCls: 'icon-edit',
    137                     handler: function () {
    138                         CRUD.Update();
    139                     }
    140                 });
    141 
    142                 a.push('-');
    143             }
    144 
    145             if (isDel) {
    146                 a.push({
    147                     text: '删除',
    148                     iconCls: 'icon-cut',
    149                     handler: function () {
    150 
    151                         CRUD.Del();
    152                     }
    153                 });
    154 
    155                 a.push('-');
    156             }
    157             return a;
    158          }
    159     </script>
    160     <script type="text/javascript">
    161 
    162         $(function () {
    163 
    164             CRUD.Init();
    165 
    166             InitForm();
    167 
    168             //查询事件
    169             $('#a_search').click(function () {
    170                 $('#dataTB').datagrid('reload', convertArray($('#fmSearch').serializeArray()));
    171 
    172             });
    173             //确定添加
    174             $('#a_AddOK').click(function () {
    175                 if ($('#fmAdd').form('validate')) {
    176                     var send = convertArray($("#fmAdd").serializeArray());
    177                     $.post(actionURL, send, function (d) {
    178                         $('#dataTB').datagrid('reload', convertArray($('#fmSearch').serializeArray()));
    179                         var res = $.parseJSON(d);
    180                         if (res.Success) {
    181                             $.messager.alert('提示', '操作成功');
    182                             $('#fmAdd').form('clear');
    183                         } else {
    184                             $.messager.alert('错误', res.Msg);
    185                         }
    186                     });
    187                 }
    188 
    189             });
    190 
    191             //取消
    192             $('#a_AddCancle').click(function () {
    193                 $('#fmAdd').form('clear');
    194                 $('#dialogAdd').dialog('close');
    195 
    196             })
    197 
    198         });    
    199     </script>
    200 
    201 </head>
    202 <body>
    203 <div id="dialogAdd" >
    204     <form id="fmAdd" style="text-align:center;">
    205         <br /><br />
    206          <input type="hidden" name="reqTypes" id="txt_editType" />
    207          <input type="hidden" name="UserID" id="txt_editID"/>
    208          用户名<input type="text" name="UName" required="true" class="easyui-validatebox" /><br /><br />
    209         卡号<input type="text" name="CardID" /><br /><br />
    210         年龄<input type="text" name="UAge" /><br /><br />
    211         密码<input type="text" name="UPwd" /><br /><br />
    212         <a class="easyui-linkbutton" id="a_AddOK">确定</a>
    213         <a class="easyui-linkbutton" id="a_AddCancle">取消</a>
    214     </form>
    215 </div>
    216     <div>
    217         <form id="fmSearch">
    218             <input type="hidden" name="reqTypes" value="search" />
    219             用户名<input type="text" name="UName" />
    220             年龄<input type="text" name="UAge" />
    221             <a class="easyui-linkbutton" id="a_search">查询</a>
    222         </form>
    223     </div>
    224    <table id="dataTB"></table>
    225 </body>
    226 </html>


    最终显示效果如图:

    JS帮助函数:

    View Code
     1 function ChangeShortDateFormat(cellval) {
     2     if (!cellval) return '';
     3     var date = new Date(parseInt(cellval.replace("/Date(", "").replace(")/", ""), 10));
     4     var month = date.getMonth() + 1 < 10 ? "0" + (date.getMonth() + 1) : date.getMonth() + 1;
     5     var currentDate = date.getDate() < 10 ? "0" + date.getDate() : date.getDate();
     6     var hour = date.getHours() < 10 ? "0" + date.getHours() : date.getHours();
     7     var minu = date.getMinutes() < 10 ? "0" + date.getMinutes() : date.getMinutes();
     8     var sec = date.getSeconds() < 10 ? "0" + date.getSeconds() : date.getSeconds();
     9 
    10     return date.getFullYear() + "-" + month + "-" + currentDate; //+ " " + hour + ":" + minu + ":" + sec;
    11 
    12 }
    13 
    14 //表单序列化有转JSON格式
    15 function convertArray(o) {
    16     var v = {};
    17     for (var i in o) {
    18         if (o[i].name != '__VIEWSTATE') {
    19             if (typeof (v[o[i].name]) == 'undefined')
    20                 v[o[i].name] = o[i].value;
    21             else
    22                 v[o[i].name] += "," + o[i].value;
    23         }
    24     }
    25     return v;
    26 }

    ********谢谢支持,感谢批评建议,努力学习中******************************

    Demo 的 下载链接

  • 相关阅读:
    WPF样式之画刷结合样式
    年度巨献-WPF项目开发过程中WPF小知识点汇总(原创+摘抄)
    30分钟学会XAML
    spring注解之@Import注解的三种使用方式
    大白话讲解Spring的@bean注解
    SpringBoot中的五种对静态资源的映射规则
    Spring注解之@Autowired、@Qualifier、@Resource、@Value
    Spring中如何使用工厂模式实现程序解耦?
    Spring注解之@Component、@Controller、@Service、@Repository
    Spring整合Redis
  • 原文地址:https://www.cnblogs.com/dedeyi/p/3035057.html
Copyright © 2011-2022 走看看