您的位置:首页 > 大数据 > 人工智能

CListContainerElement 扩展任意类型的列表控件--表头拖拽不起作用

2015-04-30 08:31 441 查看
今天在做一个程序的界面时,需要在一个列表中显示除文字以外的其他控件,如:Edit、Button、Combo等;我做界面使用的是duilib,其自带的CListUI并不能满足此项功能,需要进行扩展,在此记录,以便后续使用需要。

 

先看一下实现的效果:

 


 

今天我们的扩展主要包含如下部分:

1. 表头支持控件

在ListUI中,表头是CListHeaderItemUI,而这个类是从CControlUI继承而来,为了能支持在其中显示其他控件,它需要是一个容器,那么需要将其父类改成CContainerUI,调整基类后,需要同时将CListHeaderItemUI类中引用 CControlUI的地方全部改成CContainerUI,如:

 

[cpp]
view plaincopyprint?





LPVOID CListHeaderItemUI::GetInterface(LPCTSTR pstrName)  
{  
    if( _tcscmp(pstrName, DUI_CTR_LISTHEADERITEM) == 0 ) return this;  
    return CContainerUI::GetInterface(pstrName);  
}  

LPVOID CListHeaderItemUI::GetInterface(LPCTSTR pstrName)
{
if( _tcscmp(pstrName, DUI_CTR_LISTHEADERITEM) == 0 ) return this;
return CContainerUI::GetInterface(pstrName);
}


如果此处不改,将无法从XML文件中加载内嵌控件。

还需要修改其他如DoEvent事件中的CControlUI,否则会导致表头无法拖拉,切记。

改造后,我们可以从XML文件加载了,XML文件可以这样写:

[html]
view plaincopyprint?





<List name="listex" bkcolor="#FFFFFFFF" inset="0,0,0,0" itemshowhtml="true" vscrollbar="true" hscrollbar="true" headerbkimage="file='list_header_bg.png'" itemhotimage="file='tree_hot.bmp' corner='2,1,2,1'" itemselectedimage="file='tree_select.bmp' corner='2,1,2,1'" itemalign="center" itembkcolor="#FFE2DDDF" itemaltbk="true" hscrollbar="false" menu="true">  
<ListHeader height="24" menu="true">  
<ListHeaderItem text="" inset="1,0,1,0" minwidth="60" endellipsis="true" font="1" width="95"  normalimage="headerctrl_normal.bmp" hotimage="headerctrl_hot.bmp" pushedimage="headerctrl_down.bmp" sepimage="Headerctrl_Sperator.bmp" sepwidth="2">  
<VerticalLayout inset="1,0,5,0">  
<CheckBox name="selall" endellipsis="true"  text="全选" textcolor="#FF386382" hottextcolor="#FF386382" selectedtextcolor="#FF386382" disabledtextcolor="#FFbac0c5" textpadding="20,3,0,0" align="left" selectedimage="file='checkbox_p.png' dest='0,2,15,17'" normalimage="file='checkbox_h.png' dest='0,2,15,17'"  />  
</VerticalLayout>  
</ListHeaderItem>  
<ListHeaderItem text="域名" minwidth="100" endellipsis="true" font="1" width="200"  normalimage="headerctrl_normal.bmp" hotimage="headerctrl_hot.bmp" pushedimage="headerctrl_down.bmp" sepimage="Headerctrl_Sperator.bmp" sepwidth="2"/>  
<ListHeaderItem text="描述" minwidth="120" endellipsis="true" font="1" width="150"  normalimage="headerctrl_normal.bmp" hotimage="headerctrl_hot.bmp" pushedimage="headerctrl_down.bmp" sepimage="Headerctrl_Sperator.bmp" sepwidth="2"/>  
</ListHeader>  

