From 69cb305d0d108d8c0695aa4e80c4408366d00634 Mon Sep 17 00:00:00 2001 From: floraachy <9497495+floraachy@user.noreply.gitee.com> Date: Wed, 10 Aug 2022 06:04:27 +0000 Subject: [PATCH] =?UTF-8?q?gitee=E4=B8=8A=E4=BC=A0=E7=9A=84html=E6=96=87?= =?UTF-8?q?=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...st-html报告修改与汉化_假脸的博客-CSDN博客.html | 3005 +++++++++++++++++ 1 file changed, 3005 insertions(+) create mode 100644 第十五:Pytest-html报告修改与汉化_假脸的博客-CSDN博客.html diff --git a/第十五:Pytest-html报告修改与汉化_假脸的博客-CSDN博客.html b/第十五:Pytest-html报告修改与汉化_假脸的博客-CSDN博客.html new file mode 100644 index 0000000..5feb93f --- /dev/null +++ b/第十五:Pytest-html报告修改与汉化_假脸的博客-CSDN博客.html @@ -0,0 +1,3005 @@ + + + + + + + + + + + + + + + + + 第十五:Pytest-html报告修改与汉化_假脸的博客-CSDN博客 + + + + + + + + + + + + + + + + +
+
+ +
+
+ + + + + + + +
+
+ +
+ +
+
+
+
+

第十五:Pytest-html报告修改与汉化

+
+ +
+
+ + +
+
+ +
+ + + +

项目目录
在这里插入图片描述

+

一.实例生成报告(和python2.7配合使用无法生成报告)

+

test_pytest_html_one.py

+
import pytest
+
+
+def login(username,password):
+    """ 模拟登录 """
+    user = "linux超"
+    pwd = "linux超哥"
+
+    if user == username and pwd == password:
+        return {"code":1001,"msg":"登录成功","data":None}
+    else:
+        return {"code":1000,"msg":"用户名或密码错误","data":None}
+
+
+test_data = [
+    # 测试数据
+    {
+        "case": "用户名正确, 密码正确",
+        "user": "xxx",
+        "pwd": "xxx",
+        "expected": {"code": 1001, "msg": "登录成功", "data": None}
+    },
+    {
+        "case": "用户名正确, 密码为空",
+        "user": "xxx",
+        "pwd": "",
+        "expected": {"code": 1000, "msg": "用户名或密码错误", "data": None}
+    },
+    {
+        "case": "用户名为空, 密码正确",
+        "user": "",
+        "pwd": "xxx",
+        "expected": {"code": 1000, "msg": "用户名或密码错误", "data": None}
+    },
+    {
+        "case": "用户名错误, 密码错误",
+        "user": "x",
+        "pwd": "x",
+        "expected": {"code": 1000, "msg": "用户名或密码错误", "data": None}
+    }
+]
+
+
+# 修改Results:改变输出结果
+ids = [
+    "测试:{}->[用户名:{}-密码:{}-预期:{}]".
+        format(data["case"], data["user"], data["pwd"], data["expected"]) for data in test_data
+]
+
+
+class TestLogin(object):
+    # 添加ids参数
+    @pytest.mark.parametrize("data",test_data,ids=ids)
+    def test_login(self,data):
+        result = login(data["user"],data["pwd"])
+        assert result == data["expected"]
+
+
+if __name__ == "__main__":
+    pytest.main(['-sv',"G:\\pytestbasics\\test_pytest_html_case","--html", "report.html"])
+
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
+

在这里插入图片描述

+

1.修改Environment
在这里插入图片描述
1.1.在Environment中删除Java_Home,添加测试接口地址该如何添加?

+

1.2.在项目的根目录新键conftest.py文件。

+

conftest.py

+
def pytest_configure(config):
+    # 添加接口地址与项目名称
+    config._metadata["项目名称"] = "xxxxxx"
+    config._metadata['接口地址'] = 'xxxxxx'
+    # 删除Java_Home
+    config._metadata.pop("JAVA_HOME")
+
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
+

在这里插入图片描述

+

2.修改Summary
在这里插入图片描述
2.1.原始的报告中Summary部分只显示了测试用例数及用例执行时间,那么如果想在这个位置添加测试人员等一些信息该如何实现?

+

conftest.py

