Agent task: 开发: Phase A+E+F — CSS 全量改造 (mnote-web)
This commit is contained in:
@@ -8,6 +8,7 @@ pub(crate) mod evidence;
|
||||
mod gateway;
|
||||
mod health;
|
||||
mod hermes;
|
||||
mod ui_debug;
|
||||
mod hermes_client;
|
||||
mod hermes_tools;
|
||||
mod kernel;
|
||||
@@ -788,7 +789,8 @@ pub fn build_router(state: AppState) -> Router {
|
||||
if enable_debug_shell_routes {
|
||||
router = router
|
||||
.route("/tree", get(tree::tree_shell))
|
||||
.route("/document-debug", get(editor::document_editor_shell));
|
||||
.route("/document-debug", get(editor::document_editor_shell))
|
||||
.route("/ui-debug/components", get(ui_debug::components_shell));
|
||||
}
|
||||
|
||||
router.with_state(state)
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
//! MNOTE UI Debug 路由 handler
|
||||
//!
|
||||
//! `/ui-debug/components` 调试组件矩阵页面。
|
||||
//! 仅在 `MNOTE_WEB_ENABLE_DEBUG_SHELL_ROUTES=1` 时可用。
|
||||
|
||||
use crate::app::AppState;
|
||||
use crate::context::RequestContext;
|
||||
use crate::error::WebError;
|
||||
use crate::routes::web_shell::load_sidebar_tree_html;
|
||||
use crate::ssr::pages::ui_debug::UiDebugComponentsPage;
|
||||
use axum::extract::{Extension, State};
|
||||
use axum::response::{Html, IntoResponse, Response};
|
||||
|
||||
/// GET /ui-debug/components
|
||||
///
|
||||
/// 渲染组件矩阵调试页面。
|
||||
pub async fn components_shell(
|
||||
State(state): State<AppState>,
|
||||
Extension(context): Extension<RequestContext>,
|
||||
) -> Result<Response, WebError> {
|
||||
let workspace_id = "default";
|
||||
let sidebar_tree_html =
|
||||
load_sidebar_tree_html(state.config(), &context, workspace_id, None)
|
||||
.await
|
||||
.unwrap_or_default();
|
||||
|
||||
let body_content = crate::ssr::render_view(leptos::view! {
|
||||
<UiDebugComponentsPage
|
||||
sidebar_tree_html={sidebar_tree_html}
|
||||
/>
|
||||
});
|
||||
|
||||
let full_page = format!(
|
||||
r#"<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>UI Debug — 组件矩阵 — MNote</title>
|
||||
<style>{MNOTE_CSS}</style>
|
||||
</head>
|
||||
<body>{body_content}</body>
|
||||
</html>"#,
|
||||
MNOTE_CSS = crate::ssr::MNOTE_CSS,
|
||||
body_content = body_content,
|
||||
);
|
||||
|
||||
Ok(Html(full_page).into_response())
|
||||
}
|
||||
@@ -129,6 +129,7 @@ pub fn PageLayout(
|
||||
class="mnote-workspace-source-trigger"
|
||||
data-testid="mnote-workspace-source-trigger"
|
||||
data-mnote-action="open-workspace-source-menu"
|
||||
data-state="closed"
|
||||
aria-haspopup="menu"
|
||||
aria-expanded="false"
|
||||
title="切换我的空间或本地文件夹"
|
||||
@@ -150,6 +151,7 @@ pub fn PageLayout(
|
||||
aria-label="更多"
|
||||
data-testid="mnote-account-menu-trigger"
|
||||
data-mnote-action="open-account-menu"
|
||||
data-state="closed"
|
||||
aria-haspopup="menu"
|
||||
aria-expanded="false"
|
||||
>
|
||||
@@ -178,7 +180,7 @@ pub fn PageLayout(
|
||||
<div class="mnote-main">
|
||||
<header class="wolai-topbar" data-testid="wolai-topbar">
|
||||
<div class="wolai-topbar-left">
|
||||
<button type="button" class="wolai-icon-button wolai-menu-button" aria-label="切换侧栏" aria-pressed="false" data-mnote-action="toggle-sidebar" data-testid="wolai-sidebar-toggle"><span class="material-symbols-outlined" data-icon="menu" aria-hidden="true"></span></button>
|
||||
<button type="button" class="wolai-icon-button wolai-menu-button" aria-label="切换侧栏" data-state="closed" aria-haspopup="true" aria-expanded="false" aria-pressed="false" data-mnote-action="toggle-sidebar" data-testid="wolai-sidebar-toggle"><span class="material-symbols-outlined" data-icon="menu" aria-hidden="true"></span></button>
|
||||
<nav class="wolai-breadcrumb" aria-label="页面路径">
|
||||
<span class="wolai-breadcrumb-root">{ws_name.clone()}</span>
|
||||
<span class="wolai-breadcrumb-separator" aria-hidden="true">"›"</span>
|
||||
@@ -187,21 +189,21 @@ pub fn PageLayout(
|
||||
</div>
|
||||
<div class="wolai-topbar-actions" aria-label="页面操作">
|
||||
<span class="wolai-public-pill" data-testid="wolai-public-state" hidden></span>
|
||||
<button type="button" class="wolai-icon-button" title="星标置顶" aria-label="星标置顶" data-mnote-action="toggle-sidebar-shortcut" data-mnote-shortcut-kind="page"><span class="material-symbols-outlined" data-icon="star" aria-hidden="true"></span></button>
|
||||
<button type="button" class="wolai-icon-button" title="星标置顶" aria-label="星标置顶" data-state="closed" aria-haspopup="true" aria-expanded="false" data-mnote-action="toggle-sidebar-shortcut" data-mnote-shortcut-kind="page"><span class="material-symbols-outlined" data-icon="star" aria-hidden="true"></span></button>
|
||||
<button type="button" class="wolai-icon-button" title="演示" aria-label="演示"><span class="material-symbols-outlined" data-icon="slideshow" aria-hidden="true"></span></button>
|
||||
<button type="button" class="wolai-icon-button" title="资料库问答" aria-label="资料库问答" data-testid="mnote-knowledge-rag-settings-toggle" data-mnote-action="open-knowledge-rag-settings"><span class="material-symbols-outlined" data-icon="travel_explore" aria-hidden="true"></span></button>
|
||||
<button type="button" class="wolai-icon-button" title="评论" aria-label="评论"><span class="material-symbols-outlined" data-icon="comment" aria-hidden="true"></span></button>
|
||||
<button type="button" class="wolai-icon-button" title="分享" aria-label="分享"><span class="material-symbols-outlined" data-icon="share" aria-hidden="true"></span></button>
|
||||
<button type="button" class="wolai-icon-button" title="成员" aria-label="成员"><span class="material-symbols-outlined" data-icon="person_add" aria-hidden="true"></span></button>
|
||||
<button type="button" class="wolai-icon-button" title="页面历史" aria-label="历史" data-mnote-action="open-page-history"><span class="material-symbols-outlined" data-icon="history" aria-hidden="true"></span></button>
|
||||
<button type="button" class="wolai-icon-button" title="页面选项和全局选项" aria-label="更多" data-testid="wolai-page-settings-trigger" data-mnote-action="open-page-settings"><span class="material-symbols-outlined" data-icon="more_horiz" aria-hidden="true"></span></button>
|
||||
<button type="button" class="wolai-icon-button" title="页面选项和全局选项" aria-label="更多" data-state="closed" aria-haspopup="menu" aria-expanded="false" data-testid="wolai-page-settings-trigger" data-mnote-action="open-page-settings"><span class="material-symbols-outlined" data-icon="more_horiz" aria-hidden="true"></span></button>
|
||||
</div>
|
||||
</header>
|
||||
<article class="mnote-content">
|
||||
{children()}
|
||||
</article>
|
||||
<div class="wolai-floating-actions" aria-label="浮动操作">
|
||||
<button type="button" data-testid="wolai-floating-ai" class="wolai-floating-button wolai-floating-button--ai" aria-label="AI 助手" title="点击 进入空间智能问答" data-mnote-action="open-page-ai"><span class="material-symbols-outlined material-symbols-filled" data-icon="auto_awesome" aria-hidden="true"></span></button>
|
||||
<button type="button" data-testid="wolai-floating-ai" class="wolai-floating-button wolai-floating-button--ai" aria-label="AI 助手" data-state="closed" aria-haspopup="dialog" aria-expanded="false" title="点击 进入空间智能问答" data-mnote-action="open-page-ai"><span class="material-symbols-outlined material-symbols-filled" data-icon="auto_awesome" aria-hidden="true"></span></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -7,3 +7,4 @@ pub mod home;
|
||||
pub mod layout;
|
||||
pub mod mindmap;
|
||||
pub mod search;
|
||||
pub mod ui_debug;
|
||||
|
||||
@@ -0,0 +1,328 @@
|
||||
//! MNOTE UI Debug — 组件矩阵页面 (SSR)
|
||||
//!
|
||||
//! 调试用组件展示页面,通过 env var `MNOTE_WEB_ENABLE_DEBUG_SHELL_ROUTES=1` 启用。
|
||||
//! 包含:Button 3×3×4 矩阵、Dialog/Modal、Popover/DropdownMenu、Toast、Input/Select/Textarea。
|
||||
//! 仅在生产环境关闭的调试路由下可访问。
|
||||
|
||||
use crate::ssr::pages::layout::PageLayout;
|
||||
use leptos::prelude::*;
|
||||
|
||||
/// UI Debug 组件矩阵页面
|
||||
///
|
||||
/// 展示设计系统组件矩阵,包含主题切换。
|
||||
/// 页面使用 `.ui-debug-*` 命名空间的 CSS 样式。
|
||||
#[component]
|
||||
pub fn UiDebugComponentsPage(
|
||||
#[prop(optional)] sidebar_tree_html: Option<String>,
|
||||
#[prop(optional)] workspace_name: Option<String>,
|
||||
) -> impl IntoView {
|
||||
let sidebar_tree_html = sidebar_tree_html.unwrap_or_default();
|
||||
let workspace_name = workspace_name
|
||||
.map(|v| v.trim().to_string())
|
||||
.filter(|v| !v.is_empty())
|
||||
.unwrap_or_else(|| "开发用户 的空间".to_string());
|
||||
|
||||
// Toast JS: 简单 toast 通知系统
|
||||
let toast_js = r##"
|
||||
(function(){
|
||||
if (window.__mnoteUiDebugToastInited) return;
|
||||
window.__mnoteUiDebugToastInited = true;
|
||||
function showToast(message, kind) {
|
||||
kind = kind || 'info';
|
||||
var container = document.getElementById('ui-debug-toast-container');
|
||||
if (!container) return;
|
||||
var toast = document.createElement('div');
|
||||
toast.className = 'ui-debug-toast ui-debug-toast--' + kind;
|
||||
toast.setAttribute('role', 'status');
|
||||
toast.setAttribute('aria-live', 'polite');
|
||||
toast.textContent = message;
|
||||
container.appendChild(toast);
|
||||
requestAnimationFrame(function() { toast.classList.add('ui-debug-toast--visible'); });
|
||||
setTimeout(function() {
|
||||
toast.classList.remove('ui-debug-toast--visible');
|
||||
setTimeout(function() { if (toast.parentNode) toast.parentNode.removeChild(toast); }, 300);
|
||||
}, 2800);
|
||||
}
|
||||
window.__mnoteUiDebugToast = showToast;
|
||||
document.addEventListener('click', function(e) {
|
||||
var trigger = e.target.closest('[data-ui-debug-toast]');
|
||||
if (!trigger) return;
|
||||
var message = trigger.getAttribute('data-ui-debug-toast') || 'Toast message';
|
||||
var kind = trigger.getAttribute('data-ui-debug-toast-kind') || 'info';
|
||||
showToast(message, kind);
|
||||
});
|
||||
})();
|
||||
"##;
|
||||
|
||||
view! {
|
||||
<PageLayout current_nav="home" sidebar_tree_html={sidebar_tree_html} workspace_name={workspace_name.clone()}>
|
||||
<div class="ui-debug-root" data-ui-debug-page="components">
|
||||
// Toast container
|
||||
<div id="ui-debug-toast-container" class="ui-debug-toast-container" aria-label="通知区域"></div>
|
||||
<script inner_html={toast_js.to_string()}></script>
|
||||
|
||||
// Page header with theme toggle
|
||||
<header class="ui-debug-header">
|
||||
<h1 class="ui-debug-title">"MNote UI Debug — 组件矩阵"</h1>
|
||||
<div class="ui-debug-theme-controls">
|
||||
<button
|
||||
type="button"
|
||||
class="ui-debug-theme-btn"
|
||||
data-ui-debug-theme="light"
|
||||
title="浅色主题"
|
||||
>"☀️ 浅色"</button>
|
||||
<button
|
||||
type="button"
|
||||
class="ui-debug-theme-btn"
|
||||
data-ui-debug-theme="dark"
|
||||
title="深色主题"
|
||||
>"🌙 深色"</button>
|
||||
</div>
|
||||
// Theme JS
|
||||
<script inner_html={r##"
|
||||
(function(){
|
||||
if (window.__mnoteUiDebugThemeInited) return;
|
||||
window.__mnoteUiDebugThemeInited = true;
|
||||
var root = document.querySelector('.ui-debug-root');
|
||||
if (!root) return;
|
||||
function setTheme(theme) {
|
||||
root.setAttribute('data-ui-debug-theme', theme);
|
||||
root.querySelectorAll('[data-ui-debug-theme]').forEach(function(btn) {
|
||||
btn.classList.toggle('ui-debug-theme-btn--active', btn.getAttribute('data-ui-debug-theme') === theme);
|
||||
});
|
||||
}
|
||||
root.addEventListener('click', function(e) {
|
||||
var btn = e.target.closest('[data-ui-debug-theme]');
|
||||
if (!btn) return;
|
||||
setTheme(btn.getAttribute('data-ui-debug-theme'));
|
||||
});
|
||||
setTheme('light');
|
||||
})();
|
||||
"##.to_string()}></script>
|
||||
</header>
|
||||
|
||||
// ─── Button 3×3×4 Matrix ───
|
||||
<section class="ui-debug-section">
|
||||
<h2 class="ui-debug-section-title">"Buttons — 3 variant × 3 size × 4 state"</h2>
|
||||
<div class="ui-debug-matrix">
|
||||
{
|
||||
["primary", "secondary", "outline"]
|
||||
.iter()
|
||||
.flat_map(|variant| {
|
||||
["sm", "md", "lg"]
|
||||
.iter()
|
||||
.flat_map(move |size| {
|
||||
["default", "hover", "active", "disabled"]
|
||||
.iter()
|
||||
.map(move |state| {
|
||||
let is_disabled = *state == "disabled";
|
||||
let class = format!(
|
||||
"ui-debug-btn ui-debug-btn--{} ui-debug-btn--{}",
|
||||
variant, size
|
||||
);
|
||||
let label = format!("{}-{}-{}", variant, size, state);
|
||||
view! {
|
||||
<button
|
||||
type="button"
|
||||
class={class.clone()}
|
||||
disabled={is_disabled}
|
||||
data-ui-debug-state={*state}
|
||||
>{label.clone()}</button>
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
// ─── Dialog / Modal ───
|
||||
<section class="ui-debug-section">
|
||||
<h2 class="ui-debug-section-title">"Dialog / Modal"</h2>
|
||||
<div class="ui-debug-row">
|
||||
<button
|
||||
type="button"
|
||||
class="ui-debug-btn ui-debug-btn--primary ui-debug-btn--md"
|
||||
data-ui-debug-dialog="confirm"
|
||||
>"打开确认对话框"</button>
|
||||
<button
|
||||
type="button"
|
||||
class="ui-debug-btn ui-debug-btn--secondary ui-debug-btn--md"
|
||||
data-ui-debug-dialog="info"
|
||||
>"打开信息对话框"</button>
|
||||
<button
|
||||
type="button"
|
||||
class="ui-debug-btn ui-debug-btn--outline ui-debug-btn--md"
|
||||
data-ui-debug-dialog="danger"
|
||||
>"打开危险确认"</button>
|
||||
</div>
|
||||
// Dialog modal overlay
|
||||
<div id="ui-debug-dialog-overlay" class="ui-debug-dialog-overlay" hidden data-ui-debug-dialog-overlay="true" role="dialog" aria-modal="true" aria-label="对话框">
|
||||
<div class="ui-debug-dialog-panel">
|
||||
<header class="ui-debug-dialog-header">
|
||||
<h3 id="ui-debug-dialog-title" class="ui-debug-dialog-title"></h3>
|
||||
<button type="button" class="ui-debug-dialog-close" data-ui-debug-dialog-close="true" aria-label="关闭">"✕"</button>
|
||||
</header>
|
||||
<p id="ui-debug-dialog-body" class="ui-debug-dialog-body"></p>
|
||||
<footer class="ui-debug-dialog-footer">
|
||||
<button type="button" class="ui-debug-btn ui-debug-btn--outline ui-debug-btn--sm" data-ui-debug-dialog-close="true">"取消"</button>
|
||||
<button type="button" class="ui-debug-btn ui-debug-btn--primary ui-debug-btn--sm" id="ui-debug-dialog-confirm">"确认"</button>
|
||||
</footer>
|
||||
</div>
|
||||
</div>
|
||||
// Dialog JS
|
||||
<script inner_html={r##"
|
||||
(function(){
|
||||
if (window.__mnoteUiDebugDialogInited) return;
|
||||
window.__mnoteUiDebugDialogInited = true;
|
||||
var root = document.querySelector('.ui-debug-root');
|
||||
if (!root) return;
|
||||
var overlay = document.getElementById('ui-debug-dialog-overlay');
|
||||
var titleEl = document.getElementById('ui-debug-dialog-title');
|
||||
var bodyEl = document.getElementById('ui-debug-dialog-body');
|
||||
var dialogs = {
|
||||
confirm: { title: '确认操作', body: '确定要执行此操作吗?此操作不可撤销。' },
|
||||
info: { title: '提示信息', body: '这是一条重要的提示信息,请仔细阅读。' },
|
||||
danger: { title: '危险操作', body: '此操作将永久删除数据,确定要继续吗?' }
|
||||
};
|
||||
function showDialog(kind) {
|
||||
var d = dialogs[kind] || dialogs.info;
|
||||
titleEl.textContent = d.title;
|
||||
bodyEl.textContent = d.body;
|
||||
overlay.removeAttribute('hidden');
|
||||
}
|
||||
function hideDialog() { overlay.setAttribute('hidden', ''); }
|
||||
root.addEventListener('click', function(e) {
|
||||
var trigger = e.target.closest('[data-ui-debug-dialog]');
|
||||
if (trigger) { showDialog(trigger.getAttribute('data-ui-debug-dialog')); return; }
|
||||
if (e.target.closest('[data-ui-debug-dialog-close]')) { hideDialog(); return; }
|
||||
if (e.target === overlay) hideDialog();
|
||||
});
|
||||
document.getElementById('ui-debug-dialog-confirm').addEventListener('click', function() {
|
||||
if (window.__mnoteUiDebugToast) window.__mnoteUiDebugToast('操作已确认', 'success');
|
||||
hideDialog();
|
||||
});
|
||||
})();
|
||||
"##.to_string()}></script>
|
||||
</section>
|
||||
|
||||
// ─── Popover / DropdownMenu ───
|
||||
<section class="ui-debug-section">
|
||||
<h2 class="ui-debug-section-title">"Popover / DropdownMenu"</h2>
|
||||
<div class="ui-debug-row">
|
||||
<div class="ui-debug-popover-host">
|
||||
<button
|
||||
type="button"
|
||||
class="ui-debug-btn ui-debug-btn--primary ui-debug-btn--md"
|
||||
data-ui-debug-popover="actions"
|
||||
aria-haspopup="menu"
|
||||
aria-expanded="false"
|
||||
>"操作菜单 ▾"</button>
|
||||
<div class="ui-debug-popover" hidden data-ui-debug-popover-panel="actions" role="menu">
|
||||
<button type="button" class="ui-debug-popover-item" role="menuitem" data-ui-debug-toast="菜单项 1" data-ui-debug-toast-kind="info">"菜单项 1"</button>
|
||||
<button type="button" class="ui-debug-popover-item" role="menuitem" data-ui-debug-toast="菜单项 2" data-ui-debug-toast-kind="success">"菜单项 2"</button>
|
||||
<hr class="ui-debug-popover-separator" />
|
||||
<button type="button" class="ui-debug-popover-item ui-debug-popover-item--danger" role="menuitem" data-ui-debug-toast="删除" data-ui-debug-toast-kind="error">"删除"</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ui-debug-popover-host">
|
||||
<button
|
||||
type="button"
|
||||
class="ui-debug-btn ui-debug-btn--secondary ui-debug-btn--md"
|
||||
data-ui-debug-popover="settings"
|
||||
aria-haspopup="menu"
|
||||
aria-expanded="false"
|
||||
>"设置菜单 ▾"</button>
|
||||
<div class="ui-debug-popover" hidden data-ui-debug-popover-panel="settings" role="menu">
|
||||
<label class="ui-debug-popover-item ui-debug-popover-item--check" role="menuitemcheckbox">
|
||||
<input type="checkbox" checked /> "选项 A"
|
||||
</label>
|
||||
<label class="ui-debug-popover-item ui-debug-popover-item--check" role="menuitemcheckbox">
|
||||
<input type="checkbox" /> "选项 B"
|
||||
</label>
|
||||
<label class="ui-debug-popover-item ui-debug-popover-item--check" role="menuitemcheckbox">
|
||||
<input type="checkbox" checked /> "选项 C"
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
// Popover JS
|
||||
<script inner_html={r##"
|
||||
(function(){
|
||||
if (window.__mnoteUiDebugPopoverInited) return;
|
||||
window.__mnoteUiDebugPopoverInited = true;
|
||||
var root = document.querySelector('.ui-debug-root');
|
||||
if (!root) return;
|
||||
var activePanel = null;
|
||||
function closeActive() {
|
||||
if (activePanel) { activePanel.setAttribute('hidden', ''); activePanel = null; }
|
||||
}
|
||||
root.addEventListener('click', function(e) {
|
||||
var trigger = e.target.closest('[data-ui-debug-popover]');
|
||||
if (trigger) {
|
||||
var name = trigger.getAttribute('data-ui-debug-popover');
|
||||
var panel = root.querySelector('[data-ui-debug-popover-panel="' + name + '"]');
|
||||
if (!panel) return;
|
||||
if (activePanel === panel) { closeActive(); return; }
|
||||
closeActive();
|
||||
panel.removeAttribute('hidden');
|
||||
activePanel = panel;
|
||||
return;
|
||||
}
|
||||
var item = e.target.closest('[data-ui-debug-popover-panel]');
|
||||
if (!item && activePanel) { closeActive(); }
|
||||
});
|
||||
document.addEventListener('click', function(e) {
|
||||
if (activePanel && !root.contains(e.target)) closeActive();
|
||||
});
|
||||
})();
|
||||
"##.to_string()}></script>
|
||||
</section>
|
||||
|
||||
// ─── Toast triggers ───
|
||||
<section class="ui-debug-section">
|
||||
<h2 class="ui-debug-section-title">"Toast 通知"</h2>
|
||||
<div class="ui-debug-row">
|
||||
<button type="button" class="ui-debug-btn ui-debug-btn--primary ui-debug-btn--md" data-ui-debug-toast="操作成功完成!" data-ui-debug-toast-kind="success">"成功 Toast"</button>
|
||||
<button type="button" class="ui-debug-btn ui-debug-btn--secondary ui-debug-btn--md" data-ui-debug-toast="请注意此提示信息" data-ui-debug-toast-kind="info">"信息 Toast"</button>
|
||||
<button type="button" class="ui-debug-btn ui-debug-btn--outline ui-debug-btn--md" data-ui-debug-toast="发生了一个错误" data-ui-debug-toast-kind="error">"错误 Toast"</button>
|
||||
<button type="button" class="ui-debug-btn ui-debug-btn--primary ui-debug-btn--sm" data-ui-debug-toast="警告:即将超时" data-ui-debug-toast-kind="warning">"警告 Toast"</button>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
// ─── Input / Select / Textarea ───
|
||||
<section class="ui-debug-section">
|
||||
<h2 class="ui-debug-section-title">"Input / Select / Textarea"</h2>
|
||||
<div class="ui-debug-form-grid">
|
||||
<div class="ui-debug-field">
|
||||
<label class="ui-debug-label" for="ui-debug-input-text">"文本输入"</label>
|
||||
<input id="ui-debug-input-text" type="text" class="ui-debug-input" placeholder="输入文本..." />
|
||||
</div>
|
||||
<div class="ui-debug-field">
|
||||
<label class="ui-debug-label" for="ui-debug-input-email">"邮箱输入"</label>
|
||||
<input id="ui-debug-input-email" type="email" class="ui-debug-input" placeholder="email@example.com" />
|
||||
</div>
|
||||
<div class="ui-debug-field">
|
||||
<label class="ui-debug-label" for="ui-debug-input-disabled">"禁用输入"</label>
|
||||
<input id="ui-debug-input-disabled" type="text" class="ui-debug-input" placeholder="已禁用" disabled />
|
||||
</div>
|
||||
<div class="ui-debug-field">
|
||||
<label class="ui-debug-label" for="ui-debug-select">"下拉选择"</label>
|
||||
<select id="ui-debug-select" class="ui-debug-select">
|
||||
<option value="">"请选择..."</option>
|
||||
<option value="a">"选项 A"</option>
|
||||
<option value="b">"选项 B"</option>
|
||||
<option value="c">"选项 C"</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="ui-debug-field ui-debug-field--wide">
|
||||
<label class="ui-debug-label" for="ui-debug-textarea">"文本区域"</label>
|
||||
<textarea id="ui-debug-textarea" class="ui-debug-textarea" placeholder="输入多行文本..." rows="4"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</PageLayout>
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,873 @@
|
||||
/* ===== 基础重置 ===== */
|
||||
*, *::before, *::after {
|
||||
box-sizing: border-box;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/* ===== 基础排版 ===== */
|
||||
html, body {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: var(--wolai-font-sans);
|
||||
color: var(--wolai-text-primary);
|
||||
background: var(--wolai-bg);
|
||||
line-height: 1.6;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
a {
|
||||
color: var(--wolai-accent);
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color: var(--wolai-accent-hover);
|
||||
}
|
||||
|
||||
[hidden] {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.mnote-symbol {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
display: inline-flex;
|
||||
flex: 0 0 auto;
|
||||
color: currentColor;
|
||||
fill: none;
|
||||
stroke: currentColor;
|
||||
stroke-width: 1.9;
|
||||
stroke-linecap: round;
|
||||
stroke-linejoin: round;
|
||||
vertical-align: -0.18em;
|
||||
}
|
||||
|
||||
.mnote-symbol[data-icon="home"] {
|
||||
stroke-width: 2;
|
||||
}
|
||||
|
||||
.mnote-symbol--document {
|
||||
width: 56px;
|
||||
height: 56px;
|
||||
stroke-width: 1.35;
|
||||
}
|
||||
|
||||
.material-symbols-outlined {
|
||||
font-family: var(--wolai-font-sans);
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
font-size: 20px;
|
||||
line-height: 1;
|
||||
letter-spacing: 0;
|
||||
text-transform: none;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
white-space: nowrap;
|
||||
word-wrap: normal;
|
||||
direction: ltr;
|
||||
-webkit-font-feature-settings: "liga";
|
||||
-webkit-font-smoothing: antialiased;
|
||||
font-variation-settings: "FILL" 0, "wght" 400, "GRAD" 0, "opsz" 24;
|
||||
}
|
||||
|
||||
.material-symbols-outlined::before {
|
||||
content: "";
|
||||
display: block;
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
background: currentColor;
|
||||
-webkit-mask: var(--mnote-icon-mask) center / contain no-repeat;
|
||||
mask: var(--mnote-icon-mask) center / contain no-repeat;
|
||||
}
|
||||
|
||||
.material-symbols-outlined[data-icon="search"]::before { content: "⌕"; }
|
||||
.material-symbols-outlined[data-icon="account_tree"]::before { content: "⌘"; }
|
||||
.material-symbols-outlined[data-icon="bolt"]::before { content: "ϟ"; }
|
||||
.material-symbols-outlined[data-icon="help"]::before { content: "?"; }
|
||||
.material-symbols-outlined[data-icon="inventory_2"]::before { content: "▣"; }
|
||||
.material-symbols-outlined[data-icon="more_horiz"]::before { content: "…"; }
|
||||
.material-symbols-outlined[data-icon="menu"]::before { content: "☰"; }
|
||||
.material-symbols-outlined[data-icon="home"]::before { content: "⌂"; }
|
||||
.material-symbols-outlined[data-icon="star"]::before { content: "☆"; }
|
||||
.material-symbols-outlined[data-icon="history"]::before { content: "◷"; }
|
||||
.material-symbols-outlined[data-icon="auto_awesome"]::before { content: "✦"; }
|
||||
.material-symbols-outlined[data-icon="folder_open"]::before,
|
||||
.material-symbols-outlined[data-icon="drive_file_move"]::before { content: "▱"; }
|
||||
.material-symbols-outlined[data-icon="delete"]::before { content: "⌫"; }
|
||||
.material-symbols-outlined[data-icon="right_panel_open"]::before,
|
||||
.material-symbols-outlined[data-icon="open_in_new"]::before { content: "↗"; }
|
||||
.material-symbols-outlined[data-icon="share"]::before { content: "⇪"; }
|
||||
.material-symbols-outlined[data-icon="link"]::before { content: "∞"; }
|
||||
.material-symbols-outlined[data-icon="content_copy"]::before,
|
||||
.material-symbols-outlined[data-icon="file_copy"]::before { content: "⧉"; }
|
||||
.material-symbols-outlined[data-icon="tag"]::before { content: "#"; }
|
||||
.material-symbols-outlined[data-icon="edit"]::before { content: "✎"; }
|
||||
.material-symbols-outlined[data-icon="add"]::before { content: "+"; }
|
||||
.material-symbols-outlined[data-icon="manage_search"]::before { content: "⌕"; }
|
||||
.material-symbols-outlined[data-icon="subdirectory_arrow_right"]::before { content: "↳"; }
|
||||
|
||||
.material-symbols-filled {
|
||||
font-variation-settings: "FILL" 1, "wght" 400, "GRAD" 0, "opsz" 24;
|
||||
}
|
||||
|
||||
/* 本地 SVG mask 图标,避免 Google Material Symbols 字体未加载时露出英文图标名。 */
|
||||
.material-symbols-outlined[data-icon]::before { content: ""; }
|
||||
.material-symbols-outlined[data-icon="search"] { --mnote-icon-mask: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M10.8 18a7.2 7.2 0 1 1 0-14.4 7.2 7.2 0 0 1 0 14.4Z' fill='none' stroke='black' stroke-width='2' stroke-linecap='round'/%3E%3Cpath d='m16 16 4.2 4.2' fill='none' stroke='black' stroke-width='2' stroke-linecap='round'/%3E%3C/svg%3E"); }
|
||||
.material-symbols-outlined[data-icon="manage_search"] { --mnote-icon-mask: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M10.5 17.5a6.5 6.5 0 1 1 0-13 6.5 6.5 0 0 1 0 13Z' fill='none' stroke='black' stroke-width='2' stroke-linecap='round'/%3E%3Cpath d='m15.5 15.5 4 4M8 8.5h5M8 11h5M8 13.5h3' fill='none' stroke='black' stroke-width='2' stroke-linecap='round'/%3E%3C/svg%3E"); }
|
||||
.material-symbols-outlined[data-icon="account_tree"] { --mnote-icon-mask: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M6 6h4v4H6zM14 4h4v4h-4zM14 16h4v4h-4z' fill='none' stroke='black' stroke-width='1.8'/%3E%3Cpath d='M10 8h2a2 2 0 0 0 2-2M10 8h2a2 2 0 0 1 2 2v8' fill='none' stroke='black' stroke-width='1.8' stroke-linecap='round'/%3E%3C/svg%3E"); }
|
||||
.material-symbols-outlined[data-icon="bolt"] { --mnote-icon-mask: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M13 2 4.5 13h6L9 22l10.5-13h-6z' fill='none' stroke='black' stroke-width='2' stroke-linejoin='round'/%3E%3C/svg%3E"); }
|
||||
.material-symbols-outlined[data-icon="help"] { --mnote-icon-mask: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Ccircle cx='12' cy='12' r='9' fill='none' stroke='black' stroke-width='2'/%3E%3Cpath d='M9.8 9a2.4 2.4 0 0 1 4.6 1.1c0 1.7-1.7 2-2.2 3.1' fill='none' stroke='black' stroke-width='2' stroke-linecap='round'/%3E%3Ccircle cx='12' cy='17' r='1.1' fill='black'/%3E%3C/svg%3E"); }
|
||||
.material-symbols-outlined[data-icon="inventory_2"] { --mnote-icon-mask: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M4 5.5h16v4H4zM6 9.5h12V19H6z' fill='none' stroke='black' stroke-width='2' stroke-linejoin='round'/%3E%3Cpath d='M9.5 13.5h5' stroke='black' stroke-width='2' stroke-linecap='round'/%3E%3C/svg%3E"); }
|
||||
.material-symbols-outlined[data-icon="more_horiz"] { --mnote-icon-mask: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Ccircle cx='5' cy='12' r='2' fill='black'/%3E%3Ccircle cx='12' cy='12' r='2' fill='black'/%3E%3Ccircle cx='19' cy='12' r='2' fill='black'/%3E%3C/svg%3E"); }
|
||||
.material-symbols-outlined[data-icon="menu"] { --mnote-icon-mask: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M4 7h16M4 12h16M4 17h16' fill='none' stroke='black' stroke-width='2' stroke-linecap='round'/%3E%3C/svg%3E"); }
|
||||
.material-symbols-outlined[data-icon="home"] { --mnote-icon-mask: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M4 11 12 4l8 7v9H5v-9Z' fill='none' stroke='black' stroke-width='2' stroke-linejoin='round'/%3E%3Cpath d='M9.5 20v-6h5v6' fill='none' stroke='black' stroke-width='2' stroke-linejoin='round'/%3E%3C/svg%3E"); }
|
||||
.material-symbols-outlined[data-icon="star"] { --mnote-icon-mask: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='m12 3 2.7 5.4 6 .9-4.4 4.3 1 6-5.3-2.8-5.3 2.8 1-6-4.4-4.3 6-.9z' fill='none' stroke='black' stroke-width='2' stroke-linejoin='round'/%3E%3C/svg%3E"); }
|
||||
.material-symbols-outlined[data-icon="history"] { --mnote-icon-mask: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M4 12a8 8 0 1 0 2.3-5.7L4 8.5' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3Cpath d='M4 4v4.5h4.5M12 8v5l3.5 2' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E"); }
|
||||
.material-symbols-outlined[data-icon="auto_awesome"] { --mnote-icon-mask: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='m12 3 1.6 5.2L19 10l-5.4 1.8L12 17l-1.6-5.2L5 10l5.4-1.8zM5.5 15.5l.8 2.2 2.2.8-2.2.8-.8 2.2-.8-2.2-2.2-.8 2.2-.8zM18.5 2.5l.7 1.8 1.8.7-1.8.7-.7 1.8-.7-1.8-1.8-.7 1.8-.7z' fill='black'/%3E%3C/svg%3E"); }
|
||||
.material-symbols-outlined[data-icon="folder_open"] { --mnote-icon-mask: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M3.5 7.5h6l2 2H21v8.5a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-9a1.5 1.5 0 0 1 1.5-1.5Z' fill='none' stroke='black' stroke-width='2' stroke-linejoin='round'/%3E%3Cpath d='M4 18 7 11h14l-3 7' fill='none' stroke='black' stroke-width='2' stroke-linejoin='round'/%3E%3C/svg%3E"); }
|
||||
.material-symbols-outlined[data-icon="drive_file_move"] { --mnote-icon-mask: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M4 6h6l2 2h8v10H4z' fill='none' stroke='black' stroke-width='2' stroke-linejoin='round'/%3E%3Cpath d='m13 12 3 3-3 3M8 15h8' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E"); }
|
||||
.material-symbols-outlined[data-icon="delete"] { --mnote-icon-mask: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M5 6h14M9 6V4h6v2M8 6l1 14h6l1-14M10.5 10v6M13.5 10v6' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E"); }
|
||||
.material-symbols-outlined[data-icon="right_panel_open"] { --mnote-icon-mask: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M4 5h16v14H4zM14 5v14M8 12h6M11 9l3 3-3 3' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E"); }
|
||||
.material-symbols-outlined[data-icon="preview"] { --mnote-icon-mask: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M2.5 12s3.5-6 9.5-6 9.5 6 9.5 6-3.5 6-9.5 6-9.5-6-9.5-6Z' fill='none' stroke='black' stroke-width='2' stroke-linejoin='round'/%3E%3Ccircle cx='12' cy='12' r='2.8' fill='none' stroke='black' stroke-width='2'/%3E%3C/svg%3E"); }
|
||||
.material-symbols-outlined[data-icon="download"] { --mnote-icon-mask: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12 4v10M8.5 11.5 12 15l3.5-3.5M5 19h14' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E"); }
|
||||
.material-symbols-outlined[data-icon="notes"] { --mnote-icon-mask: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M6 5h12v14H6zM9 9h6M9 12h6M9 15h4' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E"); }
|
||||
.material-symbols-outlined[data-icon="open_in_new"] { --mnote-icon-mask: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M8 6H5v13h13v-3M12 5h7v7M10 14 19 5' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E"); }
|
||||
.material-symbols-outlined[data-icon="share"] { --mnote-icon-mask: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Ccircle cx='18' cy='5' r='3' fill='none' stroke='black' stroke-width='2'/%3E%3Ccircle cx='6' cy='12' r='3' fill='none' stroke='black' stroke-width='2'/%3E%3Ccircle cx='18' cy='19' r='3' fill='none' stroke='black' stroke-width='2'/%3E%3Cpath d='m8.7 10.7 6.6-4.4M8.7 13.3l6.6 4.4' fill='none' stroke='black' stroke-width='2' stroke-linecap='round'/%3E%3C/svg%3E"); }
|
||||
|
||||
.material-symbols-outlined[data-icon="comment"] { --mnote-icon-mask: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M5 5h14v10H9l-4 4V5Z' fill='none' stroke='black' stroke-width='2' stroke-linejoin='round'/%3E%3C/svg%3E"); }
|
||||
.material-symbols-outlined[data-icon="mode_comment"] { --mnote-icon-mask: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M5 5h14v10H9l-4 4V5Z' fill='none' stroke='black' stroke-width='2' stroke-linejoin='round'/%3E%3C/svg%3E"); }
|
||||
.material-symbols-outlined[data-icon="person_add"] { --mnote-icon-mask: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Ccircle cx='9' cy='8' r='3.2' fill='none' stroke='black' stroke-width='2'/%3E%3Cpath d='M3.5 20a5.5 5.5 0 0 1 11 0M18 8v6M15 11h6' fill='none' stroke='black' stroke-width='2' stroke-linecap='round'/%3E%3C/svg%3E"); }
|
||||
.material-symbols-outlined[data-icon="slideshow"] { --mnote-icon-mask: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M4 5h16v12H4z' fill='none' stroke='black' stroke-width='2' stroke-linejoin='round'/%3E%3Cpath d='m10 9 5 2-5 2zM9 21h6' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E"); }
|
||||
.material-symbols-outlined[data-icon="travel_explore"] { --mnote-icon-mask: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Ccircle cx='11' cy='11' r='7' fill='none' stroke='black' stroke-width='2'/%3E%3Cpath d='M4 11h14M11 4a10 10 0 0 1 0 14M11 4a10 10 0 0 0 0 14M16.5 16.5 21 21' fill='none' stroke='black' stroke-width='2' stroke-linecap='round'/%3E%3Cpath d='M7.5 8.5h2.5l1 1.5 2.5-.5 1 2-2 1 .5 2.5h-3l-1.5-2-2 .5' fill='none' stroke='black' stroke-width='1.4' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E"); }
|
||||
.material-symbols-outlined[data-icon="document_scanner"] { --mnote-icon-mask: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M7 3H5a2 2 0 0 0-2 2v2M17 3h2a2 2 0 0 1 2 2v2M7 21H5a2 2 0 0 1-2-2v-2M17 21h2a2 2 0 0 0 2-2v-2M7 8h10M7 12h10M7 16h7' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E"); }
|
||||
.material-symbols-outlined[data-icon="article"] { --mnote-icon-mask: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M6 4h12v16H6zM9 8h6M9 12h6M9 16h4' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E"); }
|
||||
.material-symbols-outlined[data-icon="sync"] { --mnote-icon-mask: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M20 6v5h-5M4 18v-5h5M7.5 9A6 6 0 0 1 18 6M16.5 15A6 6 0 0 1 6 18' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E"); }
|
||||
.material-symbols-outlined[data-icon="drive_file_rename_outline"] { --mnote-icon-mask: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='m4 17-.5 3.5L7 20l11-11-3-3zM13 8l3 3M5 6h7' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E"); }
|
||||
.material-symbols-outlined[data-icon="format_paint"] { --mnote-icon-mask: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M5 7h10l2 3-2 3H5l-2-3zM9 13v6' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E"); }
|
||||
.material-symbols-outlined[data-icon="link"] { --mnote-icon-mask: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M9.5 14.5 14.5 9.5M10.8 6.2l1.1-1.1a4 4 0 0 1 5.7 5.7l-1.6 1.6M13.2 17.8l-1.1 1.1a4 4 0 0 1-5.7-5.7L8 11.6' fill='none' stroke='black' stroke-width='2' stroke-linecap='round'/%3E%3C/svg%3E"); }
|
||||
.material-symbols-outlined[data-icon="content_copy"],
|
||||
.material-symbols-outlined[data-icon="file_copy"] { --mnote-icon-mask: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M8 8h10v12H8zM6 16H4V4h10v2' fill='none' stroke='black' stroke-width='2' stroke-linejoin='round'/%3E%3C/svg%3E"); }
|
||||
.material-symbols-outlined[data-icon="tag"] { --mnote-icon-mask: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M9 4 5 20M19 4l-4 16M4 9h16M3 15h16' fill='none' stroke='black' stroke-width='2' stroke-linecap='round'/%3E%3C/svg%3E"); }
|
||||
.material-symbols-outlined[data-icon="edit"] { --mnote-icon-mask: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='m4 17-.5 3.5L7 20l11-11-3-3zM13 8l3 3' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E"); }
|
||||
.material-symbols-outlined[data-icon="add"] { --mnote-icon-mask: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12 5v14M5 12h14' fill='none' stroke='black' stroke-width='2' stroke-linecap='round'/%3E%3C/svg%3E"); }
|
||||
.material-symbols-outlined[data-icon="subdirectory_arrow_right"] { --mnote-icon-mask: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M6 4v7a3 3 0 0 0 3 3h8M14 10l4 4-4 4' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E"); }
|
||||
.material-symbols-outlined[data-icon="account_circle"] { --mnote-icon-mask: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Ccircle cx='12' cy='12' r='9' fill='none' stroke='black' stroke-width='2'/%3E%3Ccircle cx='12' cy='9' r='3' fill='none' stroke='black' stroke-width='2'/%3E%3Cpath d='M6.8 19a5.4 5.4 0 0 1 10.4 0' fill='none' stroke='black' stroke-width='2' stroke-linecap='round'/%3E%3C/svg%3E"); }
|
||||
.material-symbols-outlined[data-icon="admin_panel_settings"] { --mnote-icon-mask: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12 3 5 6v5c0 4.5 2.9 8 7 10 4.1-2 7-5.5 7-10V6z' fill='none' stroke='black' stroke-width='2' stroke-linejoin='round'/%3E%3Cpath d='m9 12 2 2 4-5' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E"); }
|
||||
.material-symbols-outlined[data-icon="close"] { --mnote-icon-mask: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M6 6 18 18M18 6 6 18' fill='none' stroke='black' stroke-width='2' stroke-linecap='round'/%3E%3C/svg%3E"); }
|
||||
.material-symbols-outlined[data-icon="radio_button_unchecked"]::before {
|
||||
width: .78em;
|
||||
height: .78em;
|
||||
background: transparent;
|
||||
border: 2px solid currentColor;
|
||||
border-radius: 999px;
|
||||
-webkit-mask: none;
|
||||
mask: none;
|
||||
}
|
||||
/* ===== 滚动条(悬停时显示) ===== */
|
||||
::-webkit-scrollbar {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
}
|
||||
::-webkit-scrollbar-track {
|
||||
background: transparent;
|
||||
}
|
||||
::-webkit-scrollbar-thumb {
|
||||
background: transparent;
|
||||
border-radius: 4px;
|
||||
}
|
||||
:hover::-webkit-scrollbar-thumb {
|
||||
background: rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
/* ===== 页面布局:侧栏 + 内容 ===== */
|
||||
.mnote-shell {
|
||||
display: flex;
|
||||
height: 100vh;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
background: var(--wolai-bg);
|
||||
}
|
||||
|
||||
.mnote-shell[data-mnote-sidebar-collapsed="true"] .mnote-sidebar,
|
||||
.mnote-shell[data-mnote-sidebar-collapsed="true"] .wolai-sidebar,
|
||||
.mnote-shell[data-mnote-sidebar-collapsed="true"] .mnote-sidebar-resizer {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.wolai-workspace-shell {
|
||||
--wolai-bg-sidebar: #F7F7F6;
|
||||
--wolai-bg-selected: #F8E6E7;
|
||||
--wolai-accent-red: #E0525B;
|
||||
--mnote-sidebar-width: 288px;
|
||||
}
|
||||
|
||||
.wolai-sidebar {
|
||||
width: var(--mnote-sidebar-width);
|
||||
background: var(--wolai-bg-sidebar);
|
||||
}
|
||||
|
||||
.mnote-sidebar-resizer {
|
||||
display: block;
|
||||
width: 6px;
|
||||
min-height: 100vh;
|
||||
cursor: col-resize;
|
||||
position: relative;
|
||||
flex: 0 0 auto;
|
||||
overscroll-behavior: none;
|
||||
}
|
||||
|
||||
.mnote-sidebar-resizer::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: 2px;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
width: 2px;
|
||||
background: rgba(27, 28, 28, 0.08);
|
||||
}
|
||||
|
||||
.mnote-sidebar-resizer:hover::before,
|
||||
html[data-mnote-sidebar-resizing="true"] .mnote-sidebar-resizer::before {
|
||||
background: rgba(37, 99, 235, 0.42);
|
||||
}
|
||||
|
||||
.wolai-sidebar-header {
|
||||
height: 52px;
|
||||
gap: 10px;
|
||||
padding: 12px 16px 8px;
|
||||
justify-content: flex-start;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.wolai-avatar {
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 4px;
|
||||
background: #D6545D;
|
||||
color: #fff;
|
||||
font-size: 15px;
|
||||
font-weight: 700;
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
|
||||
.wolai-sidebar-header .sidebar-workspace-name {
|
||||
max-width: 190px;
|
||||
color: #202124;
|
||||
font-size: 16px;
|
||||
font-weight: 650;
|
||||
}
|
||||
|
||||
.mnote-workspace-source-trigger {
|
||||
min-width: 0;
|
||||
flex: 1 1 auto;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
border: 0;
|
||||
background: transparent;
|
||||
padding: 2px 4px;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.mnote-workspace-source-trigger:hover,
|
||||
.mnote-workspace-source-trigger[aria-expanded="true"] {
|
||||
background: var(--wolai-bg-hover);
|
||||
}
|
||||
|
||||
.wolai-sidebar-chevron {
|
||||
margin-left: auto;
|
||||
color: var(--wolai-text-secondary);
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.mnote-workspace-source-menu {
|
||||
position: absolute;
|
||||
inset-inline-start: 0;
|
||||
top: calc(100% + 6px);
|
||||
z-index: var(--wolai-z-dropdown);
|
||||
width: 250px;
|
||||
max-width: calc(100vw - 24px);
|
||||
padding: 6px;
|
||||
border: 1px solid rgba(27, 28, 28, 0.12);
|
||||
border-radius: 8px;
|
||||
background: #fff;
|
||||
box-shadow: 0 16px 36px rgba(15, 23, 42, 0.18);
|
||||
}
|
||||
|
||||
.mnote-workspace-source-menu__label {
|
||||
padding: 8px 8px 4px;
|
||||
color: var(--wolai-text-secondary);
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.mnote-workspace-source-menu__item {
|
||||
width: 100%;
|
||||
display: block;
|
||||
border: 0;
|
||||
border-radius: 6px;
|
||||
background: transparent;
|
||||
padding: 8px;
|
||||
color: var(--wolai-text-primary);
|
||||
font-size: 13px;
|
||||
line-height: 1.35;
|
||||
text-align: left;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.mnote-workspace-source-menu__item:hover {
|
||||
background: var(--wolai-bg-hover);
|
||||
}
|
||||
|
||||
.mnote-workspace-source-menu__item--primary {
|
||||
color: #1D4ED8;
|
||||
}
|
||||
|
||||
.mnote-local-folder-dialog__recent {
|
||||
display: grid;
|
||||
gap: 6px;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.mnote-local-folder-dialog__recent button {
|
||||
min-width: 0;
|
||||
max-width: 100%;
|
||||
border: 1px solid rgba(27, 28, 28, 0.12);
|
||||
border-radius: 6px;
|
||||
background: #fff;
|
||||
padding: 7px 9px;
|
||||
color: var(--wolai-text-primary);
|
||||
font-size: 13px;
|
||||
line-height: 1.4;
|
||||
text-align: left;
|
||||
cursor: pointer;
|
||||
white-space: normal;
|
||||
overflow-wrap: anywhere;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.mnote-local-folder-dialog__recent button:hover {
|
||||
background: var(--wolai-bg-hover);
|
||||
}
|
||||
|
||||
.mnote-account-menu{inset-inline-start:auto;right:8px;top:calc(100% - 10px);width:194px}.mnote-account-menu__item{display:flex;align-items:center;gap:10px}.mnote-account-menu__logout{color:#C2410C}.mnote-account-menu__logout:hover{background:#FFF7ED}.mnote-account-menu__error{padding:6px 8px 2px;color:#B91C1C;font-size:12px}.mnote-profile-dialog{position:fixed;inset:0;z-index:var(--wolai-z-modal);display:grid;place-items:center}.mnote-profile-dialog__backdrop{position:absolute;inset:0;background:rgba(15,23,42,.22)}.mnote-profile-dialog__panel{position:relative;width:min(440px,calc(100vw - 32px));max-height:calc(100vh - 48px);overflow:auto;border:1px solid var(--wolai-border);border-radius:8px;background:#fff;box-shadow:0 18px 54px rgba(15,23,42,.18);padding:20px}.mnote-profile-dialog__header,.mnote-profile-dialog__identity,.mnote-profile-dialog__list>div,.mnote-profile-dialog__list dd{display:flex;align-items:center}.mnote-profile-dialog__header{justify-content:space-between;margin-bottom:18px}.mnote-profile-dialog__eyebrow,.mnote-profile-dialog__identity span,.mnote-profile-dialog__list dt{color:var(--wolai-text-secondary);font-size:13px}.mnote-profile-dialog__header h2{font-size:20px}.mnote-profile-dialog__close,.mnote-profile-dialog__list button{border:0;border-radius:6px;background:transparent;color:var(--wolai-text-secondary);cursor:pointer}.mnote-profile-dialog__close{width:32px;height:32px}.mnote-profile-dialog__identity{gap:12px;padding:12px;border-radius:8px;background:var(--wolai-bg-sidebar)}.mnote-profile-dialog__avatar{width:36px;height:36px;display:grid;place-items:center;border-radius:6px;background:#D6545D;color:#fff;font-weight:650}.mnote-profile-dialog__list{margin-top:16px}.mnote-profile-dialog__list>div{justify-content:space-between;gap:16px;padding:11px 0;border-bottom:1px solid var(--wolai-border)}.mnote-profile-dialog__list dd{min-width:0;gap:8px;max-width:280px;font-size:13px;text-align:right;overflow-wrap:anywhere}.mnote-profile-dialog__list code{font-family:"JetBrains Mono","SFMono-Regular",Consolas,monospace;font-size:12px;white-space:normal}
|
||||
|
||||
.wolai-quick-actions {
|
||||
flex: 0 0 auto;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(7, 1fr);
|
||||
gap: 8px;
|
||||
padding: 8px 12px 18px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.wolai-quick-actions a,
|
||||
.wolai-quick-actions button {
|
||||
height: 28px;
|
||||
justify-content: center;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
color: #4B4B4B;
|
||||
border: 0;
|
||||
background: transparent;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.wolai-quick-actions a .nav-icon,
|
||||
.wolai-quick-actions button .nav-icon {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.wolai-sidebar-section {
|
||||
padding: 4px 8px 14px;
|
||||
}
|
||||
|
||||
.wolai-section-title {
|
||||
height: 28px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
color: #B5B5B2;
|
||||
font-size: 14px;
|
||||
padding: 0 8px;
|
||||
}
|
||||
|
||||
.wolai-section-icon {
|
||||
color: #FFB33F;
|
||||
}
|
||||
|
||||
.wolai-section-caret {
|
||||
color: #B5B5B2;
|
||||
}
|
||||
|
||||
.wolai-section-add {
|
||||
margin-left: auto;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
border: 0;
|
||||
border-radius: 6px;
|
||||
background: transparent;
|
||||
color: #B5B5B2;
|
||||
font-size: 22px;
|
||||
line-height: 1;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.wolai-section-add:hover {
|
||||
background: var(--wolai-bg-hover);
|
||||
color: #555;
|
||||
}
|
||||
|
||||
.wolai-page-row {
|
||||
min-height: 38px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
border-radius: 6px;
|
||||
padding: 0 12px;
|
||||
color: #535353;
|
||||
font-size: 17px;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.wolai-page-row:hover {
|
||||
background: var(--wolai-bg-hover);
|
||||
color: #202124;
|
||||
}
|
||||
|
||||
.wolai-muted-row {
|
||||
color: #747471;
|
||||
}
|
||||
|
||||
.wolai-active-row {
|
||||
background: var(--wolai-bg-selected);
|
||||
color: var(--wolai-accent-red);
|
||||
}
|
||||
|
||||
.wolai-row-icon {
|
||||
width: 22px;
|
||||
color: #111;
|
||||
text-align: center;
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
|
||||
.wolai-sidebar-footer {
|
||||
margin-top: auto;
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
border-top: 1px solid var(--wolai-border);
|
||||
background: #FBFBFA;
|
||||
}
|
||||
|
||||
.wolai-footer-entry {
|
||||
height: 46px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 8px;
|
||||
color: #6D6D69;
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
.wolai-footer-entry + .wolai-footer-entry {
|
||||
border-left: 1px solid var(--wolai-border);
|
||||
}
|
||||
|
||||
.wolai-topbar {
|
||||
height: 46px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
flex: 0 0 auto;
|
||||
padding: 0 18px;
|
||||
color: #222;
|
||||
font-size: 17px;
|
||||
}
|
||||
|
||||
.wolai-topbar-left,
|
||||
.wolai-topbar-actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.wolai-topbar-actions {
|
||||
color: #222;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.wolai-menu-icon {
|
||||
color: #4A4A4A;
|
||||
font-size: 22px;
|
||||
}
|
||||
|
||||
.wolai-home-icon {
|
||||
color: #000;
|
||||
font-size: 24px;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.wolai-floating-actions {
|
||||
position: fixed;
|
||||
right: 24px;
|
||||
bottom: 24px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
z-index: var(--wolai-z-dock);
|
||||
}
|
||||
|
||||
.wolai-floating-button {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
border: 1px solid #ECECF1;
|
||||
border-radius: 50%;
|
||||
background: #fff;
|
||||
color: #222;
|
||||
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.08);
|
||||
font-size: 18px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* 侧栏导航 */
|
||||
.mnote-sidebar {
|
||||
width: 288px;
|
||||
flex-shrink: 0;
|
||||
background: var(--wolai-bg-sidebar);
|
||||
border-right: 1px solid var(--wolai-border);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow-y: auto;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.mnote-sidebar-header {
|
||||
padding: 14px 16px 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.mnote-sidebar-brand {
|
||||
font-size: 15px;
|
||||
font-weight: 600;
|
||||
color: var(--wolai-text-primary);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.mnote-sidebar-brand:hover {
|
||||
color: var(--wolai-text-primary);
|
||||
}
|
||||
|
||||
.mnote-sidebar-nav {
|
||||
flex: 1;
|
||||
padding: 4px 8px;
|
||||
}
|
||||
|
||||
.mnote-sidebar-nav.wolai-quick-actions {
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
|
||||
.wolai-sidebar-body {
|
||||
flex: 1 1 auto;
|
||||
min-height: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.mnote-sidebar-nav a,
|
||||
.mnote-sidebar-nav button {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 30px;
|
||||
padding: 4px 8px;
|
||||
margin-bottom: 2px;
|
||||
border-radius: var(--wolai-radius);
|
||||
font-size: 14px;
|
||||
line-height: 1.4;
|
||||
color: var(--wolai-text-primary);
|
||||
text-decoration: none;
|
||||
transition: none;
|
||||
}
|
||||
|
||||
.mnote-sidebar-nav a:hover,
|
||||
.mnote-sidebar-nav button:hover {
|
||||
background: var(--wolai-bg-hover);
|
||||
}
|
||||
|
||||
.mnote-sidebar-nav a.active {
|
||||
background: var(--wolai-bg-active);
|
||||
}
|
||||
|
||||
.mnote-sidebar-nav a .nav-icon,
|
||||
.mnote-sidebar-nav button .nav-icon {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
margin-right: 5px;
|
||||
font-size: 18px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
/* 工作区名称 */
|
||||
.sidebar-workspace-name {
|
||||
font-size: 12px;
|
||||
color: var(--wolai-text-secondary);
|
||||
max-width: 120px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/* 侧栏页面树区 */
|
||||
.sidebar-tree-section {
|
||||
border-top: 1px solid var(--wolai-border);
|
||||
margin-top: 4px;
|
||||
padding-top: 4px;
|
||||
}
|
||||
|
||||
.sidebar-tree-divider {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.sidebar-tree {
|
||||
padding: 2px 0;
|
||||
}
|
||||
|
||||
.sidebar-tree .tree-root {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.sidebar-tree .tree-empty {
|
||||
padding: 6px 8px 8px;
|
||||
color: var(--wolai-text-secondary);
|
||||
font-size: 13px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.sidebar-tree .tree-node {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.sidebar-tree .tree-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 30px;
|
||||
padding: 0 8px;
|
||||
border-radius: var(--wolai-radius);
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
color: var(--wolai-text-primary);
|
||||
gap: 2px;
|
||||
}
|
||||
|
||||
.sidebar-tree .tree-row:hover {
|
||||
background: var(--wolai-bg-hover);
|
||||
}
|
||||
|
||||
.sidebar-tree .tree-row[data-active="true"] {
|
||||
background: var(--wolai-bg-active);
|
||||
}
|
||||
|
||||
.sidebar-tree .tree-row[data-active="true"] .tree-link-title {
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.sidebar-tree .tree-toggle {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
flex-shrink: 0;
|
||||
border: none;
|
||||
background: none;
|
||||
cursor: pointer;
|
||||
font-size: 12px;
|
||||
color: var(--wolai-text-secondary);
|
||||
padding: 0;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.sidebar-tree .tree-toggle:hover {
|
||||
background: var(--wolai-bg-hover);
|
||||
}
|
||||
|
||||
.sidebar-tree .tree-spacer {
|
||||
display: inline-flex;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.sidebar-tree .tree-kind-badge {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.sidebar-tree .tree-link {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border: none;
|
||||
background: none;
|
||||
cursor: pointer;
|
||||
padding: 0 4px;
|
||||
font-size: 14px;
|
||||
color: var(--wolai-text-primary);
|
||||
overflow: hidden;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.sidebar-tree .tree-link-title {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.sidebar-tree .tree-actions {
|
||||
display: none;
|
||||
gap: 2px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.sidebar-tree .tree-row:hover .tree-actions {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.sidebar-tree .tree-action {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
border: none;
|
||||
background: none;
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
color: var(--wolai-text-secondary);
|
||||
border-radius: 3px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.sidebar-tree .tree-action:hover {
|
||||
background: var(--wolai-bg-hover);
|
||||
}
|
||||
|
||||
.sidebar-tree .tree-children {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.sidebar-tree .tree-children--collapsed {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* 树行缩进 — 通过嵌套深度自动偏移 */
|
||||
.sidebar-tree .tree-node .tree-children .tree-row {
|
||||
padding-left: 28px;
|
||||
}
|
||||
|
||||
.sidebar-tree .tree-node .tree-children .tree-children .tree-row {
|
||||
padding-left: 48px;
|
||||
}
|
||||
|
||||
.sidebar-tree .tree-node .tree-children .tree-children .tree-children .tree-row {
|
||||
padding-left: 68px;
|
||||
}
|
||||
|
||||
.sidebar-tree .tree-node .tree-children .tree-children .tree-children .tree-children .tree-row {
|
||||
padding-left: 88px;
|
||||
}
|
||||
|
||||
/* 内容区域 */
|
||||
.mnote-main {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
background: var(--wolai-bg);
|
||||
}
|
||||
|
||||
.mnote-content {
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
overflow-y: auto;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.mnote-content:has(.document-workspace) {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* ===== data-state 通用规则 ===== */
|
||||
/* popover / dropdown / dialog 打开/关闭状态 */
|
||||
[data-state="open"] { display: block; }
|
||||
[data-state="closed"] { display: none !important; }
|
||||
|
||||
/* dialog/modal 状态 */
|
||||
.mnote-profile-dialog[data-state="open"],
|
||||
.ui-debug-dialog-overlay[data-state="open"],
|
||||
.wolai-search-overlay[data-state="open"] {
|
||||
display: grid;
|
||||
}
|
||||
.mnote-profile-dialog[data-state="closed"],
|
||||
.ui-debug-dialog-overlay[data-state="closed"],
|
||||
.wolai-search-overlay[data-state="closed"] {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/* popover/dropdown 状态 */
|
||||
.wolai-page-settings-popover[data-state="open"],
|
||||
.mnote-workspace-source-menu[data-state="open"],
|
||||
.ui-debug-popover[data-state="open"] {
|
||||
display: block;
|
||||
}
|
||||
.wolai-page-settings-popover[data-state="closed"],
|
||||
.mnote-workspace-source-menu[data-state="closed"],
|
||||
.ui-debug-popover[data-state="closed"] {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/* context menu 状态 */
|
||||
.mnote-tree-context-menu[data-state="open"] {
|
||||
display: block;
|
||||
}
|
||||
.mnote-tree-context-menu[data-state="closed"] {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/* drawer 状态 */
|
||||
.wolai-page-history-drawer[data-state="open"],
|
||||
.wolai-page-ai-drawer[data-state="open"] {
|
||||
display: block;
|
||||
}
|
||||
.wolai-page-history-drawer[data-state="closed"],
|
||||
.wolai-page-ai-drawer[data-state="closed"] {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/* aria-expanded 通用规则 */
|
||||
[aria-expanded="true"] > .material-symbols-outlined.nav-icon[data-icon] {
|
||||
color: var(--wolai-accent);
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,186 @@
|
||||
/* ===== 认证页面 ===== */
|
||||
.mnote-auth {
|
||||
position: relative;
|
||||
display: grid;
|
||||
min-height: 100vh;
|
||||
place-items: center;
|
||||
padding: 48px 20px;
|
||||
background: #FFFFFF;
|
||||
}
|
||||
|
||||
.mnote-auth-brand {
|
||||
position: fixed;
|
||||
top: 28px;
|
||||
left: 34px;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
color: #37352F;
|
||||
font-size: 18px;
|
||||
font-weight: 650;
|
||||
letter-spacing: 0;
|
||||
}
|
||||
|
||||
.mnote-auth-brand:hover {
|
||||
color: #37352F;
|
||||
}
|
||||
|
||||
.mnote-auth-brand-mark {
|
||||
display: inline-flex;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 6px;
|
||||
background: #37352F;
|
||||
color: #FFF;
|
||||
font-size: 18px;
|
||||
font-weight: 700;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.mnote-auth-panel {
|
||||
width: min(100%, 360px);
|
||||
color: #37352F;
|
||||
}
|
||||
|
||||
.mnote-auth-heading {
|
||||
margin-bottom: 30px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.mnote-auth-heading h1 {
|
||||
margin: 0 0 8px;
|
||||
color: #37352F;
|
||||
font-size: 28px;
|
||||
font-weight: 650;
|
||||
line-height: 1.25;
|
||||
letter-spacing: 0;
|
||||
}
|
||||
|
||||
.mnote-auth-heading p {
|
||||
color: #9B9A97;
|
||||
font-size: 14px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.mnote-auth-form {
|
||||
display: grid;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.mnote-auth-field {
|
||||
display: grid;
|
||||
gap: 7px;
|
||||
color: #6D6D69;
|
||||
font-size: 13px;
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
.mnote-auth-field input {
|
||||
width: 100%;
|
||||
height: 42px;
|
||||
border: 1px solid #DCDAD6;
|
||||
border-radius: 4px;
|
||||
background: #FFF;
|
||||
color: #37352F;
|
||||
font: 400 15px/1.4 var(--wolai-font-sans);
|
||||
letter-spacing: 0;
|
||||
outline: none;
|
||||
padding: 0 12px;
|
||||
}
|
||||
|
||||
.mnote-auth-field input::placeholder {
|
||||
color: #B5B1AA;
|
||||
}
|
||||
|
||||
.mnote-auth-field input:focus {
|
||||
border-color: #A8A39A;
|
||||
box-shadow: 0 0 0 2px rgba(55, 53, 47, 0.08);
|
||||
}
|
||||
|
||||
.mnote-auth-message {
|
||||
min-height: 20px;
|
||||
color: #9B9A97;
|
||||
font-size: 13px;
|
||||
line-height: 20px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.mnote-auth-message[data-type="error"] {
|
||||
color: #D14343;
|
||||
}
|
||||
|
||||
.mnote-auth-message[data-type="success"] {
|
||||
color: #23834D;
|
||||
}
|
||||
|
||||
.mnote-auth-submit {
|
||||
width: 100%;
|
||||
height: 42px;
|
||||
border: 0;
|
||||
border-radius: 4px;
|
||||
background: #37352F;
|
||||
color: #FFF;
|
||||
cursor: pointer;
|
||||
font: 600 15px/1 var(--wolai-font-sans);
|
||||
letter-spacing: 0;
|
||||
}
|
||||
|
||||
.mnote-auth-submit:hover {
|
||||
background: #2F2D29;
|
||||
}
|
||||
|
||||
.mnote-auth-submit:disabled {
|
||||
cursor: default;
|
||||
opacity: .58;
|
||||
}
|
||||
|
||||
.mnote-auth-quick-login {
|
||||
width: 100%;
|
||||
height: 42px;
|
||||
border: 1px solid #DCDAD6;
|
||||
border-radius: 4px;
|
||||
background: #FFF;
|
||||
color: #37352F;
|
||||
cursor: pointer;
|
||||
font: 500 14px/1 var(--wolai-font-sans);
|
||||
letter-spacing: 0;
|
||||
}
|
||||
|
||||
.mnote-auth-quick-login:hover {
|
||||
background: #F7F7F5;
|
||||
}
|
||||
|
||||
.mnote-auth-quick-login:disabled {
|
||||
cursor: default;
|
||||
opacity: .58;
|
||||
}
|
||||
|
||||
.mnote-auth-switch {
|
||||
display: block;
|
||||
margin: 18px auto 0;
|
||||
border: 0;
|
||||
background: transparent;
|
||||
color: #6D6D69;
|
||||
cursor: pointer;
|
||||
font: 400 14px/1.4 var(--wolai-font-sans);
|
||||
letter-spacing: 0;
|
||||
}
|
||||
|
||||
.mnote-auth-switch:hover {
|
||||
color: #37352F;
|
||||
}
|
||||
|
||||
@media (max-width: 640px) {
|
||||
.mnote-auth {
|
||||
align-items: start;
|
||||
padding-top: 132px;
|
||||
}
|
||||
|
||||
.mnote-auth-brand {
|
||||
top: 24px;
|
||||
left: 22px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
/* ===== 首页 ===== */
|
||||
.mnote-home {
|
||||
max-width: 720px;
|
||||
margin: 0 auto;
|
||||
padding: 72px 64px;
|
||||
}
|
||||
|
||||
.mnote-home-icon {
|
||||
width: 96px;
|
||||
height: 96px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin: 0 auto 22px;
|
||||
color: #000;
|
||||
font-size: 92px;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.mnote-home h1 {
|
||||
text-align: center;
|
||||
font-size: 44px;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0;
|
||||
margin-bottom: 34px;
|
||||
color: var(--wolai-text-primary);
|
||||
}
|
||||
|
||||
.mnote-home p {
|
||||
font-size: 16px;
|
||||
color: var(--wolai-text-secondary);
|
||||
line-height: 1.6;
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
|
||||
.mnote-home-links {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
max-width: 360px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.mnote-home-links a {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 2px 0;
|
||||
border-radius: var(--wolai-radius);
|
||||
font-size: 21px;
|
||||
font-weight: 650;
|
||||
color: var(--wolai-text-primary);
|
||||
text-decoration: none;
|
||||
transition: background-color 80ms ease;
|
||||
}
|
||||
|
||||
.mnote-home-links a:hover {
|
||||
background: var(--wolai-bg-hover);
|
||||
}
|
||||
|
||||
.mnote-home-links a::before {
|
||||
content: none;
|
||||
}
|
||||
|
||||
.mnote-home-links a span {
|
||||
width: 26px;
|
||||
text-align: center;
|
||||
color: #111;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
/* ===== 文档壳 ===== */
|
||||
.document-shell {
|
||||
width: 100%;
|
||||
min-height: 100vh;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.document-shell-header {
|
||||
padding: 48px 0 0;
|
||||
margin: 0 auto 8px;
|
||||
max-width: 760px;
|
||||
}
|
||||
|
||||
.document-shell-header h1 {
|
||||
font-size: 40px;
|
||||
font-weight: 700;
|
||||
line-height: 1.2;
|
||||
color: var(--wolai-text-primary);
|
||||
word-break: break-word;
|
||||
padding: 3px 0;
|
||||
}
|
||||
|
||||
#mnote-editor-island {
|
||||
margin: 0 15px;
|
||||
max-width: 760px;
|
||||
width: calc(100% - 30px);
|
||||
min-height: 300px;
|
||||
padding-bottom: 48px;
|
||||
}
|
||||
|
||||
#mnote-editor-island .bn-editor {
|
||||
padding: 0;
|
||||
max-width: none;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* ===== 搜索壳 ===== */
|
||||
#mnote-search-shell {
|
||||
max-width: 800px;
|
||||
min-height: 100vh;
|
||||
margin: 0 auto;
|
||||
padding: 48px 64px;
|
||||
}
|
||||
|
||||
#mnote-search-shell header {
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
#mnote-search-shell h1 {
|
||||
font-size: 32px;
|
||||
font-weight: 700;
|
||||
color: var(--wolai-text-primary);
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.search-meta,
|
||||
.search-query {
|
||||
color: var(--wolai-text-secondary);
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
#mnote-search-island {
|
||||
min-height: 200px;
|
||||
}
|
||||
|
||||
/* ===== 思维导图壳 ===== */
|
||||
#mnote-mindmap-shell {
|
||||
max-width: 1000px;
|
||||
min-height: 100vh;
|
||||
margin: 0 auto;
|
||||
padding: 48px 64px;
|
||||
}
|
||||
|
||||
#mnote-mindmap-shell header {
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
#mnote-mindmap-shell h1 {
|
||||
font-size: 32px;
|
||||
font-weight: 700;
|
||||
color: var(--wolai-text-primary);
|
||||
}
|
||||
|
||||
#mnote-mindmap-island {
|
||||
min-height: 400px;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
:root {
|
||||
/* 背景色 */
|
||||
--color-basic-50: #F7F7F5;
|
||||
--color-basic-75: #F0F0EE;
|
||||
--color-basic-100: #EBEBEB;
|
||||
--color-basic-200: #E3E3E0;
|
||||
--color-basic-300: #D4D4D1;
|
||||
--color-basic-400: #C4C4C1;
|
||||
--color-basic-500: #A9A9A6;
|
||||
--color-basic-600: #9B9A97;
|
||||
--color-basic-700: #6D6D69;
|
||||
--color-basic-800: #504F4B;
|
||||
--color-basic-900: #37352F;
|
||||
|
||||
/* wolai 语义变量 */
|
||||
--wolai-bg: #FFFFFF;
|
||||
--wolai-bg-sidebar: var(--color-basic-50);
|
||||
--wolai-bg-hover: rgba(55, 53, 47, 0.08);
|
||||
--wolai-bg-active: rgba(55, 53, 47, 0.12);
|
||||
--wolai-text-primary: var(--color-basic-900);
|
||||
--wolai-text-secondary: var(--color-basic-600);
|
||||
--wolai-border: #E9E9E8;
|
||||
--wolai-brand: #22A559;
|
||||
--wolai-accent: #2563eb;
|
||||
--wolai-accent-hover: #1d4ed8;
|
||||
--wolai-font-sans: -apple-system, BlinkMacSystemFont, "Segoe UI", "Microsoft YaHei", "PingFang SC", Helvetica, Arial, sans-serif;
|
||||
--wolai-radius: 4px;
|
||||
|
||||
/* z-index tokens */
|
||||
--wolai-z-dock: 50;
|
||||
--wolai-z-popover: 90;
|
||||
--wolai-z-dropdown: 120;
|
||||
--wolai-z-context-menu: 1000;
|
||||
--wolai-z-modal: 1200;
|
||||
|
||||
/* spacing tokens */
|
||||
--wolai-spacing-xs: 4px;
|
||||
--wolai-spacing-sm: 8px;
|
||||
--wolai-spacing-md: 12px;
|
||||
--wolai-spacing-lg: 16px;
|
||||
--wolai-spacing-xl: 24px;
|
||||
--wolai-spacing-2xl: 32px;
|
||||
|
||||
/* shadow tokens */
|
||||
--wolai-shadow-sm: 0 2px 4px rgba(15, 23, 42, 0.04);
|
||||
--wolai-shadow-md: 0 8px 24px rgba(15, 23, 42, 0.08);
|
||||
--wolai-shadow-lg: 0 18px 48px rgba(15, 23, 42, 0.12);
|
||||
--wolai-shadow-popover: 0 4px 16px rgba(15, 23, 42, 0.10);
|
||||
--wolai-shadow-modal: 0 18px 54px rgba(15, 23, 42, 0.18);
|
||||
|
||||
/* state tokens */
|
||||
--wolai-state-hover-bg: rgba(55, 53, 47, 0.06);
|
||||
--wolai-state-active-bg: rgba(55, 53, 47, 0.10);
|
||||
--wolai-state-focus-ring: 0 0 0 2px rgba(37, 99, 235, 0.35);
|
||||
--wolai-state-disabled-opacity: 0.45;
|
||||
}
|
||||
|
||||
/* Stitch 260429 atelier tokens */
|
||||
:root {
|
||||
--atelier-surface: #FAF9F9;
|
||||
--atelier-sidebar: #F5F5F5;
|
||||
--atelier-sidebar-hover: #ECEBE9;
|
||||
--atelier-sidebar-active: #E3E2E2;
|
||||
--atelier-document: #FFFFFF;
|
||||
--atelier-text: #1B1C1C;
|
||||
--atelier-text-muted: #8A8782;
|
||||
--atelier-text-soft: #B7B4AF;
|
||||
--atelier-outline: #EAEAEA;
|
||||
--atelier-primary: #006E28;
|
||||
--atelier-primary-container: #31AA4D;
|
||||
--atelier-secondary: #2367F6;
|
||||
--atelier-shadow: 0 16px 32px rgba(27, 28, 28, 0.04);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,147 @@
|
||||
"use strict";
|
||||
|
||||
const { chromium } = require("playwright");
|
||||
const { BASE_URL, UI_TIMEOUT_MS, assert, ensureAuthenticated } = require("./tree-shell-smoke-helpers");
|
||||
|
||||
const MNOTE_WEB_ENABLE_DEBUG_SHELL_ROUTES = process.env.MNOTE_WEB_ENABLE_DEBUG_SHELL_ROUTES || "0";
|
||||
|
||||
if (MNOTE_WEB_ENABLE_DEBUG_SHELL_ROUTES !== "1") {
|
||||
console.log("[task500] 跳过: MNOTE_WEB_ENABLE_DEBUG_SHELL_ROUTES 未设为 1 (当前值: '%s')", MNOTE_WEB_ENABLE_DEBUG_SHELL_ROUTES);
|
||||
console.log("[task500] 设置 MNOTE_WEB_ENABLE_DEBUG_SHELL_ROUTES=1 并重启 mnote-web 后再运行此 smoke。");
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
const PAGE_URL = `${BASE_URL}/ui-debug/components`;
|
||||
|
||||
async function main() {
|
||||
console.log("[task500] 启动 UI Debug 组件矩阵 smoke …");
|
||||
const browser = await chromium.launch({ headless: true });
|
||||
const context = await browser.newContext();
|
||||
const page = await context.newPage();
|
||||
|
||||
try {
|
||||
// 1. 认证
|
||||
await ensureAuthenticated(page);
|
||||
console.log("[task500] ✓ 已认证");
|
||||
|
||||
// 2. 导航到 /ui-debug/components
|
||||
await page.goto(PAGE_URL, { waitUntil: "networkidle", timeout: UI_TIMEOUT_MS });
|
||||
console.log("[task500] ✓ 页面已加载: %s", PAGE_URL);
|
||||
|
||||
// 3. 页面标题
|
||||
const title = await page.title();
|
||||
assert(title.includes("UI Debug"), `标题应包含 "UI Debug",实际: "${title}"`);
|
||||
console.log("[task500] ✓ 页面标题: %s", title);
|
||||
|
||||
// 4. 页面根元素
|
||||
const root = page.locator(".ui-debug-root");
|
||||
await root.waitFor({ state: "visible", timeout: UI_TIMEOUT_MS });
|
||||
console.log("[task500] ✓ .ui-debug-root 可见");
|
||||
|
||||
// 5. Button 矩阵应当可见
|
||||
const matrix = page.locator(".ui-debug-matrix");
|
||||
await matrix.waitFor({ state: "visible", timeout: UI_TIMEOUT_MS });
|
||||
const btnCount = await matrix.locator("button").count();
|
||||
assert(btnCount >= 12, `按钮矩阵应至少有 12 个按钮,实际: ${btnCount}`);
|
||||
console.log("[task500] ✓ 按钮矩阵: %d 个按钮", btnCount);
|
||||
|
||||
// 6. 主题切换
|
||||
const darkBtn = page.locator("[data-ui-debug-theme=\"dark\"]");
|
||||
await darkBtn.click();
|
||||
await page.waitForTimeout(200);
|
||||
const theme = await root.getAttribute("data-ui-debug-theme");
|
||||
assert(theme === "dark", `主题应为 dark,实际: "${theme}"`);
|
||||
console.log("[task500] ✓ 主题切换: dark");
|
||||
|
||||
// 切回 light
|
||||
const lightBtn = page.locator("[data-ui-debug-theme=\"light\"]");
|
||||
await lightBtn.click();
|
||||
await page.waitForTimeout(200);
|
||||
const theme2 = await root.getAttribute("data-ui-debug-theme");
|
||||
assert(theme2 === "light", `主题应为 light,实际: "${theme2}"`);
|
||||
|
||||
// 7. Dialog 对话框
|
||||
const dialogTrigger = page.locator("[data-ui-debug-dialog=\"info\"]");
|
||||
await dialogTrigger.click();
|
||||
await page.waitForTimeout(200);
|
||||
const dialogOverlay = page.locator("#ui-debug-dialog-overlay");
|
||||
const overlayVisible = await dialogOverlay.isVisible();
|
||||
assert(overlayVisible, "对话框应可见");
|
||||
const dialogTitle = await page.locator("#ui-debug-dialog-title").textContent();
|
||||
assert(dialogTitle.includes("提示"), `对话框标题应包含"提示",实际: "${dialogTitle}"`);
|
||||
console.log("[task500] ✓ 对话框打开: %s", dialogTitle);
|
||||
|
||||
// 关闭对话框
|
||||
const closeBtn = page.locator("[data-ui-debug-dialog-close=\"true\"]").first();
|
||||
await closeBtn.click();
|
||||
await page.waitForTimeout(200);
|
||||
const hidden = await dialogOverlay.getAttribute("hidden");
|
||||
assert(hidden !== null, "对话框应已关闭 (hidden)");
|
||||
console.log("[task500] ✓ 对话框已关闭");
|
||||
|
||||
// 8. Popover 菜单
|
||||
const popoverTrigger = page.locator("[data-ui-debug-popover=\"actions\"]");
|
||||
await popoverTrigger.click();
|
||||
await page.waitForTimeout(200);
|
||||
const popoverPanel = page.locator("[data-ui-debug-popover-panel=\"actions\"]");
|
||||
const popoverVisible = await popoverPanel.isVisible();
|
||||
assert(popoverVisible, "Popover 菜单应可见");
|
||||
const menuItems = await popoverPanel.locator("[role=\"menuitem\"]").count();
|
||||
assert(menuItems >= 2, `Popover 应至少有 2 个菜单项,实际: ${menuItems}`);
|
||||
console.log("[task500] ✓ Popover 打开: %d 个菜单项", menuItems);
|
||||
|
||||
// 关闭 popover
|
||||
await page.locator("body").click({ position: { x: 10, y: 10 } });
|
||||
await page.waitForTimeout(200);
|
||||
|
||||
// 9. Toast
|
||||
const toastTrigger = page.locator("[data-ui-debug-toast-kind=\"success\"]").first();
|
||||
await toastTrigger.click();
|
||||
await page.waitForTimeout(400);
|
||||
const toast = page.locator(".ui-debug-toast--visible");
|
||||
const toastCount = await toast.count();
|
||||
assert(toastCount >= 1, `Toast 应可见,实际数量: ${toastCount}`);
|
||||
console.log("[task500] ✓ Toast 显示");
|
||||
|
||||
// 10. Input / Select / Textarea
|
||||
const textInput = page.locator("#ui-debug-input-text");
|
||||
await textInput.waitFor({ state: "visible", timeout: UI_TIMEOUT_MS });
|
||||
await textInput.fill("测试文本");
|
||||
const inputValue = await textInput.inputValue();
|
||||
assert(inputValue === "测试文本", `输入框值应为"测试文本",实际: "${inputValue}"`);
|
||||
console.log("[task500] ✓ 文本输入: %s", inputValue);
|
||||
|
||||
const selectEl = page.locator("#ui-debug-select");
|
||||
await selectEl.selectOption("b");
|
||||
const selectValue = await selectEl.inputValue();
|
||||
assert(selectValue === "b", `下拉选择值应为"b",实际: "${selectValue}"`);
|
||||
console.log("[task500] ✓ 下拉选择: %s", selectValue);
|
||||
|
||||
const textarea = page.locator("#ui-debug-textarea");
|
||||
await textarea.fill("多行\n文本");
|
||||
const textareaValue = await textarea.inputValue();
|
||||
assert(textareaValue === "多行\n文本", `文本区域值应包含"多行",实际: "${textareaValue}"`);
|
||||
console.log("[task500] ✓ 文本区域: %s", textareaValue.replace(/\n/g, "\\n"));
|
||||
|
||||
// 11. CSS 变量检查
|
||||
const cssVar = await root.evaluate((el) => {
|
||||
const style = getComputedStyle(el);
|
||||
return style.getPropertyValue("--ui-debug-primary").trim();
|
||||
});
|
||||
assert(cssVar.length > 0, `--ui-debug-primary 应有值,实际: "${cssVar}"`);
|
||||
console.log("[task500] ✓ CSS 变量 --ui-debug-primary: %s", cssVar);
|
||||
|
||||
console.log("[task500] ✅ 全部断言通过");
|
||||
} catch (error) {
|
||||
console.error("[task500] ✗ 失败:", error.message);
|
||||
try {
|
||||
await page.screenshot({ path: "tmp/task500-failure.png", fullPage: true });
|
||||
console.log("[task500] 失败截图: tmp/task500-failure.png");
|
||||
} catch (_) {}
|
||||
process.exitCode = 1;
|
||||
} finally {
|
||||
await browser.close();
|
||||
}
|
||||
}
|
||||
|
||||
main();
|
||||
Reference in New Issue
Block a user