浏览器调试超详细笔记(从入门到精通)

一、开发者工具基础与快捷键 1. 入口 打开开发者工具(DevTools):按下F12键,或右键页面选择“检查”,直接调出调试

一、开发者工具基础与快捷键

1. 入口

  • 打开开发者工具(DevTools):按下F12键,或右键页面选择“检查”,直接调出调试面板(包含Elements、Network等10+功能区)。
  • 命令菜单:按下Ctrl+Shift+P,调出全局命令搜索框,支持通过关键词快速调用功能:
    • 输入“screenshot”:可选择“Capture full size screenshot”(滚动截全屏,自动拼接长页面)、“Capture node screenshot”(截取选中元素)等。
    • 输入“settings”:快速打开DevTools设置(如调整主题、快捷键)。

二、CSS样式调试

1. 盒模型解析

在Elements面板的“Computed”子面板中,元素的盒模型会以分层色块展示:

  • 橙色区域:代表margin(外边距,元素与其他元素的间距)。
  • 绿色区域:代表content(内容区,元素实际显示内容的区域)。
  • 蓝色区域:代表padding(内边距,内容与边框的间距)。
  • 黑色边框:代表border(边框,可通过Styles面板修改宽度、颜色)。

2. 移动设备适配调试

  • 进入方式:点击Elements面板左上角的“手机+平板”图标(Toggle device toolbar),切换到移动视图。
  • 核心功能
    • 设备列表:预设iPhone、Android等主流设备(如iPhone 14的390×844分辨率),点击即可模拟对应屏幕尺寸。
    • 自定义尺寸:在顶部输入框直接修改宽高(如320×568),或拖动边界调整,实时查看页面布局变化。
    • 旋转屏幕:点击“旋转”按钮切换横屏/竖屏(测试响应式布局在不同方向的表现)。
    • 网络切换:结合Network面板的弱网设置,模拟移动网络环境(如4G下的图片加载速度)。

