FIX STYLE

This commit is contained in:
tommy
2025-11-07 16:17:03 +08:00
parent 8640db6334
commit c72e2e48bd
3 changed files with 253 additions and 13 deletions

View File

@@ -78,6 +78,12 @@
transform 0.2s ease;
}
.ui-button-content {
display: inline-flex;
align-items: center;
gap: 0.5rem;
}
.ui-button[data-size="sm"] {
height: 2rem;
padding: 0 0.75rem;
@@ -1402,6 +1408,89 @@
color: hsl(var(--muted-foreground));
}
/* Data Table - Interactive Table */
.ui-data-table {
width: 100%;
}
.ui-data-table-toolbar {
display: flex;
justify-content: flex-end;
align-items: center;
padding: 0.75rem 0;
gap: 0.5rem;
}
.ui-data-table-columns {
position: relative;
}
.ui-data-table-columns-trigger svg {
flex-shrink: 0;
}
.ui-data-table-columns-popover {
position: absolute;
top: calc(100% + 0.5rem);
right: 0;
min-width: 200px;
padding: 0.5rem;
background-color: hsl(var(--popover));
border: 1px solid hsl(var(--border));
border-radius: calc(var(--radius));
box-shadow: var(--shadow-lg);
z-index: 50;
animation: fadeIn 0.15s ease;
}
@keyframes fadeIn {
from {
opacity: 0;
transform: translateY(-0.5rem);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.ui-data-table-columns-option {
display: flex;
align-items: center;
gap: 0.75rem;
padding: 0.625rem 0.75rem;
font-size: 0.875rem;
color: hsl(var(--foreground));
cursor: pointer;
border-radius: calc(var(--radius) - 4px);
transition: background-color 0.15s ease;
user-select: none;
}
.ui-data-table-columns-option:hover {
background-color: hsl(var(--muted) / 0.5);
}
.ui-data-table-columns-option span {
flex: 1;
}
.ui-data-table-empty {
padding: 3rem 1rem;
text-align: center;
color: hsl(var(--muted-foreground));
font-size: 0.875rem;
}
.ui-data-table-checkbox-cell {
width: 48px;
padding: 0.75rem;
}
.ui-table-row.is-selected {
background-color: hsl(var(--muted) / 0.5);
}
.ui-calendar {
border: 1px solid hsl(var(--border));
border-radius: calc(var(--radius) - 2px);

View File

@@ -4,9 +4,9 @@ use std::{
rc::Rc,
};
use super::{utils::merge_class, Button, ButtonSize, ButtonVariant};
use crate::components::ui::Checkbox;
use dioxus::prelude::*;
use super::utils::merge_class;
#[component]
pub fn Table(#[props(into, default)] class: Option<String>, children: Element) -> Element {
let classes = merge_class("ui-table", class);
@@ -249,30 +249,53 @@ pub fn InteractiveTable(
rsx! {
div {
class: wrapper_class,
onclick: {
let mut open = columns_menu_open.clone();
move |_| {
if open() {
open.set(false);
}
}
},
div {
class: "ui-data-table-toolbar",
if !toggleable_columns.is_empty() {
div {
class: "ui-data-table-columns",
onfocusout: {
let mut open = columns_menu_open.clone();
move |_| open.set(false)
},
button {
Button {
variant: ButtonVariant::Outline,
size: ButtonSize::Sm,
class: "ui-data-table-columns-trigger",
"data-open": if columns_menu_open() { "true" } else { "false" },
onclick: {
on_click: {
let mut open = columns_menu_open.clone();
move |_| {
move |evt: MouseEvent| {
evt.stop_propagation();
let next = !open();
open.set(next);
}
},
"列显隐"
svg {
width: "16",
height: "16",
view_box: "0 0 24 24",
fill: "none",
stroke: "currentColor",
stroke_width: "2",
stroke_linecap: "round",
stroke_linejoin: "round",
rect { x: "3", y: "3", width: "7", height: "7" }
rect { x: "14", y: "3", width: "7", height: "7" }
rect { x: "14", y: "14", width: "7", height: "7" }
rect { x: "3", y: "14", width: "7", height: "7" }
}
"列控制"
}
if columns_menu_open() {
div {
class: "ui-data-table-columns-popover",
onclick: move |evt| {
evt.stop_propagation();
},
for column in toggleable_columns.iter() {
{
let column_id = column.id.clone();

View File

@@ -1,9 +1,9 @@
use crate::components::ui::{
Avatar, Badge, BadgeVariant, Button, ButtonSize, ButtonVariant, Card, CardContent,
CardDescription, CardFooter, CardHeader, CardTitle, CheckboxChipGroup, CheckboxChipOption,
DateRange, DateRangePicker, Input, Label, Pagination, Popover, Select, SelectOption, Slider,
Switch, Table, TableBody, TableCell, TableHead, TableHeader, TableRow, ToggleGroup,
ToggleGroupItem, ToggleGroupMode,
DateRange, DateRangePicker, Input, InteractiveTable, Label, Pagination, Popover, Select,
SelectOption, Slider, Table, TableBody, TableCaption, TableCell, TableColumnConfig,
TableFooter, TableHead, TableHeader, TableRow, TableRowData,
};
use chrono::NaiveDate;
use dioxus::prelude::*;
@@ -948,6 +948,134 @@ pub fn Orders() -> Element {
span { class: "orders-metric-sub", "调整筛选条件或清除限制重新查看。" }
}
} else {
// 示例1基础表格
h3 { style: "margin-top: 1rem;", "1. 基础表格 (Table)" }
Table {
TableCaption { "订单数据表格" }
TableHeader {
TableRow {
TableHead { "订单号" }
TableHead { "客户" }
TableHead { "状态" }
TableHead { "金额" }
}
}
TableBody {
for order in paginated_orders.iter().take(3).cloned() {
TableRow {
TableCell { "{order.number}" }
TableCell { "{order.customer_name}" }
TableCell {
Badge { variant: order.status.badge(), "{order.status.label()}" }
}
TableCell { {format!("¥{:.2}", order.total)} }
}
}
}
TableFooter {
TableRow {
TableCell { "总计 (前3项)" }
TableCell { }
TableCell { }
TableCell {
{
let total: f32 = paginated_orders.iter().take(3).map(|o| o.total).sum();
format!("¥{:.2}", total)
}
}
}
}
}
// 示例2InteractiveTable with 行选择 + 列可见性控制
h3 { style: "margin-top: 2rem;", "2. 高级数据表格 (InteractiveTable) - 行选择 + 列切换" }
{
let mut selected_rows = use_signal(|| std::collections::HashSet::<String>::new());
let selected_count = selected_rows().len();
let columns = vec![
TableColumnConfig {
id: "number".to_string(),
label: "订单号".to_string(),
toggleable: false,
visible_by_default: true,
},
TableColumnConfig {
id: "customer".to_string(),
label: "客户".to_string(),
toggleable: true,
visible_by_default: true,
},
TableColumnConfig {
id: "date".to_string(),
label: "日期".to_string(),
toggleable: true,
visible_by_default: true,
},
TableColumnConfig {
id: "status".to_string(),
label: "状态".to_string(),
toggleable: true,
visible_by_default: true,
},
TableColumnConfig {
id: "payment".to_string(),
label: "支付".to_string(),
toggleable: true,
visible_by_default: true,
},
TableColumnConfig {
id: "channel".to_string(),
label: "渠道".to_string(),
toggleable: true,
visible_by_default: false,
},
TableColumnConfig {
id: "total".to_string(),
label: "金额".to_string(),
toggleable: true,
visible_by_default: true,
},
];
let rows: Vec<TableRowData> = paginated_orders
.iter()
.map(|order| {
let mut cells = std::collections::HashMap::new();
cells.insert("number".to_string(), order.number.clone());
cells.insert("customer".to_string(), format!("{} ({})", order.customer_name, order.customer_email));
cells.insert("date".to_string(), order.placed_on.format("%Y-%m-%d").to_string());
cells.insert("status".to_string(), order.status.label().to_string());
cells.insert("payment".to_string(), order.payment_status.label().to_string());
cells.insert("channel".to_string(), order.channel.label().to_string());
cells.insert("total".to_string(), format!("¥{:.2}", order.total));
TableRowData {
id: order.number.clone(),
cells,
}
})
.collect();
rsx! {
div { style: "margin-bottom: 0.5rem;",
span { style: "font-size: 0.875rem; color: var(--muted-foreground);",
"已选择 {selected_count} 行"
}
}
InteractiveTable {
columns: columns,
rows: rows,
default_selected: Some(vec![]),
empty_state: Some("没有数据".to_string()),
on_selection_change: move |_selected: Vec<String>| {
// 选中的订单回调
}
}
}
}
// 示例3完整功能表格 (原始设计)
h3 { style: "margin-top: 2rem;", "3. 完整功能表格" }
Table {
TableHeader {
TableRow {