<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    duansky'weblog

    統計

    留言簿(3)

    友情鏈接

    閱讀排行榜

    評論排行榜

    ExtJS專題-TreePanel(1)

    這次我們來學習下ExtJS中的樹面板(TreePanel),很多人都說,只是為了樹,都要好好學習ExtJS!可見大家對Tree的一往情深。從另一方面來說,Tree這種結構在實際項目中也的確用得相當廣泛,所以我們很有必要研究一下它。這次我們完成的樹大致上有這樣的功能:它的節點是動態異步從后臺(存儲在數據庫中一張電子產品分類表)加載的,節點之間可以拖曳,節點可以編輯,同時還支持右鍵菜單,而且,它能夠和TabPanel結合構成經典的布局方式。呵呵,是不是很強大?!大家已經看到,我們組件的講解是逐步遞推的,所以我們這里也會用到剛學過的GridPanel和TabPanel這些實用的面板。我們看效果先:

    ?

    ?

    ?

    好啦,洪哥,我們動手吧!

    ?

    1.????? 首先還是主要的顯示頁面tree.html,這里有兩個地方要注意一下,一個是我們引用的JS如果采用GBK的默認編碼,瀏覽器會顯示未結束的字符串常量的錯誤,所以我們一般會修改JS文件的編碼方式為UTF-8,或者在導入JS時加上編碼字符集。第二個是我們要定義一個顯示TreePanel的DIV。

    ?

    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "

    <html>

    <head>

    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

    <title>Insert title here</title>

    <link rel="stylesheet" type="text/css" href="resources/css/ext-all.css" />

    <script type="text/javascript" src="resources/js/ext-base.js"></script>

    <script type="text/javascript" src="resources/js/ext-all.js"></script>

    <script type="text/javascript" src="resources/js/tree.js" charset="gbk"></script>

    </head>

    <body>

    <div id="tree-panel" style="overflow:auto; height:300px;width:200px;border:2px solid #c3daf9;"></div>

    </body>

    </html>

    ?

    2.????? 然后是我們的主體JS文件,tree.js,為了凸顯主題,這個我已經做了必要的簡化,還做了詳細的注釋,大家好好看一下。

    ?

    Ext.onReady(function() {

    ??? Ext.QuickTips.init();// 浮動信息提示

    ??? Ext.BLANK_IMAGE_URL = 'resources/images/default/s.gif';// 替換圖片文件地址為本地

    ?

    ??? // 創建一個簡寫

    ??? var Tree = Ext.tree;

    ??? // 定義根節點的Loader

    ??? var treeloader = new Tree.TreeLoader({

    ??????????? // dataUrl : 'tree.jsp'//這里可以不需要指定URL,在加載前事件響應里面設置

    ??????????? });

    ?

    ??? // 添加一個樹形面板

    ??? var treepanel = new Tree.TreePanel({

    ??????? // renderTo:"tree_div",//如果使用renderTo,則不能使用setRootNode()方法,需要在TreePanel中設置root屬性。

    ??????? el : 'tree-panel',// 將樹形添加到一個指定的div中,非常重要!

    ??????? region : 'west',

    ??????? title : '功能菜單',

    ??????? width : 200,

    ??????? minSize : 180,

    ??????? maxSize : 250,

    ??????? split : true,

    ??????? autoHeight : false,

    ??????? frame : true,// 美化界面

    ??????? // width : 200,//面板寬度

    ??????? // title : '可編輯和拖動的異步樹',//標題

    ??????? // autoScroll : true, // 自動滾動

    ??????? enableDD : true,// 是否支持拖拽效果

    ??????? containerScroll : true,// 是否支持滾動條

    ??????? rootVisible : true, // 是否隱藏根節點,很多情況下,我們選擇隱藏根節點增加美觀性

    ??????? border : true, // 邊框

    ??????? animate : true, // 動畫效果

    ??????? loader : treeloader

    ??????????? // 樹加載

    ??????? });

    ??? // 異步加載根節點

    ??? var rootnode = new Tree.AsyncTreeNode({

    ??????????????? id : '0',

    ??????????????? text : '家電品牌總類',

    ??????????????? draggable : false,// 根節點不容許拖動

    ??????????????? expanded : true

    ??????????? });

    ?

    ??? // 為tree設置根節點

    ??? treepanel.setRootNode(rootnode);

    ?

    ??? // 響應加載前事件,傳遞node參數

    ??? treepanel.on('beforeload', function(node) {

    ??????????????? treepanel.loader.dataUrl = 'tree.jsp?parentId=' + node.id; // 定義子節點的Loader

    ??????????? });

    ??? // 渲染樹形

    ??? treepanel.render();

    ??? // 展開節點,第一個參數表示是否級聯展開子節點

    ??? rootnode.expand(true);

    ?

    ??? // 設置樹的點擊事件

    ??? function treeClick(node, e) {

    ??????? if (node.isLeaf()) {

    ??????????? e.stopEvent();

    ??????????? var n = contentPanel.getComponent(node.id);

    ??????????? if (!n) {

    ??????????????? var n = contentPanel.add({

    ??????????????????????????? 'id' : node.id,

    ??????????????????????????? 'title' : node.text,

    ??????????????????????????? closable : true,

    ??????????????????????????? autoLoad : {

    ??????????????????????????????? url : 'tabFrame.jsp?url=grid.html',

    ??????????????????????????????? scripts : true

    ??????????????????????????? } // 通過autoLoad屬性載入目標頁,如果要用到腳本,必須加上scripts屬性

    ??????????????????????? });

    ??????????? }

    ??????????? contentPanel.setActiveTab(n);

    ??????? }

    ??? }

    ??? // 增加鼠標單擊事件

    ??? treepanel.on('click', treeClick);

    ?

    ??? // 定義右鍵菜單

    ??? var rightClick = new Ext.menu.Menu({

    ??????????????? id : 'rightClickCont',

    ??????????????? items : [{

    ??????????????????????????? id : 'rMenu1',

    ??????????????????????????? text : '添加節點',

    ??????????????????????????? // 增加菜單點擊事件

    ??????????????????????????? handler : function() {

    ??????????????????????????????? alert('添加節點的實現!');

    ??????????????????????????? }

    ??????????????????????? }, {

    ??????????????????????????? id : 'rMenu2',

    ??????????????????????????? text : '編輯節點'

    ??????????????????????? }, {

    ??????????????????????????? id : 'rMenu3',

    ??????????????????????????? text : '刪除節點'

    ??????????????????????? }]

    ??????????? });

    ??? // 增加右鍵點擊事件

    ??? treepanel.on('contextmenu', function(node, event) {// 聲明菜單類型

    ??????????????? event.preventDefault();// 阻止瀏覽器默認右鍵菜單顯示

    ??????????????? rightClick.showAt(event.getXY());// 取得鼠標點擊坐標,展示菜單

    ??????????? });

    ?

    ??? /*

    ???? * 設置tree的節點放置函數此函數有一個很重要的參數對象e e對象有三個重要的屬性,分別為dropNode,target,point

    ???? * 1.dropNode為在拖動時鼠標抓住的節點 2.target為將要放置在某處的節點

    ???? * 3.point為被放置的狀態,分別有append表示添加,above節點的上方,below節點的下方。

    ???? *

    ???? */

    ??? treepanel.on('nodedrop', function(e) {

    ?

    ??????????????? if (e.point == 'append') {

    ??????????????????? alert('當前"' + e.dropNode.text + '"劃到"' + e.target.text

    ??????????????????????????? + '"里面!');

    ??????????????? } else if (e.point == 'above') {

    ??????????????????? alert('當前"' + e.dropNode.text + '"放在了"' + e.target.text

    ??????????????????????????? + '"上面!');

    ??????????????? } else if (e.point == 'below') {

    ??????????????????? alert('當前"' + e.dropNode.text + '"放在了"' + e.target.text

    ??????????????????????????? + '"下面!');

    ??????????????? }

    ??????????? });

    ?

    ??? // 在原有的樹形添加一個TreeEditor

    ??? var treeEditer = new Tree.TreeEditor(treepanel, {

    ??????????????? allowBlank : false

    ??????????? });

    ??? /*

    ???? * 為創建的treeEditer添加事件 有兩個事件最為常用,一個為beforestartedit另一個為complete

    ???? * 從名字就可以看出,beforestartedit事件是在編輯前的事件,因此可以通過它來判斷那些節點可以編輯那些不可以。

    ???? * complete為編輯之后的事件,在這里面可以添加很多事件,比如添加一個Ext.Ajax向后臺傳送修改的值等等。

    ???? */

    ??? treeEditer.on("beforestartedit", function(treeEditer) {

    ??????????????? var tempNode = treeEditer.editNode;// 將要編輯的節點

    ??????????????? if (tempNode.isLeaf()) {// 這里設定葉子節點才容許編輯

    ??????????????????? return true;

    ??????????????? } else {

    ??????????????????? return false;

    ??????????????? }

    ??????????? });

    ?

    ??? treeEditer.on("complete", function(treeEditer) {

    ??????????????? alert("被修改為" + treeEditer.editNode.text);

    ??????????? });

    ?

    ??? // (1)通過TabPanel控件的html屬性配合<iframe>實現。該方法是利用

    ??? // html屬性中包含<iframe>的語法來調用另一個頁面,具體見代碼。

    ??? // (2)通過TabPanel控件的autoLoad屬性實現。該方法是利用autoLoad屬性,它有很多參數,

    ??? // 其中有兩個比較重要,url表示要載入的文件,scripts表示載入的文件是否含有腳本,該屬性相當重要,

    ??? // 如果在新的頁面中要創建Ext控件,必須指定該參數。該方法實現較前一個復雜,因為引入的文件不是一個完整的html文件,

    ??? // 有可能只是內容的一部分,但是資源占用較少,而且載入速度較快(它有一個載入指示)

    ?

    ??? // 添加第一個節點(html)

    ??? treepanel.root.appendChild(new Ext.tree.TreeNode({

    ??????? id : 'htmlPanel',

    ??????? text : '通過html打開',

    ??????? listeners : {

    ??????????? 'click' : function(node, event) {

    ??????????????? event.stopEvent();

    ??????????????? var n = contentPanel.getComponent(node.id);

    ??????????????? if (!n) { // 判斷是否已經打開該面板

    ??????????????????? n = contentPanel.add({

    ??????????????????????? 'id' : node.id,

    ??????????????????????? 'title' : node.text,

    ??????????????????????? closable : true, // 通過html載入目標頁

    ??????????????????????? html : '<iframe scrolling="auto" frameborder="0" width="100%" height="100%" src="grid.html"></iframe>'

    ??????????????????? });

    ??????????????? }

    ??????????????? contentPanel.setActiveTab(n);

    ??????????? }

    ??????? }

    ??? }));

    ?

    ??? // 添加第二個節點(autoLoad)

    ??? treepanel.root.appendChild(new Ext.tree.TreeNode({

    ??????????????? id : 'autoLoadPanel',

    ??????????????? text : '通過autoLoad打開',

    ??????????????? listeners : {

    ??????????????????? 'click' : function(node, event) {

    ??????????????????????? event.stopEvent();

    ??????????????????????? var n = contentPanel.getComponent(node.id);

    ??????????????????????? if (!n) { // //判斷是否已經打開該面板

    ??????????????????????????? n = contentPanel.add({

    ??????????????????????????????????????? 'id' : node.id,

    ??????????????????????????????????????? 'title' : node.text,

    ??????????????????????????????????????? closable : true,

    ??????????????????????????????????????? autoLoad : {

    ??????????????????????????????????????????? url : 'tabFrame.jsp?url=grid.html',

    ??????????????????????????????????????????? scripts : true

    ??????????????????????????????????????? } // 通過autoLoad屬性載入目標頁,如果要用到腳本,必須加上scripts屬性

    ??????????????????????????????????? });

    ??????????????????????? }

    ??????????????????????? contentPanel.setActiveTab(n);

    ??????????????????? }

    ??????????????? }

    ??????????? }));

    ?

    ??? // 右邊具體功能面板區

    ??? var contentPanel = new Ext.TabPanel({

    ??????? region : 'center',

    ??????? enableTabScroll : true,

    ??????? activeTab : 0,

    ??????? items : [{

    ??????????? id : 'homePage',

    ??????????? title : '首頁',

    ??????????? autoScroll : true,

    ??????????? html : '<div style="position:absolute;color:#ff0000;top:40%;left:40%;">Tree控件和TabPanel控件結合功能演示</div>'

    ??????? }]

    ??? });

    ?

    ??? new Ext.Viewport({

    ??????????????? layout : 'border', // 使用border布局

    ??????????????? defaults : {

    ??????????????????? activeItem : 0

    ??????????????? },

    ??????????????? items : [treepanel, contentPanel]

    ??????????? });

    ?

    });

    ?

    3.?? 再接著是tree.js中ExtJS的TreeLoader調用的tree.jsp,在目錄樹上點擊TreeNode后會加載下一級節點。tree.jsp負責TreeNode點擊后,傳回由下一級節點構造的JSON數據,也就是前臺樹異步請求訪問的后臺WEB組件。它會調用JAVABEAN操作數據庫,得到每個節點的子節點數據。這里由于我們后臺需要返回給客戶端JSON格式的數據,也就是需要操作JSON數據格式。所以我們首先要下載JSON-lib,地址:http://json-lib.sourceforge.net/打開網址后,首頁上有一段話:
    ?Json-lib requires (at least) the following dependencies in your classpath:
    ????? jakarta commons-lang 2.3
    ????? jakarta commons-beanutils 1.7.0
    ????? jakarta commons-collections 3.2
    ????? jakarta commons-logging 1.1.1
    ????? ezmorph 1.0.4
    ?? 需要下載上述jar文件,配合JSON-lib 一起使用。
    ?? commons 下載地址:http://commons.apache.org/
    ?? ezmorph 下載地址:http://ezmorph.sourceforge.net
    ?? 或者,到 http://www.docjar.com 搜索下載。
    ?? JSON的用法,我們已經提過多次,大家可參考相關文檔。看看tree.jsp的代碼:

    ?

    <%@ page language="java" pageEncoding="utf-8"%>

    <jsp:useBean class="org.leno.javabean.JSONTree" id="JSONTree"></jsp:useBean>

    <%

    ??? String parentId = "";

    ??? if (request.getParameter("parentId") != null) {

    ??????? parentId = request.getParameter("parentId").toString();

    ??? }

    ??? JSONTree.setparentId(parentId);

    %>

    <%=JSONTree.getJSONString()%>

    ?

    4.?????? 后臺用到的JAVA類,這里包括訪問數據庫的數據源工廠類DataSourceFactory(這里用到了DBCP連接池,大家要記得導入連接sqlserver 2000數據庫和dbcp連接池的相關JAR包!),定義樹節點的屬性,包括節點ID、Text、圖標、是否為葉子節點、是否展開等的類JSONTreeNode,還有類似DAO能夠封裝數據訪問和格式轉換細節的JSONTree。

    ?

    package org.leno.javabean;

    ?

    import java.sql.SQLException;

    import org.apache.commons.dbcp.BasicDataSource;

    ?

    public class DataSourceFactory {

    ?

    ??? /**

    ???? * @param args

    ???? */

    ??? private static BasicDataSource ds;

    ?

    ??? public static BasicDataSource getDataSource() {

    ??????? if (ds == null) {

    ??????????? ds = new BasicDataSource();

    ??????????? ds.setDriverClassName("com.microsoft.jdbc.sqlserver.SQLServerDriver");

    ??????????? ds.setUrl("jdbc:microsoft:sqlserver://localhost:1433;DatabaseName=java28");

    ??????????? ds.setUsername("sa");

    ??????????? ds.setPassword("123");

    ??????????? ds.setMaxActive(5);

    ??????? }

    ??????? return ds;

    ?

    ??? }

    ?

    ??? public static void main(String[] args) {

    ??????? // TODO Auto-generated method stub

    ??????? try {

    ??????????? System.out.println(DataSourceFactory.getDataSource()

    ??????????????????? .getConnection());

    ??????? } catch (SQLException e) {

    ??????????? // TODO Auto-generated catch block

    ??????????? e.printStackTrace();

    ??????? }

    ?

    ??? }

    ?

    }

    package org.leno.javabean;

    ?

    /**

    ?* @author leno

    ?*定義樹節點的屬性,包括節點ID、Text、圖標、是否為葉子節點、是否展開等。

    ?*/

    public class JSONTreeNode {

    ?

    ??????? private String id;??????????? //ID

    ???????? private String text;????????? //節點顯示

    ???????? private String cls;?????????? //圖標

    ???????? private boolean leaf;???????? //是否葉子

    ???????? private String href;????????? //鏈接

    ???????? private String hrefTarget;??? //鏈接指向

    ???????? private boolean expandable;?? //是否展開

    ???????? private String description;?? //描述信息

    ????????

    ??????? get/set……

    }

    package org.leno.javabean;

    ?

    import java.sql.*;

    import java.util.*;

    import net.sf.json.JSONArray;

    ?

    public class JSONTree {

    private String parentId;

    ???

    ??? public String getJSONString(){?????

    ??????? Connection con =null;

    ??????? Statement st = null;

    ??????? ResultSet rs = null;

    ??????? List<JSONTreeNode> treeNodeArray = null;

    ???????

    ??????? String SQLString = "SELECT * FROM Categories WHERE parentId="+this.parentId+" ORDER BY categoryId";???

    ???????????

    ??????? try

    ??????? {

    ??????????? con = DataSourceFactory.getDataSource().getConnection();

    ??????????? st = con.createStatement();

    ??????????? //查找所有擁有下級類別的類別ID

    ??????????? rs = st.executeQuery("SELECT parentId FROM Categories WHERE parentId>0 Group By parentId Order By parentId");???????????

    ???????????

    ??????????? StringBuffer parentIDBuffer =new StringBuffer();

    ??????????? parentIDBuffer.append("|");????????

    ??????????? while(rs.next())

    ??????????? {

    ??????????????? parentIDBuffer.append(rs.getString("parentId"));

    ??????????????? parentIDBuffer.append("|");

    ??????????? }

    ??????????? //得到所有的parentcategoryId列表

    ??????????? String parentIDString = parentIDBuffer.toString();????????

    ???????????

    ??????????? rs = st.executeQuery(SQLString);???

    ??????????? treeNodeArray = new ArrayList<JSONTreeNode>();

    ??????????? while(rs.next())

    ??????????? {

    ??????????????? JSONTreeNode treeNode = new JSONTreeNode();

    ??????????????? String categoryId = rs.getString("categoryId");

    ??????????????? treeNode.setId(categoryId);

    ??????????????? treeNode.setText(rs.getString("categoryName"));

    ??????????????? treeNode.setDescription(rs.getString("description"));?????????

    //??????????????????? treeNode.setHref("rightframe.jsp?categoryId="

    //????????????????????? + rs.getString("categoryId").toString());

    //??????????????????? treeNode.setHrefTarget("rightFrame");??????????????

    ???????????????

    ??????????????? if (parentIDString.indexOf("|"+categoryId+"|")>=0) //父節點

    ??????????????????? {

    ??????????????????????? treeNode.setCls("folder");

    ??????????????????????? treeNode.setLeaf(false);

    ??????????????????????? treeNode.setExpandable(false);

    ??????????????????? }

    ??????????????????? else //子節點

    ?????????????????? {

    ??????????????????????? treeNode.setCls("file");

    ??????????????????????? treeNode.setLeaf(true);

    ??????????????????????? treeNode.setExpandable(false);

    ??????????????????? }

    ??????????????????? treeNodeArray.add(treeNode);

    ??????????? }

    ???????????

    ??????????? JSONArray JsonArray = JSONArray.fromObject(treeNodeArray); //得到JSON數組????

    ?

    ??????????? return JsonArray.toString();//返回JSON數據

    ??????? }

    ??????? catch(Exception e)

    ??????? {

    ??????????? System.out.println("getJSONString() of JSONTree.java throws : "+e.toString());

    ??????????? return "";

    ??????? }

    ??????? finally

    ??????? {

    ?????????? try {

    ?????????? if(con!=null&&!con.isClosed()){

    ??????????????? con.close();

    ?????????? }

    ??????? } catch (SQLException e) {

    ??????????? // TODO Auto-generated catch block

    ??????????? e.printStackTrace();

    ??????? }

    ??????? }

    ??? }??

    ?

    ?

    ??? public String getparentId() {

    ??????? return parentId;

    ??? }

    ?

    ??? public void setparentId(String parentId) {

    ??????? this.parentId = parentId;

    ??? }

    ?

    }

    ?

    5.????? 最后是我們的數據庫腳本script.sql,大家用SQLServer 2000數據庫創建一個java28的database,然后執行下列腳本即可。

    ?

    create table Categories

    (

    ??? categoryId int identity(1,1) primary key,

    ??? categoryName varchar(30),

    ??? description varchar(100),

    ??? parentId int

    )

    insert into Categories values('電腦','關于電腦',0);

    insert into Categories values('電視機','關于電視機',0);

    insert into Categories values('數碼相機','關于數碼相機',0);

    insert into Categories values('冰箱','關于冰箱',0);

    insert into Categories values('聯想電腦','關于聯想電腦',1);

    insert into Categories values('創維電視機','關于創維電視機',2);

    insert into Categories values('索尼相機','關于索尼相機',3);

    insert into Categories values('海爾冰箱','關于海爾冰箱',4);

    ?

    insert into Categories values('旭日電腦','關于旭日電腦',5);

    insert into Categories values('天逸電腦','關于天逸電腦',5);

    insert into Categories values('創維液晶電視','關于創維液晶電視機',6);

    insert into Categories values('索尼M23相機','關于索尼M23相機',7);

    insert into Categories values('海爾G1冰箱','關于海爾G1冰箱',8);

    ?

    select * from Categories

    SELECT parentId FROM Categories WHERE parentId>0 Group By parentId Order By parentId

    ?

    可能有人對ExtJS中樹的節點屬性不是很了解,所以我們要啰嗦一下。ExtJS只要求返回的數據格式類似下面這樣即可:
    [{'text':'welcome.html','id':'welcome.html','cls':'file',myPara:'myValue'},
    {'text':'welcome2.html','id':'welcome2.html','leaf':true,'cls':'file','href':'welcome2.html'}]
    這些數據是存儲到一個數組中的,數組中的每一項代表一個節點,每一個節點都包含以下幾個主要屬性:
    text:定義該節點顯示的名稱;
    id:定義該節點的頁面ID,便于document.getElementById方法獲取該節點;
    leaf:true或者false,定義該節點是否是葉子節點;
    cls:定義該節點的class(顯示的樣式);
    href:定義點擊該節點后鏈接的頁面;
    另外你還可以為節點增加自定義的屬性,方法如上面的myPara:'myValue'一樣。ExtJS會自動將返回的數據解析成節點并正確顯示到頁面上。

    ?

    好啦,今天我們TreePanel的學習就到這里,下次我們會學習FormPanel。祝愿大家學有所成。

    ?

    本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/lenotang/archive/2008/10/19/3102727.aspx

    posted on 2010-08-17 14:58 duansky 閱讀(4496) 評論(0)  編輯  收藏 所屬分類: Ext

    主站蜘蛛池模板: 亚洲国产精品自在线一区二区| 免费一级毛片一级毛片aa| 亚洲日产韩国一二三四区| 一级午夜a毛片免费视频| 免费一级毛片女人图片| 深夜A级毛片视频免费| 免费夜色污私人影院在线观看| 精品国产_亚洲人成在线| 日韩免费在线观看| 国产精品亚洲精品爽爽| 四虎影视永久免费观看地址| 久久综合亚洲色hezyo| 四虎精品亚洲一区二区三区| 日本一区二区在线免费观看| 区三区激情福利综合中文字幕在线一区亚洲视频1 | 999久久久免费精品播放| 亚洲精品国产成人99久久| a拍拍男女免费看全片| 亚洲国产日韩视频观看| 国精无码欧精品亚洲一区| 两个人看的www免费| 日韩精品一区二区亚洲AV观看| 114级毛片免费观看| 亚洲色欲色欱wwW在线| 四虎1515hm免费国产| 好吊色永久免费视频大全 | 亚洲裸男gv网站| 三级毛片在线免费观看| 久久精品国产亚洲av水果派| 最近免费中文字幕4| 一区二区免费国产在线观看| 亚洲AV无码码潮喷在线观看 | 国产一卡二卡≡卡四卡免费乱码| 一区二区视频在线免费观看| 夜夜亚洲天天久久| 在线不卡免费视频| a级成人毛片免费图片| 亚洲 日韩 色 图网站| 亚洲中文字幕无码一区| 永久免费的网站在线观看| 一区二区三区视频免费观看|