请选择 进入手机版 | 继续访问电脑版

Yii2|Yii爱好者中文社区门户

 找回密码
 注册

QQ登录

只需一步,快速开始

搜索
热搜: yii 控制器 数组
查看: 15441|回复: 11

YII2-RBAC实现详细讲解之基础构建

  [复制链接]

4

主题

23

帖子

211

积分

中级会员

Rank: 3Rank: 3

积分
211
发表于 2015-1-8 22:40:18 | 显示全部楼层 |阅读模式
本帖最后由 agui 于 2015-1-8 22:50 编辑

最近在看YII2的RBAC的原理,在网上找了一下,没有很详细的实现说明,因此自己摸索了一下,写出来,供大家参考,如有不对的地方,一起交流


我也看了网上的其他的一些实现方法,也从GITHUB下载了一些老外的实现方法,大多使用了YII的AR,感觉都抛弃了YII本身的结构,使得实现变得有点复杂,一般新手很难理解。


我这里没有使用AR,而是使用了YII本身的DbManager类,因为这个类已将RBAC的增删改查都实现好了,如果自己再去写AR有点没有必要
首先,写一个类继承DbManager类,目的是使用DbManager类中的一些受保护的方法,然后定义一个控制器RbacController.php,再有就是几张视图。

PS:看大家的需要,继续更新.....
Rbac.php类如下:主要是将DbManager类里一些封装的方法公开。
  1. namespace app\models;

  2. use yii\rbac\DbManager;
  3. class Rbac extends DbManager{
  4.         
  5.         public function createItem($item){
  6.                
  7.                 if(empty($item->name) || $this->getOneItem($item->name) !== null)
  8.                         return false;
  9.                 return $this->addItem($item) ? true : false;
  10.                
  11.         }
  12.         
  13.         public function getOneItem($name){
  14.                 return $this->getItem($name);
  15.         }
  16.         
  17.         public function updateOneItem($name, $item){
  18.                
  19.                 return $this->updateItem($name, $item);
  20.         }
  21.         
  22.         public function deleteOneItem($name){
  23.                
  24.                 if($item = $this->getOneItem($name))
  25.                         return $this->removeItem($item);
  26.                 else
  27.                         return false;
  28.                
  29.         }
  30.         
  31. }
复制代码






点评

海!外直播 t.cn/RxlBL8D 禁闻视频 t.cn/RxrADkq 防火长城(GFW)拦截的基本都是良心的,广电总局封禁的基本都是优秀的,文化部批判的都是美好的,中宣部查删的都是真实的。这已经形成社会的某种共识...  发表于 2017-6-13 05:57
回复

使用道具 举报

4

主题

23

帖子

211

积分

中级会员

Rank: 3Rank: 3

积分
211
 楼主| 发表于 2015-1-8 22:44:01 | 显示全部楼层