+
@pytest.mark.optionalhook
+def pytest_html_results_summary(prefix):
+    prefix.extend([html.p("所属部门: xxx")])
+    prefix.extend([html.p("测试人员: xxx")])
+
  • 1
  • 2
  • 3
  • 4
+

在这里插入图片描述

+

3.修改Results:Results主要展示的是测试结果信息,比如Test列显示的内容很长,它主要是测试用例所在的路径及测试类,测试用例及测试数据拼接而成的,可读性很差。所以改成显:测试+用例名称[user:用户名-pwd:密码] 。
在这里插入图片描述
4.优化Test
在这里插入图片描述
4.1.原始的测试报告的Test列表的信息是怎么生成的。找到pytest-html插件的安装位置,打开plugin.py文件。

+
class TestResult:
+    def __init__(self, outcome, report, logfile, config):
+        self.test_id = report.nodeid
+        
+        if getattr(report, "when", "call") != "call":
+            self.test_id = "::".join([report.nodeid, report.when])
+            self.time = getattr(report, "duration", 0.0)
+            self.outcome = outcome
+
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
+

4.2.第3行,5行,就是报告中Test信息的来源,test_pytest_html_one.py::TestLogin::test_login[data0] 这样一条信息,实际是用例的nodeid,而【data0】是测试用例参数化时的每个参数。
其中参数化方法@pytest.mark.parametrize(“data”, test_data)的参数ids的作用主要就是用来标记测试用例(第9篇文章),增加测试用例执行后输出信息的可读性,因此可以使用这个参数来改变【data0】,让它显测试数据。

+

conftest.py

+
# 改变输出结果
+ids = [
+    "测试:{}->[用户名:{}-密码:{}-预期:{}]".
+        format(data["case"], data["user"], data["pwd"], data["expected"]) for data in test_data
+]
+
+class TestLogin(object):
+    # 添加ids参数
+    @pytest.mark.parametrize("data", test_data, ids=ids)
+    def test_login(self, data):
+        result = login(data["user"], data["pwd"])
+        assert result == data["expected"]
+
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
+

在这里插入图片描述
4.3.中文部分显示的都是乱码。

+

4.4.解决中文乱码

+

conftest.py

+
import pytest
+from py._xmlgen import html
+
+@pytest.mark.hookwrapper
+def pytest_runtest_makereport(item):
+    outcome = yield
+    report = outcome.get_result()
+    getattr(report, 'extra', [])
+    report.nodeid = report.nodeid.encode("utf-8").decode("unicode_escape")  # 解决乱码
+
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
+

在这里插入图片描述

+

5.删除多余部分
在这里插入图片描述
5.1.要删除前面多余的部分,查看html报告的页面元素属性。
在这里插入图片描述
5.2.使用js代码改变这个元素的innerText。