3. DOM节点定位

  • 快捷键查询:在Elements面板按下Ctrl+F,激活搜索框,支持多种定位方式:
    • 标签名(如div):匹配所有该标签的元素。
    • 属性选择器(如[name="phone"]):匹配包含指定属性的元素。
    • Xpath表达式(如//button[@type="submit"]):通过路径定位元素。
  • Console命令查询:在Console面板输入JS命令,直接获取节点:
    • document.getElementById("username"):通过ID获取(唯一元素)。
    • document.getElementsByClassName("btn"):通过类名获取(返回集合)。
    • $("css选择器"):DevTools快捷方式(如$("input[name='phone']"),等价于document.querySelector)。
    • $x("Xpath表达式"):专门用于Xpath定位(如$x("//*[@id='loginBtn']"),返回匹配节点数组)。

三、样式编辑与状态模拟全解

1. Styles面板深度使用

  • 样式来源标识
    • user agent stylesheet:浏览器内置默认样式(如<body>默认有8px margin),可通过自定义样式覆盖。
    • inherited from <parent>:从父元素继承的样式(如<li>继承<ul>list-style),点击父元素名可跳转至对应节点。
  • 动态编辑
    • 直接点击样式值(如color: red中的red),可修改为任意有效值(如#ff0000rgb(255,0,0)),页面实时更新。
    • 点击样式前的勾选框,可临时禁用该样式(快速验证是否为该样式导致的显示问题)。
    • 点击空白处,输入新属性(如font-size: 16px),为元素添加样式。

2. 元素状态(伪类)强制触发

在Styles面板点击“:hov”按钮,勾选对应伪类,可强制元素进入该状态(无需手动操作鼠标/键盘):

伪类触发条件调试场景注意事项
:active元素被按下(鼠标未松开)按钮点击时的样式(如背景色变深)需保持勾选状态,松开鼠标仍生效
:focus元素获得焦点(点击或Tab键选中)输入框聚焦时的边框高亮、提示文字消失常用于表单验证样式调试
:focus-within元素自身或子元素获焦表单容器在输入框获焦时整体高亮(如添加阴影)需确保子元素可获焦(如input)
:targetURL锚点与元素id匹配(如#section1对应id="section1"锚点导航后目标区域的高亮效果需在地址栏添加锚点并刷新页面
:hover鼠标悬停在元素上导航菜单展开、图片放大效果勾选后无需移动鼠标,直接查看样式
:visited链接被访问过已访问链接与未访问链接的颜色区分(如已读文章变灰)受浏览器安全限制,可修改的样式有限(仅color等)
:focus-visible键盘操作(Tab键)获焦(鼠标点击不触发)提升无障碍访问体验(如键盘导航时焦点更明显)需通过Tab键触发,鼠标点击无效

3. 类名与布局调试工具

  • .cls功能区:在Styles面板顶部,可直接输入类名(如active),按回车添加;点击已添加的类名可切换启用/禁用,右键可删除。适用于调试依赖类名的动态样式(如Vue的:class绑定)。
  • 样式复制:右键点击样式规则(如div { color: red; }),可选择:
    • “Copy rule”:复制完整样式(选择器+属性)。
    • “Copy selector”:复制该元素的CSS选择器(如#app > div > .login-btn)。
  • Layout布局分析
    • Grid布局:勾选“Show grid overlays”,页面中使用display: grid的元素会显示网格线,配合“Show track sizes”可查看每行/列的尺寸(如100px 1fr)。
    • Flex布局:勾选“Show flex overlays”,display: flex的元素会显示主轴/交叉轴方向,子元素的分布一目了然(如justify-content: center的居中效果)。
    • 对齐属性调试:在“Computed”面板搜索alignjustify,可查看元素的对齐方式(如align-items: center),点击属性值可直接修改并预览效果。

四、Elements面板与UI自动化定位

1. 元素编辑与DOM操作

  • 元素选取:点击Elements面板左上角的“箭头”图标(或按下Ctrl+Shift+C),鼠标移动到页面元素上会高亮显示,点击即可在面板中定位到对应HTML代码。
  • 实时编辑:右键HTML代码,选择“Edit as HTML”,可直接修改标签、属性或内容(如将<button>改为<a>),按Ctrl+Enter保存,页面立即更新。此操作仅影响当前页面渲染,刷新后恢复原状(安全用于调试)。
  • DOM结构调整:拖拽HTML节点可调整位置(如交换两个<li>的顺序);右键节点可选择“Delete element”删除,或“Duplicate”复制(快速测试重复元素的布局)。

2. Selenium元素定位实战

以登录页面为例,详解常用定位方法:

  • By.NAME:通过name属性定位(适用于表单元素):

    # 定位用户名输入框并输入内容
    driver.find_element(By.NAME, "phone").send_keys("13552460107")
    
    
  • By.XPATH

    • 相对路径(推荐)://input[@name="phone"](匹配所有name="phone"input),优势是不依赖父节点结构,稳定性高。
    • 绝对路径(不推荐):/html/body/div[1]/div/div[2]/input(从根节点开始,一旦页面结构变化就会失效)。
    • 定位验证:在Elements面板按Ctrl+F,粘贴Xpath表达式,右侧会显示匹配数量(需确保为1个,否则可能定位错误)。
  • 实战案例:完整登录流程自动化

    from selenium import webdriver
    from selenium.webdrivermon.by import By
    
    driver = webdriver.Chrome()
    driver.get("<http://8.129.91.152:8765/Index/login.html>")  # 打开登录页
    driver.find_element(By.XPATH, '//input[@name="phone"]').send_keys("13552460107")  # 输入手机号
    driver.find_element(By.XPATH, '//input[@type="password"]').send_keys("Lemon123456")  # 输入密码
    driver.find_element(By.XPATH, '//button[@type="button"]').click()  # 点击登录按钮
    
    

五、Network网络请求全链路分析

1. HTTP协议与报文结构

  • 请求报文(客户端→服务器):
    • 请求行POST /api/login HTTP/1.1(方法+路径+协议版本)。
    • 请求头Host: 8.129.91.152(服务器地址)、Content-Type: application/json(数据格式)、Cookie: sessionid=xxx(会话标识)等。
    • 请求体{"phone":"13552460107","password":"123"}(POST请求的参数,GET请求参数在URL中)。
  • 响应报文(服务器→客户端):
    • 响应行HTTP/1.1 200 OK(协议版本+状态码+状态描述)。
    • 响应头Content-Type: application/json(返回数据格式)、Set-Cookie: token=xxx(服务器设置Cookie)等。
    • 响应体{"code":0,"msg":"登录成功","data":{"username":"xxx"}}(服务器返回的实际数据)。

2. 状态码与请求方法详解

  • 状态码分类
    • 2xx(成功):200(请求成功)、201(资源创建成功)。
    • 3xx(重定向):302(临时重定向,如登录后跳首页)、304(资源未修改,使用缓存)。
    • 4xx(客户端错误):400(请求参数错误)、401(未登录)、403(权限不足)、404(资源不存在)。
    • 5xx(服务器错误):500(服务器内部错误,如代码报错)、503(服务器过载,暂时不可用)。
  • 常用请求方法
    • GET:从服务器获取资源(参数在URL,如/api/user?id=1),用于查询数据。
    • POST:向服务器提交数据(参数在请求体),用于创建/修改资源(如登录、提交表单)。
    • PUT:全量更新资源(如修改用户所有信息),PATCH:部分更新(如只改手机号)。

3. 关键设置与问题定位

  • 基础设置
    • Preserve log(持续记录):勾选后,页面跳转或刷新时,之前的请求不会被清空(便于跟踪跨页面请求,如登录→首页的接口调用)。
    • Disable cache(禁用缓存):勾选后,所有请求都会绕过缓存,直接从服务器获取最新资源(避免因缓存导致的“修改不生效”问题)。
    • Throttling(网络节流):在Network面板顶部选择网络类型(如“Slow 3G”),模拟低速网络环境。
  • 前后端问题定位流程
  • 检查是否有请求:Network面板无对应接口→前端未触发请求(如按钮点击事件未绑定、条件判断错误)→ 前端问题。
  • 检查响应数据:响应体数据错误(如返回code:500)→ 后端处理逻辑错误→ 后端问题。无响应(请求一直pending)→ 后端未处理(如接口未部署、超时)→ 后端问题。
  • 检查渲染结果:响应数据正确,但页面显示异常(如列表为空)→ 前端渲染错误(如Vue的v-for绑定错误)→ 前端问题。

4. 过滤与搜索

  • 请求类型过滤:点击Network面板顶部的类型按钮(如“XHR/fetch”),仅显示对应类型的请求:
    • XHRXMLHttpRequest,传统AJAX请求(如jQuery的$.ajax)。

    • fetch:现代异步请求API(基于Promise,如fetch('/api/data'))。

    • WSWebSocket,实时双向通信(如聊天消息、股票行情)。

    • 三者对比:

    • 特性XMLHttpRequestFetchWebSocket
      异步处理回调函数(易嵌套)Promise(支持async/await)事件监听(onmessage)
      跨域需手动处理CORS自动处理CORS自动处理跨域
      实时性低(需轮询)低(需轮询)高(长连接,实时推送)
      适用场景简单数据请求复杂异步交互(单页应用)实时通信(聊天、游戏)
  • 属性过滤语法:在搜索框输入特定语法,精准筛选:
    • status-code:404 → 所有404错误的请求。
    • method:post → 所有POST请求。
    • domain:baidu → 所有百度域名的请求。
    • size:>100k → 大小超过100KB的资源。
    • mime-type:image/png → 所有PNG图片。
  • 内容搜索:点击Network面板的“Search”按钮(或按Ctrl+F),输入关键字(如"username":"admin"),可匹配请求头、请求体、响应体中的内容(快速定位包含特定参数的请求)。

5. 接口调试与弱网测试

  • 编辑并重新发送:右键请求→“Edit and resend”,可修改:
    • 请求方法(如将GET改为POST)。
    • 请求头(如添加Authorization: token)。
    • 请求体参数(如修改手机号为13800138000)。修改后点击“Send”,查看新的响应结果(用于验证参数边界值、权限控制等)。
  • 弱网测试场景
    • 模拟2G网络:查看页面加载超时提示是否合理(如“网络较慢,请稍后再试”)。
    • 模拟网络中断:在请求过程中切换到“Offline”,测试前端是否能捕获错误并提示(如“网络连接已断开”)。
    • 验证数据一致性:弱网下重复提交表单(如多次点击支付),检查后端是否防止重复提交(如幂等设计)。
  • HAR文件导入导出
    • 导出:右键请求→“Save all as HAR with content”,保存为.har文件(包含所有请求详情)。
    • 导入:在Network面板拖拽.har文件,可重现请求(用于前端与后端共享问题场景,避免“我这能复现,你那不能”)。

六、Memory存储与Cookie机制

1. 本地存储(localStorage)与会话存储(sessionStorage)

核心作用:由前端 JS 直接操作,将数据存储在浏览器本地,减少与服务器的交互(提升页面加载速度)。

操作方法(两者 API 完全相同):

// 存储数据
localStorage.setItem("username", "张三");  // 本地存储
sessionStorage.setItem("token", "abc123");  // 会话存储

// 获取数据
console.log(localStorage.getItem("username"));  // 输出"张三"

// 删除数据
localStorage.removeItem("username");

// 清空所有数据
sessionStorage.clear();

区别:

特性本地存储(localStorage)会话存储(sessionStorage)
生命周期永久保存(除非手动删除或通过 JS 清除)仅在当前会话有效,关闭标签页/浏览器后自动删除
作用域同一域名下的所有标签页、窗口共享数据仅当前标签页/窗口可见,同一域名的其他标签页无法访问
存储容量约 5-10MB(不同浏览器略有差异)约 5-10MB(与本地存储一致)
典型使用场景保存用户主题偏好、历史浏览记录、长期登录状态等保存表单临时输入内容(如填写一半的注册信息)、页面间临时传递的参数(如从列表页跳转详情页的 ID)

2. Cookies 详解

Cookies 是服务器发送到浏览器并保存在本地的小型文本文件,主要用于跟踪用户状态(如登录信息、购物车数据),每次请求同一域名时,浏览器会自动携带对应的 Cookies 到服务器。

(1)组成结构

一个完整的 Cookie 格式如下(各属性用分号分隔):

name=value; expires=Fri, 31 Dec 2025 23:59:59 GMT; path=/; domain=example; secure; HttpOnly

各属性含义:

  • name=value:Cookie 的名称和值(核心数据,如 userId=123)。
  • expires:过期时间(GMT 格式),若不设置则为“会话 Cookie”(关闭浏览器后失效);设置后为“持久 Cookie”(到期后自动删除)。
  • path=/:限制 Cookie 仅在指定路径下生效(如 path=/user 表示仅 /user 路径下的页面可访问)。
  • domain=example:限制 Cookie 仅在指定域名下生效(如 domain=example 表示 www.exampleblog.example 均可访问)。
  • secure:仅在 HTTPS 协议下传输 Cookie(防止明文传输被窃取)。
  • HttpOnly:禁止前端 JS 通过 document.cookie 访问 Cookie(防御 XSS 攻击窃取登录态)。

(2)与 Session 的协同工作机制

Cookies 常与服务器的 Session 配合,实现用户会话管理,流程如下:

  1. 首次登录:用户提交账号密码后,服务器验证通过,生成一个唯一的 Session ID(如 sess_abc123),并在服务器内存/数据库中创建对应的 Session 对象(存储用户信息,如用户名、权限)。

  2. 设置 Cookie:服务器通过 Set-Cookie 响应头,将 Session ID 发送给浏览器:

    Set-Cookie: sessionId=sess_abc123; path=/; HttpOnly; secure
    
    
  3. 后续请求:浏览器每次请求该域名时,自动在请求头中携带 Cookie:

    Cookie: sessionId=sess_abc123
    
    
  4. 验证身份:服务器从 Cookie 中提取 Session ID,查找对应的 Session 对象,若存在则识别用户身份(如“已登录”),否则视为“未登录”。

  5. 会话结束:当用户退出登录或 Session 过期(服务器设置,如 30 分钟未活动),服务器删除 Session 对象,后续请求携带的 Session ID 会被视为无效。

(3)操作方式

  • 前端 JS 操作(仅能访问非 HttpOnly 的 Cookie):

    // 查看所有可访问的 Cookie(字符串形式,用分号分隔)
    console.log(document.cookie);  // 输出 "username=张三; theme=dark"
    
    // 设置 Cookie(需符合格式,注意编码特殊字符)
    document.cookie = "rememberMe=true; expires=Fri, 31 Dec 2025 23:59:59 GMT; path=/";
    
    // 删除 Cookie(设置过期时间为过去的时间)
    document.cookie = "rememberMe=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/";
    
    
  • 服务器设置(以 HTTP 响应头为例):

    // 后端通过响应头设置 Cookie
    Set-Cookie: token=xyz789; path=/; HttpOnly; secure; SameSite=Lax
    
    

3. 三种存储方式对比

长期数据用 localStorage,临时数据用 sessionStorage,身份验证用 Cookies + Session)

特性localStoragesessionStorageCookies
存储大小5-10MB5-10MB约 4KB(单个域名限制数量,通常 50 个以内)
有效期永久(除非手动删除)会话级(窗口关闭失效)可设置过期时间(持久)或会话级
发送到服务器否(仅本地使用)否(仅本地使用)是(每次请求自动携带)
前端 JS 访问权限可读写可读写仅能读写非 HttpOnly 的 Cookie
跨域访问限制同域名可访问同窗口同域名可访问受 domain 和 path 限制
主要用途长期本地数据存储临时数据传递用户会话管理、身份验证

七、Console控制台

Console 是前端调试的“命令行工具”,主要用于执行代码、打印信息、排查错误,是开发和测试过程中高频使用的面板。

1. 功能与常用命令

(1)打印信息与调试输出

Console 提供多种打印方法,满足不同调试需求:

  • console.log():最常用,打印普通信息(支持字符串、变量、对象等)。

    const user = { name: "张三", age: 20 };
    console.log("用户信息:", user);  // 输出对象详情,可展开查看属性
    
    
  • console.warn():打印警告信息(黄色背景,用于非致命问题,如“已废弃的API”)。

    console.warn("该方法将在v2.0版本移除,请使用新方法");
    
    
  • console.error():打印错误信息(红色背景,用于致命错误,如“函数未定义”)。

    console.error("登录失败:用户名或密码错误");
    
    
  • console.table():将数组/对象以表格形式展示(清晰直观,适合数据结构复杂的场景)。

    const list = [
      { id: 1, name: "苹果" },
      { id: 2, name: "香蕉" }
    ];
    console.table(list);  // 以表格展示id和name
    
    
  • console.dir():打印DOM元素的详细属性(比console.log()更适合查看元素的方法和属性)。

    console.dir(document.querySelector("button"));  // 展示按钮元素的所有属性和方法
    
    

(2)调试辅助命令

  • debugger:在代码中插入断点,执行到此时会暂停,可在 Sources 面板逐步调试(等价于在 Sources 面板手动设置断点)。

    function login() {
      debugger;  // 执行到此处暂停
      const username = document.getElementById("username").value;
      // ...
    }
    
    
  • $0:在 Elements 面板选中DOM元素后,$0 代表该元素(快速在 Console 中操作选中的元素)。

    $0.style.color = "red";  // 将选中的元素文字改为红色
    
    
  • clear()Ctrl+L:清空控制台内容(避免信息过多干扰查看)。

2. 与自动化测试相关的实用技巧

(1)验证元素定位表达式

在 UI 自动化测试中,可通过 Console 快速验证 Xpath 或 CSS 选择器是否正确:

  • Xpath 验证:使用 $x("Xpath表达式"),返回匹配的元素数组(长度为0表示无匹配,长度>1需优化表达式)。

    $x('//input[@name="phone"]');  // 查找name为phone的输入框,返回数组
    
    
  • CSS 选择器验证:使用 $("CSS选择器")(返回第一个匹配元素)或 $$("CSS选择器")(返回所有匹配元素数组)。

    $("button[type='submit']");  // 查找type为submit的按钮
    $$("ul li");  // 查找所有ul下的li元素
    
    

(2)模拟用户操作

通过 Console 执行 JS 代码,可模拟点击、输入等用户行为(用于快速验证交互逻辑):

// 模拟输入手机号
document.querySelector('input[name="phone"]').value = "13552460107";

// 模拟点击登录按钮
document.querySelector('button[type="button"]').click();

3. 查看与操作存储数据

(1)Cookies 操作

// 查看当前页面所有可访问的Cookie(非HttpOnly类型)
console.log(document.cookie);  // 输出格式:"name1=value1; name2=value2"

// 设置Cookie(注意:仅能设置非HttpOnly的Cookie)
document.cookie = "remember_me=1; expires=2025-12-31T23:59:59Z; path=/";

// 删除Cookie(设置过期时间为过去的时间)
document.cookie = "remember_me=; expires=1970-01-01T00:00:00Z; path=/";

(2)本地存储/会话存储操作

// 查看localStorage数据
console.log(localStorage.getItem("username"));

// 修改sessionStorage数据
sessionStorage.setItem("token", "new_token_123");

4. 错误排查与日志分析

  • 前端报错定位:Console 会显示 JS 错误的具体位置(文件名、行号)和原因(如“Uncaught ReferenceError: xxx is not defined”表示变量未定义),点击错误信息可直接跳转到 Sources 面板对应的代码行。
  • 网络请求错误:当接口请求失败时(如 404、500),Console 会显示错误提示,包含请求 URL 和状态码,结合 Network 面板可快速定位问题。

八、Performance 性能分析

Performance 面板用于记录和分析页面的加载、渲染、交互等性能数据,帮助定位性能瓶颈(如页面加载慢、动画卡顿)。

1. 核心指标与性能分析维度

(1)关键性能指标

  • FPS(Frames Per Second,帧率):每秒渲染的帧数,直接影响动画流畅度。
    • 绿色柱状图越高,FPS 越高(理想值为 60 FPS,即每帧耗时约 16ms)。
    • 出现红色柱状图表示帧率过低(<30 FPS),用户会感觉到卡顿(如滑动不流畅、动画掉帧)。
  • Loading(加载):页面资源(HTML、CSS、JS、图片等)的加载耗时。
  • Scripting(脚本执行):JS 代码执行耗时(如复杂计算、DOM 操作)。
  • Rendering(渲染):页面布局(Layout)和绘制(Paint)的耗时(如频繁修改元素位置导致的重排)。
  • Painting(绘制):将渲染结果绘制到屏幕的耗时(如大面积背景色变化)。

2. 性能分析步骤

(1)录制性能数据

  1. 打开 Performance 面板,点击左侧的“录制”按钮(圆形按钮)。
  2. 操作页面(如刷新页面、滚动、点击按钮),模拟用户行为。
  3. 完成操作后点击“停止”按钮,面板会生成性能报告(包含火焰图、时间轴等)。

(2)分析关键区域

  • Main(主线程):展示浏览器主线程的所有活动(按时间顺序排列),每个长条代表一个任务(如函数执行、布局计算)。
    • 长条越长,任务耗时越久(若超过 50ms,可能导致卡顿)。
    • 长条右上角出现红色三角,表示该任务是“长任务”(耗时>50ms),需重点优化(如拆分复杂计算、使用 Web Worker 处理耗时操作)。
  • 火焰图(Call Tree):展示函数调用关系,从下到上为调用链(下层函数调用上层函数),可按“Self Time”(函数自身执行时间)排序,定位耗时最长的函数。
  • Summary(摘要):按类别统计耗时占比(如 Scripting 占 60%、Rendering 占 30%),快速判断性能瓶颈类型(如脚本执行耗时过高)。

3. 常见性能问题与优化方向

  • 加载缓慢
    • 问题:资源体积过大(如未压缩的 JS/CSS)、请求次数过多(如小图片未合并)。
    • 优化:启用 Gzip 压缩、使用 CDN 加速、图片懒加载、合并资源减少请求。
  • 脚本执行耗时过长
    • 问题:存在长任务(如循环遍历大量数据、复杂正则匹配)。
    • 优化:拆分任务为小块(使用 requestIdleCallback)、将计算密集型操作移至 Web Worker(避免阻塞主线程)。
  • 频繁重排重绘
    • 问题:频繁修改元素的 widthheightoffsetTop 等属性(触发重排),或修改 backgroundcolor 等(触发重绘)。
    • 优化:批量修改样式(使用 class 切换)、使用 transformopacity 实现动画(仅触发合成,不重排重绘)。

4. 工具

  • Lighthouse:Performance 面板内置的性能评估工具,点击“Generate report”可生成综合评分(包含加载速度、可访问性、SEO 等),并给出具体优化建议(如“启用文本压缩”“减少未使用的 CSS”)。
  • 性能导出:点击“Export”可将性能数据导出为 JSON 文件,便于与团队共享分析(如前端与后端共同排查接口响应慢导致的性能问题)。

发布者:admin,转转请注明出处:http://www.yc00.com/web/1754948657a5219569.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信