视图:_itemform.php 主要是为角色或者权限的录入修改使用 用到了Ajax的验证
  1. <?php
  2. use yii\helpers\Html;
  3. use yii\helpers\Url;
  4. ?>
  5. <div style="width:100%;margin:0 25%;">
  6.         <div class="list-group col-md-6">
  7.         <?php echo empty($model->name) ? Html::beginForm([ 'create-item','type'=>$type],'post') :
  8.                                                                          Html::beginForm(['update-item','name'=>$model->name],'post');?>
  9.                 <div class="list-group-item"><?php echo empty($model->name) ? '添加':'修改';?><?php echo $type==1?'角色':'权限';?></div>
  10.                 <div class="list-group-item"><?php echo Html::label('名称:',null,['class'=>'col-md-3']).Html::textInput('description',$model->description);?></div>
  11.                 <div class="list-group-item">
  12.                         <?php echo Html::label('标 识:',null,['class'=>'col-md-3']).Html::textInput('name',$model->name,['id'=>'itemName']);?>
  13.                         <div id="item-name-error" class="col-md-offset-3"></div>
  14.                 </div>
  15.                 <div class="list-group-item"><?php echo Html::label('规则名称:',null,['class'=>'col-md-3']).Html::textInput('ruleName',$model->ruleName);?></div>
  16.                 <div class="list-group-item"><?php echo Html::label('数据:',null,['class'=>'col-md-3']).Html::textInput('data',$model->data);?></div>
  17.                 <div class="list-group-item">
  18.                         <?php echo Html::button(empty($model->name)? '添加信息':'修改信息',['type'=>'submit','class'=>'btn btn-success col-md-offset-4']);?>
  19.                         <input type="button" value="返回上一页" onclick="history.go(-1);" class="btn btn-default" />
  20.                 </div>
  21.         <?php echo Html::endForm();?>
  22.         </div>
  23. </div>
  24. <script>
  25. <?php $this->beginBlock('JS_END');?>

  26.         $('#itemName').blur(function(){
  27.                         if($('#itemName').val() == ''){
  28.                                 alert('标识必须填写');
  29.                                 return;
  30.                         }
  31.                                
  32.                         $.ajax({
  33.                                 url:'<?php echo Url::to(['ajax-ishas-item']);?>',
  34.                                 data:{'name':$('#itemName').val(),'newRecord':'<?php echo empty($model->name) ? '':$model->name; ?>'},
  35.                                 dataType:'json',
  36.                                 type:'post',
  37.                                 success: function(result){
  38.                                                 if(result)
  39.                                                         $('#item-name-error').css('color','green').html('该标识可以使用!');       
  40.                                                 else
  41.                                                         $('#item-name-error').css('color','red').html('该标识已使用,请修改标识!');
  42.                                         }
  43.                                 });
  44.                 });
  45. <?php
  46. $this->endBlock();
  47. $this->registerJs($this->blocks['JS_END'],\yii\web\view::POS_END);
  48. ?>
  49. </script>
复制代码



回复 支持 1 反对 0

使用道具 举报

4

主题

23

帖子

211

积分

中级会员

Rank: 3Rank: 3

积分
211
 楼主| 发表于 2015-1-8 22:41:43 | 显示全部楼层
