成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

使用Antd表格組件實現日程表

開發 前端
20多天前,遇到一個日程表的業務需求,可以動態增加列、對單元格進行合并,結合公司的jsp項目的已有功能完成單元格的增、刪、改操作。

[[353267]]

本文轉載自微信公眾號「神奇的程序員K」,作者神奇的程序員K 。轉載本文請聯系神奇的程序員K公眾號。

 前言

20多天前,遇到一個日程表的業務需求,可以動態增加列、對單元格進行合并,結合公司的jsp項目的已有功能完成單元格的增、刪、改操作。進行需求分析整理后,經過了一番查找,發現React版本的antd的表格組件功能很強大,可定制程度很高,可以助我完成這個業務需求的開發。

由于要和jsp進行交互,所以在實現過程中,遇到了一些難題踩了挺多坑,本文就跟大家分享下我從0到1實現這個需求的過程與思路,歡迎各位感興趣的開發者閱讀本文。

環境搭建

因為公司的項目是基于jsp的,antd本想用Vue版本的,無奈它與jsp的一些語法沖突了跑不起來,于是就嘗試了react版本的antd,它跑起來了沒有發現任何兼容性問題,一切正常。給React點個贊??。

由于要與項目中已有的功能進行交互,沒法用腳手架,我只能以cdn的方式引入react,如下所示,按順序引入react、axios、lodah以及antd所需要的文件。

  1. <script crossOrigin type="text/javascript" src="lib/react.production.min.js"></script> 
  2.    <script crossOrigin type="text/javascript" src="lib/react-dom.production.min.js"></script> 
  3.    <script src="lib/babel.min.js"></script> 
  4.    <script type="text/javascript" src="lib/moment.min.js"></script> 
  5.    <script src="lib/lodash.min.js"></script> 
  6.    <script type="text/javascript" src="lib/antd.min.js"></script> 
  7.    <script type="text/javascript" src="lib/axios.min.js"></script> 
  8.    <link rel="stylesheet" href="lib/antd.min.css"

 

 

 

 

 

 

 

 

上述用到的資源文件地址: react-antd-schedule/lib

