<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12
        

      JS組件系列——在ABP中封裝BootstrapTable

       前言:關(guān)于ABP框架,博主關(guān)注差不多有兩年了吧,一直遲遲沒有嘗試。一方面博主覺得像這種復(fù)雜的開發(fā)框架肯定有它的過人之處,系統(tǒng)的穩(wěn)定性和健壯性比一般的開源框架肯定強(qiáng)很多,可是另一方面每每想到它繁瑣的封裝和復(fù)雜的開發(fā)流程就望而卻步,就這樣遲遲沒有行動(dòng)。最近在項(xiàng)目里面用到了ABP框架,沒辦法,只有硬著頭皮上了。經(jīng)過這一段時(shí)間的熟悉,算是對(duì)這個(gè)框架有了一個(gè)大概的了解。今天來分享下如何在ABP框架的模式里面使用bootstrapTable組件。

      本文原創(chuàng)地址:http://www.rzrgm.cn/landeanfen/p/7261651.html

      一、關(guān)于ABP

      ABP是“ASP.NET Boilerplate Project (ASP.NET樣板項(xiàng)目)”的簡稱,它是一個(gè)成熟的開源框架,基于DDD+Repository模式,自帶Zero權(quán)限和認(rèn)證模塊,避免了從零開始搭建框架的煩惱。關(guān)于ABP的框架優(yōu)勢就此打住,因?yàn)檫@樣說下去要說三天三夜,脫離文本主題。

      關(guān)于ABP的入門,博主不想說太多,園子里面tkb至簡和陽光銘睿有很多入門級(jí)的文章,有興趣的可以了解下,還是給出它的官網(wǎng)和開源地址。

      ABP官方網(wǎng)站http://www.aspnetboilerplate.com

      ABP開源項(xiàng)目https://github.com/aspnetboilerplate

      PS:如果你不愿意去看它的源碼,可以直接查看ABP官網(wǎng)上面的演示地址:https://aspnetzero.com/?ref=abptmplpage

      點(diǎn)擊CREATE MY DEMO按鈕,系統(tǒng)會(huì)自動(dòng)為你生成演示地址

      進(jìn)入對(duì)應(yīng)的Demo URL

      使用演示的用戶名和密碼登陸進(jìn)去

      可以看到Zero模塊的實(shí)現(xiàn)效果。

      二、jTable在ABP中的運(yùn)用

      如果你下載ABP的源碼,并且選擇的是混合開發(fā)模式(ABP提供了兩種開發(fā)模式,一種是基于MVVM的Angular.js的模式;另一種就是MVC+jQuery的混合開發(fā)模式),如下圖:

      當(dāng)你Down下來源碼之后你就會(huì)發(fā)現(xiàn),ABP的源碼里面的UI部分的表格都是使用jTable去實(shí)現(xiàn)的。為什么會(huì)用jTable?原因很簡單,jTable是ABP的作者kalkan寫的一款開源插件,自己寫的肯定用自己的東西嘍。下面jTable的效果來一發(fā)。

      來一個(gè)jtable的父子表:

      如果是不帶父子表的簡單表格,其實(shí)jTable的效果其實(shí)還行,可是加上一些復(fù)雜的功能之后,那一片片藍(lán)色的區(qū)域不忍直視,并且jTable的api還有待完善,很多需要的功能都需要自己去實(shí)現(xiàn),于是就接到了將所有的表格組件換成BootstrapTable的需求,才有了今天的主題:在ABP中封裝BootstrapTable。

      三、Bootstrap Table在ABP中的封裝

      接到需求,博主各種百度、各種谷歌,都找不到Bootstrap Table組件在ABP中的封裝,有的只是在ABP的項(xiàng)目里面簡單的用傳統(tǒng)的方式去初始化組件,這并不是博主想要的。說到這里不得不說一下,如果你使用ABP開發(fā)的過程中遇到一些難題,你會(huì)發(fā)現(xiàn)很難從百度里面搜索到相關(guān)答案,谷歌里面有時(shí)能找到,但大部分都是英文社區(qū),所以如果你英文較弱,在查找資料上面會(huì)很吃虧,有時(shí)一個(gè)簡單的配置問題需要折騰很久。

      1、jTable在ABP項(xiàng)目里面的初始化

      首先來看看jTable在一般的ABP項(xiàng)目里面是如何初始化的。比如我們?cè)贏pplication里面有一個(gè)如下的接口和實(shí)現(xiàn)

       public interface IRequisitionAppService : IApplicationService
          {
              Task<PagedResultDto<RequisitionListDto>> GetRequisitionListAsync(GetRequisitionListInput input);
          }
        [AbpAuthorize(OrderAppPermissions.Pages_Order_Requisition)]
          public class RequisitionAppService : AbpZeroTemplateAppServiceBase, IRequisitionAppService
          {
              private readonly IRepository<Requisition, long> _requisitionRepository;
              public RequisitionAppService(IRepository<Requisition, long> requisitionRepository)
              {
                  _requisitionRepository = requisitionRepository;
              }
      
           public async Task<PagedResultDto<RequisitionListDto>> GetRequisitionListAsync(GetRequisitionListInput input)
              {
                  var query = _requisitionRepository.GetAll()
                                                          .WhereIf(input.Status != null, w => (int)w.Status == input.Status.Value)
                                                          .WhereIf(
                                                              !input.Filter.IsNullOrWhiteSpace(),
                                                              u =>
                                                                  u.No.Contains(input.Filter) ||
                                                                  u.Remark.Contains(input.Filter)
                                                          );
      
                  var count = await query.CountAsync();
      
                  var list = await query
                  .OrderBy(input.Sorting)
                  .PageBy(input)
                  .ToListAsync();
      
                  var dtos = list.MapTo<List<RequisitionListDto>>();
                  return new PagedResultDto<RequisitionListDto>(
                      count,
                      dtos
                      );
              }
      
      
          }

      然后我們前端有一個(gè)頁面的列表數(shù)據(jù)從這個(gè)接口GetRequisitionListAsync()獲取

      <div class="portlet-body">
          <div id="dataListTable"></div>
      </div>
      (function () {
          $(function () {
              var _$dataListTable = $('#dataListTable');
              var _service = abp.services.app.requisition;
              _$dataListTable.jtable({
                  paging: true,
                  sorting: true,
                  selecting: true,
                  actions: {
                      listAction: {
                          method: _service.getRequisitionListAsync
                      }
                  },
                  fields: {
                      id: {
                          key: true,
                          list: false
                      },
                      details: {
                          width: '1%',
                          sorting: false,
                          edit: false,
                          create: false,
                          listClass: 'child-opener-image-column',
                          display: function (detailData) {
                              var $img = $('<img class="child-opener-image" src="/Common/Images/list_metro.png" title="申購明細(xì)" />');
                              $img.click(function () {
                                  _$dataListTable.jtable('openChildTable',
                                      $img.closest('tr'),
                                      {
                                          title: "申購明細(xì)",
                                          showCloseButton: true,
                                          actions: {
                                              listAction: {
                                                  method: _service.getRequisitionDetailListByIdAsync
                                              }
                                          },
                                          fields: {
                                              materialClassParentNameAndName: {
                                                  title: app.localize('MaterialClassName'),
                                                  width: '8%'
                                              },
                                              materialInfoTypeNo: {
                                                  title: app.localize('TypeNo'),
                                                  width: '5%'
                                              },
                                              materialInfoLengthDisplayName: {
                                                  title: app.localize('LengthDisplayName'),
                                                  width: '3%'
                                              },
                                              materialInfoWeight: {
                                                  title: app.localize('Weight'),
                                                  width: '5%',
                                                  display: function (data) {
                                                      return data.record.materialInfoMinWeight + '-' + data.record.materialInfoMaxWeight;
                                                  }
                                              },
                                              materialInfoMouldTypeDisplayName: {
                                                  title: app.localize('MouldTypeDisplayName'),
                                                  width: '6%'
                                              },
                                              materialInfoProductionRemark: {
                                                  title: app.localize('ProductionRemark'),
                                                  width: '8%'
                                              },
                                              materialInfoBundleCountDisplayName: {
                                                  title: app.localize('BundleCountDisplayName'),
                                                  width: '3%'
                                              },
                                              materialInfoUnitDisplayName: {
                                                  title: app.localize('UnitDisplayName'),
                                                  width: '3%'
                                              },
                                              materialInfoProcessCost: {
                                                  title: app.localize('ProcessCost'),
                                                  width: '6%'
                                              },
                                              materialInfoProductRemark: {
                                                  title: app.localize('ProductRemark'),
                                                  width: '6%'
                                              },
                                              materialInfoRemark: {
                                                  title: app.localize('Remark'),
                                                  width: '6%'
                                              },
                                              count: {
                                                  title: app.localize('申購數(shù)量'),
                                                  width: '6%'
                                              },
                                              remark: {
                                                  title: app.localize('申購備注'),
                                                  width: '6%'
                                              }
                                          }
                                      }, function (data) {
                                          data.childTable.jtable('load',
                                              { requisitionId: detailData.record.id }
                                          );
                                      });
                              });
                              return $img;
                          }
                      },
                      no: {
                          title: "申購單號(hào)",
                          width: '20%'
                      },
                      creatorUserName: {
                          title: "申購人",
                          width: '20%'
                      },
                      creationTime: {
                          title: "申購時(shí)間",
                          width: '10%',
                          display: function (data) {
                              return moment(data.record.creationTime).format('YYYY-MM-DD HH:mm:ss');
                          }
                      },
                      sumCount: {
                          title: "總數(shù)",
                          width: '10%'
                      },
                      status: {
                          title: "狀態(tài)",
                          width: '20%',
                          display: function (data) {
                              if (data.record.status === app.order.requisitionAuditStatus.audit)
                                  return '<span class="label label-info">' + app.localize('Autdit') + '</span>'
                              else if (data.record.status === app.order.requisitionAuditStatus.auditPass)
                                  return '<span class="label label-success">' + app.localize('Pass') + '</span>'
                              else if (data.record.status === app.order.requisitionAuditStatus.auditReject)
                                  return '<span class="label label-danger">' + app.localize('Reject') + '</span>'
                              else if (data.record.status === app.order.requisitionAuditStatus.delete)
                                  return '<span class="label label-danger">' + app.localize('Abandon') + '</span>'
                              else
                                  return '<span class="label label-danger">' + app.localize('Unknown') + '</span>'
                          }
                      }
                  }
      
              });
          });
      })();

      得到如下效果:

      代碼釋疑:

      (1) var _service = abp.services.app.requisition; 這一句聲明當(dāng)前頁面需要使用哪個(gè)服務(wù)。

      (2)  _service.getRequisitionListAsync 這一句對(duì)應(yīng)的是服務(wù)調(diào)用的方法,你會(huì)發(fā)現(xiàn)在后臺(tái)方法名是GetRequisitionListAsync(),而在js里面卻變成了getRequisitionListAsync(),我們暫且稱之為“潛規(guī)則”。

      2、bootstrapTable在ABP項(xiàng)目里面的封裝

      通過上述代碼你會(huì)發(fā)現(xiàn),ABP在application層里面定義的方法,最終會(huì)生成某一些js對(duì)應(yīng)的function,這里難點(diǎn)來了。我們找遍了bootstrapTable組件的api,都沒有通過某一個(gè)function去獲取數(shù)據(jù)的啊。這可如何是好?為這個(gè)問題,博主折騰了兩天。最開始博主想,function最終還不是要換成http請(qǐng)求的,我們只要拿到http請(qǐng)求的url,然后將function轉(zhuǎn)換為url不就行了么:

       

      我們使用bootstrapTable組件初始化的時(shí)候聲明  {url:'/api/services/app/requisition/GetRequisitionListAsync'}  這樣不就行了么?呵呵,經(jīng)過測試,這樣確實(shí)能正確取到數(shù)據(jù)。但是不夠理想,因?yàn)檫@前面的前綴是ABP給我們生成的,是否會(huì)變化我們尚且不說,給每一個(gè)url加上這么一長串著實(shí)看著很不爽,于是進(jìn)一步想,是否我們的bootstrapTable也可以使用function去初始化呢,組件沒有,難道我們就不能給他擴(kuò)展一個(gè)嗎?我們不用url獲取數(shù)據(jù),通過調(diào)用這個(gè)function取到數(shù)據(jù),然后將數(shù)據(jù)渲染到組件不就行了。思路有了,那么這里有兩個(gè)難題:一是如何將原來url的方式變成這里的調(diào)用function的方式呢?二是參數(shù)的封裝。經(jīng)過查看組件的源碼發(fā)現(xiàn),如果是服務(wù)端分頁,組件最終是進(jìn)入到initServer()這個(gè)方法去獲取數(shù)據(jù),然后渲染到頁面上面的,組件原始的initServer()方法如下:

      BootstrapTable.prototype.initServer = function (silent, query) {
              var that = this,
                  data = {},
                  params = {
                      pageSize: this.options.pageSize === this.options.formatAllRows() ?
                          this.options.totalRows : this.options.pageSize,
                      pageNumber: this.options.pageNumber,
                      searchText: this.searchText,
                      sortName: this.options.sortName,
                      sortOrder: this.options.sortOrder
                  },
                  request;
      
              if (!this.options.url && !this.options.ajax) {
                  return;
              }
      
              if (this.options.queryParamsType === 'limit') {
                  params = {
                      search: params.searchText,
                      sort: params.sortName,
                      order: params.sortOrder
                  };
                  if (this.options.pagination) {
                      params.limit = this.options.pageSize === this.options.formatAllRows() ?
                          this.options.totalRows : this.options.pageSize;
                      params.offset = this.options.pageSize === this.options.formatAllRows() ?
                          0 : this.options.pageSize * (this.options.pageNumber - 1);
                  }
              }
      
              if (!($.isEmptyObject(this.filterColumnsPartial))) {
                  params['filter'] = JSON.stringify(this.filterColumnsPartial, null);
              }
      
              data = calculateObjectValue(this.options, this.options.queryParams, [params], data);
      
              $.extend(data, query || {});
      
              // false to stop request
              if (data === false) {
                  return;
              }
      
              if (!silent) {
                  this.$tableLoading.show();
              }
              request = $.extend({}, calculateObjectValue(null, this.options.ajaxOptions), {
                  type: this.options.method,
                  url: this.options.url,
                  data: this.options.contentType === 'application/json' && this.options.method === 'post' ?
                      JSON.stringify(data) : data,
                  cache: this.options.cache,
                  contentType: this.options.contentType,
                  dataType: this.options.dataType,
                  success: function (res) {
                      res = calculateObjectValue(that.options, that.options.responseHandler, [res], res);
      
                      that.load(res);
                      that.trigger('load-success', res);
                  },
                  error: function (res) {
                      that.trigger('load-error', res.status, res);
                  },
                  complete: function () {
                      if (!silent) {
                          that.$tableLoading.hide();
                      }
                  }
              });
      
              if (this.options.ajax) {
                  calculateObjectValue(this, this.options.ajax, [request], null);
              } else {
                  $.ajax(request);
              }
          };
      組件原始initServer()方法

      代碼不難讀懂,解析參數(shù),整合參數(shù),得到參數(shù),發(fā)送ajax請(qǐng)求,在success事件里面將得到的數(shù)據(jù)渲染到界面。讀懂了這段代碼,我們?cè)賮矸庋bfunction就容易多了。

      最終我們封裝的代碼如下:

      (function ($) {
          'use strict';
      
          //debugger;
          //通過構(gòu)造函數(shù)獲取到bootstrapTable里面的初始化方法
          var BootstrapTable = $.fn.bootstrapTable.Constructor,
              _initData = BootstrapTable.prototype.initData,
              _initPagination = BootstrapTable.prototype.initPagination,
              _initBody = BootstrapTable.prototype.initBody,
              _initServer = BootstrapTable.prototype.initServer,
              _initContainer = BootstrapTable.prototype.initContainer;
      
          //重寫
          BootstrapTable.prototype.initData = function () {
              _initData.apply(this, Array.prototype.slice.apply(arguments));
          };
      
          BootstrapTable.prototype.initPagination = function () {
              _initPagination.apply(this, Array.prototype.slice.apply(arguments));
          };
      
          BootstrapTable.prototype.initBody = function (fixedScroll) {
              _initBody.apply(this, Array.prototype.slice.apply(arguments));
          };
      
          BootstrapTable.prototype.initServer = function (silent, query) {
              //構(gòu)造自定義參數(shù)
              for (var key in this.options.methodParams) {
                  $.fn.bootstrapTable.defaults.methodParams[key] = this.options.methodParams[key];
              }
              //如果傳了url,則走原來的邏輯
              if (this.options.url) {
                  _initServer.apply(this, Array.prototype.slice.apply(arguments));
                  return;
              }
              //如果定義了abpMethod,則走abpMethod的邏輯
              if (!this.options.abpMethod) {
                  return;
              }
              var that = this,
                  data = {},
                  params = {
                      pageSize: this.options.pageSize === this.options.formatAllRows() ?
                          this.options.totalRows : this.options.pageSize,
                      pageNumber: this.options.pageNumber,
                      searchText: this.searchText,
                      sortName: this.options.sortName,
                      sortOrder: this.options.sortOrder
                  },
                  request;
      
              
              //debugger;
              if (this.options.queryParamsType === 'limit') {
                  params = {
                      search: params.searchText,
                      sort: params.sortName,
                      order: params.sortOrder
                  };
                  if (this.options.pagination) {
                      params.limit = this.options.pageSize === this.options.formatAllRows() ?
                          this.options.totalRows : this.options.pageSize;
                      params.offset = this.options.pageSize === this.options.formatAllRows() ?
                          0 : this.options.pageSize * (this.options.pageNumber - 1);
                  }
              }
      
              if (!($.isEmptyObject(this.filterColumnsPartial))) {
                  params['filter'] = JSON.stringify(this.filterColumnsPartial, null);
              }
      
              data = $.fn.bootstrapTable.utils.calculateObjectValue(this.options, this.options.queryParams, [params], data);
      
              $.extend(data, query || {});
      
              // false to stop request
              if (data === false) {
                  return;
              }
      
              if (!silent) {
                  this.$tableLoading.show();
              }
              
              this.options.abpMethod(data).done(function (result) {
                  result = $.fn.bootstrapTable.utils.calculateObjectValue(that.options, that.options.responseHandler, [result], result);
                  that.load(result);
                  that.trigger('load-success', result);
              });
              request = $.extend({}, $.fn.bootstrapTable.utils.calculateObjectValue(null, this.options.ajaxOptions), {
                  type: this.options.method,
                  url: this.options.url,
                  data: this.options.contentType === 'application/json' && this.options.method === 'post' ?
                      JSON.stringify(data) : data,
                  cache: this.options.cache,
                  contentType: this.options.contentType,
                  dataType: this.options.dataType,
                  success: function (res) {
                      debugger;
                      res = $.fn.bootstrapTable.utils.calculateObjectValue(that.options, that.options.responseHandler, [res], res);
      
                      that.load(res);
                      that.trigger('load-success', res);
                  },
                  error: function (res) {
                      that.trigger('load-error', res.status, res);
                  },
                  complete: function () {
                      if (!silent) {
                          that.$tableLoading.hide();
                      }
                  }
              });
      
              if (this.options.ajax) {
                  $.fn.bootstrapTable.utils.calculateObjectValue(this, this.options.ajax, [request], null);
              } else {
                  $.ajax(request);
              }
          }
      
          BootstrapTable.prototype.initContainer = function () {
              _initContainer.apply(this, Array.prototype.slice.apply(arguments));
          };
      
          abp.bootstrapTableDefaults = {
              striped: false,
              classes: 'table table-striped table-bordered table-advance table-hover',
              pagination: true,
              cache: false,
              sidePagination: 'server',
              uniqueId: 'id',
              showRefresh: false,
              search: false,
              method: 'post',
              //toolbar: '#toolbar',
              pageSize: 10,
              paginationPreText: '上一頁',
              paginationNextText: '下一頁',
              queryParams: function (param) {
                  //$.fn.bootstrapTable.defaults.methodParams.propertyIsEnumerable()
                  var abpParam = {
                      Sorting: param.sort,
                      filter: param.search,
                      skipCount: param.offset,
                      maxResultCount: param.limit
                  };
                  for (var key in $.fn.bootstrapTable.defaults.methodParams) {
                      abpParam[key] = $.fn.bootstrapTable.defaults.methodParams[key];
                  }
                  return abpParam;
              },
              responseHandler: function (res) {
                  if (res.totalCount)
                      return { total: res.totalCount, rows: res.items };
                  else
                      return { total: res.result.totalCount, rows: res.result.items };
              },
              methodParams: {},
              abpMethod: function () { }
          };
          
          $.extend($.fn.bootstrapTable.defaults, abp.bootstrapTableDefaults);
      })(jQuery);

      代碼釋疑:增加兩個(gè)參數(shù) methodParams: {},abpMethod: function () { } 來獲取abp的function和參數(shù),然后獲取數(shù)據(jù)的時(shí)候如果定義了abpMethod,則通過function獲取數(shù)據(jù),否則還是走原來的邏輯。

      然后我們調(diào)用就簡單了

       //選取界面上要先數(shù)據(jù)的表格
              var _$SendOrdersTable = $('#SendOrdersTable');
              //獲取服務(wù)層方法
              var _SendOrderService = abp.services.app.sendOrder;
      
              _$SendOrdersTable.bootstrapTable({
                  abpMethod: _SendOrderService.getSendOrderListAsync,
                  detailView: true,
                  onExpandRow: function (index, row, $detail) {
                      var cur_table = $detail.html('<table></table>').find('table');
                      $(cur_table).bootstrapTable({
                          showRefresh: false,
                          search: false,
                          pagination: false,
                          abpMethod: _SendOrderService.getSendOrderDetailListAsync,
                          methodParams: { SendOrderId: row.id },
                          columns: [
                              {
                                  field: 'materialClassName',
                                  title: app.localize('MaterialClassName'),
                                  width: '8%'
                              },
                              {
                                  field: 'typeNo',
                                  title: app.localize('TypeNo'),
                                  width: '8%'
                              }
                          ]
                      });
                  },
                  columns: [{
                      field: 'no',
                      title: app.localize('SendOrderNO'),
                      align: 'center'
                  },
                  {
                      field: 'supplierName',
                      title: app.localize('SupplierName'),
                      align: 'center'
                  },
                  {
                      title: app.localize('SendOrderTime'),
                      align: 'center',
                      field: 'createdDate',
                      formatter: function (data) {
                          return moment(data).format('YYYY-MM-DD HH:mm:ss');
                      }
                  },
      
                  {
                      field: 'status',
                      align: 'center',
                      title: app.localize('SendOrderStatus'),
                      formatter: function (data) {
                          var value = "";
                          if (data == 1) {
                              value = '<span class="label label-info">' + app.localize('Autdit') + '</span>';
                          }
                          else if (data == 2) {
                              value = '<span class="label label-success">' + app.localize('Pass') + '</span>';
                          }
                          else if (data == 3) {
                              value = '<span class="label label-default">' + app.localize('Reject') + '</span>';
                          }
                          else
                              value = '<span class="label label-default">' + app.localize('Abandon') + '</span>';
                          return value;
                      }
                  },
      
                  {
                      field: 'createName',
                      align: 'center',
                      title: app.localize('SendOrderCreator'),
                  },
      
      
                  {
                      field: 'sumCount',
                      align: 'center',
                      title: app.localize('SendOrderTotalCount'),
                  },
                  ]
              });

      得到如下效果

      四、總結(jié) 

      通過以上一個(gè)簡單的封裝,順利將bootstrapTable融入到了ABP的操作方式里面。是不是很easy!在使用ABP的過程中,博主還做了其他一些封裝,以后有機(jī)會(huì)再來介紹,關(guān)于ABP的技術(shù)交流歡迎聯(lián)系博主。這一篇就到這里,歡迎交流。如果你覺得本文能夠幫助你,可以右邊隨意 打賞 博主,打賞后可以獲得博主永久免費(fèi)的技術(shù)支持。

      本文原創(chuàng)出處:http://www.rzrgm.cn/landeanfen/

      歡迎各位轉(zhuǎn)載,但是未經(jīng)作者本人同意,轉(zhuǎn)載文章之后必須在文章頁面明顯位置給出作者和原文連接,否則保留追究法律責(zé)任的權(quán)利

      posted @ 2017-07-31 16:03  懶得安分  閱讀(9365)  評(píng)論(24)    收藏  舉報(bào)
      主站蜘蛛池模板: 博客| 99久久精品午夜一区二区| 国产精品中文字幕日韩| 国产精品无码成人午夜电影| 亚洲av永久无码精品网站| 久久精品国产久精国产果冻传媒| 办公室强奷漂亮少妇同事| 亚洲精品无码高潮喷水在线| av新版天堂在线观看| 国产午夜福利精品片久久| 中文字幕一区二区网站| 宝丰县| 亚洲av产在线精品亚洲第一站| 亚洲中文字幕日产无码成人片| 丁香五月网久久综合| 国产欧美日韩视频一区二区三区 | 一本色道久久88精品综合| 国产成人精品亚洲资源| 人妻少妇一区二区三区| 久久亚洲国产精品久久| 制服丝袜中文字幕在线| 亚洲啪啪精品一区二区的| 少妇xxxxx性开放| 美女又黄又免费的视频| 亚洲色欲在线播放一区| 女同精品女同系列在线观看| 亚洲色一区二区三区四区| h无码精品动漫在线观看| 粉嫩一区二区三区粉嫩视频| 国产女人18毛片水真多1| 精品少妇人妻av无码专区| 国产精品第一页中文字幕| 中文字幕第55页一区| 97视频精品全国免费观看| 韩国 日本 亚洲 国产 不卡| 怡春院欧美一区二区三区免费| 99久久精品费精品国产一区二| 精品国产午夜福利在线观看 | 色欲AV无码一区二区人妻| 女同精品女同系列在线观看| 狠狠v日韩v欧美v|