RbacController.php 主要实现了基础的RBAC数据写入查看功能,目前规则这块还没有写好。
  1. namespace backend\controllers;

  2. use yii\db\Query;
  3. use yii\data\ActiveDataProvider;
  4. class RbacController extends BaseController{
  5.         /**
  6.          * 角色/权限列表
  7.          * @param number $type
  8.          * @return Ambigous <string, string>
  9.          */
  10.         public function actionItemindex($type = 1){
  11.                 $auth = \Yii::$app->getAuthManager();
  12.                 $dataProvider = new ActiveDataProvider([
  13.                         'query' => (new Query())->from($auth->itemTable)
  14.                                                                         ->where(['type'=>$type])
  15.                                                                         ->orderBy(['created_at'=>SORT_DESC]),
  16.                         'pagination' => ['pageSize' => 8],
  17.                 ]);
  18.                 return $this->render('itemIndex',['dataProvider'=>$dataProvider,'type'=>$type]);
  19.         }
  20.        
  21.         /**
  22.          * 添加角色/权限
  23.          * @param unknown $type
  24.          * @return Ambigous <string, string>
  25.          */
  26.         public function actionCreateItem($type){
  27.                
  28.                 $item = new \yii\rbac\Item();
  29.                
  30.                 if($item->name === null  && ($data = \Yii::$app->request->post())){
  31.                         $item->name = $data['name'];
  32.                         $item->description = $data['description'];
  33.                         $item->ruleName = $data['ruleName'];
  34.                         $item->data = $data['data'];
  35.                         $item->type = $type;
  36.                        
  37.                         $rbac = \Yii::$container->get('\app\models\Rbac');
  38.                         if($rbac->createItem($item))
  39.                                 return $this->success(['view-item','name'=>$item->name]);       
  40.                         else
  41.                                 return $this->error('数据插入失败!');
  42.                        
  43.                 }
  44.                 return $this->render('_itemform',['model'=>$item,'type'=>$type]);
  45.                
  46.         }
  47.         /**
  48.          * 更新一个 角色/权限
  49.          * @param unknown $name
  50.          * @return Ambigous <\backend\controllers\Ambigous, string, string>|Ambigous <string, string>
  51.          */
  52.         public function actionUpdateItem($name){
  53.                 $rbac = \Yii::$container->get('\app\models\Rbac');
  54.                 if(empty($item = $rbac->getOneItem($name)))
  55.                         return $this->error('不存在的项目');
  56.                 if($data = \Yii::$app->request->post()){
  57.                         $name = $item->name;
  58.                         $item->name = $data['name'];
  59.                         $item->description = $data['description'];
  60.                         $item->ruleName = $data['ruleName'];
  61.                         $item->data = $data['data'];
  62.                        
  63.                         if($rbac->updateOneItem($name,$item))
  64.                                 return $this->success(['view-item','name'=>$item->name]);
  65.                         else
  66.                                 return $this->error('数据修改失败!');
  67.                        
  68.                 }
  69.                 return $this->render('_itemform',['model'=>$item,'type'=>$item->type]);
  70.                
  71.         }
  72.         /**
  73.          * 删除一个角色 权限
  74.          * @param unknown $name
  75.          * @return Ambigous <\backend\controllers\Ambigous, string, string>
  76.          */
  77.         public function actionDeleteItem($name){
  78.                 $rbac = \Yii::$container->get('\app\models\Rbac');
  79.                 //使用了MyISAM引擎,因此不支持级联删除,所以不允许有子节点的情况下删除父节点
  80.                 if((new Query())->from($rbac->itemChildTable)->andWhere(['parent'=>$name])->orWhere(['child'=>$name])->count()>0)
  81.                         return $this->error('该项目下还有子节点,请先删除子节点再删除该节点');
  82.                 if($rbac->deleteOneItem($name))
  83.                         return $this->success(['itemindex']);
  84.                 else
  85.                         return $this->error('删除失败!');
  86.         }
  87.         /**
  88.          * 查看信息 角色  权限
  89.          * @param unknown $name
  90.          * @return Ambigous <string, string>
  91.          */
  92.         public function actionViewItem($name){
  93.                 $rbac = \Yii::$container->get('\app\models\Rbac');
  94.                 $item = $rbac->getOneItem($name);
  95.                 if($item !== null)
  96.                         return $this->render('itemView',['model'=>$item]);
  97.                 else
  98.                         $this->goBack();
  99.         }
  100.        
  101.         /**
  102.          * Ajax判断角色 权限是否存在主键冲突
  103.          * @return string
  104.          */
  105.         public function actionAjaxIshasItem(){
  106.                 $data = \Yii::$app->request->post();
  107.                 $rbac = \Yii::$container->get('\app\models\Rbac');
  108.                
  109.                 $result = $rbac->getOneItem($data['name']);
  110.                 if($data['name'] == $data['newRecord'])
  111.                         return json_encode($result === null ? false:true);
  112.                 else
  113.                         return json_encode($result === null ? true:false);
  114.         }
  115.        
  116.         /**
  117.          * 子节点列表
  118.          * @return Ambigous <string, string>
  119.          */
  120.         public function actionItemChildindex(){
  121.                 $auth = \Yii::$app->getAuthManager();
  122.                 $dataProvider = new ActiveDataProvider([
  123.                         'query' => (new Query())->from($auth->itemChildTable)
  124.                                                                         ->orderBy(['parent'=>SORT_DESC]),
  125.                 ]);
  126.                
  127.                 return $this->render('itemChildIndex',['dataProvider'=>$dataProvider]);
  128.         }
  129.        
  130.         /**
  131.          * 添加子节点  可以为角色 权限添加子节点  (不能将一个权限作为角色的子节点 )
  132.          */
  133.         public function actionCreateItemChild(){
  134.                
  135.                 if($data = \Yii::$app->request->post()){
  136.                         $rbac = \Yii::$container->get('\app\models\Rbac');
  137.                         if(empty($data['parent']) || empty($data['childs']) || !($parent = $rbac->getOneItem($data['parent'])))
  138.                                 return $this->error('父节点或子节点信息错误!');
  139.                         $errors = 0;
  140.                         foreach ($data['childs'] as $v){
  141.                                 if(!($child = $rbac->getOneItem($v)))
  142.                                         return $this->error('不存在的子节点!');
  143.                                 try {
  144.                                         $rbac->addChild($parent,$child);
  145.                                 }catch (\Exception $e){
  146.                                         $errors++;
  147.                                 }                               
  148.                         }
  149.                        
  150.                         if($errors)
  151.                                 return $this->success(['item-childindex'],$errors.'条信息没有插入成功');
  152.                         else
  153.                                 return $this->success(['item-childindex']);
  154.                        
  155.                 }

  156.                 return $this->render('_itemChildForm',['model'=>['parent'=>'','child'=>'']]);
  157.         }
  158.        
  159.         /**
  160.          * 删除子节点
  161.          * @param unknown $parent
  162.          * @param unknown $child
  163.          * @return Ambigous <\backend\controllers\Ambigous, string, string>
  164.          */
  165.         public function actionDeleteItemChild($parent,$child){
  166.                 $rbac = \Yii::$container->get('\app\models\Rbac');
  167.                 if(empty($parent) || empty($child) || !($parent = $rbac->getOneItem($parent)) || !($child = $rbac->getOneItem($child)))
  168.                         return $this->error('错误的参数');
  169.                 return $rbac->removeChild($parent, $child) ?  $this->success(['item-childindex']) : $this->error('删除失败');
  170.                
  171.         }
  172.         /**
  173.          * Ajax请求所有的项目
  174.          */
  175.         public function actionAjaxGetAllitem(){
  176.                 $auth = \Yii::$app->getAuthManager();
  177.                 $items = (new Query)->select(['name','description','type'])->from($auth->itemTable)->orderBy(['type'=>SORT_ASC])->all($auth->db);
  178.                
  179.                 return $this->renderAjax('itemViewAll',['data'=>$items]);
  180.                
  181.         }
  182.        
  183.         /**
  184.          * 用户权限列表
  185.          */
  186.         public function actionAssignmentIndex(){
  187.                 $auth = \Yii::$app->getAuthManager();
  188.                 return $this->render('assignmentIndex',['data'=>(new Query())->from($auth->assignmentTable)->orderBy(['user_id'=>SORT_DESC])->all()]);
  189.                
  190.         }
  191.         /**
  192.          * 为用户分配角色
  193.          */
  194.         public function actionCreateAssignment(){
  195.                
  196.                 $rbac = \Yii::$container->get('\app\models\Rbac');
  197.                 if(($data = \Yii::$app->request->post()) && !empty($data['user_id']) && !empty($data['item_name'])){
  198.                         $item = $rbac->getOneItem($data['item_name']);
  199.                         $role = new \yii\rbac\Role();
  200.                         if(empty($item))
  201.                                 return $this->error('错误的传入参数');
  202.                         $role->name = $item->name;
  203.                        
  204.                         if($rbac->assign($role,$data['user_id']))
  205.                                 return $this->success(['assignment-index']);
  206.                         else
  207.                                 return $this->error('分配权限失败');
  208.                        
  209.                 }
  210.                 $arr = array_combine((new Query())->select(['name'])->from($rbac->itemTable)->where(['type'=>1])->orderBy(['name'=>SORT_DESC])->column(), (new Query())->select(['description'])->from($rbac->itemTable)->where(['type'=>1])->orderBy(['name'=>SORT_DESC])->column());
  211.                 return $this->render('_assignment',['roles'=>$arr]);
  212.                
  213.         }
  214.         /**
  215.          * 删除用户角色
  216.          * @param unknown $user_id
  217.          * @param unknown $item_name
  218.          */
  219.         public function actionDeleteAssignment($user_id,$item_name){
  220.                
  221.                 $rbac = \Yii::$container->get('\app\models\Rbac');
  222.                 $item = $rbac->getOneItem($item_name);
  223.                
  224.                 if($rbac->revoke($item, $user_id))
  225.                         return $this->success(['assignment-index']);
  226.                 else
  227.                         return $this->error('删除失败');
  228.         }
  229.        
  230. }