我們需要把react相關代碼寫在text/babel標簽中,如下所示,我們打印antd和react看看是否有值。

  1. <script type="text/babel"
  2.     console.log("react"); 
  3.     console.log(React); 
  4.     console.log("antd"
  5.     console.log(antd); 
  6. </script> 

 

打開瀏覽器控制臺,出現下述信息,代表我們的環境已經搭建成功。

image-20201119155715157

接下來,我們寫個HelloWord來測試下效果。

  1. <div id="root" style="width: 94%;overflow: hidden"></div> 
  2. <script type="text/babel"
  3.     // 自定義hook 
  4.     const App = () => { 
  5.         const onChange = (date, dateString) => { 
  6.             console.log(date, dateString); 
  7.         } 
  8.         return ( 
  9.             <div> 
  10.                 React+antd引入成功 
  11.                 <br /> 
  12.                 <antd.DatePicker onChange={onChange} /> 
  13.             </div> 
  14.         ); 
  15.     }; 
  16.     ReactDOM.render(<App />, document.getElementById("root")); 
  17. </script> 

 

 

 

 

執行上述代碼,打開瀏覽器如果看到下述效果,就證明我們的環境已經搭好了。

image-20201119161505912

需要注意的是,CDN引入React和antd,他們是在全局暴露了一個對象,在使用它內部的方法時就需要React.xx、antd.xx來訪問了。

需求分析

當我收到需求簡述后,我對其進行了整理:

  • 表格列要展示的內容:日期、日程內容(接口動態返回),日程內容列用戶可以自己手動增加。
  • 表格行展示的內容為每一天的數據,每一天的數據分為:上午、下午、晚上三個時間段。
  • 日程內容分為天日程和某個時間段的日程兩種狀態,如果為天日程則需要進行單元格合并。
  • 日程內容列的每個單元格有5種狀態,需要通過某種方式來區分,讓用戶一眼就能看出當前日程處于什么狀態。
  • 日程內容單元格的內容如果為空時,需要將單元格進行合并,顯示一個增加圖標,點擊增加圖標后,打開系統的彈窗進行增加操作,操作完成后,渲染內容至剛才點擊的單元格。
  • 如果內容單元格有內容時,根據不同的狀態,打開不同的彈窗進行改、刪操作,操作完后,更新結果至對應的單元格。

需求確定后,老板給我分了一個后端,跟后端溝通后開發周期估了1周,我頁面估了2天的時間,剩下的3天與后端進行數據對接。

2天后,我把頁面弄完了,表格需要的數據格式也定義好了,把數據格式發給后端后,他說好,沒問題。

因為沒有UI給設計圖,所以第一版,我就憑著自己的直覺來弄了,搞出來的東西蠻丑的,下圖就是我根據需求實現的頁面。

image-20201119172808318

然而,事情沒有預想中那么順利,我頁面做好后,到開發周期的最后一天下午,后端把接口給我了,但返回的數據不是我預想的格式,我又進行了二次處理,頁面渲染出來后,快到下班時間了,到了預估的開發時間沒有完成需求,倒也能理解,畢竟后端那邊要處理的數據比較復雜。

本來預估了一周的開發時間,后面需求的不斷增加、變更、UI設計效果圖,我的頁面代碼也從一開始的100多行累加到現在的1000多行,這一套折騰下來,直到需求開發完成交給測試,花了20多天的時間。

需求實現

接下來,就跟大家分享下在實現這個需求時,遇到的難點、踩到的一些坑以及我的解決方案。

最后實現的效果如下所示,實現代碼請移步:react-antd-schedule/index.html

image-20201119175256753

動態增加列

這個日程表用戶可以通過點增加圖標來增加一列日程,此時我們就需要往表格頭部增加一列數據,一開始我覺得只要往antd的columns和dataSource中添加一條數據就行了,如下所示:

  1. const App = () => { 
  2.         const [columns, setColumns] = React.useState([]); 
  3.         const [optRecords, setOptRecords] = React.useState([]); 
  4.            //增加按鈕函數 
  5.         const btnClick = (e) => { 
  6.             index++; 
  7.             let columnsObj = { 
  8.                 dataIndex: 'rcnr' + (index), 
  9.                 title: '日程內容' + index
  10.                 align: 'center'
  11.                 onCell: tdSet, 
  12.                 render: rctd_render, 
  13.             } 
  14.             // 表格列新增一列 
  15.             columns.push(columnsObj) 
  16.             setColumns(columns); 
  17.             // 處理表格數據 
  18.             for (let i = 0; i < optRecords.length; i++) { 
  19.                 let key = "rcnr"+index
  20.                 // 表格數據新增一條 
  21.                 optRecords[i][key] = {text:"", code:"0"
  22.             } 
  23.             setOptRecords(optRecords); 
  24.         } 
  25.  } 

當我在瀏覽器執行看效果時,發現沒有生效,于是我下意識的打開了瀏覽器控制臺看看是不是報錯了,啪的一下,很快啊~新增加的那一列被渲染上去了,我大E了啊,antd不講武德啊。

于是,我多試了幾次,發現還是不渲染,打開控制臺后就奇跡般的渲染上去了,有點摸不著頭腦,就求助了下網友,我才恍然大悟,原來是antd沒有監聽到引用地址的改變,得到了下述解決方案,用一個函數去處理它,讓antd監聽到引用地址改變,它才會將數據進行渲染。

  1. const App = () => { 
  2.        const [optRecords, setOptRecords] = React.useState([]); 
  3.        const [columns, setColumns] = React.useState([]); 
  4.           //增加按鈕函數 
  5.        const btnClick = (e) => { 
  6.            if (tableLoadingStatus) { 
  7.                alert("表格數據尚未加載完成"); 
  8.                return false
  9.            } 
  10.            columnsIndex++; 
  11.            let columnsObj = { 
  12.                dataIndex: "rcnr" + (columnsIndex), 
  13.                title: "日程內容" + columnsIndex, 
  14.                align: "left"
  15.                className: "rcnrfontSet"
  16.                width: 189.5, 
  17.                onCell: tdSet, 
  18.                render: rctd_render 
  19.            }; 
  20.            // 表格列新增一列 
  21.            setColumns((arr => [...arr, columnsObj])); 
  22.            // 處理表格數據 
  23.            setOptRecords((arr) => arr.map((item) => { 
  24.                return { ...item, ["rcnr" + columnsIndex]: { wz: columnsIndex - 1 } }; 
  25.            })); 
  26.             
  27.        }; 

表格列補齊

在后端返回的數據中,如果有不存在的日程,直接連字段都沒返回,這就造成了antd在渲染的時候列與表格數據不對應而引發的武發渲染的問題,于是我只能把所有數據遍歷一遍,求出最大列長度,然后將列少的數據進行補全,由于添加數據時接口需要傳當前點擊的是哪一列,剛才補全的數據中是不包含wz字段的,因此我們需要再遍歷一次數據,把wz字段加上去,代碼如下:

  1. // 表格數據渲染函數 
  2.         const tableDataRendering = function(res) { 
  3.           // 獲取最大子節點的key數量 
  4.             let maxChildLength = Object.keys(defaultData[0].children[0]).length; 
  5.             for (let i = 0; i < defaultData.length; i++) { 
  6.                 for (let j = 0; j < defaultData[i].children.length; j++) { 
  7.                     const currentObjLength = Object.keys(defaultData[i].children[j]).length; 
  8.                     if (currentObjLength > maxChildLength) { 
  9.                         maxChildLength = currentObjLength; 
  10.                     } 
  11.                 } 
  12.             } 
  13.  
  14.             // 補齊缺少的節點 
  15.             for (let i = 0; i < defaultData.length; i++) { 
  16.                 for (let j = 0; j < defaultData[i].children.length; j++) { 
  17.                     const currentObjLength = Object.keys(defaultData[i].children[j]).length; 
  18.                     // 當前節點的長度小于第一個子節點的長度就補齊 
  19.                     for (let k = currentObjLength; k < maxChildLength; k++) { 
  20.                         defaultData[i].children[j]["rcnr" + k] = {}; 
  21.                     } 
  22.                 } 
  23.             } 
  24.  
  25.             // 如果存在空對象添加位置字段 
  26.             for (let i = 0; i < defaultData.length; i++) { 
  27.                 for (let j = 0; j < defaultData[i].children.length; j++) { 
  28.                     // 獲取每天的時間段對象 
  29.                     const item = defaultData[i].children[j]; 
  30.                     // 獲取所有的key 
  31.                     const keys = Object.keys(item); 
  32.                     // 提取所有的日程字段 
  33.                     for (let k = 1; k < keys.length; k++) { 
  34.                         // 日程為空添加wz字段 
  35.                         if (Object.keys(item[keys[k]]).length <= 1) { 
  36.                             defaultData[i].children[j][keys[k]].wz = k - 1; 
  37.                         } 
  38.                     } 
  39.                 } 
  40.             } 
  41.         } 

監聽子窗口關閉

但點擊單元格做完對應的操作后,彈窗關閉,此時我們需要在當前頁面監聽到子窗口關閉,然后向后臺請求接口重新獲取數據渲染頁面,在打開的彈窗中提供了一個方法,可以調用父頁面的方法,但是這個方法必須寫在hooks外面他才能獲取到。

此時,問題就產生了,如果寫在hooks外面,那么就無法拿到antd表格內部的數據做到頁面重新渲染,經過一番思考后,想到了可以Proxy來實現,當被代理的對象發生改變時,就觸發hooks里的代理函數,實現代碼如下:

  1. <script type="text/babel"
  2.       // 聲明代理變量 
  3.     let pageStateEngineer; 
  4.     // 需要進行代理的對象 
  5.     let pageState = { status: false }; 
  6.     // 監聽子頁面關閉,彈窗頁面在關閉時可調用這個方法,觸發頁面刷新 
  7.     const getSubpageData = (status) => { 
  8.         console.log("子頁面關閉"); 
  9.         pageStateEngineer.status = true
  10.     }; 
  11.     const App = () => { 
  12.         // 代理處理函數 
  13.         const pageStateHandler = { 
  14.             setfunction(recObj, key, value) { 
  15.                 // 表格狀態改為正在加載 
  16.                 setTableLoadingStatus(true); 
  17.                 // 重新請求接口,獲取最新數據 
  18.                 axios.post('http://mock-api.com/mnE66LKJ.mock/getTableListData', { 
  19.                 }).then(function(res) { 
  20.                     // 數據請求成功,改變表格加載層狀態 
  21.                     setTableLoadingStatus(false); 
  22.                     if (res.status === 200) { 
  23.                         // 執行表格數據渲染函數 
  24.                         tableDataRendering(res); 
  25.                     } else { 
  26.                         alert("服務器錯誤"); 
  27.                     } 
  28.                 }); 
  29.                 // 修改對象屬性 
  30.                 recObj[key] = value; 
  31.                 return true
  32.             } 
  33.         }; 
  34.          
  35.         // 第一次渲染時,在借口調用成功后創建proxy 
  36.         React.useEffect(() => { 
  37.             // 調用接口獲取表格數據 
  38.             axios.post('http://mock-api.com/mnE66LKJ.mock/getTableListData', { 
  39.                 ls: 0, 
  40.                 ts: 0 
  41.             }).then(function(res) { 
  42.                 //創建代理,監聽pageState對象改變,pageStateHandler處理變更 
  43.                 pageStateEngineer = new Proxy(pageState, pageStateHandler); 
  44.             }) 
  45.         } 
  46.     } 
  47. </script> 

 

重新渲染表格

用戶在使用日程表時,他會執行刪除某個日程,此時表格渲染函數就要從columns和dataSource中各刪除一條數據了,一開始我是直接覆蓋其數據,這樣做引用地址沒變,就引發了動態增加列的那個bug,antd監聽不到引用地址改變沒有刷新頁面。但是我又不知道用戶具體刪了哪條數據,不好自己寫函數去處理。

經過一番求助后,得到了三個解決方案:

  • 使用immer來解決這個問題,經過折騰后還是沒實現,他返回的數組是只讀的,antd無法對數據進行操作,故放棄。
  • 使用use-immer來替代React的useState來解決這個問題,這個就比較坑爹了,官方提供了umd的js庫,但是通過cdn引入進來后,我硬是沒找到它暴露出來的對象是哪個,沒法用,故放棄。
  • 使用lodash的cloneDeep方法進行深拷貝讓其引用地址改變,這樣antd就能監聽到數據改變,從而觸發頁面刷新。

三個解決方案,經過驗證后,只有第三個是可行的,于是我采取了它,實現代碼如下:

  1. const App = () => { 
  2.         // 表格列格式定義 
  3.         const defaultColumns = [ 
  4.             { 
  5.                 dataIndex: "rq"
  6.                 title: "日期"
  7.                 align: "center"
  8.                 fixed: "left"
  9.                 colSpan: 2, 
  10.                 width: 140.5, 
  11.                 className: "rqfontSet"
  12.                 onCell: dateHandle, 
  13.                 render: (value, item, index) => {} 
  14.             }, 
  15.             { 
  16.                 dataIndex: "sjd"
  17.                 title: "時間段"
  18.                 width: 70, 
  19.                 colSpan: 0, 
  20.                 fixed: "left"
  21.                 align: "center"
  22.                 className: "sjdfontSet"
  23.                 render: (value, item, index) => { 
  24.                     let v1 = value.charAt(0); 
  25.                     let v2 = value.charAt(1); 
  26.                     return <div>{v1}<br />{v2}</div>; 
  27.                 } 
  28.             } 
  29.         ]; 
  30.  
  31.         // 表格數據渲染函數 
  32.         const tableDataRendering = function(res) { 
  33.           // 根據日程列字段數據賦值表格列的日程字段,rcList中包含sjd所以需要1開始 
  34.             for (let i = 1; i < rcList.length; i++) { 
  35.                 let rcnr = { 
  36.                     dataIndex: rcList[i], 
  37.                     title: "日程內容" + i, 
  38.                     align: "left"
  39.                     width: 189.5, 
  40.                     className: "rcnrfontSet"
  41.                     onCell: tdSet, 
  42.                     render: rctd_render 
  43.                 }; 
  44.                 defaultColumns.push(rcnr); 
  45.             } 
  46.  
  47.             // 渲染表格數據 
  48.             handleData(defaultData); 
  49.             // 渲染表格列,使用cloneDeep進行深拷貝,觸發useState的更新 
  50.             setColumns(_.cloneDeep(defaultColumns)); 
  51.         } 
  52.      // 計算要合并的列數 
  53.         const handleData = (data) => { 
  54.             if (data == null) { 
  55.                 data = defaultData; 
  56.             } 
  57.             let newArr = []; 
  58.             data.map(item => { 
  59.                 if (item.children) { 
  60.                     item.children.forEach((subItem, i) => { 
  61.                         let obj = { ...item }; 
  62.                         Object.assign(obj, subItem); 
  63.                         delete obj.children; 
  64.                         obj.rowLength = item.children.length; 
  65.                         newArr.push(obj); 
  66.                     }); 
  67.                 } 
  68.             }); 
  69.             // console.log("處理好的表格數據"); 
  70.             // console.log(newArr); 
  71.             // 將處理好的數據放入optRecords,使用cloneDeep進行深拷貝,觸發useState的更新 
  72.             setOptRecords(_.cloneDeep(newArr)); 
  73.         }; 
  74.   } 

還有一種解決方案是使用JSON.parse進行深拷貝,但是這種深拷貝有個問題:但json數據中有函數時,里面的函數會失效沒法執行,由于我需要自定義antd的表格,在json數據中包含了函數,因此我不能使用這個方法。

觸頂/觸底加載數據

由于業務需要,不能使用antd的分頁功能,需要實現觸頂向前加載30條數據,觸底向后加載30條數據??偣仓荒芗虞d3個月的數據。

實現代碼如下:

 

這里需要比較坑的地方就是如果觸頂/觸底時,拖動橫向滾動也會觸發滾動監聽,因此我們需要排除橫向滾動事件。

  1. <script type="text/babel"
  2.     // 觸頂數據起始條數 
  3.     let dataToppingStartNum = 0; 
  4.     // 觸底數據起始條數 
  5.     let dataBottomOutStartNum = 30; 
  6.     // 橫向/垂直滾動條起始位置 
  7.     let levelPosition; 
  8.     let verticalPosition; 
  9.     // 觸底/觸頂次數 
  10.     let topFrequency = 0; 
  11.     let bottomFrequency = 0; 
  12.     const App = () => { 
  13.         // 橫向滾動條位置 
  14.         levelPosition = document.querySelector(".ant-table-body").scrollLeft; 
  15.         // 縱向滾動條位置 
  16.         verticalPosition = document.querySelector(".ant-table-body").scrollTop; 
  17.         // 獲取表格容器 
  18.         let antdTable = document.querySelector(".ant-table-body"); 
  19.         //頁面滾動監聽 
  20.         antdTable.onscroll = function() { 
  21.             // 觸底向后加載數據 
  22.             if (antdTable.scrollTop + antdTable.clientHeight >= antdTable.scrollHeight) { 
  23.                 // 判斷是否橫向滾動 
  24.                 if (antdTable.scrollLeft !== levelPosition) { 
  25.                     // 更新位置 
  26.                     levelPosition = antdTable.scrollLeft; 
  27.                     return false
  28.                 } 
  29.                 // 第一次觸底不觸發數據加載 
  30.                 if (bottomFrequency === 0) { 
  31.                     bottomFrequency++; 
  32.                     return false
  33.                 } 
  34.                 if (bottomFrequency > 0) { 
  35.                     bottomFrequency = 0; 
  36.                 } 
  37.                 dataBottomOutStartNum += 30; 
  38.                 // 判斷已加載的數據 
  39.                 if (dataBottomOutStartNum > 90) { 
  40.                     alert("最多只能向后加載90天的數據"); 
  41.                     return false
  42.                 } 
  43.                 // 保留向上滑動的天數 
  44.                 let bottomTS = 0; 
  45.                 // 頁面第一次向上滑動,修改位置 
  46.                 if (dataToppingStartNum !== 0) { 
  47.                     bottomTS = -30; 
  48.                 } 
  49.                 setTableLoadingStatus(true); 
  50.                 axios.post('http://mock-api.com/mnE66LKJ.mock/getTableListData', { 
  51.                     ts: bottomTS, 
  52.                     ls: dataBottomOutStartNum 
  53.                 }).then(function(res) { 
  54.                     // 數據請求成功,改變表格加載層狀態 
  55.                     setTableLoadingStatus(false); 
  56.                     if (res.status === 200) { 
  57.                         // 執行表格數據渲染函數 
  58.                         tableDataRendering(res); 
  59.                     } else { 
  60.                         alert("服務器錯誤"); 
  61.                     } 
  62.                 }); 
  63.             } 
  64.  
  65.             // 觸頂向前加載數據 
  66.             if (antdTable.scrollTop === 0) { 
  67.                 // 判斷是否橫向滾動 
  68.                 if (antdTable.scrollLeft !== levelPosition) { 
  69.                     // 更新位置 
  70.                     levelPosition = antdTable.scrollLeft; 
  71.                     return false
  72.                 } 
  73.                 // 第一次觸頂不觸發數據加載 
  74.                 if (topFrequency === 0) { 
  75.                     topFrequency++; 
  76.                     return false
  77.                 } 
  78.                 if (topFrequency > 0) { 
  79.                     topFrequency = 0; 
  80.                 } 
  81.                 dataBottomOutStartNum += 30; 
  82.                 if (dataBottomOutStartNum > 90) { 
  83.                     alert("最多只能向前加載90天的數據"); 
  84.                     return false
  85.                 } 
  86.                 dataToppingStartNum -= 30; 
  87.                 setTableLoadingStatus(true); 
  88.                 axios.post('http://mock-api.com/mnE66LKJ.mock/getTableListData', { 
  89.                     ts: dataToppingStartNum, 
  90.                     ls: dataBottomOutStartNum 
  91.                 }).then(function(res) { 
  92.                     // 數據請求成功,改變表格加載層狀態 
  93.                     setTableLoadingStatus(false); 
  94.                     if (res.status === 200) { 
  95.                         // 執行表格數據渲染函數 
  96.                         tableDataRendering(res); 
  97.                     } else { 
  98.                         alert("服務器錯誤"); 
  99.                     } 
  100.                 }); 
  101.             } 
  102.         } 
  103.     } 
  104. </script> 

這里需要比較坑的地方就是如果觸頂/觸底時,拖動橫向滾動也會觸發滾動監聽,因此我們需要排除橫向滾動事件。

責任編輯:武曉燕 來源: 神奇的程序員k
相關推薦

2013-05-03 09:27:36

Ubuntu 13.1

2011-03-17 13:09:45

Ubuntu 11.1

2009-12-16 10:41:47

Android日程表

2009-09-29 13:32:40

Ubuntu 9.10Linux操作系統發布日程表

2009-03-05 08:30:57

LinuxUbuntu日程表

2013-09-09 15:38:13

Fedora 20Fedora操作系統

2021-03-21 20:23:07

樹莓派Linux

2009-03-23 07:36:43

Ubuntu 9.10win7正式版

2017-03-16 14:01:00

2011-06-02 09:58:09

CentOS 6.0

2015-10-29 11:36:45

Google技術經理程序員

2010-04-07 11:44:40

Ubuntu 10.1

2022-09-22 12:38:46

antd form組件代碼

2025-03-24 00:00:00

2009-12-21 17:53:45

Fedora Core

2015-05-11 17:21:33

Google IO2015

2022-07-06 08:29:12

antdInput 組件

2021-05-12 09:07:09

Java數據結構算法

2011-06-16 09:25:17

Firefox 5.0

2009-12-15 14:05:42

Fedora Core
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 欧美爱爱视频 | 少妇一级淫片免费播放 | 国产高清免费在线 | 男女免费观看在线爽爽爽视频 | 亚洲国产高清在线 | 黄色大片在线免费观看 | 国产成人久久精品 | 国产精品网址 | 久久精品视频网站 | 日日干夜夜干 | 精品国产一区二区国模嫣然 | 国产亚洲精品久久情网 | 亚洲区一区二区 | 天天干天天爽 | 免费人成激情视频在线观看冫 | 久久久久资源 | av日韩精品| 黄网站免费在线观看 | www.日本在线观看 | 九九综合| 亚洲成人精品 | 日本天堂视频 | 在线观看中文视频 | 99精品久久久久久中文字幕 | 在线第一页 | 黄色片网站在线观看 | 激情影院久久 | 美国一级片在线观看 | a黄视频| 国产二区在线播放 | avhd101在线成人播放 | av性色全交蜜桃成熟时 | 日韩精品在线网站 | 日韩成人在线网址 | 无码一区二区三区视频 | 久久久久亚洲精品国产 | 久久伊人在 | 亚洲国产一区二区在线 | 日日夜精品视频 | 亚洲精品一区中文字幕乱码 | 大象视频一区二区 |