+
// 找到Test列中所有的表格元素
+var test_name = document.getElementBysClassName("col-name");
+// 修改第1个表格的innerText属性
+test_name[0].innerText = test_name[0].innerText.split("\[")[1].split(["\]")[0];  //[符号分割一次,再以]分割一次,得到目标字符串
+
  • 1
  • 2
  • 3
  • 4
+

在这里插入图片描述
5.3.前面的代码只能修改一个表格,如果要修改多个表格只能使用循环。

+
var case_name_td = document.getElementsByClassName("col-name")
+    for(var i = 0; i < case_name_td.length; i++)
+        try{
+            case_name_td[i].innerText = case_name_td[i].innerText.split("\[")[1].split("\]")[0];
+        }
+        catch(err){
+            // 如果表格中没有[]会抛异常,如果抛异常我就显示null,如果你想显示别的东西自己改吧,因为通常只要我们使用参数化就有[]显示
+            case_name_td[i].innerText = "null";
+        }
+
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
+

5.4.js代码写好了但是要放在哪里?通过查看报告的html源码发现在html代码的开头引入了这样一些代码。
在这里插入图片描述
5.5.在pytest-html插件的源码中发现插件的resource目录下有main.js文件,里面的代码就是上述html代码中的js脚本。
在这里插入图片描述

+

5.6.在main.js中确实存在init()方法,因此把编写的js代码放到init()方法内部。

+
function init () {
+    reset_sort_headers();
+
+    add_collapse();
+
+    show_filters();
+
+    toggle_sort_states(find('.initial-sort'));
+
+    find_all('.sortable').forEach(function(elem) {
+        elem.addEventListener("click",
+                              function(event) {
+                                  sort_column(elem);
+                              }, false)
+    });
+    // 修改用例报告显示的用例名称
+    var case_name_td = document.getElementsByClassName("col-name")
+        for(var i = 0; i < case_name_td.length; i++)
+            try{
+                case_name_td[i].innerText = case_name_td[i].innerText.split("\[")[1].split("\]")[0];
+            }
+            catch(err){
+                // 如果表格中没有[]会抛异常,如果抛异常我就显示null,如果你想显示别的东西自己改吧,因为通常只要我们使用参数化就有[]显示
+                case_name_td[i].innerText = "null";
+            }
+};
+
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
+

在这里插入图片描述

+

6.删除Links
在这里插入图片描述
conftest.py

+
@pytest.mark.optionalhook
+def pytest_html_results_table_header(cells):
+    cells.pop(-1)  # 删除link列
+
+@pytest.mark.optionalhook
+def pytest_html_results_table_row(report, cells):
+    cells.pop(-1)  # 删除link列
+
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
+

在这里插入图片描述

+

7.增加失败截图与用例描述

+

https://blog.csdn.net/hyq413950612/article/details/123743418?spm=1001.2014.3001.5502

+

https://blog.csdn.net/hyq413950612/article/details/123790898

+

二.完整的conftest.py文件

+
import pytest
+from selenium import webdriver
+from py._xmlgen import html
+
+_driver = None
+# 测试失败时添加截图和测试用例描述(用例的注释信息)
+
+@pytest.mark.hookwrapper
+def pytest_runtest_makereport(item):
+    """当测试失败的时候,自动截图,展示到html报告中"""
+    pytest_html = item.config.pluginmanager.getplugin('html')
+    outcome = yield
+    report = outcome.get_result()
+    extra = getattr(report, 'extra', [])
+
+    if report.when == 'call' or report.when == "setup":
+        xfail = hasattr(report, 'wasxfail')
+        if (report.skipped and xfail) or (report.failed and not xfail):
+            file_name = report.nodeid.replace("::", "_")+".png"
+            screen_img = _capture_screenshot()
+            if file_name:
+                html = '<div><img src="data:image/png;base64,%s" alt="screenshot" style="width:600px;height:300px;" ' \
+                       'οnclick="window.open(this.src)" align="right"/></div>' % screen_img
+                extra.append(pytest_html.extras.html(html))
+            report.extra = extra
+
+    extra.append(pytest_html.extras.text('some string', name='Different title'))
+    report.description = str(item.function.__doc__)
+    report.nodeid = report.nodeid.encode("utf-8").decode("unicode_escape")  # 解决乱码
+
+
+
+def _capture_screenshot():
+    '''截图保存为base64'''
+    return _driver.get_screenshot_as_base64()
+
+
+def pytest_configure(config):
+    # 添加接口地址与项目名称
+    config._metadata["项目名称"] = "Linux超博客园自动化测试项目v1.0"
+    config._metadata['接口地址'] = 'https://www.cnblogs.com/linuxchao/'
+    # 删除Java_Home
+    config._metadata.pop("JAVA_HOME")
+
+
+@pytest.mark.optionalhook
+def pytest_html_results_summary(prefix):
+    prefix.extend([html.p("所属部门: xx测试中心")])
+    prefix.extend([html.p("测试人员: Linux超")])
+
+
+@pytest.mark.optionalhook
+def pytest_html_results_table_header(cells):
+    cells.insert(1, html.th('Description'))
+    cells.pop(-1)  # 删除link列
+
+
+@pytest.mark.optionalhook
+def pytest_html_results_table_row(report, cells):
+    cells.insert(1, html.td(report.description))
+    cells.pop(-1)  # 删除link列
+
+
+def pytest_configure(config):
+    # 添加接口地址与项目名称
+    config._metadata["项目名称"] = "xxxxx"
+    config._metadata['接口地址'] = 'xxxxx'
+    # 删除Java_Home
+    config._metadata.pop("JAVA_HOME")
+
+
+@pytest.fixture(scope='module')     #或者改成session
+def driver():
+    global _driver
+    _driver = webdriver.Chrome()
+
+    yield _driver
+    _driver.quit()
+
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
+

三.汉化报告
在这里插入图片描述
1.修改plugin.py文件主要用来生成测试报告的html代码。

+
# if len(log) == 0:
+#     log = html.div(class_='empty log')
+#     log.append('No log output captured.')
+if len(log) == 0:
+       log = html.div(class_='empty log')
+       log.append('未捕获到日志')
+additional_html.append(log)
+
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
+
# head = html.head(
+#     html.meta(charset='utf-8'),
+#     html.title('Test Report'),
+#     html_css)
+head = html.head(
+       html.meta(charset='utf-8'),
+       html.title('测试报告'),
+       html_css)
+
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
+
# outcomes = [Outcome('passed', self.passed),
+#             Outcome('skipped', self.skipped),
+#             Outcome('failed', self.failed),
+#             Outcome('error', self.errors, label='errors'),
+#             Outcome('xfailed', self.xfailed,
+#                     label='expected failures'),
+#             Outcome('xpassed', self.xpassed,
+#                     label='unexpected passes')]
+outcomes = [Outcome('passed', self.passed, label="通过"),
+            Outcome('skipped', self.skipped, label="跳过"),
+            Outcome('failed', self.failed, label="失败"),
+            Outcome('error', self.errors, label='错误'),
+            Outcome('xfailed', self.xfailed,
+                    label='预期失败'),
+            Outcome('xpassed', self.xpassed,
+                    label='预期通过')]
+
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
+
# if self.rerun is not None:
+#     outcomes.append(Outcome('rerun', self.rerun))
+if self.rerun is not None:
+    outcomes.append(Outcome('重跑', self.rerun))
+
+# summary = [html.p(
+#     '{0} tests ran in {1:.2f} seconds. '.format(
+#         numtests, suite_time_delta)),
+#     html.p('sfsf',
+#            class_='filter',
+#            hidden='true')]
+summary = [html.p(
+    '执行了{0}个测试用例, 历时:{1:.2f}秒 . '.format(
+        numtests, suite_time_delta)),
+    html.p('(取消)勾选复选框, 以便筛选测试结果',
+           class_='filter',
+           hidden='true')]
+
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
+
# cells = [
+#     html.th('Result',
+#             class_='sortable result initial-sort',
+#             col='result'),
+#     html.th('Test', class_='sortable', col='name'),
+#     html.th('Duration', class_='sortable numeric', col='duration'),
+#     html.th('Links')]
+cells = [
+    html.th('通过/失败',
+            class_='sortable result initial-sort',
+            col='result'),
+    html.th('用例', class_='sortable', col='name'),
+    html.th('耗时', class_='sortable numeric', col='duration'),
+    html.th('链接')]
+
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
+
# results = [html.h2('Results'), html.table([html.thead(
+#     html.tr(cells),
+#     html.tr([
+#         html.th('No results found. Try to check the filters',
+#                 colspan=len(cells))],
+#             id='not-found-message', hidden='true'),
+#     id='results-table-head'),
+#     self.test_logs], id='results-table')]
+results = [html.h2('测试结果'), html.table([html.thead(
+    html.tr(cells),
+    html.tr([
+        html.th('无测试结果, 试着选择其他测试结果条件',
+                colspan=len(cells))],
+            id='not-found-message', hidden='true'),
+    id='results-table-head'),
+    self.test_logs], id='results-table')]
+
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
+
#html.p('Report generated on {0} at {1} by '.format( 
+html.p('生成报告时间{0} {1} Pytest-Html版本:'.format( 
+
  • 1
  • 2
+
# body.extend([html.h2('Summary')] + summary_prefix
+#             + summary + summary_postfix)
+body.extend([html.h2('用例统计')] + summary_prefix  
+            + summary + summary_postfix)
+
  • 1
  • 2
  • 3
  • 4
+
# environment = [html.h2('Environment')]
+environment = [html.h2('测试环境')]  
+
  • 1
  • 2
+

2.修改main.js文件。

+
/*
+function add_collapse() {
+    // Add links for show/hide all
+    var resulttable = find('table#results-table');
+    var showhideall = document.createElement("p");
+    showhideall.innerHTML = '<a href="javascript:show_all_extras()">Show all details</a> / ' +
+                            '<a href="javascript:hide_all_extras()">Hide all details</a>';
+    resulttable.parentElement.insertBefore(showhideall, resulttable);
+*/
+function add_collapse() { 
+    // Add links for show/hide all
+    var resulttable = find('table#results-table');
+    var showhideall = document.createElement("p");
+    showhideall.innerHTML = '<a href="javascript:show_all_extras()">显示详情</a> / ' +
+                            '<a href="javascript:hide_all_extras()">隐藏详情</a>';
+    resulttable.parentElement.insertBefore(showhideall, resulttable);
+
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
+

3.修改style.css文件主要用来美化测试报告的。

+
.expander::after {
+    content: " (展开详情)";
+    color: #BBB;
+    font-style: italic;
+    cursor: pointer;
+}
+.collapser::after {
+    content: " (隐藏详情)";
+    color: #BBB;
+    font-style: italic;
+    cursor: pointer;
+}
+
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
+

在这里插入图片描述

+

四.安装汉化版插件

+

1.汉化版的pytest-html插件源码上传到GitHub。
https://github.com/13691579846/pytest-html

+

2.方法一:

+

2.1.如果已经安装过pytest-html,先卸载 pip uninstall pytest-html

+

2.2.下载插件源码到本地
git clone https://github.com/13691579846/pytest-html

+

2.3.打开CMD切换到插件中setup.py文件所在目录,执行命令python setup.py install
在这里插入图片描述

+

3.方法二:

+

3.1.如果未安装过pytest-html插件,请先执行如下命令安装
pip install pytest-html

+

3.2.按照方法1的方式下载汉化后的插件,把下载后的插件中的部分附件覆盖到第三方库目录下pytest-html下的部分文件
在这里插入图片描述

+

4.方法三:

+

4.1.直接下载汉化后的源码,把源码中的pytest_html直接丢到python第三方库存放目录即可。

+
+ + +
+ +
+ +
+
+
+
+ +
+ 关注 + +
+
+
+ +
+
+ +
+
+
+ + + + +
+ + + +
+
参与评论
+
+
+ + + +
+
+ + +
+
+ 还能输入1000个字符 +
+
+   +
+
+
+ 表情包 + 插入表情 + +
+
+ 表情包 + 代码片 + +
+
+ + + + + +
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+ + + + +
+ +
+ + + + +
+
+
+ +
+ +
+ 04-03 + + 1009 + +
+
+
+ +
+
+ + + + + + + + + +
+
+

“相关推荐”对你有帮助么?

+
+
    +
  • +
    + + +
    +
    非常没帮助
    +
  • +
  • +
    + + +
    +
    没帮助
    +
  • +
  • +
    + + +
    +
    一般
    +
  • +
  • +
    + + +
    +
    有帮助
    +
  • +
  • +
    + + +
    +
    非常有帮助
    +
  • +
+
+
+ + 提交 +
+
+
+
+ ©️2022 CSDN + 皮肤主题:大白 + 设计师:CSDN官方博客 + + 返回首页 + +
+ + +
+ + + +
+
+ +
+ + + +
+
+ +
+
+
+

打赏作者

+
+
+ + + +
+
+

假脸

+

你的鼓励将是我创作的最大动力

+
+
+
+
+
+
+ ¥2 + ¥4 + ¥6 + ¥10 + ¥20 + +
输入1-500的整数
+
+
+
+ + + 余额支付 + (余额:-- ) +
+
+ + + 扫码支付 +
+
+
+
+
+
+ 扫码支付:¥2 +
+
+
+ + 获取中 +
+
+
+ + + 扫码支付 +
+
+
+
+

您的余额不足,请更换扫码支付或充值

+

打赏作者

+
+
+
+
+
实付
+
使用余额支付
+
+
+
+ + 点击重新获取 +
+
+
扫码支付
+
+
+ +
+ + 钱包余额 + 0 +
+ +
+
+

抵扣说明:

+

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

+
+
+
+
+ 余额充值 +
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + +

举报

选择你想要举报的内容(必选)
  • 内容涉黄
  • 政治相关
  • 内容抄袭
  • 涉嫌广告
  • 内容侵权
  • 侮辱谩骂
  • 样式问题
  • 其他
+
+ + + + 新手
引导
+
+ + + + + + + 客服 + + + + + + 举报 + + + + + + 返回
顶部
+
+ +
+
\ No newline at end of file