复制代码



回复 支持 反对

使用道具 举报

4

主题

23

帖子

211

积分

中级会员

Rank: 3Rank: 3

积分
211
 楼主| 发表于 2015-1-8 22:46:04 | 显示全部楼层
角色或权限查看的视图:itemIndex.php
  1. <?php
  2. use yii\grid\GridView;
  3. use yii\helpers\Html;

  4. echo  Html::a($type == 1 ?'添加角色':'添加权限',['create-item','type'=>$type],['class'=>'btn btn-success']);


  5. echo GridView::widget([
  6.         'dataProvider' => $dataProvider,
  7.         'columns' =>[
  8.                         ['class' => 'yii\grid\SerialColumn'],
  9.                         'description:text:名称',
  10.             'name:text:标识',
  11.                         ['attribute'=>'type','label'=>'类型','value'=>function($model, $key, $index, $column){if($model['type']==1)return '角色'; else return '权限';}],
  12.             'rule_name:text:规则名称',
  13.             'created_at:date:创建日期',
  14.             'updated_at:date:修改时间',

  15.             [
  16.                     'class' => 'yii\grid\ActionColumn',
  17.                                 'header' => '操作',
  18.                                 'template' => '{view}  {update}  {delete}',
  19.                                 'buttons' => [
  20.                                       'view' => function ($url, $model, $key) {
  21.                                                   return  Html::a('查看',['view-item','name'=>$model['name']]);
  22.                                              },
  23.                                            'update' => function ($url, $model, $key) {
  24.                                                         return  Html::a('更新',['update-item','name'=>$model['name']]);
  25.                                              },
  26.                                            'delete' => function ($url, $model, $key) {
  27.                                                      return  Html::a('删除',['delete-item','name'=>$model['name']]);
  28.                                              }
  29.                                 ]
  30.                         ]
  31.         ],
  32.        
  33.         'layout' => "\n{items}\n{summary}{pager}",
  34.        
  35. ]);
