Skip to content
项目
群组
代码片段
帮助
正在加载...
帮助
为 GitLab 提交贡献
登录
切换导航
U
ubains-module-test
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
计划
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
郑晓兵
ubains-module-test
Commits
7822010f
提交
7822010f
authored
4月 11, 2025
作者:
彭甘宇
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
提交统一平台代码,实现自动化创建会议和座位编排功能。
上级
8a3ef6d6
显示空白字符变更
内嵌
并排
正在显示
3 个修改的文件
包含
215 行增加
和
76 行删除
+215
-76
bases.py
统一平台/base/bases.py
+86
-3
01创建本地会议.py
统一平台/cases/主流程功能/01创建本地会议.py
+40
-73
03修改会议.py
统一平台/cases/主流程功能/03修改会议.py
+89
-0
没有找到文件。
统一平台/base/bases.py
浏览文件 @
7822010f
...
...
@@ -211,6 +211,7 @@ def safe_send_keys(element_locator, value, wd):
element
=
WebDriverWait
(
wd
,
5
)
.
until
(
EC
.
visibility_of_element_located
(
element_locator
))
element
.
clear
()
# 清除元素的当前值
element
.
send_keys
(
value
)
# 向元素发送指定的键值
sleep
(
3
)
except
TimeoutException
:
# 如果元素在指定时间内未被找到或不可点击,打印超时异常信息
INFO
(
f
"超时异常:元素 {element_locator} 在20秒内未找到或无法点击。"
)
...
...
@@ -465,13 +466,84 @@ def read_csv_data(csv_file_path):
# 读取测试用例xlsx文件中的JSON数据进行数据驱动函数
import
openpyxl
def
read_xlsx_data
(
xlsx_file_path
,
sheet_name
=
None
):
# def read_xlsx_data(xlsx_file_path, sheet_name=None):
# """
# 读取XLSX文件中的数据,并将其转换为一个包含字典的列表,每个字典代表一行测试用例数据。
#
# 参数:
# xlsx_file_path (str): XLSX文件的路径。
# sheet_name (str, optional): 工作表的名称。如果未指定,则使用活动工作表。
#
# 返回:
# list: 包含字典的列表,每个字典包含测试用例的名称和参数。
# """
# try:
# # 打开XLSX文件
# workbook = openpyxl.load_workbook(xlsx_file_path)
# except FileNotFoundError:
# raise FileNotFoundError(f"文件未找到: {xlsx_file_path}")
# except Exception as e:
# raise Exception(f"无法打开文件: {e}")
#
# # 选择工作表
# if sheet_name:
# try:
# sheet = workbook[sheet_name]
# except KeyError:
# raise KeyError(f"工作表未找到: {sheet_name}")
# else:
# sheet = workbook.active
#
# # 读取表头,从第三行开始
# headers = [cell.value for cell in sheet[3]]
#
# # 打印表头列名
# # INFO(f"表头列名: {headers}")
#
# # 找到表头中名为 'JSON' 的列索引
# try:
# json_index = headers.index('JSON')
# except ValueError as e:
# raise ValueError(f"表头中没有找到所需的列: {e}")
#
# ddt_cases = []
# # 遍历XLSX文件中的每一行数据,从第四行开始
# for row_num, row in enumerate(sheet.iter_rows(min_row=4, values_only=True), start=4):
# # 获取 JSON 列的数据
# json_data = row[json_index]
#
# # 打印 JSON 数据以进行调试
# # INFO(f"行 {row_num} 的 JSON 数据: {json_data}")
#
# # 检查 JSON 数据是否为空
# if json_data is None or json_data.strip() == "":
# # INFO(f"跳过行 {row_num},JSON 数据为空")
# continue
#
# # 解析 JSON 字符串
# try:
# parsed_json = json.loads(json_data)
# except json.JSONDecodeError:
# raise ValueError(f"行 {row_num} 的 JSON 数据无法解析: {json_data}")
#
# # 将解析后的 JSON 数据添加到列表中
# ddt_cases.append(parsed_json)
#
# # 日志记录:XLSX文件已读取
# # INFO("XLSX文件已读取")
# # 返回包含所有测试用例数据的列表
# return ddt_cases
# 获取当前进程的 CPU 占用率函数
def
read_xlsx_data
(
xlsx_file_path
,
sheet_name
=
None
,
case_type
=
None
):
"""
读取XLSX文件中的数据,并将其转换为一个包含字典的列表,每个字典代表一行测试用例数据。
参数:
xlsx_file_path (str): XLSX文件的路径。
sheet_name (str, optional): 工作表的名称。如果未指定,则使用活动工作表。
case_type (str, optional): 测试用例类型,例如 '标准版' 或 'XX项目需求'。如果未指定,则读取所有测试用例。
返回:
list: 包含字典的列表,每个字典包含测试用例的名称和参数。
...
...
@@ -499,12 +571,17 @@ def read_xlsx_data(xlsx_file_path, sheet_name=None):
# 打印表头列名
# INFO(f"表头列名: {headers}")
# 找到表头中名为 'JSON' 的列索引
# 找到表头中名为 'JSON'
和 '功能类别'
的列索引
try
:
json_index
=
headers
.
index
(
'JSON'
)
except
ValueError
as
e
:
raise
ValueError
(
f
"表头中没有找到所需的列: {e}"
)
try
:
category_index
=
headers
.
index
(
'版本'
)
except
ValueError
as
e
:
raise
ValueError
(
f
"表头中没有找到所需的列: {e}"
)
ddt_cases
=
[]
# 遍历XLSX文件中的每一行数据,从第四行开始
for
row_num
,
row
in
enumerate
(
sheet
.
iter_rows
(
min_row
=
4
,
values_only
=
True
),
start
=
4
):
...
...
@@ -525,6 +602,13 @@ def read_xlsx_data(xlsx_file_path, sheet_name=None):
except
json
.
JSONDecodeError
:
raise
ValueError
(
f
"行 {row_num} 的 JSON 数据无法解析: {json_data}"
)
# 获取功能类别
category
=
row
[
category_index
]
# 检查是否需要过滤测试用例类型
if
case_type
and
category
!=
case_type
:
continue
# 将解析后的 JSON 数据添加到列表中
ddt_cases
.
append
(
parsed_json
)
...
...
@@ -533,7 +617,6 @@ def read_xlsx_data(xlsx_file_path, sheet_name=None):
# 返回包含所有测试用例数据的列表
return
ddt_cases
# 获取当前进程的 CPU 占用率函数
def
get_cpu_usage
(
interval
=
1
):
"""
获取当前进程的 CPU 占用率。
...
...
统一平台/cases/主流程功能/01创建本地会议.py
浏览文件 @
7822010f
...
...
@@ -10,79 +10,46 @@ sys.path.append(platform_path)
# 导入模块
from
统一平台
.
base
.
bases
import
*
class
Unified_Platform_0001
:
tags
=
[
'统一平台'
,
'创建-本地会议-立即开始'
]
def
teststeps
(
self
):
wd
=
GSTORE
[
'wd'
]
safe_click
((
By
.
XPATH
,
"//p[contains(text(),'新建会议')]"
),
wd
)
wd
.
switch_to
.
window
(
wd
.
window_handles
[
1
])
# 选择会议室
INFO
(
"选择多会议室与参会人"
)
safe_send_keys
((
By
.
XPATH
,
"//input[@placeholder='请输入会议室名称']"
),
'测试会议室'
,
wd
)
send_keyboard
((
By
.
XPATH
,
"//input[@placeholder='请输入会议室名称']"
),
wd
)
# 选择测试会议室的前三个
safe_click
((
By
.
XPATH
,
"//body[1]/div[1]/div[2]/div[1]/div[2]/div[1]/div[2]/div[1]/div[1]/div[4]/div[2]/table[1]/tbody[1]/tr[1]/td[1]/div[1]/label[1]/span[1]/span[1]"
),
wd
)
safe_click
((
By
.
XPATH
,
"//body[1]/div[1]/div[2]/div[1]/div[2]/div[1]/div[2]/div[1]/div[1]/div[4]/div[2]/table[1]/tbody[1]/tr[2]/td[1]/div[1]/label[1]/span[1]/span[1]"
),
wd
)
safe_click
((
By
.
XPATH
,
"//body[1]/div[1]/div[2]/div[1]/div[2]/div[1]/div[2]/div[1]/div[1]/div[4]/div[2]/table[1]/tbody[1]/tr[3]/td[1]/div[1]/label[1]/span[1]/span[1]"
),
wd
)
# 选择参会人分配到第一个会议室
safe_click
((
By
.
XPATH
,
"(//img)[7]"
),
wd
)
safe_send_keys
((
By
.
XPATH
,
"//input[contains(@placeholder,'请输入关键字搜索')]"
),
'pgy'
,
wd
)
send_keyboard
((
By
.
XPATH
,
"//input[contains(@placeholder,'请输入关键字搜索')]"
),
wd
)
# 全选搜索的参会人
safe_click
((
By
.
XPATH
,
"//div[contains(@class,'meeting_user')]//div[contains(@class,'el-table__fixed-header-wrapper')]//span[contains(@class,'el-checkbox__inner')]"
),
wd
)
safe_click
((
By
.
XPATH
,
"//span[contains(text(),'完成')]"
),
wd
)
# 选择参会人分配到第二个会议室
safe_click
((
By
.
XPATH
,
"(//img)[9]"
),
wd
)
safe_send_keys
((
By
.
XPATH
,
"//input[contains(@placeholder,'请输入关键字搜索')]"
),
'测试'
,
wd
)
send_keyboard
((
By
.
XPATH
,
"//input[contains(@placeholder,'请输入关键字搜索')]"
),
wd
)
# 全选搜索的参会人
safe_click
((
By
.
XPATH
,
"//div[contains(@class,'meeting_user')]//div[contains(@class,'el-table__fixed-header-wrapper')]//span[contains(@class,'el-checkbox__inner')]"
),
wd
)
safe_click
((
By
.
XPATH
,
"//span[contains(text(),'完成')]"
),
wd
)
# 获取当前脚本所在的目录
current_dir
=
os
.
path
.
dirname
(
os
.
path
.
abspath
(
__file__
))
# 会议创建,并查看详情
safe_click
((
By
.
XPATH
,
"//span[contains(text(),'确定创建')]"
),
wd
)
safe_click
((
By
.
XPATH
,
"//span[contains(text(),'查看详情')]"
),
wd
)
# 切换窗口2,转到会议详情界面
# wd.switch_to.window(wd.window_handles[1])
INFO
(
"查看会议详情是否正确包含:多会议室、参会人、会议名称、会议时间等信息"
)
SELENIUM_LOG_SCREEN
(
wd
,
"75
%
"
)
# 构建XLSX文件的绝对路径
xlsx_file_path
=
os
.
path
.
join
(
current_dir
,
'..'
,
'..'
,
'data'
,
'统一平台PC端测试用例.xlsx'
)
class
Unified_Platform_0002
:
tags
=
[
'统一平台'
,
'创建-本地会议-预定会议'
]
class
Unified_Platform_0001
:
#执行指令:
# cd ./统一平台/
# hytest --tag 统一平台
tags
=
[
'创建会议'
]
ddt_cases
=
read_xlsx_data
(
xlsx_file_path
,
sheet_name
=
"新建会议&"
)
def
teststeps
(
self
):
wd
=
GSTORE
[
'wd'
]
safe_click
((
By
.
XPATH
,
"(//img[@class='el-tooltip item'])[3]"
),
wd
)
# 选择会议室
INFO
(
"选择多会议室与参会人"
)
safe_send_keys
((
By
.
XPATH
,
"//input[@placeholder='请输入会议室名称']"
),
'测试会议室'
,
wd
)
send_keyboard
((
By
.
XPATH
,
"//input[@placeholder='请输入会议室名称']"
),
wd
)
# 选择测试会议室的前三个
safe_click
((
By
.
XPATH
,
"//body[1]/div[1]/div[2]/div[1]/div[2]/div[1]/div[2]/div[1]/div[1]/div[4]/div[2]/table[1]/tbody[1]/tr[1]/td[1]/div[1]/label[1]/span[1]/span[1]"
),
wd
)
safe_click
((
By
.
XPATH
,
"//body[1]/div[1]/div[2]/div[1]/div[2]/div[1]/div[2]/div[1]/div[1]/div[4]/div[2]/table[1]/tbody[1]/tr[2]/td[1]/div[1]/label[1]/span[1]/span[1]"
),
wd
)
safe_click
((
By
.
XPATH
,
"//body[1]/div[1]/div[2]/div[1]/div[2]/div[1]/div[2]/div[1]/div[1]/div[4]/div[2]/table[1]/tbody[1]/tr[3]/td[1]/div[1]/label[1]/span[1]/span[1]"
),
wd
)
# 选择参会人分配到第一个会议室
safe_click
((
By
.
XPATH
,
"(//img)[7]"
),
wd
)
safe_send_keys
((
By
.
XPATH
,
"//input[contains(@placeholder,'请输入关键字搜索')]"
),
'test'
,
wd
)
send_keyboard
((
By
.
XPATH
,
"//input[contains(@placeholder,'请输入关键字搜索')]"
),
wd
)
# 全选搜索的参会人
safe_click
((
By
.
XPATH
,
"//div[contains(@class,'meeting_user')]//div[contains(@class,'el-table__fixed-header-wrapper')]//span[contains(@class,'el-checkbox__inner')]"
),
wd
)
safe_click
((
By
.
XPATH
,
"//span[contains(text(),'完成')]"
),
wd
)
# 选择参会人分配到第二个会议室
safe_click
((
By
.
XPATH
,
"(//img)[9]"
),
wd
)
safe_send_keys
((
By
.
XPATH
,
"//input[contains(@placeholder,'请输入关键字搜索')]"
),
'admin'
,
wd
)
send_keyboard
((
By
.
XPATH
,
"//input[contains(@placeholder,'请输入关键字搜索')]"
),
wd
)
# 全选搜索的参会人
safe_click
((
By
.
XPATH
,
"//div[contains(@class,'meeting_user')]//div[contains(@class,'el-table__fixed-header-wrapper')]//span[contains(@class,'el-checkbox__inner')]"
),
wd
)
safe_click
((
By
.
XPATH
,
"//span[contains(text(),'完成')]"
),
wd
)
# 会议创建,并查看详情
safe_click
((
By
.
XPATH
,
"//span[contains(text(),'确定创建')]"
),
wd
)
safe_click
((
By
.
XPATH
,
"//span[contains(text(),'查看详情')]"
),
wd
)
# 切换窗口2,转到会议详情界面
# wd.switch_to.window(wd.window_handles[1])
INFO
(
"查看会议详情是否正确包含:多会议室、参会人、会议名称、会议时间等信息"
)
SELENIUM_LOG_SCREEN
(
wd
,
"75
%
"
)
\ No newline at end of file
# 保存当前窗口句柄
original_window
=
wd
.
current_window_handle
# 进入创建会议的页面
safe_click
((
By
.
XPATH
,
"//p[contains(text(),'新建会议')]"
),
wd
)
wd
.
switch_to
.
window
(
wd
.
window_handles
[
1
])
name
=
self
.
name
for
step
in
self
.
para
:
locator_type
=
get_by_enum
(
step
.
get
(
'locator_type'
))
locator_value
=
step
.
get
(
'locator_value'
)
element_type
=
step
.
get
(
'element_type'
)
element_value
=
step
.
get
(
'element_value'
)
expented_result
=
step
.
get
(
'expented_result'
)
print
(
f
"执行JSON:{step}"
)
if
step
.
get
(
"page"
)
==
"CreateMeeting"
:
if
element_type
==
"input"
:
safe_send_keys
((
locator_type
,
locator_value
),
element_value
,
wd
)
sleep
(
1
)
elif
element_type
==
"click"
:
safe_click
((
locator_type
,
locator_value
),
wd
)
sleep
(
1
)
elif
element_type
==
"getText"
:
# 获取提示文本
notify_text
=
elment_get_text
((
locator_type
,
locator_value
),
wd
)
INFO
(
f
"获取弹窗提示内容为:{notify_text}"
)
CHECK_POINT
(
"判断会议是否创建成功"
,
expented_result
==
notify_text
)
SELENIUM_LOG_SCREEN
(
wd
,
"50
%
"
)
# 切换回原来的窗口
wd
.
close
()
# 关闭当前窗口
wd
.
switch_to
.
window
(
original_window
)
# 切换回原来的窗口
\ No newline at end of file
统一平台/cases/主流程功能/03修改会议.py
0 → 100644
浏览文件 @
7822010f
import
sys
import
os
# 获取当前脚本的绝对路径
current_dir
=
os
.
path
.
dirname
(
os
.
path
.
abspath
(
__file__
))
# 构建统一平台的绝对路径
platform_path
=
os
.
path
.
abspath
(
os
.
path
.
join
(
current_dir
,
'..'
,
'..'
,
'..'
))
# 添加路径
sys
.
path
.
append
(
platform_path
)
# 导入模块
from
统一平台
.
base
.
bases
import
*
class
Unified_Platform_0001
:
tags
=
[
'统一平台'
,
'修改本地会议'
]
def
teststeps
(
self
):
wd
=
GSTORE
[
'wd'
]
safe_click
((
By
.
XPATH
,
"//p[contains(text(),'新建会议')]"
),
wd
)
wd
.
switch_to
.
window
(
wd
.
window_handles
[
1
])
# 选择会议室
INFO
(
"选择多会议室与参会人"
)
safe_send_keys
((
By
.
XPATH
,
"//input[@placeholder='请输入会议室名称']"
),
'测试会议室'
,
wd
)
send_keyboard
((
By
.
XPATH
,
"//input[@placeholder='请输入会议室名称']"
),
wd
)
# 选择测试会议室的前三个
safe_click
((
By
.
XPATH
,
"//body[1]/div[1]/div[2]/div[1]/div[2]/div[1]/div[2]/div[1]/div[1]/div[4]/div[2]/table[1]/tbody[1]/tr[1]/td[1]/div[1]/label[1]/span[1]/span[1]"
),
wd
)
safe_click
((
By
.
XPATH
,
"//body[1]/div[1]/div[2]/div[1]/div[2]/div[1]/div[2]/div[1]/div[1]/div[4]/div[2]/table[1]/tbody[1]/tr[2]/td[1]/div[1]/label[1]/span[1]/span[1]"
),
wd
)
safe_click
((
By
.
XPATH
,
"//body[1]/div[1]/div[2]/div[1]/div[2]/div[1]/div[2]/div[1]/div[1]/div[4]/div[2]/table[1]/tbody[1]/tr[3]/td[1]/div[1]/label[1]/span[1]/span[1]"
),
wd
)
# 选择参会人分配到第一个会议室
safe_click
((
By
.
XPATH
,
"(//img)[7]"
),
wd
)
safe_send_keys
((
By
.
XPATH
,
"//input[contains(@placeholder,'请输入关键字搜索')]"
),
'pgy'
,
wd
)
send_keyboard
((
By
.
XPATH
,
"//input[contains(@placeholder,'请输入关键字搜索')]"
),
wd
)
# 全选搜索的参会人
safe_click
((
By
.
XPATH
,
"//div[contains(@class,'meeting_user')]//div[contains(@class,'el-table__fixed-header-wrapper')]//span[contains(@class,'el-checkbox__inner')]"
),
wd
)
safe_click
((
By
.
XPATH
,
"//span[contains(text(),'完成')]"
),
wd
)
# 选择参会人分配到第二个会议室
safe_click
((
By
.
XPATH
,
"(//img)[9]"
),
wd
)
safe_send_keys
((
By
.
XPATH
,
"//input[contains(@placeholder,'请输入关键字搜索')]"
),
'测试'
,
wd
)
send_keyboard
((
By
.
XPATH
,
"//input[contains(@placeholder,'请输入关键字搜索')]"
),
wd
)
# 全选搜索的参会人
safe_click
((
By
.
XPATH
,
"//div[contains(@class,'meeting_user')]//div[contains(@class,'el-table__fixed-header-wrapper')]//span[contains(@class,'el-checkbox__inner')]"
),
wd
)
safe_click
((
By
.
XPATH
,
"//span[contains(text(),'完成')]"
),
wd
)
# 会议创建,并查看详情
safe_click
((
By
.
XPATH
,
"//span[contains(text(),'确定创建')]"
),
wd
)
safe_click
((
By
.
XPATH
,
"//span[contains(text(),'查看详情')]"
),
wd
)
# 切换窗口2,转到会议详情界面
# wd.switch_to.window(wd.window_handles[1])
INFO
(
"查看会议详情是否正确包含:多会议室、参会人、会议名称、会议时间等信息"
)
SELENIUM_LOG_SCREEN
(
wd
,
"75
%
"
)
class
Unified_Platform_0002
:
tags
=
[
'统一平台'
,
'修改-视讯会议'
]
def
teststeps
(
self
):
wd
=
GSTORE
[
'wd'
]
safe_click
((
By
.
XPATH
,
"(//img[@class='el-tooltip item'])[3]"
),
wd
)
# 选择会议室
INFO
(
"选择多会议室与参会人"
)
safe_send_keys
((
By
.
XPATH
,
"//input[@placeholder='请输入会议室名称']"
),
'测试会议室'
,
wd
)
send_keyboard
((
By
.
XPATH
,
"//input[@placeholder='请输入会议室名称']"
),
wd
)
# 选择测试会议室的前三个
safe_click
((
By
.
XPATH
,
"//body[1]/div[1]/div[2]/div[1]/div[2]/div[1]/div[2]/div[1]/div[1]/div[4]/div[2]/table[1]/tbody[1]/tr[1]/td[1]/div[1]/label[1]/span[1]/span[1]"
),
wd
)
safe_click
((
By
.
XPATH
,
"//body[1]/div[1]/div[2]/div[1]/div[2]/div[1]/div[2]/div[1]/div[1]/div[4]/div[2]/table[1]/tbody[1]/tr[2]/td[1]/div[1]/label[1]/span[1]/span[1]"
),
wd
)
safe_click
((
By
.
XPATH
,
"//body[1]/div[1]/div[2]/div[1]/div[2]/div[1]/div[2]/div[1]/div[1]/div[4]/div[2]/table[1]/tbody[1]/tr[3]/td[1]/div[1]/label[1]/span[1]/span[1]"
),
wd
)
# 选择参会人分配到第一个会议室
safe_click
((
By
.
XPATH
,
"(//img)[7]"
),
wd
)
safe_send_keys
((
By
.
XPATH
,
"//input[contains(@placeholder,'请输入关键字搜索')]"
),
'test'
,
wd
)
send_keyboard
((
By
.
XPATH
,
"//input[contains(@placeholder,'请输入关键字搜索')]"
),
wd
)
# 全选搜索的参会人
safe_click
((
By
.
XPATH
,
"//div[contains(@class,'meeting_user')]//div[contains(@class,'el-table__fixed-header-wrapper')]//span[contains(@class,'el-checkbox__inner')]"
),
wd
)
safe_click
((
By
.
XPATH
,
"//span[contains(text(),'完成')]"
),
wd
)
# 选择参会人分配到第二个会议室
safe_click
((
By
.
XPATH
,
"(//img)[9]"
),
wd
)
safe_send_keys
((
By
.
XPATH
,
"//input[contains(@placeholder,'请输入关键字搜索')]"
),
'admin'
,
wd
)
send_keyboard
((
By
.
XPATH
,
"//input[contains(@placeholder,'请输入关键字搜索')]"
),
wd
)
# 全选搜索的参会人
safe_click
((
By
.
XPATH
,
"//div[contains(@class,'meeting_user')]//div[contains(@class,'el-table__fixed-header-wrapper')]//span[contains(@class,'el-checkbox__inner')]"
),
wd
)
safe_click
((
By
.
XPATH
,
"//span[contains(text(),'完成')]"
),
wd
)
# 会议创建,并查看详情
safe_click
((
By
.
XPATH
,
"//span[contains(text(),'确定创建')]"
),
wd
)
safe_click
((
By
.
XPATH
,
"//span[contains(text(),'查看详情')]"
),
wd
)
# 切换窗口2,转到会议详情界面
# wd.switch_to.window(wd.window_handles[1])
INFO
(
"查看会议详情是否正确包含:多会议室、参会人、会议名称、会议时间等信息"
)
SELENIUM_LOG_SCREEN
(
wd
,
"75
%
"
)
\ No newline at end of file
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论