<List name="listex" bkcolor="#FFFFFFFF" inset="0,0,0,0" itemshowhtml="true" vscrollbar="true" hscrollbar="true" headerbkimage="file='list_header_bg.png'" itemhotimage="file='tree_hot.bmp' corner='2,1,2,1'" itemselectedimage="file='tree_select.bmp' corner='2,1,2,1'" itemalign="center" itembkcolor="#FFE2DDDF" itemaltbk="true" hscrollbar="false" menu="true">
<ListHeader height="24" menu="true">
<ListHeaderItem text="" inset="1,0,1,0" minwidth="60" endellipsis="true" font="1" width="95"  normalimage="headerctrl_normal.bmp" hotimage="headerctrl_hot.bmp" pushedimage="headerctrl_down.bmp" sepimage="Headerctrl_Sperator.bmp" sepwidth="2">
<VerticalLayout inset="1,0,5,0">
<CheckBox name="selall" endellipsis="true"  text="全选" textcolor="#FF386382" hottextcolor="#FF386382" selectedtextcolor="#FF386382" disabledtextcolor="#FFbac0c5" textpadding="20,3,0,0" align="left" selectedimage="file='checkbox_p.png' dest='0,2,15,17'" normalimage="file='checkbox_h.png' dest='0,2,15,17'"  />
</VerticalLayout>
</ListHeaderItem>
<ListHeaderItem text="域名" minwidth="100" endellipsis="true" font="1" width="200"  normalimage="headerctrl_normal.bmp" hotimage="headerctrl_hot.bmp" pushedimage="headerctrl_down.bmp" sepimage="Headerctrl_Sperator.bmp" sepwidth="2"/>
<ListHeaderItem text="描述" minwidth="120" endellipsis="true" font="1" width="150"  normalimage="headerctrl_normal.bmp" hotimage="headerctrl_hot.bmp" pushedimage="headerctrl_down.bmp" sepimage="Headerctrl_Sperator.bmp" sepwidth="2"/>
</ListHeader>


这样显示出来的效果如下:

 


注意:

此处需要将内嵌控件的ListHeaderItem 添加一个inset属性,控制内嵌的控件不要铺满整个ListHeaderItem ,否则表头拖动不了,如:

ListHeaderItem text="" inset="1,0,1,0"

 

2. 列表项支持控件

CListUI的某一行CListContainerElementUI继承至容器CContainerUI,这样一来我们只需要将需要的控件添加到此容器中,即可正确的显示相关的控件了,此处并不需要做调整,只是这样一来会带来一个问题,那就是所添加的列的宽度无法与表头的宽度保持一致。

要解决这个问题,需要给CListContainerElementUI添加SetPos函数,在此函数中,重新校正数据列宽与表头宽度一致,具体如下:

[cpp]
view plaincopyprint?





void SetPos(RECT rc)  
{  
CContainerUI::SetPos(rc);  
if( m_pOwner == NULL ) return;  
if (m_pHeader == NULL)  
{  
return;  
}  
TListInfoUI* pInfo = m_pOwner->GetListInfo();  
int nCount = m_items.GetSize();  
for (int i = 0; i < nCount; i++)  
{  
CControlUI *pHorizontalLayout = static_cast<CControlUI*>(m_items[i]);  
// if (pHorizontalLayout != NULL)   
// {   
// RECT rtHeader = pHeaderItem->GetPos();
  
// RECT rt = pHorizontalLayout->GetPos();
  
// rt.left = pInfo->rcColumn[i].left;
  
// rt.right = pInfo->rcColumn[i].right;
  
// pHorizontalLayout->SetPos(rt);   
// }   
   
CListHeaderItemUI *pHeaderItem = static_cast<CListHeaderItemUI*>(m_pHeader->GetItemAt(i));  
if (pHorizontalLayout != NULL && pHeaderItem != NULL)  
{  
RECT rtHeader = pHeaderItem->GetPos();  
RECT rt = pHorizontalLayout->GetPos();  
rt.left = rtHeader.left;  
rt.right = rtHeader.right;  
pHorizontalLayout->SetPos(rt);  
}  
}  
    }  
CListHeaderUI *m_pHeader;  

void SetPos(RECT rc)
{
CContainerUI::SetPos(rc);
if( m_pOwner == NULL ) return;
if (m_pHeader == NULL)
{
return;
}
TListInfoUI* pInfo = m_pOwner->GetListInfo();
int nCount = m_items.GetSize();
for (int i = 0; i < nCount; i++)
{
CControlUI *pHorizontalLayout = static_cast<CControlUI*>(m_items[i]);
// if (pHorizontalLayout != NULL)
// {
// RECT rtHeader = pHeaderItem->GetPos();
// RECT rt = pHorizontalLayout->GetPos();
// rt.left = pInfo->rcColumn[i].left;
// rt.right = pInfo->rcColumn[i].right;
// pHorizontalLayout->SetPos(rt);
// }

CListHeaderItemUI *pHeaderItem = static_cast<CListHeaderItemUI*>(m_pHeader->GetItemAt(i));
if (pHorizontalLayout != NULL && pHeaderItem != NULL)
{
RECT rtHeader = pHeaderItem->GetPos();
RECT rt = pHorizontalLayout->GetPos();
rt.left = rtHeader.left;
rt.right = rtHeader.right;
pHorizontalLayout->SetPos(rt);
}
}
}
CListHeaderUI *m_pHeader;