复制代码



回复 支持 反对

使用道具 举报

4

主题

23

帖子

211

积分

中级会员

Rank: 3Rank: 3

积分
211
 楼主| 发表于 2015-1-8 22:48:19 | 显示全部楼层
子节点的创建视图:_itemChildForm.php 使用了Ajax刷新节点列表
  1. <?php
  2. use yii\helpers\Html;
  3. use yii\helpers\Url;
  4. ?>
  5. <div style="width:100%;margin:0 5%;">
  6.         <div class="list-group col-md-10">
  7.         <?php echo Html::beginForm(['create-item-child'],'post');?>
  8.                 <div class="list-group-item">
  9.                         <?php echo Html::label('父节点:',null,['class'=>'col-md-3']).Html::textInput('parent',$model['parent'],['id'=>'parent-item-value']);?>
  10.                         <span class="glyphicon glyphicon-plus btn" id="parent-node"></span>
  11.                 </div>
  12.                 <div class="bg-success" id="parent-node-contents"></div>
  13.                 <div class="list-group-item">
  14.                         <?php echo Html::label('子节点:',null,['class'=>'col-md-3'])?>
  15.                         <span class="glyphicon glyphicon-plus btn" id="child-node"></span>
  16.                 </div>
  17.                 <div id="child-node-contents"></div>
  18.                 <div class="list-group-item">
  19.                         <?php echo Html::button(empty($model['parent'])? '添加信息':'修改信息',['type'=>'submit','class'=>'btn btn-success col-md-offset-4']);?>
  20.                         <input type="button" value="返回上一页" onclick="history.go(-1);" class="btn btn-default" />
  21.                 </div>
  22.         <?php echo Html::endForm();?>
  23.         </div>
  24. </div>
  25. <script>
  26. <?php $this->beginBlock('GET_ITEM_NODE');?>
  27.         $('#parent-node').click(function(){
  28.                 if($('#parent-node-contents').html() == ''){
  29.                         $.ajax({
  30.                                 url:'<?php echo Url::toRoute(['ajax-get-allitem'])?>',
  31.                                 type:'get',
  32.                                 success:function(data){
  33.                                                 $('#parent-node-contents').html(data);
  34.                                                 $('#parent-node').removeClass('glyphicon glyphicon-plus');
  35.                                                 $('#parent-node').addClass('glyphicon glyphicon-minus');
  36.                                                 //为每个子节点绑定事件
  37.                                                 $('#parent-node-contents table tr td').click(function(){
  38.                                                         $('#parent-item-value').val($(this).find('strong').html());
  39.                                                         $(this).siblings().removeClass('bg-info');
  40.                                                         $(this).addClass('bg-info');
  41.                                                         }).css('cursor','pointer');
  42.                                         }
  43.                                 });
  44.                 }else{
  45.                         if($('#parent-node-contents').css('display') == 'none'){
  46.                                 $('#parent-node-contents').css('display','');
  47.                                 $('#parent-node').removeClass('glyphicon glyphicon-plus');
  48.                                 $('#parent-node').addClass('glyphicon glyphicon-minus');
  49.                         }else{
  50.                                 $('#parent-node-contents').css('display','none');
  51.                                 $('#parent-node').removeClass('glyphicon glyphicon-minus');
  52.                                 $('#parent-node').addClass('glyphicon glyphicon-plus');
  53.                         }
  54.                 }
  55.         });

  56.         $('#child-node').click(function(){
  57.                 if($('#child-node-contents').html() == ''){
  58.                         if($('#parent-node-contents').html() == '')
  59.                                 return alert('请先选择父节点');
  60.                         $('#child-node').removeClass('glyphicon glyphicon-plus');
  61.                         $('#child-node').addClass('glyphicon glyphicon-minus');
  62.                         $('#child-node-contents').html($('#parent-node-contents').html());
  63.                         //取消所有绑定事件
  64.                         $('#child-node-contents table tr td').unbind("click").css('cursor','pointer').removeClass('bg-info');
  65.                         //添加CHECK BOX
  66.                         $('#child-node-contents table tr td span').before('<input type="checkbox" name="childs[]" class="child-items" value="" />  ');
  67.                         //绑定点击事件
  68.                         $('#child-node-contents table tr td').click(function(){
  69.                                 var childValueObj = $(this).find('.child-items');
  70.                                 if(childValueObj.val() == '')
  71.                                         childValueObj.val($(this).find('strong').html());
  72.                                 if(childValueObj.prop('checked')){
  73.                                         childValueObj.prop('checked',false)
  74.                                         $(this).removeClass('bg-info');
  75.                                 }else{
  76.                                         //判断添加关系
  77.                                         if($('#parent-item-value').val() == childValueObj.val())
  78.                                                 return alert('不能为自己添加子节点');
  79.                                         if($("#parent-node-contents table tr td strong:contains('"+$('#parent-item-value').val()+"')").attr('type') == 2 && $(this).find('strong').attr('type') == 1)
  80.                                                 return alert('不能将角色作为权限的子节点');
  81.                                        
  82.                                         childValueObj.prop('checked',true)
  83.                                         $(this).addClass('bg-info');
  84.                                 }
  85.                         });
  86.                 }else{
  87.                         if($('#child-node-contents').css('display') == 'none'){
  88.                                 $('#child-node-contents').css('display','');
  89.                                 $('#child-node').removeClass('glyphicon glyphicon-plus');
  90.                                 $('#child-node').addClass('glyphicon glyphicon-minus');
  91.                         }else{
  92.                                 $('#child-node-contents').css('display','none');
  93.                                 $('#child-node').removeClass('glyphicon glyphicon-minus');
  94.                                 $('#child-node').addClass('glyphicon glyphicon-plus');
  95.                         }
  96.                 }
  97.         });

  98.        
  99. <?php $this->endBlock();
  100. $this->registerJs($this->blocks['GET_ITEM_NODE'],\yii\web\View::POS_END);
  101. ?>
  102. </script>
