提交 e5cb4bc2 authored 作者: 陈泽健's avatar 陈泽健

上传预定系统登录模块代码

上级 27893344
# 默认忽略的文件
/shelf/
/workspace.xml
# 基于编辑器的 HTTP 客户端请求
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml
预定系统标准版
\ No newline at end of file
<component name="InspectionProjectProfileManager">
<settings>
<option name="USE_PROJECT_PROFILE" value="false" />
<version value="1.0" />
</settings>
</component>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Black">
<option name="sdkName" value="Python 3.10 (pythonProject1)" />
</component>
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.10 (pythonProject1)" project-jdk-type="Python SDK" />
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/预定系统标准版.iml" filepath="$PROJECT_DIR$/.idea/预定系统标准版.iml" />
</modules>
</component>
</project>
\ No newline at end of file
此差异已折叠。
<?xml version="1.0" encoding="UTF-8"?>
<module type="PYTHON_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/.venv" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>
\ No newline at end of file
import pytest
import logging
import os
import csv
import configparser
from selenium.common import StaleElementReferenceException
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from 登录模块.base.Broswer_driver import Browser_driver
# 初始化日志记录器
logging.basicConfig(level=logging.ERROR, format='%(asctime)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
def read_csv_data(file_path=None):
"""
读取 CSV 文件数据
"""
data = []
if file_path is None:
file_path = os.getenv('CSV_FILE_PATH', 'Login_Test.csv')
try:
with open(file_path, mode='r', encoding='utf-8') as csvfile:
csv_reader = csv.DictReader(csvfile)
for row in csv_reader:
data.append((row['username'], row['password'], row['verification_code']))
except FileNotFoundError:
logger.error("CSV 文件未找到,请检查文件路径")
pytest.exit("CSV 文件未找到,请检查文件路径")
except csv.Error as e:
logger.error(f"CSV 格式错误: {e}")
pytest.exit(f"CSV 格式错误: {e}")
except Exception as e:
logger.error(f"出现错误: {e}")
pytest.exit(f"出现错误: {e}")
return data
@pytest.fixture(scope='session')
def driver():
"""
初始化浏览器并打开指定URL
"""
url = 'https://nat.ubainsyun.com:11046'
logging.info("'----------' 正在初始化浏览器 '----------'")
try:
driver = Browser_driver().browser_init()
logging.info("'----------' 浏览器初始化成功 '----------'")
except Exception as e:
logging.error(f"浏览器初始化失败: {e}")
raise
driver.implicitly_wait(10)
driver.maximize_window()
logging.info("'----------' 正在打开URL '----------'")
try:
driver.get(url)
logging.info(f"成功打开URL: {url}")
except Exception as e:
logging.error(f"打开URL失败: {e}")
raise
handle_ssl_warning(driver)
yield driver
driver.quit()
def handle_ssl_warning(driver):
"""
处理 SSL 证书警告
"""
try:
logging.info("'----------' 正在处理SSL证书警告 '----------'")
WebDriverWait(driver, 10).until(
EC.element_to_be_clickable((By.XPATH, '//*[@id="details-button"]'))
).click()
WebDriverWait(driver, 10).until(
EC.element_to_be_clickable((By.XPATH, '//*[@id="proceed-link"]'))
).click()
WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.TAG_NAME, 'body'))
)
logging.info("'----------' SSL证书警告处理完成 '----------'")
except Exception as e:
logging.error(f"处理 SSL 证书警告遇到错误: {e}")
raise
def _find_element(driver, by, value):
"""
查找元素,并处理可能的异常
"""
try:
return WebDriverWait(driver, 20).until(
EC.presence_of_element_located((by, value))
)
except StaleElementReferenceException:
return WebDriverWait(driver, 20).until(
EC.presence_of_element_located((by, value))
)
def send_sms_verification_code(driver, phone_number):
"""
模拟发送短信验证码
"""
# 假设有一个发送短信验证码的API接口
# 这里只是一个示例,实际应用中需要调用真实的API
logging.info(f"模拟发送短信验证码至 {phone_number}")
def perform_login(driver, username, password, verification_code):
"""
执行登录操作
"""
driver.implicitly_wait(5)
driver.refresh()
try:
username_input = _find_element(driver, By.XPATH, '//*[@id="app"]/div/div[3]/div[1]/div[2]/div/form/div[1]/div/input')
username_input.clear()
username_input.send_keys(username)
password_input = _find_element(driver, By.XPATH, '//*[@id="app"]/div/div[3]/div[1]/div[2]/div/form/div[2]/div/input')
password_input.clear()
password_input.send_keys(password)
# 假设验证码已经发送并接收
send_sms_verification_code(driver, username) # 发送验证码
verification_input = _find_element(driver, By.XPATH, '//*[@id="app"]/div/div[3]/div[1]/div[2]/div/form/div[3]/div[1]/div/input')
verification_input.clear()
verification_input.send_keys(verification_code)
login_button = _find_element(driver, By.XPATH, '//*[@id="app"]/div/div[3]/div[1]/div[2]/div/form/div[4]/input')
login_button.click()
if check_login_null(driver):
logger.info("登录失败,必填项不能为空!断言成功!")
elif check_login_success(driver):
logger.info("登录成功,断言成功!")
return_to_login_page(driver)
elif check_login_failure(driver):
logger.info("登录失败, 必填项错误!断言成功!")
else:
logger.error("登录状态未知,断言失败!")
pytest.fail("登录状态未知,断言失败!")
except StaleElementReferenceException as e:
logger.error(f"元素已失效,重新查找... {e}")
pytest.fail(f"元素已失效,重新查找... {e}")
except Exception as e:
logger.error(f"登录操作失败: {e}")
pytest.fail(f"登录操作失败: {e}")
def return_to_login_page(driver):
"""
返回登录页面
"""
try:
logout_button = _find_element(driver, By.XPATH, '//*[@id="app"]/div/div[1]/div/img[3]')
logout_button.click()
logging.info("已成功返回登录页面")
driver.refresh()
driver.implicitly_wait(5)
except Exception as e:
logger.error(f"返回登录页面失败: {e}")
pytest.fail(f"返回登录页面失败: {e}")
def check_login_null(driver):
"""
检查登录失败,必填项为空的情况
"""
try:
login_element_text = WebDriverWait(driver, 10).until(
EC.visibility_of_element_located((By.XPATH, '/html/body/div[2]/p'))
).text
assert "请输入" in login_element_text, "登录失败后未找到'请输入'提示语"
return True
except Exception as e:
logger.error(f"登录失败检查失败: {e}")
return False
def check_login_success(driver):
"""
检查登录成功的情况
"""
try:
message_element_text = WebDriverWait(driver, 10).until(
EC.visibility_of_element_located((By.XPATH, "//*[contains(text(), '欢迎')]"))
).text
assert "欢迎 预定标准版测试" == message_element_text, "登录成功后找到'欢迎 预定标准版测试'提示语"
return True
except Exception as e:
logger.error(f"登录成功检查失败: {e}")
return False
def check_login_failure(driver):
"""
检查登录失败的情况
"""
try:
login_element_text = WebDriverWait(driver, 10).until(
EC.visibility_of_element_located((By.XPATH, '//*[@id="app"]/div/div[3]/div[1]/div[1]/div[1]'))
).text
assert "账号登录" == login_element_text, "登录失败后未找到'账号登录'提示语"
return True
except Exception as e:
logger.error(f"登录失败检查失败: {e}")
return False
@pytest.mark.parametrize("username,password,verification_code", read_csv_data())
def test_login_from_csv(driver, username, password, verification_code):
"""
从 CSV 文件读取并测试登录情况
"""
logger.info(f"'----------' 开始执行测试 '----------'")
perform_login(driver, username, password, verification_code)
logger.info(f"'----------' 执行完成测试 '----------'")
driver.implicitly_wait(10)
if __name__ == '__main__':
pytest.main()
username,password,verification_code
admin@czj,Ubains@4321,
,Ubains@4321,csba
admin@czj,Ubains@4321,
,Ubains@4321,csba
admin@czj,Ubains@4321,
,Ubains@4321,csba
admin@czj2,Ubains@4321,csba
admin@czj,Ubains@4321,csba
admin@,Ubains@4321,csba
admin@czj,Ubains@4321,
,Ubains@4321,csba
admin@czj,Ubains@4321,
,Ubains@4321,csba
admin@czj,Ubains@4321,
,Ubains@4321,csba
admin@czj2,Ubains@4321,csba
admin@czj,Ubains@4321,csba
admin@,Ubains@4321,csba
admin@czj,Ubains@4321,
,Ubains@4321,csba
admin@czj,Ubains@4321,
admin@czj,Ubains@4321,
,Ubains@4321,csba
admin@czj,Ubains@4321,
,Ubains@4321,csba
admin@czj,Ubains@4321,
,Ubains@4321,csba
admin@czj2,Ubains@4321,csba
admin@czj,Ubains@4321,csba
admin@,Ubains@4321,csba
admin@czj,Ubains@4321,
,Ubains@4321,csba
admin@czj,Ubains@4321,
,Ubains@4321,csba
admin@czj,Ubains@4321,
,Ubains@4321,csba
admin@czj2,Ubains@4321,csba
admin@czj,Ubains@4321,csba
admin@,Ubains@4321,csba
admin@czj,Ubains@4321,
,Ubains@4321,csba
admin@czj,Ubains@4321,
,Ubains@4321,csba
admin@czj,Ubains@4321,
,Ubains@4321,csba
admin@czj2,Ubains@4321,csba
admin@czj,Ubains@4321,csba
admin@,Ubains@4321,csba
admin@czj,Ubains@4321,
,Ubains@4321,csba
admin@czj,Ubains@4321,
,Ubains@4321,csba
admin@czj,Ubains@4321,
,Ubains@4321,csba
admin@czj2,Ubains@4321,csba
admin@czj,Ubains@4321,csba
admin@,Ubains@4321,csba
admin@czj,Ubains@4321,
,Ubains@4321,csba
admin@czj,Ubains@4321,
,Ubains@4321,csba
admin@czj,Ubains@4321,
,Ubains@4321,csba
admin@czj2,Ubains@4321,csba
admin@czj,Ubains@4321,csba
admin@,Ubains@4321,csba
admin@czj,Ubains@4321,
,Ubains@4321,csba
admin@czj,Ubains@4321,
,Ubains@4321,csba
admin@czj,Ubains@4321,
,Ubains@4321,csba
admin@czj2,Ubains@4321,csba
admin@czj,Ubains@4321,csba
\ No newline at end of file
import pytest
import logging
from selenium import webdriver
from selenium.common import StaleElementReferenceException
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import csv
from 登录模块.base.Broswer_driver import Browser_driver
def read_csv_data():
"""
读取 CSV 文件数据
"""
data = []
try:
with open('Login_Test.csv', mode='r', encoding='utf-8') as csvfile:
csv_reader = csv.DictReader(csvfile)
for row in csv_reader:
data.append((row['username'], row['password'], row['verification_code']))
except FileNotFoundError:
logger.error("CSV 文件未找到,请检查文件路径")
pytest.exit("CSV 文件未找到,请检查文件路径")
except Exception as e:
logger.error(f"出现错误: {e}")
pytest.exit(f"出现错误: {e}")
return data
# 设置日志
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
@pytest.fixture(scope='session')
def driver():
"""
初始化浏览器并打开指定URL
"""
url = 'https://192.168.5.218'
logging.info("'----------' 正在初始化浏览器 '----------'")
try:
driver = Browser_driver().browser_init() # 初始化浏览器驱动
logging.info("'----------' 浏览器初始化成功 '----------'")
except Exception as e:
logging.error(f"浏览器初始化失败: {e}")
raise
driver.implicitly_wait(10) # 设置隐式等待时间为10秒
driver.maximize_window() # 最大化浏览器窗口
logging.info("'----------' 正在打开URL '----------'")
try:
driver.get(url)
logging.info(f"成功打开URL: {url}")
except Exception as e:
logging.error(f"打开URL失败: {e}")
raise
handle_ssl_warning(driver) # 处理可能存在的SSL证书警告
yield driver
driver.quit() # 在测试结束后关闭浏览器
def handle_ssl_warning(driver):
"""处理 SSL 证书警告"""
try:
logging.info("'----------' 正在处理SSL证书警告 '----------'")
WebDriverWait(driver, 10).until(
EC.element_to_be_clickable((By.XPATH, '//*[@id="details-button"]'))
).click()
WebDriverWait(driver, 10).until(
EC.element_to_be_clickable((By.XPATH, '//*[@id="proceed-link"]'))
).click()
# 等待页面加载完成
WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.TAG_NAME, 'body'))
)
logging.info("'----------' SSL证书警告处理完成 '----------'")
except Exception as e:
logging.error(f"处理 SSL 证书警告遇到错误: {e}")
raise
def _find_element(driver, by, value):
"""
查找元素,并处理可能的异常
"""
try:
return WebDriverWait(driver, 20).until(
EC.presence_of_element_located((by, value))
)
except StaleElementReferenceException:
return WebDriverWait(driver, 20).until(
EC.presence_of_element_located((by, value))
)
def perform_login(driver, username, password, verification_code):
"""
执行登录操作
"""
try:
# 清除并输入用户名
username_input = _find_element(driver, By.XPATH,
'//*[@id="app"]/div/div[3]/div[1]/div[2]/div/form/div[1]/div/input')
username_input.clear()
username_input.send_keys(username)
# 清除并输入密码
password_input = _find_element(driver, By.XPATH,
'//*[@id="app"]/div/div[3]/div[1]/div[2]/div/form/div[2]/div/input')
password_input.clear()
password_input.send_keys(password)
# 清除并输入验证码
verification_input = _find_element(driver, By.XPATH,
'//*[@id="app"]/div/div[3]/div[1]/div[2]/div/form/div[3]/div[1]/div/input')
verification_input.clear()
verification_input.send_keys(verification_code)
# 点击登录按钮
login_button = _find_element(driver, By.XPATH, '//*[@id="app"]/div/div[3]/div[1]/div[2]/div/form/div[4]/input')
login_button.click()
if username | password | verification_code == "":
check_login_null(driver)
logger.info("登录失败,必填项不能为空!断言成功!\n")
elif check_login_failure(driver):
logger.info("登录失败, 必填项错误!断言成功!\n")
elif check_login_success(driver):
logger.info("登录成功,断言成功!\n")
return_to_login_page(driver) # 返回登录页面
# # 检查登录是否成功
# if check_login_null(driver):
# logger.info("登录失败,必填项不能为空!断言成功!\n")
#
# elif check_login_success(driver):
# logger.info("登录成功,断言成功!\n")
# return_to_login_page(driver) # 返回登录页面
# elif check_login_failure(driver):
# logger.info("登录失败, 必填项错误!断言成功!\n")
else:
logger.error("登录状态未知,断言失败!\n")
pytest.fail("登录状态未知,断言失败!")
except StaleElementReferenceException as e:
logger.error(f"元素已失效,重新查找... {e}\n")
pytest.fail(f"元素已失效,重新查找... {e}")
except Exception as e:
logger.error(f"登录操作失败: {e}\n")
pytest.fail(f"登录操作失败: {e}")
def return_to_login_page(driver):
"""
返回登录页面
"""
try:
logout_button = _find_element(driver, By.XPATH, '//*[@id="app"]/div/div[1]/div/div[1]/div[2]/div[2]')
logout_button.click()
logging.info("已成功返回登录页面\n")
except Exception as e:
logger.error(f"返回登录页面失败: {e}\n")
pytest.fail(f"返回登录页面失败: {e}")
def check_login_null(driver):
"""
检查登录失败,必填项为空的情况
"""
try:
login_element_text = WebDriverWait(driver, 10).until(
EC.visibility_of_element_located((By.XPATH, '/html/body/div[2]/p'))
).text
assert "请输入" in login_element_text, "登录失败后未找到'请输入'提示语"
return True
except Exception as e:
logger.error(f"登录失败检查失败: {e}")
return False
def check_login_success(driver):
"""
检查登录成功的情况
"""
try:
message_element_text = WebDriverWait(driver, 10).until(
EC.visibility_of_element_located((By.XPATH, "//*[contains(text(), '欢迎')]"))
).text
assert "欢迎 预定标准版测试" == message_element_text, "登录成功后找到'欢迎 预定标准版测试'提示语"
driver.find_element(By.XPATH, '//*[@id="app"]/div/div[1]/div/img[3]').click()
driver.refresh()
driver.implicitly_wait(5)
return True
except Exception as e:
logger.error(f"登录成功检查失败: {e}")
return False
def check_login_failure(driver):
"""
检查登录失败的情况
"""
try:
login_element_text = WebDriverWait(driver, 10).until(
EC.visibility_of_element_located((By.XPATH, '//*[@id="app"]/div/div[3]/div[1]/div[1]/div[1]'))
).text
assert "账号登录" == login_element_text, "登录失败后未找到'账号登录'提示语"
return True
except Exception as e:
logger.error(f"登录失败检查失败: {e}")
return False
@pytest.mark.parametrize("username,password,verification_code", read_csv_data())
def test_login_from_csv(driver, username, password, verification_code):
"""
从 CSV 文件读取并测试登录情况
"""
logger.info(f"'----------' 开始执行测试 '----------'\n")
perform_login(driver, username, password, verification_code)
logger.info(f"'----------' 执行完成测试 '----------'\n")
driver.implicitly_wait(10)
if __name__ == '__main__':
pytest.main()
import logging
import pytest
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.common import StaleElementReferenceException
class Base:
def __init__(self, driver):
self.driver = driver
self.logger = logging.getLogger(__name__)
def find_element(self, by, value):
"""
查找元素,并处理可能的异常
"""
try:
return WebDriverWait(self.driver, 30).until(
EC.presence_of_element_located((by, value))
)
except StaleElementReferenceException:
return WebDriverWait(self.driver, 30).until(
EC.presence_of_element_located((by, value))
)
def perform_login(self, username, password, verification_code):
"""
执行登录操作
"""
self.driver.implicitly_wait(5)
self.driver.refresh()
try:
# 清除并输入用户名
username_input = self.find_element(By.XPATH, '//*[@id="app"]/div/div[3]/div[1]/div[2]/div/form/div[1]/div/input')
username_input.clear()
username_input.send_keys(username)
# 清除并输入密码
password_input = self.find_element(By.XPATH, '//*[@id="app"]/div/div[3]/div[1]/div[2]/div/form/div[2]/div/input')
password_input.clear()
password_input.send_keys(password)
# 清除并输入验证码
verification_input = self.find_element(By.XPATH, '//*[@id="app"]/div/div[3]/div[1]/div[2]/div/form/div[3]/div[1]/div/input')
verification_input.clear()
verification_input.send_keys(verification_code)
# 点击登录按钮
login_button = self.find_element(By.XPATH, '//*[@id="app"]/div/div[3]/div[1]/div[2]/div/form/div[4]/input')
login_button.click()
# 检查登录是否成功
if self.check_login_null():
self.logger.info("登录失败,必填项不能为空!断言成功!")
elif self.check_login_success():
self.logger.info("登录成功,断言成功!")
self.return_to_login_page()
elif self.check_login_failure():
self.logger.info("登录失败, 必填项错误!断言成功!")
else:
self.logger.error("登录状态未知,断言失败!")
pytest.fail("登录状态未知,断言失败!")
except StaleElementReferenceException as e:
self.logger.error(f"元素已失效,重新查找... {e}")
pytest.fail(f"元素已失效,重新查找... {e}")
except Exception as e:
self.logger.error(f"登录操作失败: {e}")
pytest.fail(f"登录操作失败: {e}")
def return_to_login_page(self):
"""
返回登录页面
"""
try:
# 定位到退出按钮并点击
logout_button = self.find_element(By.XPATH, '//*[@id="app"]/div/div[1]/div/img[3]')
logout_button.click()
# 记录日志,表明已成功尝试返回登录页面
self.logger.info("已成功返回登录页面")
# 刷新页面,并等待一段时间以确保页面加载完成
self.driver.refresh()
self.driver.implicitly_wait(5)
except Exception as e:
# 如果发生异常,记录错误日志并使测试用例失败
self.logger.error(f"返回登录页面失败: {e}")
pytest.fail(f"返回登录页面失败: {e}")
def check_login_null(self):
"""
检查登录失败,必填项为空的情况
"""
try:
login_element_text = WebDriverWait(self.driver, 10).until(
EC.visibility_of_element_located((By.XPATH, '/html/body/div[2]/p'))
).text
# 断言登录失败后,提示信息中包含'请输入'关键词
assert "请输入" in login_element_text, "登录失败后未找到'请输入'提示语"
return True
except Exception as e:
self.logger.error(f"登录失败检查失败: {e}")
return False
def check_login_success(self):
"""
检查登录成功的情况
"""
try:
message_element_text = WebDriverWait(self.driver, 10).until(
EC.visibility_of_element_located((By.XPATH, "//*[contains(text(), '欢迎')]"))
).text
# 断言欢迎信息是否符合预期
assert "欢迎 预定标准版测试" == message_element_text, "登录成功后找到'欢迎 预定标准版测试'提示语"
return True
except Exception as e:
self.logger.error(f"登录成功检查失败: {e}")
return False
def check_login_failure(self):
"""
检查登录失败的情况
"""
try:
login_element_text = WebDriverWait(self.driver, 10).until(
EC.visibility_of_element_located((By.XPATH, '//*[@id="app"]/div/div[3]/div[1]/div[1]/div[1]'))
).text
# 断言登录元素的文本是否为"账号登录",如果符合,则说明登录失败检查成功
assert "账号登录" == login_element_text, "登录失败后未找到'账号登录'提示语"
return True
except Exception as e:
self.logger.error(f"登录失败检查失败: {e}")
return False
from time import sleep
from selenium.webdriver.common.by import By
from webdriver_manager.chrome import ChromeDriverManager
from selenium import webdriver
from selenium.webdriver.chrome.service import Service as ChromeService
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
class BasePage(object):
def __init__(self):
print('初始化开始!')
# 自动下载驱动
# self.driver = webdriver.Chrome(service=ChromeService(ChromeDriverManager().install()))
# 直接指定下载好的 ChromeDriver 路径
# # try:
self.driver_path = "C:\Program Files\Google\Chrome\Application\chromedriver.exe" # 替换为实际路径
self.driver = webdriver.Chrome(service=ChromeService(self.driver_path))
sleep(5)
print('初始化成功,驱动正常!')
# except Exception as e:
# print(f"初始化失败: {e}")
import os
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
import logging
# 配置日志
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
class Browser_driver(object):
def browser_init(self):
# logging.info('初始化开始!')
# 动态获取 chromedriver 路径
driver_path = os.getenv('CHROMEDRIVER_PATH', "C:\\Program Files\\Google\\Chrome\\Application\\chromedriver.exe")
try:
# 尝试使用指定路径初始化 WebDriver
self.driver = webdriver.Chrome(service=Service(driver_path))
# 设置隐式等待时间
self.driver.implicitly_wait(5) # 延长至5秒
# logging.info('初始化成功,驱动正常!')
except Exception as e:
logging.error(f'初始化失败: {e}')
raise
return self.driver
\ No newline at end of file
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论