此处往列表项中添加了表头的指针,需要在插入一行的时候,将表头的指针传递进来,用于在SetPos的时候获取表头宽度。

注意以上代码中的注释部分,原本打算从TListInfoUI的rcColumn中获取表头项宽度的,但发现新添加行时,rcCulumn中的值全是0,需要在插入行前主动调用一次CListUI::SetPos(GetPos());才能正常,使用起来较麻烦,且容易忘记;即使是添加上了,测试发现获取到的位置有一定的偏移,所以采用将Header传入,实时获取了。

以下是一行数据的XML文件描述:

[html]
view plaincopyprint?





<?xml version="1.0" encoding="UTF-8"?>  
<Window>  
  <ListContainerElement >  
<CheckBox name="selectme" endellipsis="true"  text="亲,选我吧!" textcolor="#FF386382" hottextcolor="#FF386382" selectedtextcolor="#FF386382" disabledtextcolor="#FFbac0c5" textpadding="20,3,0,0" align="left" selectedimage="file='checkbox_p.png' dest='0,2,15,17'" normalimage="file='checkbox_h.png' dest='0,2,15,17'"  />  
<HorizontalLayout inset="4,4,4,4">  
<Edit text="测试文本" bordersize="1" height="20" bordercolor="#FF4775CC" name="domain" ></Edit>  
</HorizontalLayout>  
<HorizontalLayout >  
<VerticalLayout>  
<Button text="按钮1" width="50" pushedimage="button_down.bmp" hotimage="button_over.bmp" normalimage="button_nor.bmp" name="ttt" ></Button>  
<Button text="按钮2" width="50" pushedimage="button_down.bmp" hotimage="button_over.bmp" normalimage="button_nor.bmp" name="ttt" ></Button>  
<Label text="这是从XML文件中加载的列表项"></Label>  
</VerticalLayout>  
</HorizontalLayout>  
  </ListContainerElement>  
</Window>  

<?xml version="1.0" encoding="UTF-8"?>
<Window>
<ListContainerElement >
<CheckBox name="selectme" endellipsis="true"  text="亲,选我吧!" textcolor="#FF386382" hottextcolor="#FF386382" selectedtextcolor="#FF386382" disabledtextcolor="#FFbac0c5" textpadding="20,3,0,0" align="left" selectedimage="file='checkbox_p.png' dest='0,2,15,17'" normalimage="file='checkbox_h.png' dest='0,2,15,17'"  />
<HorizontalLayout inset="4,4,4,4">
<Edit text="测试文本" bordersize="1" height="20" bordercolor="#FF4775CC" name="domain" ></Edit>
</HorizontalLayout>
<HorizontalLayout >
<VerticalLayout>
<Button text="按钮1" width="50" pushedimage="button_down.bmp" hotimage="button_over.bmp" normalimage="button_nor.bmp" name="ttt" ></Button>
<Button text="按钮2" width="50" pushedimage="button_down.bmp" hotimage="button_over.bmp" normalimage="button_nor.bmp" name="ttt" ></Button>
<Label text="这是从XML文件中加载的列表项"></Label>
</VerticalLayout>
</HorizontalLayout>
</ListContainerElement>
</Window>
注意,此处需要确保ListContainerElement 的子控件个数不少于列表的列数

 在代码中加载此XML文件,将行数据添加到列表中:

[cpp]
view plaincopyprint?





CListUIEx *pList = static_cast<CListUIEx*>(m_PaintManager.FindControl(_T("listex")));  
CDialogBuilder builder;  
CListContainerElementUI* pLine = (CListContainerElementUI*)(builder.Create(_T("sigle_list_item_column.xml"),(UINT)0, this));  
if( pLine != NULL )   
{  
pList->InsertItem(0, 60, pLine); //此函数是经过二次封装的
  
}  