复制代码



回复 支持 反对

使用道具 举报

175

主题

861

帖子

4万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
46528
发表于 2015-1-9 11:09:45 | 显示全部楼层
好贴要顶
回复

使用道具 举报

0

主题

2

帖子

126

积分

注册会员

Rank: 2

积分
126
发表于 2015-1-12 10:47:06 | 显示全部楼层
楼主有具体的demo吗
回复 支持 反对

使用道具 举报

0

主题

15

帖子

170

积分

注册会员

Rank: 2

积分
170
发表于 2015-1-31 11:35:16 | 显示全部楼层
RBAC 讲的真很详细,在学这个帮助很大。
回复 支持 反对

使用道具 举报

0

主题

3

帖子

128

积分

注册会员

Rank: 2

积分
128
发表于 2015-2-10 16:46:09 | 显示全部楼层
太需要了,谢谢楼主
回复 支持 反对

使用道具 举报

0

主题

1

帖子

130

积分

注册会员

Rank: 2

积分
130
发表于 2015-6-9 11:20:31 | 显示全部楼层
号贴要顶,正在研究这个。希望lz。继续完善哈,坐等。。。。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

Archiver|手机版|小黑屋|Yii2|Yii爱好者中文社区门户  

GMT+8, 2017-6-29 15:04 , Processed in 0.332170 second(s), 27 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

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