fix(eslint): reduce warnings in GitHub Actions deployment

- Disable formatting rules (handled by Prettier)
- Relaxed strict Vue/JS rules for demo code compatibility
- Fix syntax errors in ApiPlayground and VoiceCloningDemo
- Fix duplicate else-if condition in ApiPlayground
- Fix Promise executor async pattern in AutoregressiveAudioDemo
- Add TypeScript file support to ESLint config

Warnings reduced from 295 to 251 problems.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
sanbuphy
2026-02-18 17:38:10 +08:00
parent 8b01686e68
commit 0eba9e87e9
456 changed files with 28450 additions and 9677 deletions
@@ -597,19 +597,21 @@ onUnmounted(() => {
<template>
<div
ref="demoRef"
class="browser-devtools-demo"
:class="{ 'dark-mode': isDark }"
ref="demoRef"
>
<!-- Top Controls (Custom for Demo) -->
<div class="demo-controls">
<div class="control-label">Chrome DevTools 模拟器</div>
<div class="control-label">
Chrome DevTools 模拟器
</div>
<div class="control-actions">
<select
v-model="selectedTour"
@change="handleTourSelect"
class="tour-select"
:disabled="isAutoPlaying"
@change="handleTourSelect"
>
<option
v-for="opt in tourOptions"
@@ -620,7 +622,11 @@ onUnmounted(() => {
{{ opt.label }}
</option>
</select>
<button v-if="isAutoPlaying" class="stop-btn" @click="stopTour">
<button
v-if="isAutoPlaying"
class="stop-btn"
@click="stopTour"
>
停止演示
</button>
</div>
@@ -628,8 +634,8 @@ onUnmounted(() => {
<!-- Virtual Cursor & Highlight -->
<div
class="virtual-cursor"
v-if="cursorVisible"
class="virtual-cursor"
:style="{ transform: `translate(${cursorX}px, ${cursorY}px)` }"
>
<svg
@@ -648,10 +654,10 @@ onUnmounted(() => {
</svg>
</div>
<div
class="highlight-box"
v-if="highlightVisible"
class="highlight-box"
:style="highlightStyle"
></div>
/>
<!-- Main UI Container -->
<div class="devtools-container">
@@ -662,20 +668,33 @@ onUnmounted(() => {
class="icon-btn element-picker"
title="选择页面中的元素以进行检查"
>
<svg width="16" height="16" viewBox="0 0 24 24" fill="#6e6e6e">
<svg
width="16"
height="16"
viewBox="0 0 24 24"
fill="#6e6e6e"
>
<path
d="M4 4h9v2H4V4zm0 4h5v2H4V8zm0 4h5v2H4v-2zm12-5l-4 4h3v4h2v-4h3l-4-4z"
/>
</svg>
</div>
<div class="icon-btn device-toggle" title="切换设备工具栏">
<svg width="16" height="16" viewBox="0 0 24 24" fill="#6e6e6e">
<div
class="icon-btn device-toggle"
title="切换设备工具栏"
>
<svg
width="16"
height="16"
viewBox="0 0 24 24"
fill="#6e6e6e"
>
<path
d="M17 1.01L7 1c-1.1 0-2 .9-2 2v18c0 1.1.9 2 2 2h10c1.1 0 2-.9 2-2V3c0-1.1-.9-1.99-2-1.99zM17 19H7V5h10v14z"
/>
</svg>
</div>
<div class="separator"></div>
<div class="separator" />
<div class="tabs">
<div
v-for="tab in tabs"
@@ -692,24 +711,54 @@ onUnmounted(() => {
</div>
</div>
<div class="header-right">
<div class="icon-btn settings" title="设置"></div>
<div class="icon-btn close" title="关闭">×</div>
<div
class="icon-btn settings"
title="设置"
>
</div>
<div
class="icon-btn close"
title="关闭"
>
×
</div>
</div>
</div>
<!-- Body Area -->
<div class="devtools-body">
<!-- 1. Console Panel -->
<div v-if="activeTab === 'console'" class="panel console-panel-layout">
<div class="console-toolbar" @mouseenter="showInfo('控制台工具栏')">
<div class="icon-btn clear" title="清除控制台">🚫</div>
<div class="separator"></div>
<div class="dropdown-trigger">top </div>
<div class="icon-btn eye" title="创建实时表达式">👁</div>
<div class="filter-box">
<span class="filter-icon">🔍</span><input placeholder="过滤" />
<div
v-if="activeTab === 'console'"
class="panel console-panel-layout"
>
<div
class="console-toolbar"
@mouseenter="showInfo('控制台工具栏')"
>
<div
class="icon-btn clear"
title="清除控制台"
>
🚫
</div>
<div class="separator" />
<div class="dropdown-trigger">
top
</div>
<div
class="icon-btn eye"
title="创建实时表达式"
>
👁
</div>
<div class="filter-box">
<span class="filter-icon">🔍</span><input placeholder="过滤">
</div>
<div class="dropdown-trigger">
默认级别
</div>
<div class="dropdown-trigger">默认级别 </div>
</div>
<div class="console-main-area">
<div class="console-sidebar">
@@ -744,16 +793,22 @@ onUnmounted(() => {
:class="log.type"
>
<div class="log-gutter">
<span class="icon error" v-if="log.type === 'error'"
></span
>
<span class="icon warn" v-else-if="log.type === 'warn'"
></span
>
<span class="icon" v-else-if="log.type === 'command'"
>&gt;</span
>
<span class="icon" v-else>&lt;</span>
<span
v-if="log.type === 'error'"
class="icon error"
></span>
<span
v-else-if="log.type === 'warn'"
class="icon warn"
></span>
<span
v-else-if="log.type === 'command'"
class="icon"
>&gt;</span>
<span
v-else
class="icon"
>&lt;</span>
</div>
<div class="log-content">
<pre>{{ log.msg }}</pre>
@@ -767,10 +822,10 @@ onUnmounted(() => {
<span class="prompt">&gt;</span>
<input
v-model="consoleInput"
@keyup.enter="runConsoleCommand"
class="input-field"
placeholder=""
/>
@keyup.enter="runConsoleCommand"
>
</div>
</div>
</div>
@@ -784,10 +839,18 @@ onUnmounted(() => {
>
</div>
<div class="drawer-tab">控制台</div>
<div class="drawer-tab">AI 辅助</div>
<div class="drawer-tab">新变化</div>
<div class="drawer-tab">问题</div>
<div class="drawer-tab">
控制台
</div>
<div class="drawer-tab">
AI 辅助
</div>
<div class="drawer-tab">
新变化
</div>
<div class="drawer-tab">
问题
</div>
<div class="drawer-tab active">
搜索 <span class="close-icon">×</span>
</div>
@@ -799,12 +862,16 @@ onUnmounted(() => {
<input
placeholder="A terminal is just a grid of same-sized cells..."
class="search-input"
/>
<div class="search-actions">Aa ab .*</div>
>
<div class="search-actions">
Aa ab .*
</div>
</div>
<div class="search-results">
<div class="no-results">
<div class="no-results-title">未找到匹配项</div>
<div class="no-results-title">
未找到匹配项
</div>
<div class="no-results-desc">
没有与您的搜索查询相符的结果
</div>
@@ -816,84 +883,80 @@ onUnmounted(() => {
</div>
<!-- 2. Elements Panel -->
<div v-else-if="activeTab === 'elements'" class="panel elements-panel">
<div
v-else-if="activeTab === 'elements'"
class="panel elements-panel"
>
<div class="dom-tree-panel">
<div class="dom-tree-content">
<div class="dom-node" data-tag="html">
<div
class="dom-node"
data-tag="html"
>
<div class="line-content">
<span class="arrow expanded"></span>
<span class="tag-name">html</span>
<span class="attr-name">class</span>=<span class="attr-val"
>"mac"</span
>
<span class="attr-name">lang</span>=<span class="attr-val"
>"zh-CN"</span
>
<span class="attr-name">dir</span>=<span class="attr-val"
>"ltr"</span
>
<span class="attr-name">style</span>=<span class="attr-val"
>"--ev-doc-font-size: 14px..."</span
>
<span class="attr-name">class</span>=<span class="attr-val">"mac"</span>
<span class="attr-name">lang</span>=<span class="attr-val">"zh-CN"</span>
<span class="attr-name">dir</span>=<span class="attr-val">"ltr"</span>
<span class="attr-name">style</span>=<span class="attr-val">"--ev-doc-font-size: 14px..."</span>
</div>
<div class="children">
<div class="dom-node" data-tag="head">
<div
class="dom-node"
data-tag="head"
>
<div class="line-content">
<span class="arrow"></span>
<span class="tag-name">head</span>
<span class="dots">...</span>
</div>
</div>
<div class="dom-node" data-tag="body">
<div
class="dom-node"
data-tag="body"
>
<div class="line-content">
<span class="arrow expanded"></span>
<span class="tag-name">body</span>
<span class="node-trail">== $0</span>
</div>
<div class="children">
<div class="dom-node selected" data-tag="div">
<div
class="dom-node selected"
data-tag="div"
>
<div class="line-content">
<span class="arrow expanded"></span>
<span class="tag-name">div</span>
<span class="attr-name">id</span>=<span
class="attr-val"
>"app"</span
>
>"app"</span>
<span class="attr-name">data-v-app</span>
</div>
<div class="children">
<div class="dom-node">
<div class="line-content">
<span class="indent"></span
><span class="tag-name">div</span
><span class="dots">...</span
><span class="tag-name">/div</span>
<span class="indent" /><span class="tag-name">div</span><span class="dots">...</span><span class="tag-name">/div</span>
</div>
</div>
<div class="dom-node">
<div class="line-content">
<span class="indent"></span
><span class="tag-name">script</span>
<span class="indent" /><span class="tag-name">script</span>
<span class="attr-name">type</span>=<span
class="attr-val"
>"module"</span
>
>"module"</span>
<span class="attr-name">src</span>=<span
class="attr-val"
>"/easy-vibe/..."</span
><span class="tag-name">/script</span>
>"/easy-vibe/..."</span><span class="tag-name">/script</span>
</div>
</div>
<div class="dom-node">
<div class="line-content">
<span class="indent"></span
><span class="tag-name">div</span>
<span class="indent" /><span class="tag-name">div</span>
<span class="attr-name">id</span>=<span
class="attr-val"
>"el-popper-container-3083"</span
><span class="tag-name">&gt;</span
><span class="dots">...</span
><span class="tag-name">/div</span>
>"el-popper-container-3083"</span><span class="tag-name">&gt;</span><span class="dots">...</span><span class="tag-name">/div</span>
</div>
</div>
</div>
@@ -907,10 +970,7 @@ onUnmounted(() => {
<span class="tag-name">div</span>
<span class="attr-name">style</span>=<span
class="attr-val"
>"all: initial;"</span
><span class="tag-name">&gt;</span
><span class="dots">...</span
><span class="tag-name">/div</span>
>"all: initial;"</span><span class="tag-name">&gt;</span><span class="dots">...</span><span class="tag-name">/div</span>
</div>
</div>
<div class="dom-node">
@@ -919,14 +979,10 @@ onUnmounted(() => {
<span class="tag-name">div</span>
<span class="attr-name">id</span>=<span
class="attr-val"
>"immersive-translate-browser-popup"</span
>
>"immersive-translate-browser-popup"</span>
<span class="attr-name">style</span>=<span
class="attr-val"
>"all: initial;"</span
><span class="tag-name">&gt;</span
><span class="dots">...</span
><span class="tag-name">/div</span>
>"all: initial;"</span><span class="tag-name">&gt;</span><span class="dots">...</span><span class="tag-name">/div</span>
</div>
</div>
</div>
@@ -940,9 +996,14 @@ onUnmounted(() => {
</div>
</div>
</div>
<div class="breadcrumbs">html.mac > body > div#app</div>
<div class="breadcrumbs">
html.mac > body > div#app
</div>
<!-- Bottom Drawer (Shared) -->
<div class="bottom-drawer" style="border-top: 1px solid #ccc">
<div
class="bottom-drawer"
style="border-top: 1px solid #ccc"
>
<div class="bottom-drawer-header">
<div
class="icon-btn more"
@@ -950,10 +1011,18 @@ onUnmounted(() => {
>
</div>
<div class="drawer-tab">控制台</div>
<div class="drawer-tab">AI 辅助</div>
<div class="drawer-tab">新变化</div>
<div class="drawer-tab">问题</div>
<div class="drawer-tab">
控制台
</div>
<div class="drawer-tab">
AI 辅助
</div>
<div class="drawer-tab">
新变化
</div>
<div class="drawer-tab">
问题
</div>
<div class="drawer-tab active">
搜索 <span class="close-icon">×</span>
</div>
@@ -965,12 +1034,16 @@ onUnmounted(() => {
<input
placeholder="A terminal is just a grid of same-sized cells..."
class="search-input"
/>
<div class="search-actions">Aa ab .*</div>
>
<div class="search-actions">
Aa ab .*
</div>
</div>
<div class="search-results">
<div class="no-results">
<div class="no-results-title">未找到匹配项</div>
<div class="no-results-title">
未找到匹配项
</div>
<div class="no-results-desc">
没有与您的搜索查询相符的结果
</div>
@@ -982,35 +1055,77 @@ onUnmounted(() => {
</div>
<div class="styles-panel">
<div class="styles-tabs">
<div class="style-tab active">样式</div>
<div class="style-tab">计算样式</div>
<div class="style-tab">布局</div>
<div class="style-tab">事件监听器</div>
<div class="style-tab">»</div>
<div class="style-tab active">
样式
</div>
<div class="style-tab">
计算样式
</div>
<div class="style-tab">
布局
</div>
<div class="style-tab">
事件监听器
</div>
<div class="style-tab">
»
</div>
</div>
<div class="styles-content">
<!-- Box Model Mock -->
<div class="box-model-container">
<div class="box-margin">
<div class="label">margin</div>
<div class="val-top">-</div>
<div class="val-left">-</div>
<div class="val-right">-</div>
<div class="val-bottom">-</div>
<div class="label">
margin
</div>
<div class="val-top">
-
</div>
<div class="val-left">
-
</div>
<div class="val-right">
-
</div>
<div class="val-bottom">
-
</div>
<div class="box-border">
<div class="label">border</div>
<div class="val-top">-</div>
<div class="val-left">-</div>
<div class="val-right">-</div>
<div class="val-bottom">-</div>
<div class="label">
border
</div>
<div class="val-top">
-
</div>
<div class="val-left">
-
</div>
<div class="val-right">
-
</div>
<div class="val-bottom">
-
</div>
<div class="box-padding">
<div class="label">padding</div>
<div class="val-top">-</div>
<div class="val-left">-</div>
<div class="val-right">-</div>
<div class="val-bottom">-</div>
<div class="label">
padding
</div>
<div class="val-top">
-
</div>
<div class="val-left">
-
</div>
<div class="val-right">
-
</div>
<div class="val-bottom">
-
</div>
<div class="box-content">
<div class="val-content">1600 x 3461</div>
<div class="val-content">
1600 x 3461
</div>
</div>
</div>
</div>
@@ -1018,35 +1133,40 @@ onUnmounted(() => {
</div>
<div class="filter-bar">
<input placeholder="过滤" />
<input placeholder="过滤">
<span class="filter-opt">:hov</span>
<span class="filter-opt">.cls</span>
<span class="filter-opt">+</span>
</div>
<div
class="style-rule"
v-for="(rule, idx) in cssRules"
:key="idx"
class="style-rule"
>
<div class="selector">{{ rule.selector }} {</div>
<div class="selector">
{{ rule.selector }} {
</div>
<div
class="property"
v-for="(val, key) in rule.styles"
:key="key"
class="property"
>
<span class="prop-name">{{ key }}</span
>: <span class="prop-val">{{ val }}</span
>;
<span class="prop-name">{{ key }}</span>: <span class="prop-val">{{ val }}</span>;
</div>
<div class="selector">
}
</div>
<div class="selector">}</div>
</div>
</div>
</div>
</div>
<!-- 3. Sources Panel -->
<div v-else-if="activeTab === 'sources'" class="panel sources-panel">
<div
v-else-if="activeTab === 'sources'"
class="panel sources-panel"
>
<div class="file-navigator">
<div class="nav-header">
<span class="nav-tab active">Page</span>
@@ -1079,7 +1199,7 @@ onUnmounted(() => {
</div>
<div class="editor-content">
<div class="line-numbers">
1<br />2<br />3<br />4<br />5<br />6
1<br>2<br>3<br>4<br>5<br>6
</div>
<div class="code-text">
<pre>{{ fileContent }}</pre>
@@ -1091,14 +1211,19 @@ onUnmounted(() => {
<div class="section-title">
<span class="arrow"></span> Watch
</div>
<div class="section-content empty">No watch expressions</div>
<div class="section-content empty">
No watch expressions
</div>
</div>
<div class="debug-section">
<div class="section-title">
<span class="arrow"></span> Breakpoints
</div>
<div class="section-content">
<label><input type="checkbox" checked /> main.js:12</label>
<label><input
type="checkbox"
checked
> main.js:12</label>
</div>
</div>
<div class="debug-section">
@@ -1110,10 +1235,15 @@ onUnmounted(() => {
</div>
<!-- 4. Network Panel -->
<div v-else-if="activeTab === 'network'" class="panel network-panel">
<div
v-else-if="activeTab === 'network'"
class="panel network-panel"
>
<div class="network-toolbar">
<div class="record-icon">🔴</div>
<div class="separator"></div>
<div class="record-icon">
🔴
</div>
<div class="separator" />
<span class="filter-btn active">All</span>
<span class="filter-btn">Fetch/XHR</span>
<span class="filter-btn">JS</span>
@@ -1123,28 +1253,50 @@ onUnmounted(() => {
<div class="network-split-view">
<div class="network-grid">
<div class="network-grid-header">
<div class="col name">Name</div>
<div class="col status">Status</div>
<div class="col type">Type</div>
<div class="col size">Size</div>
<div class="col time">Time</div>
<div class="col waterfall">Waterfall</div>
<div class="col name">
Name
</div>
<div class="col status">
Status
</div>
<div class="col type">
Type
</div>
<div class="col size">
Size
</div>
<div class="col time">
Time
</div>
<div class="col waterfall">
Waterfall
</div>
</div>
<div class="network-rows">
<div
class="network-row"
v-for="(req, idx) in networkRequests"
:key="idx"
class="network-row"
:class="{
selected: selectedRequest && selectedRequest.id === req.id
}"
@click="selectRequest(req)"
>
<div class="col name">{{ req.name }}</div>
<div class="col status">{{ req.status }}</div>
<div class="col type">{{ req.type }}</div>
<div class="col size">{{ req.size }}</div>
<div class="col time">{{ req.time }}</div>
<div class="col name">
{{ req.name }}
</div>
<div class="col status">
{{ req.status }}
</div>
<div class="col type">
{{ req.type }}
</div>
<div class="col size">
{{ req.size }}
</div>
<div class="col time">
{{ req.time }}
</div>
<div class="col waterfall">
<div
class="waterfall-bar"
@@ -1152,45 +1304,46 @@ onUnmounted(() => {
width: req.waterfall + 'px',
left: idx * 10 + 'px'
}"
></div>
/>
</div>
</div>
</div>
</div>
<!-- Network Detail Panel (Right Side) -->
<div class="network-detail" v-if="selectedRequest">
<div
v-if="selectedRequest"
class="network-detail"
>
<div class="detail-header">
<span
class="detail-title"
:class="{ active: activeDetailTab === 'headers' }"
@click="activeDetailTab = 'headers'"
>Headers</span
>
>Headers</span>
<span
class="detail-title"
:class="{ active: activeDetailTab === 'preview' }"
@click="activeDetailTab = 'preview'"
>Preview</span
>
>Preview</span>
<span
class="detail-title"
:class="{ active: activeDetailTab === 'response' }"
@click="activeDetailTab = 'response'"
>Response</span
>
<span class="close-detail" @click="selectedRequest = null"
>×</span
>
>Response</span>
<span
class="close-detail"
@click="selectedRequest = null"
>×</span>
</div>
<div class="detail-content">
<div v-if="activeDetailTab === 'headers'">
<div class="detail-section">
<div class="section-label">General</div>
<div class="section-label">
General
</div>
<div class="detail-row">
<span class="key">Request URL:</span>
<span class="val"
>http://localhost:3000/{{ selectedRequest.name }}</span
>
<span class="val">http://localhost:3000/{{ selectedRequest.name }}</span>
</div>
<div class="detail-row">
<span class="key">Request Method:</span>
@@ -1198,31 +1351,33 @@ onUnmounted(() => {
</div>
<div class="detail-row">
<span class="key">Status Code:</span>
<span class="val status-code"
>{{ selectedRequest.status }} OK</span
>
<span class="val status-code">{{ selectedRequest.status }} OK</span>
</div>
</div>
<div class="detail-section">
<div class="section-label">Response Headers</div>
<div class="section-label">
Response Headers
</div>
<div
class="detail-row"
v-for="(val, key) in selectedRequest.headers"
:key="key"
class="detail-row"
>
<span class="key">{{ key }}:</span>
<span class="val">{{ val }}</span>
</div>
</div>
<div
class="detail-section"
v-if="selectedRequest.requestHeaders"
class="detail-section"
>
<div class="section-label">Request Headers</div>
<div class="section-label">
Request Headers
</div>
<div
class="detail-row"
v-for="(val, key) in selectedRequest.requestHeaders"
:key="key"
class="detail-row"
>
<span class="key">{{ key }}:</span>
<span class="val">{{ val }}</span>
@@ -1232,7 +1387,9 @@ onUnmounted(() => {
<div v-if="activeDetailTab === 'preview'">
<div class="detail-section">
<div class="section-label">Preview</div>
<div class="section-label">
Preview
</div>
<div class="preview-content">
{{ selectedRequest.preview }}
</div>
@@ -1241,7 +1398,9 @@ onUnmounted(() => {
<div v-if="activeDetailTab === 'response'">
<div class="detail-section">
<div class="section-label">Response</div>
<div class="section-label">
Response
</div>
<div class="preview-content">
{{ selectedRequest.preview }}
</div>
@@ -1259,16 +1418,26 @@ onUnmounted(() => {
>
<div class="storage-sidebar">
<div class="sidebar-section">
<div class="section-title">Application</div>
<div class="section-item">Manifest</div>
<div class="section-item">Service Workers</div>
<div class="section-title">
Application
</div>
<div class="section-item">
Manifest
</div>
<div class="section-item">
Service Workers
</div>
</div>
<div class="sidebar-section">
<div class="section-title">Storage</div>
<div class="section-title">
Storage
</div>
<div class="section-item active">
<span class="arrow"></span> Local Storage
</div>
<div class="section-item indent">http://localhost</div>
<div class="section-item indent">
http://localhost
</div>
<div class="section-item">
<span class="arrow"></span> Session Storage
</div>
@@ -1280,16 +1449,24 @@ onUnmounted(() => {
<div class="storage-content">
<div class="storage-table">
<div class="table-header">
<div class="col key">Key</div>
<div class="col value">Value</div>
<div class="col key">
Key
</div>
<div class="col value">
Value
</div>
</div>
<div
class="table-row"
v-for="(item, idx) in localStorageData"
:key="idx"
class="table-row"
>
<div class="col key">{{ item.key }}</div>
<div class="col value">{{ item.value }}</div>
<div class="col key">
{{ item.key }}
</div>
<div class="col value">
{{ item.value }}
</div>
</div>
</div>
</div>
@@ -1297,7 +1474,10 @@ onUnmounted(() => {
</div>
<!-- Info Bar Overlay -->
<div class="info-bar" v-if="hoverInfo">
<div
v-if="hoverInfo"
class="info-bar"
>
<span class="info-icon">💡</span> {{ hoverInfo }}
</div>
</div>
@@ -182,21 +182,29 @@ const selectNode = (node) => {
<div class="virtual-page-container">
<div class="virtual-browser-bar">
<div class="dots">
<span class="dot red"></span>
<span class="dot yellow"></span>
<span class="dot green"></span>
<span class="dot red" />
<span class="dot yellow" />
<span class="dot green" />
</div>
<div class="address-bar">
http://localhost:3000/demo
</div>
<div class="address-bar">http://localhost:3000/demo</div>
</div>
<div
class="virtual-page-content"
:style="liveStyles.container"
@click.self="selectNode('container')"
>
<h1 :style="liveStyles.h1" @click.stop="selectNode('h1')">
<h1
:style="liveStyles.h1"
@click.stop="selectNode('h1')"
>
{{ liveContent.h1 }}
</h1>
<button :style="liveStyles.button" @click.stop="selectNode('button')">
<button
:style="liveStyles.button"
@click.stop="selectNode('button')"
>
{{ liveContent.button }}
</button>
</div>
@@ -214,20 +222,33 @@ const selectNode = (node) => {
class="icon-btn element-picker"
title="选择页面中的元素以进行检查"
>
<svg width="16" height="16" viewBox="0 0 24 24" fill="#6e6e6e">
<svg
width="16"
height="16"
viewBox="0 0 24 24"
fill="#6e6e6e"
>
<path
d="M4 4h9v2H4V4zm0 4h5v2H4V8zm0 4h5v2H4v-2zm12-5l-4 4h3v4h2v-4h3l-4-4z"
/>
</svg>
</div>
<div class="icon-btn device-toggle" title="切换设备工具栏">
<svg width="16" height="16" viewBox="0 0 24 24" fill="#6e6e6e">
<div
class="icon-btn device-toggle"
title="切换设备工具栏"
>
<svg
width="16"
height="16"
viewBox="0 0 24 24"
fill="#6e6e6e"
>
<path
d="M17 1.01L7 1c-1.1 0-2 .9-2 2v18c0 1.1.9 2 2 2h10c1.1 0 2-.9 2-2V3c0-1.1-.9-1.99-2-1.99zM17 19H7V5h10v14z"
/>
</svg>
</div>
<div class="separator"></div>
<div class="separator" />
<div class="tabs">
<div
v-for="tab in tabs"
@@ -241,81 +262,87 @@ const selectNode = (node) => {
</div>
</div>
<div class="header-right">
<div class="icon-btn settings"></div>
<div class="icon-btn close">×</div>
<div class="icon-btn settings">
</div>
<div class="icon-btn close">
×
</div>
</div>
</div>
<!-- Body -->
<div class="devtools-body">
<!-- Elements Panel -->
<div v-if="activeTab === 'elements'" class="panel elements-panel">
<div
v-if="activeTab === 'elements'"
class="panel elements-panel"
>
<div class="dom-tree-panel">
<div class="dom-tree-content">
<div
class="dom-node"
@click="selectNode('container')"
:class="{ selected: selectedNode === 'container' }"
@click="selectNode('container')"
>
<div class="line-content">
<span class="arrow expanded"></span>
<span class="tag-name">div</span>
<span class="attr-name">class</span>=<span class="attr-val"
>"virtual-page-content"</span
>
<span class="node-trail" v-if="selectedNode === 'container'"
>== $0</span
>
<span class="attr-name">class</span>=<span class="attr-val">"virtual-page-content"</span>
<span
v-if="selectedNode === 'container'"
class="node-trail"
>== $0</span>
</div>
<div class="children">
<div
class="dom-node"
@click.stop="selectNode('h1')"
:class="{ selected: selectedNode === 'h1' }"
@click.stop="selectNode('h1')"
>
<div class="line-content">
<span class="indent"></span>
<span class="indent" />
<span class="tag-name">h1</span>
<span class="node-trail" v-if="selectedNode === 'h1'"
>== $0</span
>
<span
v-if="selectedNode === 'h1'"
class="node-trail"
>== $0</span>
</div>
<div class="line-content">
<span class="indent"></span>
<span class="indent" />
<input
v-model="liveContent.h1"
class="dom-text-input"
@click.stop="selectNode('h1')"
/>
>
</div>
<div class="line-content">
<span class="indent"></span
><span class="tag-name">/h1</span>
<span class="indent" /><span class="tag-name">/h1</span>
</div>
</div>
<div
class="dom-node"
@click.stop="selectNode('button')"
:class="{ selected: selectedNode === 'button' }"
@click.stop="selectNode('button')"
>
<div class="line-content">
<span class="indent"></span>
<span class="indent" />
<span class="tag-name">button</span>
<span class="node-trail" v-if="selectedNode === 'button'"
>== $0</span
>
<span
v-if="selectedNode === 'button'"
class="node-trail"
>== $0</span>
</div>
<div class="line-content">
<span class="indent"></span>
<span class="indent" />
<input
v-model="liveContent.button"
class="dom-text-input"
@click.stop="selectNode('button')"
/>
>
</div>
<div class="line-content">
<span class="indent"></span
><span class="tag-name">/button</span>
<span class="indent" /><span class="tag-name">/button</span>
</div>
</div>
</div>
@@ -333,15 +360,31 @@ const selectNode = (node) => {
<!-- Interactive Styles Panel -->
<div class="styles-panel">
<div class="styles-tabs">
<div class="style-tab active">样式 (Styles)</div>
<div class="style-tab">计算 (Computed)</div>
<div class="style-tab active">
样式 (Styles)
</div>
<div class="style-tab">
计算 (Computed)
</div>
</div>
<div class="styles-content">
<!-- Preset Selector -->
<div class="style-section" v-if="availablePresets.length > 0">
<div class="style-section-title"> 快速预设 (Presets)</div>
<select class="preset-select" @change="applyPreset">
<option value="" disabled selected>
<div
v-if="availablePresets.length > 0"
class="style-section"
>
<div class="style-section-title">
快速预设 (Presets)
</div>
<select
class="preset-select"
@change="applyPreset"
>
<option
value=""
disabled
selected
>
选择一种风格 (Select Preset)...
</option>
<option
@@ -356,29 +399,35 @@ const selectNode = (node) => {
<!-- CSS Properties -->
<div class="style-rule">
<div class="selector">element.style {</div>
<div class="selector">
element.style {
</div>
<div
class="property"
v-for="(val, key) in currentStyles"
:key="key"
class="property"
>
<span class="prop-name">{{ key }}</span
>:
<span class="prop-name">{{ key }}</span>:
<input
v-model="liveStyles[selectedNode][key]"
class="style-input"
/>
>
;
</div>
<div class="selector">}</div>
<div class="selector">
}
</div>
</div>
<div class="style-add-hint"></div>
<div class="style-add-hint" />
</div>
</div>
</div>
<!-- Other Panels (Simplified placeholders) -->
<div v-else class="panel placeholder-panel">
<div
v-else
class="panel placeholder-panel"
>
<div class="placeholder-text">
此演示主要展示 Elements 面板的实时编辑功能请切换回 "元素" 面板
</div>
@@ -59,11 +59,21 @@ const clearAll = () => {
</script>
<template>
<el-card class="app-demo" shadow="hover">
<el-card
class="app-demo"
shadow="hover"
>
<template #header>
<div class="header">
<span class="title">Application (应用面板)</span>
<el-button type="danger" size="small" icon="Delete" @click="clearAll">Clear All</el-button>
<el-button
type="danger"
size="small"
icon="Delete"
@click="clearAll"
>
Clear All
</el-button>
</div>
</template>
@@ -94,26 +104,54 @@ const clearAll = () => {
<div class="content">
<div class="toolbar">
<el-input
v-model="newEntry.key"
placeholder="Key"
size="small"
style="width: 120px"
/>
<el-input
v-model="newEntry.value"
placeholder="Value"
size="small"
style="width: 120px"
/>
<el-button type="primary" size="small" @click="addEntry">Add</el-button>
<el-input
v-model="newEntry.key"
placeholder="Key"
size="small"
style="width: 120px"
/>
<el-input
v-model="newEntry.value"
placeholder="Value"
size="small"
style="width: 120px"
/>
<el-button
type="primary"
size="small"
@click="addEntry"
>
Add
</el-button>
</div>
<el-table :data="storageData[activeTab]" style="width: 100%" height="250" border>
<el-table-column prop="key" label="Key" width="120" />
<el-table-column prop="value" label="Value" min-width="150" />
<el-table-column v-if="activeTab === 'cookies'" prop="domain" label="Domain" width="110" />
<el-table-column label="Action" width="70" align="center">
<el-table
:data="storageData[activeTab]"
style="width: 100%"
height="250"
border
>
<el-table-column
prop="key"
label="Key"
width="120"
/>
<el-table-column
prop="value"
label="Value"
min-width="150"
/>
<el-table-column
v-if="activeTab === 'cookies'"
prop="domain"
label="Domain"
width="110"
/>
<el-table-column
label="Action"
width="70"
align="center"
>
<template #default="scope">
<el-button
type="danger"
@@ -126,14 +164,23 @@ const clearAll = () => {
</el-table-column>
</el-table>
<div class="info-bar" v-if="activeTab === 'local'">
持久化存储即便关闭浏览器数据也会保留
<div
v-if="activeTab === 'local'"
class="info-bar"
>
持久化存储即便关闭浏览器数据也会保留
</div>
<div class="info-bar" v-else-if="activeTab === 'session'">
临时存储关闭标签页后数据会被清空
<div
v-else-if="activeTab === 'session'"
class="info-bar"
>
临时存储关闭标签页后数据会被清空
</div>
<div class="info-bar" v-else>
Cookies通常用于身份验证会随请求发送给服务器
<div
v-else
class="info-bar"
>
Cookies通常用于身份验证会随请求发送给服务器
</div>
</div>
</div>
@@ -90,20 +90,49 @@ const runShortcut = (cmd) => {
</script>
<template>
<el-card class="console-demo" shadow="hover">
<el-card
class="console-demo"
shadow="hover"
>
<template #header>
<div class="header">
<span class="title">Console (控制台)</span>
<el-button size="small" @click="clearConsole" icon="Delete" circle title="Clear console" />
<el-button
size="small"
icon="Delete"
circle
title="Clear console"
@click="clearConsole"
/>
</div>
</template>
<div class="console-body" ref="consoleRef">
<div v-for="(log, index) in logs" :key="index" class="log-item" :class="log.type">
<span class="icon" v-if="log.type === 'error'"></span>
<span class="icon" v-else-if="log.type === 'warn'"></span>
<span class="icon" v-else-if="log.type === 'info'"></span>
<span class="icon" v-else-if="log.type === 'result'"></span>
<div
ref="consoleRef"
class="console-body"
>
<div
v-for="(log, index) in logs"
:key="index"
class="log-item"
:class="log.type"
>
<span
v-if="log.type === 'error'"
class="icon"
></span>
<span
v-else-if="log.type === 'warn'"
class="icon"
></span>
<span
v-else-if="log.type === 'info'"
class="icon"
></span>
<span
v-else-if="log.type === 'result'"
class="icon"
></span>
<span class="content">{{ log.message }}</span>
</div>
</div>
@@ -114,7 +143,9 @@ const runShortcut = (cmd) => {
placeholder="输入 JS 代码,按回车执行..."
@keyup.enter="executeCommand"
>
<template #prepend>></template>
<template #prepend>
>
</template>
</el-input>
</div>
@@ -35,7 +35,10 @@ const updateStyle = (prop, value) => {
</script>
<template>
<el-card class="elements-demo" shadow="hover">
<el-card
class="elements-demo"
shadow="hover"
>
<template #header>
<div class="header">
<span class="title">Elements (元素面板)</span>
@@ -45,7 +48,9 @@ const updateStyle = (prop, value) => {
<div class="devtools-layout">
<!-- Left: DOM Tree -->
<div class="panel dom-panel">
<div class="panel-header">DOM Tree</div>
<div class="panel-header">
DOM Tree
</div>
<div class="dom-content">
<div class="dom-line">
<span class="tag">&lt;div</span> <span class="attr">id</span>="app" <span class="attr">class</span>="container"<span class="tag">&gt;</span>
@@ -79,18 +84,24 @@ const updateStyle = (prop, value) => {
<!-- Right: Styles -->
<div class="panel style-panel">
<div class="panel-header">Styles ({{ selectedElement === 'box' ? '.box' : '.text' }})</div>
<div class="panel-header">
Styles ({{ selectedElement === 'box' ? '.box' : '.text' }})
</div>
<div class="style-content">
<div class="css-rule">
<span class="selector">{{ selectedElement === 'box' ? '.box' : '.text' }}</span> {
<div v-for="(value, prop) in styles[selectedElement]" :key="prop" class="css-prop">
<div
v-for="(value, prop) in styles[selectedElement]"
:key="prop"
class="css-prop"
>
<span class="prop-name">{{ prop }}</span>:
<span class="prop-value">
<!-- Simple editable input simulation -->
<input
v-model="styles[selectedElement][prop]"
class="style-input"
/>
<!-- Simple editable input simulation -->
<input
v-model="styles[selectedElement][prop]"
class="style-input"
>
</span>;
</div>
}
@@ -101,7 +112,9 @@ const updateStyle = (prop, value) => {
<!-- Preview Area -->
<div class="preview-area">
<div class="preview-label">页面预览 (Page Preview)</div>
<div class="preview-label">
页面预览 (Page Preview)
</div>
<div class="preview-content">
<div :style="styles.box">
<span :style="styles.text">Hello DevTools</span>
@@ -110,7 +123,7 @@ const updateStyle = (prop, value) => {
</div>
<div class="footer-tip">
点击左侧 DOM 树中的元素在右侧 Styles 面板修改样式下方预览会实时更新
点击左侧 DOM 树中的元素在右侧 Styles 面板修改样式下方预览会实时更新
</div>
</el-card>
</template>
@@ -60,13 +60,30 @@ const addFailedRequest = () => {
</script>
<template>
<el-card class="network-demo" shadow="hover">
<el-card
class="network-demo"
shadow="hover"
>
<template #header>
<div class="header">
<span class="title">Network (网络面板)</span>
<div class="actions">
<el-button type="primary" size="small" icon="Refresh" @click="refresh">刷新页面</el-button>
<el-button type="danger" size="small" icon="Warning" @click="addFailedRequest">模拟请求失败</el-button>
<el-button
type="primary"
size="small"
icon="Refresh"
@click="refresh"
>
刷新页面
</el-button>
<el-button
type="danger"
size="small"
icon="Warning"
@click="addFailedRequest"
>
模拟请求失败
</el-button>
</div>
</div>
</template>
@@ -75,37 +92,68 @@ const addFailedRequest = () => {
:data="requests"
style="width: 100%"
height="300"
@row-click="showDetails"
class="network-table"
@row-click="showDetails"
>
<el-table-column prop="name" label="Name" min-width="120">
<template #default="scope">
<span :class="{ error: scope.row.status >= 400 }">{{ scope.row.name }}</span>
</template>
</el-table-column>
<el-table-column prop="status" label="Status" width="80">
<el-table-column
prop="name"
label="Name"
min-width="120"
>
<template #default="scope">
<el-tag :type="scope.row.status >= 400 ? 'danger' : 'success'" size="small">
<span :class="{ error: scope.row.status >= 400 }">{{ scope.row.name }}</span>
</template>
</el-table-column>
<el-table-column
prop="status"
label="Status"
width="80"
>
<template #default="scope">
<el-tag
:type="scope.row.status >= 400 ? 'danger' : 'success'"
size="small"
>
{{ scope.row.status }}
</el-tag>
</template>
</el-table-column>
<el-table-column prop="type" label="Type" width="90" />
<el-table-column prop="size" label="Size" width="80" />
<el-table-column prop="time" label="Time" width="80">
<template #default="scope">{{ scope.row.time }}ms</template>
<el-table-column
prop="type"
label="Type"
width="90"
/>
<el-table-column
prop="size"
label="Size"
width="80"
/>
<el-table-column
prop="time"
label="Time"
width="80"
>
<template #default="scope">
{{ scope.row.time }}ms
</template>
</el-table-column>
<el-table-column label="Waterfall" min-width="150">
<el-table-column
label="Waterfall"
min-width="150"
>
<template #default="scope">
<div class="timeline-container">
<div class="timeline-bar" :style="getTimelineStyle(scope.row)"></div>
<div
class="timeline-bar"
:style="getTimelineStyle(scope.row)"
/>
</div>
</template>
</el-table-column>
</el-table>
<div class="footer-tip">
💡 点击某一行可以查看请求详情
💡 点击某一行可以查看请求详情
</div>
<!-- Detail Drawer -->
@@ -127,30 +175,32 @@ const addFailedRequest = () => {
<p><strong>Status Code:</strong> {{ selectedRequest.status }}</p>
</div>
<div class="detail-section">
<h4>Response Headers</h4>
<p><strong>Content-Type:</strong> {{ selectedRequest.type === 'document' ? 'text/html' : selectedRequest.type === 'fetch' ? 'application/json' : 'text/plain' }}</p>
<p><strong>Cache-Control:</strong> max-age=3600</p>
<h4>Response Headers</h4>
<p><strong>Content-Type:</strong> {{ selectedRequest.type === 'document' ? 'text/html' : selectedRequest.type === 'fetch' ? 'application/json' : 'text/plain' }}</p>
<p><strong>Cache-Control:</strong> max-age=3600</p>
</div>
</el-tab-pane>
<el-tab-pane label="Preview">
<div class="preview-box">
<div v-if="selectedRequest.status >= 400">
Failed to load response data
</div>
<div v-else-if="selectedRequest.type === 'fetch' || selectedRequest.type === 'xhr'">
<pre>{ "id": 123, "data": "Sample API response" }</pre>
</div>
<div v-else-if="selectedRequest.type === 'png' || selectedRequest.type === 'jpeg'">
<div class="fake-image">Image Preview</div>
</div>
<div v-else>
<pre>&lt;html&gt;...&lt;/html&gt;</pre>
<div v-if="selectedRequest.status >= 400">
Failed to load response data
</div>
<div v-else-if="selectedRequest.type === 'fetch' || selectedRequest.type === 'xhr'">
<pre>{ "id": 123, "data": "Sample API response" }</pre>
</div>
<div v-else-if="selectedRequest.type === 'png' || selectedRequest.type === 'jpeg'">
<div class="fake-image">
Image Preview
</div>
</div>
<div v-else>
<pre>&lt;html&gt;...&lt;/html&gt;</pre>
</div>
</div>
</el-tab-pane>
<el-tab-pane label="Response">
<div class="response-raw">
(Raw response data would appear here)
(Raw response data would appear here)
</div>
</el-tab-pane>
</el-tabs>
@@ -235,16 +235,42 @@ const flatNext = () => {
</script>
<template>
<el-card class="sources-demo" shadow="hover">
<el-card
class="sources-demo"
shadow="hover"
>
<template #header>
<div class="header">
<span class="title">Sources (源代码调试)</span>
<div class="controls">
<el-button-group>
<el-button type="success" size="small" icon="VideoPlay" @click="flatRun" :disabled="isRunning && demoState.line !== -1 && !breakpoints.includes(demoState.line)">Run</el-button>
<el-button type="primary" size="small" icon="VideoPause" @click="flatResume" :disabled="!breakpoints.includes(demoState.line)">Resume</el-button>
<el-button type="info" size="small" icon="ArrowRight" @click="flatNext">Step</el-button>
</el-button-group>
<el-button-group>
<el-button
type="success"
size="small"
icon="VideoPlay"
:disabled="isRunning && demoState.line !== -1 && !breakpoints.includes(demoState.line)"
@click="flatRun"
>
Run
</el-button>
<el-button
type="primary"
size="small"
icon="VideoPause"
:disabled="!breakpoints.includes(demoState.line)"
@click="flatResume"
>
Resume
</el-button>
<el-button
type="info"
size="small"
icon="ArrowRight"
@click="flatNext"
>
Step
</el-button>
</el-button-group>
</div>
</div>
</template>
@@ -261,38 +287,50 @@ const flatNext = () => {
}"
@click="toggleBreakpoint(index)"
>
<div class="line-num">{{ index + 1 }}</div>
<div class="code-text">{{ line }}</div>
<div class="line-num">
{{ index + 1 }}
</div>
<div class="code-text">
{{ line }}
</div>
</div>
</div>
<div class="sidebar">
<div class="section">
<div class="section-title">Scope (Variables)</div>
<div class="var-list">
<div class="var-item">
<span class="name">count:</span>
<span class="value">{{ demoState.vars.count !== undefined ? demoState.vars.count : 'undefined' }}</span>
</div>
<div class="var-item">
<span class="name">max:</span>
<span class="value">{{ demoState.vars.max !== undefined ? demoState.vars.max : 'undefined' }}</span>
</div>
<div class="section-title">
Scope (Variables)
</div>
<div class="var-list">
<div class="var-item">
<span class="name">count:</span>
<span class="value">{{ demoState.vars.count !== undefined ? demoState.vars.count : 'undefined' }}</span>
</div>
<div class="var-item">
<span class="name">max:</span>
<span class="value">{{ demoState.vars.max !== undefined ? demoState.vars.max : 'undefined' }}</span>
</div>
</div>
</div>
<div class="section">
<div class="section-title">Console Output</div>
<div class="output-list">
<div v-for="(log, i) in demoState.output" :key="i" class="log-line">
{{ log }}
</div>
<div class="section-title">
Console Output
</div>
<div class="output-list">
<div
v-for="(log, i) in demoState.output"
:key="i"
class="log-line"
>
{{ log }}
</div>
</div>
</div>
</div>
</div>
<div class="footer-tip">
点击行号设置断点点击 Run 开始执行代码将在断点处暂停
点击行号设置断点点击 Run 开始执行代码将在断点处暂停
</div>
</el-card>
</template>