CListUIEx *pList = static_cast<CListUIEx*>(m_PaintManager.FindControl(_T("listex")));
CDialogBuilder builder;
CListContainerElementUI* pLine = (CListContainerElementUI*)(builder.Create(_T("sigle_list_item_column.xml"),(UINT)0, this));
if( pLine != NULL )
{
pList->InsertItem(0, 60, pLine); //此函数是经过二次封装的
}
 加载的效果如下:

 


这样我们可以在列表的不同项中显示任意内容,甚至是一个完整的窗口了。

 

3. 通过代码动态添加列及列表项

 

以上的处理均是调整后从XML加载相应的加载已经配置好的列表进行显示,在完成上述工作后,我这边进一步封装了几个函数,以便于动态的添加列[指定内嵌控件]、动态的插入行以及动态的在某一行列中添加控件。

 1). 以下代码用于动态的添加列:

[cpp]
view plaincopyprint?





BOOL CListUIEx::InsertColumn(  
 int nCol,  
 CListHeaderItemUI *pHeaderItem  
 )  
{  
CListHeaderUI *pHeader = CListUI::GetHeader();  
if (pHeader == NULL)  
{  
return FALSE;  
}  
if (pHeader->AddAt(pHeaderItem, nCol))  
{  
return TRUE;  
}  
   
delete pHeaderItem;  
pHeaderItem = NULL;  
return FALSE;  
}  
   
BOOL CListUIEx::SetHeaderItemData(int nColumn, CControlUI* pControl)  
{  
CListHeaderUI *pHeader = CListUI::GetHeader();  
if (pHeader == NULL)  
{  
return FALSE;  
}  
CListHeaderItemUI *pHeaderItem = (CListHeaderItemUI *)pHeader->GetItemAt(nColumn);  
pHeaderItem->Add(pControl);  
}  

BOOL CListUIEx::InsertColumn(
int nCol,
CListHeaderItemUI *pHeaderItem
)
{
CListHeaderUI *pHeader = CListUI::GetHeader();
if (pHeader == NULL)
{
return FALSE;
}
if (pHeader->AddAt(pHeaderItem, nCol))
{
return TRUE;
}

delete pHeaderItem;
pHeaderItem = NULL;
return FALSE;
}

BOOL CListUIEx::SetHeaderItemData(int nColumn, CControlUI* pControl)
{
CListHeaderUI *pHeader = CListUI::GetHeader();
if (pHeader == NULL)
{
return FALSE;
}
CListHeaderItemUI *pHeaderItem = (CListHeaderItemUI *)pHeader->GetItemAt(nColumn);
pHeaderItem->Add(pControl);
}
调用代码如下[添加一列,并且向此列中嵌入一个CheckBox]:

[cpp]
view plaincopyprint?





CListHeaderItemUI *pHeaderItem = new CListHeaderItemUI;  
pHeaderItem->SetTextStyle(DT_RIGHT|DT_VCENTER|DT_SINGLELINE);  
pHeaderItem->SetText("新增列  ");  
pHeaderItem->SetAttribute(_T("sepimage"), _T("Headerctrl_Sperator.bmp"));  
pHeaderItem->SetAttribute(_T("sepwidth"), _T("1"));  
pHeaderItem->SetAttribute(_T("pushedimage"), _T("headerctrl_down.bmp"));  
pHeaderItem->SetAttribute(_T("hotimage"), _T("headerctrl_hot.bmp"));  
pHeaderItem->SetAttribute(_T("normalimage"), _T("headerctrl_normal.bmp"));  
pHeaderItem->SetFixedWidth(150);  
pList->InsertColumn(3, pHeaderItem);  
   
CCheckBoxUI *pBtnUI = new CCheckBoxUI;  
pBtnUI->SetText("选择");  
pBtnUI->SetAttribute(_T("selectedimage"), _T("file='checkbox_p.png' dest='0,2,15,17'"));  
pBtnUI->SetAttribute(_T("normalimage"), _T("file='checkbox_h.png' dest='0,2,15,17'"));  
pBtnUI->SetAttribute(_T("textpadding"), _T("20,3,0,0"));  
pBtnUI->SetAttribute(_T("align"), _T("right"));  
pBtnUI->SetFloat(true);  
pBtnUI->SetAttribute("pos", "20,3, 65, 20");  
   
