zoukankan      html  css  js  c++  java
  • 基于ArcGIS10.0和Oracle10g的空间数据管理平台八(C#开发)图层分类标准定义

        我的独立博客网址是:http://wuyouqiang.sinaapp.com/

        我的新浪微博:http://weibo.com/freshairbrucewoo

        欢迎大家相互交流,共同提高技术。

        本系统的分层按照“数据分类”、“要素类别”和“图层”进行组织管理。一个数据分类包含一个或多个要素类别,一个要素类别包含一个或多个图层。图层分层标准可以作为创建图库的数据集和要素类时的参考标准。

        数据分类和要素类别的定义是通过将用户提供的相关信息存储到数据库中,主要的信息有相应的名称、ID编号、描述等,存放要素类别的表还保存有数据分类的ID,这样就可以知道要素类别是属于哪一个数据分类了。数据分类和要素类别的管理就是管理存放这些数据的两种表,只需要对这两张表通过SQL语句进行相应的添加、删除和修改就实现了。

        图层标准的管理通过将用户定义的标准写入数据库,图层标准主要涉及到图层名称、图层映射的表名、图层中文名称、图层编号、图层描述等信息。图层还必须对应一张数据表来存放图层的数据,而这张表本身就是属于图层标准的一部分,所以在定义一个图层标准的同时还需要定义映射表的数据结构标准,定义这种表的信息会全部存储到另一张表中,这些信息在导入标准和创建图层的时候都可能用到,这些信息包括字段名称、字段类型、字段长度和字段约束等。

        “数据分类”、“要素类别”和“图层”之间关系如下图所示。

     

        下面根据代码来讲解具体每一个功能的详细实现。

    1.在Load函数中初始化根节点:用树形控件来表示数据分层管理的层次。

     1         ///<summary>
    2 /// 初始化根节点
    3 ///</summary>
    4 ///<param name="sender"></param>
    5 ///<param name="e"></param>
    6 private void FrmLayerManager_Load(object sender, EventArgs e)
    7 {
    8 Node n = new Node();
    9 n.Text = "数据分层管理";
    10 n.Image = Resources.category;
    11
    12 LayerManagerTree.Nodes.Add(n);
    13 n.Nodes.Add(new Node());
    14 }

    2.树形一个节点展开后的处理工作,就是从数据库中读取以后的下层节点,并在节点中显示。

     1         ///<summary>
    2 /// 树形控件的节点展开以后的处理,更新所有的子节点
    3 ///</summary>
    4 ///<param name="sender"></param>
    5 ///<param name="e"></param>
    6 private void LayerManagerTree_AfterExpand(object sender, AdvTreeNodeEventArgs e)
    7 {
    8 UpdateNode(e.Node);
    9 }
    10
    11 ///<summary>
    12 /// 更新tn节点的子节点信息
    13 ///</summary>
    14 ///<param name="tn"></param>
    15 private void UpdateNode(Node tn)
    16 {
    17 string sql;
    18 SqlHelper sh = new SqlHelper();
    19 OracleDataReader odr;
    20
    21 switch (tn.Level)
    22 {
    23 case 0:
    24 tn.Nodes.Clear();
    25 sql = "select name from category where name='数据标准'";
    26 odr = sh.ReturnDataReader(sql);
    27
    28 while (odr.Read())
    29 {
    30 Node n = new Node();
    31 n.Text = odr[0].ToString();
    32 n.Image = Resources.datastand;
    33 tn.Nodes.Add(n);
    34
    35 n.Nodes.Add(new Node());
    36 }
    37 break;
    38 case 1:
    39 tn.Nodes.Clear();
    40 sql = "select name from element where category='" + tn.Text + "'";
    41 odr = sh.ReturnDataReader(sql);
    42
    43 while (odr.Read())
    44 {
    45 Node n = new Node();
    46 n.Text = odr[0].ToString();
    47 n.Image = Resources.layer;
    48 tn.Nodes.Add(n);
    49
    50 n.Nodes.Add(new Node());
    51 }
    52 break;
    53 case 2:
    54 tn.Nodes.Clear();
    55 sql = "select table_name from layer l, jcsjk_element e where e.id = l.pid and e.name='"
    56 + tn.Text + "' and e.category='数据标准'";
    57 odr = sh.ReturnDataReader(sql);
    58
    59 while (odr.Read())
    60 {
    61 Node n = new Node();
    62 n.Text = odr[0].ToString();
    63
    64 tn.Nodes.Add(n);
    65 }
    66 break;
    67 default:
    68 break;
    69 }
    70 }

    3.当在树形控件中选择一个节点时,在右边控件中显示其具体定义。

     1         ///<summary>
    2 /// 选择树形控件的某一个节点,在右边的DataGridView控件中显示定义标准
    3 ///</summary>
    4 ///<param name="sender"></param>
    5 ///<param name="e"></param>
    6 private void LayerManagerTree_AfterNodeSelect(object sender, AdvTreeNodeEventArgs e)
    7 {
    8 Node n = new Node();
    9 n = e.Node;
    10 selectNodeText = n.Text;
    11
    12 UpdateTree(n.Level);
    13 }
    14
    15 ///<summary>
    16 /// 显示某一个标准的具体定义
    17 ///</summary>
    18 ///<param name="index"></param>
    19 private void UpdateTree(int index)
    20 {
    21 string sql = string.Empty;
    22 SqlHelper sh = new SqlHelper();
    23 DataSet ds;
    24
    25 switch (index)
    26 {
    27 case 1:
    28 sql = "select d.ID,TABLE_NAME,TABLE_MAPNAME,TYPE,d.DESCRIPTION from " +
    29 "layer d,element e,category c where d.pid=e.id" +
    30 " and category=c.name and c.name='" + selectNodeText + "'";
    31
    32 break;
    33 case 2:
    34 sql = "select l.ID,TABLE_NAME,TABLE_MAPNAME,TYPE,l.DESCRIPTION from layer l,element e " +
    35 "where l.pid=e.id and e.name = '" + selectNodeText + "' and e.category='数据标准'";
    36
    37 break;
    38 case 3:
    39 sql = "select l.ID,TABLE_NAME,TABLE_MAPNAME,TYPE,l.DESCRIPTION from layer l,element e where table_name='"
    40 + selectNodeText + "' and e.category='数据标准' and l.pid=e.id";
    41
    42 break;
    43 default:
    44 break;
    45
    46 }
    47
    48 if (index >= 1 && index <= 3)
    49 {
    50 ds = sh.ReturnDataSet(sql, "jcslayer");
    51
    52 dataGridViewX1.DataSource = ds.Tables[0];
    53 dataGridViewX1.Columns[0].HeaderText = "图层代码";
    54 dataGridViewX1.Columns[1].HeaderText = "图层名";
    55 dataGridViewX1.Columns[2].HeaderText = "图层映射名";
    56 dataGridViewX1.Columns[3].HeaderText = "类型";
    57 dataGridViewX1.Columns[4].HeaderText = "描述";
    58 }
    59 }

    4.鼠标右击树形控件节点,显示对应的右击菜单

     1         ///<summary>
    2 /// 鼠标右击树形控件节点,显示对应的右击菜单
    3 ///</summary>
    4 ///<param name="sender"></param>
    5 ///<param name="e"></param>
    6 private void LayerManagerTree_NodeMouseDown(object sender, TreeNodeMouseEventArgs e)
    7 {
    8 if (e.Button == MouseButtons.Right)
    9 {
    10 Node n = new Node();
    11 n = e.Node;
    12 selectNodeText = n.Text;
    13
    14 switch (n.Level)
    15 {
    16 case 0:
    17 contextMenuStrip1.Show(MousePosition);
    18 break;
    19 case 1:
    20 contextMenuStrip2.Show(MousePosition);
    21 break;
    22 case 2:
    23 contextMenuStrip3.Show(MousePosition);
    24 break;
    25 case 3:
    26 contextMenuStrip4.Show(MousePosition);
    27 break;
    28 default:
    29 break;
    30
    31 }
    32 }
    33 }

    5.添加数据分类

     1         ///<summary>
    2 /// 添加数据分类
    3 ///</summary>
    4 ///<param name="sender"></param>
    5 ///<param name="e"></param>
    6 private void AddDataCategory_Click(object sender, EventArgs e)
    7 {
    8 FrmCategory adl = new FrmCategory();
    9 adl.Text = "添加地图数据分类";
    10 adl.ShowDialog();
    11
    12 Node n = LayerManagerTree.FindNodeByText(selectNodeText);
    13 UpdateTree(n.Level);//更新树形控件
    14 UpdateNode(n);//更新节点
    15 }

        在添加数据分类、修改数据分类、添加要素分类和更新要素分类都是用到一个FrmCategory类,它也是一个和对话框关联的类,下面是这个类具体的实现代码(不包括界面代码):

      1         private string saveId;//保存原ID,以备更新使用
    2 private string saveName;//保存原Name
    3 public string categoryName;//保存原分类名称
    4
    5 public FrmCategory()
    6 {
    7 InitializeComponent();
    8 }
    9
    10 //根据Tag值的不同实现不同的功能,因为界面都是一样的
    11 //四个功能:1.添加数据分类;2.更新数据分类;3.添加要素类分类;4.更新要素类分类
    12 private void AddBtn_Click(object sender, EventArgs e)
    13 {
    14 //1.不为空检查
    15 if (IdTxt.Text.Trim() == "" || NameTxt.Text.Trim() == "")
    16 {
    17 ErrLabel.Text = "类别编码和类别名称都不能为空!";
    18 return;
    19 }
    20 //2.记录已存在检查
    21 SqlHelper sh = new SqlHelper();
    22 string sql;
    23 //根据标签判断是什么功能
    24 if (this.Tag == "update")
    25 {
    26 //更新数据分类
    27 sql = "select * from category where name='" + NameTxt.Text + "'" + " and name!='"
    28 + saveName + "'" + " or id=" + int.Parse(IdTxt.Text) + " and id!=" + saveId;
    29 }
    30 else if (this.Tag == "addElement")
    31 {
    32 //增加要素分类
    33 sql = "select * from element where id=" + int.Parse(IdTxt.Text) + " or name='"
    34 + NameTxt.Text + "' and category='" + categoryName + "'";
    35 }
    36 else if (this.Tag == "updateElement")
    37 {
    38 //更新要素分类
    39 sql = "select * from element where id=" + int.Parse(IdTxt.Text) +
    40 " and id!=" + saveId + " or name='" + NameTxt.Text + "'" +
    41 " and name!='" + saveName + "' and category='" + categoryName + "'";
    42 }
    43 else
    44 {
    45 //添加数据分类
    46 sql = "select * from category where id=" +
    47 int.Parse(IdTxt.Text) + " or name='" + NameTxt.Text + "'";
    48 }
    49
    50 if (sh.GetRecordCount(sql) > 0)
    51 {
    52 ErrLabel.Text = "类别编码或类别名称已存在!";
    53 return;
    54 }
    55
    56 //3.构造插入或更新哈希表
    57 Hashtable ht = new Hashtable();
    58
    59 ht.Add("ID", IdTxt.Text);
    60 ht.Add("NAME", NameTxt.Text);
    61 ht.Add("DESCRIPTION", DescTxt.Text);
    62
    63 //如果是增加要素分类,就需要多添加两个字段的值
    64 if (this.Tag == "addElement")
    65 {
    66 ht.Add("category", categoryName);
    67 ht.Add("datasetname", comboBoxEx1.SelectedItem.ToString());
    68 }
    69
    70 if (this.Tag == "update")
    71 {
    72 //更新了数据分类的名称,要素类分类的分类名称跟着改变
    73 if (sh.Update("category", "ID=" + saveId, ht) <= 0)
    74 {
    75 ErrLabel.Text = "更新地图数据分层类别失败";
    76 return;
    77 }
    78 else
    79 {
    80 ht.Clear();
    81 ht.Add("category", NameTxt.Text);
    82 sh.Update("element", "category='" + saveName + "'", ht);
    83 }
    84 }
    85 else if (this.Tag == "addElement")
    86 {
    87 if (sh.Insert("element", ht) <= 0)
    88 {
    89 ErrLabel.Text = "添加要素分类失败";
    90 return;
    91 }
    92 }
    93 else if (this.Tag == "updateElement")
    94 {
    95 ht.Add("datasetname", comboBoxEx1.SelectedItem.ToString());
    96 //更新了要素类分类的id,图层的pid相应改变
    97 if (sh.Update("element", "ID=" + saveId, ht) <= 0)
    98 {
    99 ErrLabel.Text = "更新地图数据分层类别失败";
    100 return;
    101 }
    102 else
    103 {
    104 ht.Clear();
    105 ht.Add("pid", IdTxt.Text);
    106 sh.Update("layer", "pid='" + saveId + "'", ht);
    107 }
    108 }
    109 else
    110 {
    111 if (sh.Insert("category", ht) <= 0)
    112 {
    113 ErrLabel.Text = "添加地图数据分层类别失败";
    114 return;
    115 }
    116
    117 }
    118 MessageBox.Show("操作成功!");
    119 this.Close();
    120 }
    121
    122 private void CancelBtn_Click(object sender, EventArgs e)
    123 {
    124 this.Close();
    125 }
    126
    127 private void AddDataLayer_Load(object sender, EventArgs e)
    128 {
    129 //如果是更新操作就保存原来的ID和名称
    130 if (this.Tag == "update" || this.Tag == "updateElement")
    131 {
    132 //IdTxt.Enabled = false;
    133 saveId = IdTxt.Text;
    134 saveName = NameTxt.Text;
    135 }
    136 //如果是要素类分类操作就加载具体的数据集,以便指定要素类属于哪一个数据集
    137 if (this.Tag == "addElement" || this.Tag == "updateElement")
    138 {
    139 labelX4.Visible = true;
    140 comboBoxEx1.Visible = true;
    141 IFeatureWorkspace pFW = MapOperation.GetFeatrueWorkspace();
    142 IWorkspace pW = pFW as IWorkspace;
    143 IEnumDataset pED = pW.get_Datasets(esriDatasetType.esriDTFeatureDataset);
    144 IFeatureDataset pFD = pED.Next() as IFeatureDataset;
    145 while (pFD != null)
    146 {
    147 comboBoxEx1.Items.Add(pFD.Name);
    148 pFD = pED.Next() as IFeatureDataset;
    149 }
    150 comboBoxEx1.Items.Add("属性表");
    151 comboBoxEx1.SelectedIndex = 0;
    152 }
    153 }
    154
    155 ///<summary>
    156 /// 设置ID
    157 ///</summary>
    158 ///<param name="id">ID值</param>
    159 public void SetId(string id)
    160 {
    161 IdTxt.Text = id;
    162 }
    163
    164 ///<summary>
    165 /// 设置名称
    166 ///</summary>
    167 ///<param name="name">名称值</param>
    168 public void SetName(string name)
    169 {
    170 NameTxt.Text = name;
    171 }
    172
    173 ///<summary>
    174 /// 设置描述
    175 ///</summary>
    176 ///<param name="description">描述值</param>
    177 public void SetDescription(string description)
    178 {
    179 DescTxt.Text = description;
    180 }
    181
    182 ///<summary>
    183 /// 设置数据集名称
    184 ///</summary>
    185 ///<param name="strDataSet">数据集名称</param>
    186
    187 public void SetDataSet(string strDataSet)
    188 {
    189 comboBoxEx1.SelectedIndex = comboBoxEx1.FindString(strDataSet);
    190 }

    6.添加要素类别,通用使用上面提到的那个类和其操作界面,通过不同的命令来执行不同的操作(用一个变量来表示)。

     1         ///<summary>
    2 /// 添加要素类别
    3 ///</summary>
    4 ///<param name="sender"></param>
    5 ///<param name="e"></param>
    6 private void AddElementCategory_Click(object sender, EventArgs e)
    7 {
    8 FrmCategory fc = new FrmCategory();
    9 fc.Tag = "addElement";
    10 fc.Text = "添加要素分类";
    11 fc.categoryName = selectNodeText;
    12
    13 fc.ShowDialog();
    14
    15 Node n = LayerManagerTree.FindNodeByText(selectNodeText);
    16 UpdateTree(n.Level);//更新树形控件
    17 UpdateNode(n);//更新节点
    18 }

    7.删除数据分类,就是把数据库中定义数据分类的记录删除掉。

     1         ///<summary>
    2 /// 删除数据分类
    3 ///</summary>
    4 ///<param name="sender"></param>
    5 ///<param name="e"></param>
    6 private void DelDataCategory_Click(object sender, EventArgs e)
    7 {
    8 SqlHelper sh = new SqlHelper();
    9
    10 Hashtable ht = new Hashtable();
    11 Node n = LayerManagerTree.FindNodeByText(selectNodeText);
    12
    13 foreach (Node t in n.Nodes)
    14 {
    15 DeleteElement(t.Text);
    16 }
    17
    18 ht.Add("name", n.Text);
    19 if (sh.Del("jcsjk_category", "name='" + selectNodeText + "'", ht) > 0)
    20 {
    21 n.Remove();
    22 MessageBox.Show("删除地图数据分类成功");
    23 }
    24 else
    25 {
    26 MessageBox.Show("删除地图数据分类失败");
    27 }
    28 }

    8.更新数据分类,同样是更新数据库的一条定义的记录。

     1         ///<summary>
    2 /// 更新数据分类
    3 ///</summary>
    4 ///<param name="sender"></param>
    5 ///<param name="e"></param>
    6 private void UpdateDataCategory_Click(object sender, EventArgs e)
    7 {
    8 FrmCategory fc = new FrmCategory();
    9 fc.Tag = "update";
    10 fc.Text = "更新地图数据分类";
    11 fc.categoryName = selectNodeText;
    12
    13 SqlHelper sh = new SqlHelper();
    14 string sql = "select id,name, description from category where name='"
    15 + selectNodeText + "'";
    16 OracleDataReader odr = sh.ReturnDataReader(sql);
    17 if (odr.Read())
    18 {
    19 fc.SetId(odr[0].ToString());
    20 fc.SetName(odr[1].ToString());
    21 fc.SetDescription(odr[2].ToString());
    22 }
    23
    24 fc.ShowDialog();
    25 }

    9.其他操作,其他的操作包括要素类的增删改等,具体实现方式都差不多,只是针对不同的层或内容进行操作。

      1         ///<summary>
    2 /// 添加图层
    3 ///</summary>
    4 ///<param name="sender"></param>
    5 ///<param name="e"></param>
    6 private void AddLayerCategory_Click(object sender, EventArgs e)
    7 {
    8 FrmLayer fl = new FrmLayer();
    9 fl.Text = "添加图层";
    10 fl.category = selectNodeText;
    11 fl.ShowDialog();
    12
    13 Node n = LayerManagerTree.FindNodeByText(selectNodeText);
    14 UpdateTree(n.Level);
    15 UpdateNode(n);
    16 }
    17
    18 ///<summary>
    19 /// 删除要素类别
    20 ///</summary>
    21 ///<param name="sender"></param>
    22 ///<param name="e"></param>
    23 private void DelElementCategory_Click(object sender, EventArgs e)
    24 {
    25 if (DeleteElement(selectNodeText))
    26 {
    27 Node n = LayerManagerTree.FindNodeByText(selectNodeText);
    28 n.Remove();
    29 MessageBox.Show("删除要素类别成功!");
    30 }
    31 else
    32 {
    33 MessageBox.Show("删除要素类别失败!");
    34 }
    35 }
    36
    37 ///<summary>
    38 /// 删除一个要素类别
    39 ///</summary>
    40 ///<param name="name">要素名称</param>
    41 ///<returns>成功true,失败false</returns>
    42 private bool DeleteElement(string name)
    43 {
    44 bool result = false;
    45
    46 Node n = LayerManagerTree.FindNodeByText(name);
    47
    48 foreach (Node t in n.Nodes)
    49 {
    50 DeleteLayer(t.Text);
    51 }
    52
    53 SqlHelper sh = new SqlHelper();
    54 Hashtable ht = new Hashtable();
    55 ht.Add("name", name);
    56
    57 if (sh.Del("element", "name='" + name + "' and category='数据标准'", ht) > 0)
    58 {
    59 result = true;
    60 }
    61 else
    62 {
    63 result = false;
    64 }
    65
    66 return result;
    67 }
    68
    69 ///<summary>
    70 /// 更新要素类别
    71 ///</summary>
    72 ///<param name="sender"></param>
    73 ///<param name="e"></param>
    74 private void UpdateElementCategory_Click(object sender, EventArgs e)
    75 {
    76 FrmCategory fc = new FrmCategory();
    77 fc.Tag = "updateElement";
    78 fc.Text = "更新要素类别";
    79
    80 SqlHelper sh = new SqlHelper();
    81 string sql = "select id,name,description,datasetname from element where name='"
    82 + selectNodeText + "' and category='数据标准'";
    83 OracleDataReader odr = sh.ReturnDataReader(sql);
    84 if (odr.Read())
    85 {
    86 fc.SetId(odr[0].ToString());
    87 fc.SetName(odr[1].ToString());
    88 fc.SetDescription(odr[2].ToString());
    89 fc.SetDataSet(odr[3].ToString());
    90 }
    91
    92 fc.ShowDialog();
    93 }
    94
    95 ///<summary>
    96 /// 删除图层定义
    97 ///</summary>
    98 ///<param name="sender"></param>
    99 ///<param name="e"></param>
    100 private void DelLayerDefine_Click(object sender, EventArgs e)
    101 {
    102 if (DeleteLayer(selectNodeText))
    103 {
    104 Node n = LayerManagerTree.FindNodeByText(selectNodeText);
    105 n.Remove();
    106 MessageBox.Show("删除图层定义成功!");
    107 }
    108 else
    109 {
    110 MessageBox.Show("删除图层定义失败!");
    111 }
    112 }
    113
    114 ///<summary>
    115 /// 更新图层定义
    116 ///</summary>
    117 ///<param name="sender"></param>
    118 ///<param name="e"></param>
    119 private void UpdateLayerDefine_Click(object sender, EventArgs e)
    120 {
    121 FrmLayer fl = new FrmLayer();
    122 fl.Text = "更新图层定义";
    123 fl.Tag = "update";
    124
    125 //fl.category = selectNodeText;
    126
    127 SqlHelper sh = new SqlHelper();
    128 string sql = "select l.ID,TABLE_NAME,TABLE_MAPNAME,TYPE,l.DESCRIPTION from " +
    129 "layer l,element e where table_name='" + selectNodeText
    130 + "' and l.pid=e.id and category='数据标准'";
    131 OracleDataReader odr = sh.ReturnDataReader(sql);
    132
    133 if (odr.Read())
    134 {
    135 fl.SetId(odr[0].ToString());
    136 fl.SetTableName(odr[1].ToString());
    137 fl.SetTabelMapName(odr[2].ToString());
    138
    139 if ("PL" == odr[3].ToString())
    140 {
    141 fl.SetType(1);
    142 }
    143 else if ("PA" == odr[3].ToString())
    144 {
    145 fl.SetType(2);
    146 }
    147 else
    148 {
    149 fl.SetType(0);
    150 }
    151 fl.SetDescription(odr[4].ToString());
    152 }
    153
    154 fl.ShowDialog();
    155 }
    156
    157 ///<summary>
    158 /// 删除一个图层
    159 ///</summary>
    160 ///<param name="layerName">图层名称</param>
    161 ///<returns>成功true,失败false</returns>
    162 private bool DeleteLayer(string layerName)
    163 {
    164 bool result = false;
    165 SqlHelper sh = new SqlHelper();
    166 string sql = "select l.id from layer l,element e where e.id=l.pid and table_name='"
    167 + layerName + "' and category='数据标准'";
    168 OracleDataReader odr = sh.ReturnDataReader(sql);
    169 int layerId;
    170 if (odr.Read())
    171 {
    172 layerId = int.Parse(odr[0].ToString());
    173 }
    174 else
    175 {
    176 return false;
    177 }
    178 Hashtable ht = new Hashtable();
    179
    180 ht.Add("id", layerId);
    181
    182 if (sh.Del("layer", "id=" + layerId, ht) > 0)
    183 {
    184 result = true;
    185 }
    186 else
    187 {
    188 result = false;
    189 }
    190
    191 return result;
    192 }

    10.总结

        这里主要实现的是对空间数据进行分类管理的一种方案,以后导入导出或查询的空间数据都在这些分类下面进行操作,还有一个例外,就是不属于任何分类的数据,简单称为游离数据或图层。这里的实现都比较简单,主要是一些对数据库的操作,在配合一些逻辑操作就OK了,没有什么技术含量。

  • 相关阅读:
    Android Studio --“Cannot resolve symbol” 解决办法
    js与android webview交互
    关于post与get请求参数存在特殊字符问题
    Fragment 学习笔记(1)
    Android Studio 错误集
    UVA
    UVA
    UVALive
    考试题string——线段树。
    洛谷 1552 [APIO2012]派遣
  • 原文地址:https://www.cnblogs.com/brucewoo/p/2262497.html
Copyright © 2011-2022 走看看