pList->SetHeaderItemData(3, pBtnUI);  

CListHeaderItemUI *pHeaderItem = new CListHeaderItemUI;
pHeaderItem->SetTextStyle(DT_RIGHT|DT_VCENTER|DT_SINGLELINE);
pHeaderItem->SetText("新增列  ");
pHeaderItem->SetAttribute(_T("sepimage"), _T("Headerctrl_Sperator.bmp"));
pHeaderItem->SetAttribute(_T("sepwidth"), _T("1"));
pHeaderItem->SetAttribute(_T("pushedimage"), _T("headerctrl_down.bmp"));
pHeaderItem->SetAttribute(_T("hotimage"), _T("headerctrl_hot.bmp"));
pHeaderItem->SetAttribute(_T("normalimage"), _T("headerctrl_normal.bmp"));
pHeaderItem->SetFixedWidth(150);
pList->InsertColumn(3, pHeaderItem);

CCheckBoxUI *pBtnUI = new CCheckBoxUI;
pBtnUI->SetText("选择");
pBtnUI->SetAttribute(_T("selectedimage"), _T("file='checkbox_p.png' dest='0,2,15,17'"));
pBtnUI->SetAttribute(_T("normalimage"), _T("file='checkbox_h.png' dest='0,2,15,17'"));
pBtnUI->SetAttribute(_T("textpadding"), _T("20,3,0,0"));
pBtnUI->SetAttribute(_T("align"), _T("right"));
pBtnUI->SetFloat(true);
pBtnUI->SetAttribute("pos", "20,3, 65, 20");

pList->SetHeaderItemData(3, pBtnUI);
2). 以下代码用于动态的添加行,动态的指定一列的内容: 

[cpp]
view plaincopyprint?





int CListUIEx::InsertItem(int nItem, int nHeight)  
{  
CListContainerElementUIEx *pListItem = new CListContainerElementUIEx;  
pListItem->SetFixedHeight(nHeight);/*固定一个行高*/  
pListItem->SetList(this);  
   
CListHeaderUI *pHeader = CListUI::GetHeader();  
if (NULL != pHeader)  
{  
int nHeaderCount = pHeader->GetCount();  
for (int i = 0; i < nHeaderCount; i++)  
{  
pListItem->InsertColumn(i);  
}  
}  
if ( !CListUI::AddAt(pListItem, nItem) )  
{  
delete pListItem;  
pListItem = NULL;  
return -1;  
}  
return nItem;  
}  
   
void CListUIEx::SetItemData(int nItem,  
int nColumn,  
LPCTSTR Text, LPCTSTR Name)  
{  
//存放文本   
CHorizontalLayoutUI *pSubHor = GetListSubItem(nItem, nColumn);  
CLabelUI *pLabel = new CLabelUI;  
pLabel->SetText(Text);//控件属性就根据需求设置吧,我简单设置一下
  
pLabel->SetTextStyle(DT_CENTER);  
pLabel->SetAttribute("endellipsis", "true");  
pSubHor->SetAttribute("inset", "3,1,3,1");  
pLabel->SetName(Name);  
pSubHor->Add(pLabel);//添加到父控件
  
}  
   
void CListUIEx::SetItemData(int nItem, int nColumn,CControlUI* pControl)  
{  
CHorizontalLayoutUI *pSubHor = GetListSubItem(nItem, nColumn);  
pSubHor->SetAttribute("inset", "3,0,3,1");  
pSubHor->Add(pControl);//添加到父控件   
}  

int CListUIEx::InsertItem(int nItem, int nHeight)
{
CListContainerElementUIEx *pListItem = new CListContainerElementUIEx;
pListItem->SetFixedHeight(nHeight);/*固定一个行高*/
pListItem->SetList(this);

CListHeaderUI *pHeader = CListUI::GetHeader();
if (NULL != pHeader)
{
int nHeaderCount = pHeader->GetCount();
for (int i = 0; i < nHeaderCount; i++)
{
pListItem->InsertColumn(i);
}
}
if ( !CListUI::AddAt(pListItem, nItem) )
{
delete pListItem;
pListItem = NULL;
return -1;
}
return nItem;
}

void CListUIEx::SetItemData(int nItem,
int nColumn,
LPCTSTR Text, LPCTSTR Name)
{
//存放文本
CHorizontalLayoutUI *pSubHor = GetListSubItem(nItem, nColumn);
CLabelUI *pLabel = new CLabelUI;
pLabel->SetText(Text);//控件属性就根据需求设置吧,我简单设置一下
pLabel->SetTextStyle(DT_CENTER);
pLabel->SetAttribute("endellipsis", "true");
pSubHor->SetAttribute("inset", "3,1,3,1");
pLabel->SetName(Name);
pSubHor->Add(pLabel);//添加到父控件
}

void CListUIEx::SetItemData(int nItem, int nColumn,CControlUI* pControl)
{
CHorizontalLayoutUI *pSubHor = GetListSubItem(nItem, nColumn);
pSubHor->SetAttribute("inset", "3,0,3,1");
pSubHor->Add(pControl);//添加到父控件
}


通过如下代码来添加一行数据:

[cpp]
view plaincopyprint?





CListUIEx *pList = static_cast<CListUIEx*>(m_PaintManager.FindControl(_T("listex")));  
int nIndex = pList->GetCount();  
pList->InsertItem(nIndex);  
   
CEditUI *pControl = new CEditUI;   
pControl->SetText("");  
pControl->SetName("edit");  
pControl->SetBorderColor(RGB(255, 0, 0));  
pControl->SetAttribute("bordersize", "1");  
pControl->SetAttribute("bordercolor", "#FF4775CC");  
pList->SetItemData(nIndex, 0, pControl);  
   
CButtonUI *pBtnUI = new CButtonUI;  
pBtnUI->SetText("添加");  
pBtnUI->SetFixedWidth(60);  
pBtnUI->SetAttribute(_T("pushedimage"), _T("button_down.bmp"));  
pBtnUI->SetAttribute(_T("hotimage"), _T("button_over.bmp"));  
pBtnUI->SetAttribute(_T("normalimage"), _T("button_nor.bmp"));  
pList->SetItemData(nIndex, 1, pBtnUI);  
   
pList->SetItemData(nIndex, 2, "这是一行动态添加的数据", "testid");  
if (pList->GetHeader()->GetCount() > 3)  
{  
pList->SetItemData(nIndex, 3, "新增列数据", "testid1");  
}  

CListUIEx *pList = static_cast<CListUIEx*>(m_PaintManager.FindControl(_T("listex")));
int nIndex = pList->GetCount();
pList->InsertItem(nIndex);

CEditUI *pControl = new CEditUI;
pControl->SetText("");
pControl->SetName("edit");
pControl->SetBorderColor(RGB(255, 0, 0));
pControl->SetAttribute("bordersize", "1");
pControl->SetAttribute("bordercolor", "#FF4775CC");
pList->SetItemData(nIndex, 0, pControl);

CButtonUI *pBtnUI = new CButtonUI;
pBtnUI->SetText("添加");
pBtnUI->SetFixedWidth(60);
pBtnUI->SetAttribute(_T("pushedimage"), _T("button_down.bmp"));
pBtnUI->SetAttribute(_T("hotimage"), _T("button_over.bmp"));
pBtnUI->SetAttribute(_T("normalimage"), _T("button_nor.bmp"));
pList->SetItemData(nIndex, 1, pBtnUI);

pList->SetItemData(nIndex, 2, "这是一行动态添加的数据", "testid");
if (pList->GetHeader()->GetCount() > 3)
{
pList->SetItemData(nIndex, 3, "新增列数据", "testid1");
}


至此,ListUI的扩展就告一段落了,目前已经完全满足了的使用需求,相信也能满足绝大部分其他人的需求了,测试程序的完整效果图如下:

 


 

测试程序代码下载地址:http://download.csdn.net/detail/tragicguy/7087559

  

后记:

扩展此控件,参考了文章:http://blog.csdn.net/xdrt81y/article/details/17588961

 此份测试代码改自 群友 【朗】 的 ListExtension.

 同时特别感谢群友 tojen 的帮助!

duilib功能确实很强大,给我这种UI小白带来了希望,希望有越来越多的高级控件能纳入的基础源码库中,方便大众;也希望其他扩展过duilib功能的大侠,放出代码来,造福众人。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: