feat: 部分二次确认弹框样式调整

This commit is contained in:
hzm
2026-03-09 20:16:04 +08:00
parent d4255fc1c8
commit f39f152efa
5 changed files with 107 additions and 22 deletions

View File

@@ -15,20 +15,31 @@ export default function ConfirmModal({
onConfirm, onConfirm,
onCancel, onCancel,
confirmText = '确定删除', confirmText = '确定删除',
icon,
confirmVariant = 'danger', // 'danger' | 'primary' | 'secondary'
}) { }) {
const handleOpenChange = (open) => { const handleOpenChange = (open) => {
if (!open) onCancel(); if (!open) onCancel();
}; };
const confirmButtonToneClass =
confirmVariant === 'primary'
? 'button'
: confirmVariant === 'secondary'
? 'button secondary'
: 'button danger';
return ( return (
<Dialog open onOpenChange={handleOpenChange}> <Dialog open onOpenChange={handleOpenChange}>
<DialogContent <DialogContent
overlayClassName="!z-[1200]" overlayClassName="!z-[12000]"
showCloseButton={false} showCloseButton={false}
className="!z-[1210] max-w-[400px] flex flex-col gap-5 p-6" className="!z-[12010] max-w-[400px] flex flex-col gap-5 p-6"
> >
<DialogHeader className="flex flex-row items-center gap-3 text-left"> <DialogHeader className="flex flex-row items-center gap-3 text-left">
<TrashIcon width="20" height="20" className="shrink-0 text-[var(--danger)]" /> {icon || (
<TrashIcon width="20" height="20" className="shrink-0 text-[var(--danger)]" />
)}
<DialogTitle className="flex-1 text-base font-semibold">{title}</DialogTitle> <DialogTitle className="flex-1 text-base font-semibold">{title}</DialogTitle>
</DialogHeader> </DialogHeader>
<DialogDescription className="text-left text-sm leading-relaxed text-[var(--muted-foreground)]"> <DialogDescription className="text-left text-sm leading-relaxed text-[var(--muted-foreground)]">
@@ -44,7 +55,7 @@ export default function ConfirmModal({
</button> </button>
<button <button
type="button" type="button"
className="button danger min-w-0 flex-1 cursor-pointer h-auto min-h-[48px] py-3 sm:h-11 sm:min-h-0 sm:py-0" className={`${confirmButtonToneClass} min-w-0 flex-1 cursor-pointer h-auto min-h-[48px] py-3 sm:h-11 sm:min-h-0 sm:py-0`}
onClick={onConfirm} onClick={onConfirm}
> >
{confirmText} {confirmText}

View File

@@ -34,7 +34,7 @@ import {
DialogHeader, DialogHeader,
DialogTitle, DialogTitle,
} from '@/components/ui/dialog'; } from '@/components/ui/dialog';
import { CloseIcon, DragIcon, ExitIcon, SettingsIcon, StarIcon, TrashIcon } from './Icons'; import { CloseIcon, DragIcon, ExitIcon, SettingsIcon, StarIcon, TrashIcon, ResetIcon } from './Icons';
const NON_FROZEN_COLUMN_IDS = [ const NON_FROZEN_COLUMN_IDS = [
'yesterdayChangePercent', 'yesterdayChangePercent',
@@ -1117,6 +1117,8 @@ export default function PcFundTable({
<ConfirmModal <ConfirmModal
title="重置列宽" title="重置列宽"
message="是否重置表格列宽为默认值?" message="是否重置表格列宽为默认值?"
icon={<ResetIcon width="20" height="20" className="shrink-0 text-[var(--primary)]" />}
confirmVariant="primary"
onConfirm={handleResetSizing} onConfirm={handleResetSizing}
onCancel={() => setResetConfirmOpen(false)} onCancel={() => setResetConfirmOpen(false)}
confirmText="重置" confirmText="重置"

View File

@@ -267,6 +267,8 @@ export default function PcTableSettingModal({
key="reset-order-confirm" key="reset-order-confirm"
title="重置表头设置" title="重置表头设置"
message="是否重置表头顺序和显示/隐藏为默认值?" message="是否重置表头顺序和显示/隐藏为默认值?"
icon={<ResetIcon width="20" height="20" className="shrink-0 text-[var(--primary)]" />}
confirmVariant="primary"
onConfirm={() => { onConfirm={() => {
onResetColumnOrder?.(); onResetColumnOrder?.();
onResetColumnVisibility?.(); onResetColumnVisibility?.();

View File

@@ -1,7 +1,8 @@
'use client'; "use client";
import { useEffect, useState } from 'react'; import { useEffect, useRef, useState } from "react";
import { Dialog, DialogContent, DialogTitle } from '@/components/ui/dialog'; import { Dialog, DialogContent, DialogTitle } from '@/components/ui/dialog';
import { Progress } from '@/components/ui/progress';
import ConfirmModal from './ConfirmModal'; import ConfirmModal from './ConfirmModal';
import { ResetIcon, SettingsIcon } from './Icons'; import { ResetIcon, SettingsIcon } from './Icons';
@@ -22,6 +23,21 @@ export default function SettingsModal({
const [sliderDragging, setSliderDragging] = useState(false); const [sliderDragging, setSliderDragging] = useState(false);
const [resetWidthConfirmOpen, setResetWidthConfirmOpen] = useState(false); const [resetWidthConfirmOpen, setResetWidthConfirmOpen] = useState(false);
const [localSeconds, setLocalSeconds] = useState(tempSeconds); const [localSeconds, setLocalSeconds] = useState(tempSeconds);
const pageWidthTrackRef = useRef(null);
const clampedWidth = Math.min(2000, Math.max(600, Number(containerWidth) || 1200));
const pageWidthPercent = ((clampedWidth - 600) / (2000 - 600)) * 100;
const updateWidthByClientX = (clientX) => {
if (!pageWidthTrackRef.current || !setContainerWidth) return;
const rect = pageWidthTrackRef.current.getBoundingClientRect();
if (!rect.width) return;
const ratio = (clientX - rect.left) / rect.width;
const clampedRatio = Math.min(1, Math.max(0, ratio));
const rawWidth = 600 + clampedRatio * (2000 - 600);
const snapped = Math.round(rawWidth / 10) * 10;
setContainerWidth(snapped);
};
useEffect(() => { useEffect(() => {
if (!sliderDragging) return; if (!sliderDragging) return;
@@ -115,23 +131,32 @@ export default function SettingsModal({
)} )}
</div> </div>
<div style={{ display: 'flex', alignItems: 'center', gap: 12 }}> <div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
<input <div
type="range" ref={pageWidthTrackRef}
min={600} className="group relative"
max={2000} style={{ flex: 1, height: 14, cursor: 'pointer', display: 'flex', alignItems: 'center' }}
step={10} onPointerDown={(e) => {
value={Math.min(2000, Math.max(600, Number(containerWidth) || 1200))} setSliderDragging(true);
onChange={(e) => setContainerWidth(Number(e.target.value))} updateWidthByClientX(e.clientX);
onPointerDown={() => setSliderDragging(true)} e.currentTarget.setPointerCapture?.(e.pointerId);
className="page-width-slider"
style={{
flex: 1,
height: 6,
accentColor: 'var(--primary)',
}} }}
/> onPointerMove={(e) => {
if (!sliderDragging) return;
updateWidthByClientX(e.clientX);
}}
>
<Progress value={pageWidthPercent} />
<div
className="pointer-events-none absolute top-1/2 -translate-y-1/2"
style={{ left: `${pageWidthPercent}%`, transform: 'translate(-50%, -50%)' }}
>
<div
className="h-3 w-3 rounded-full bg-primary shadow-md shadow-primary/40"
/>
</div>
</div>
<span className="muted" style={{ fontSize: '0.8rem', minWidth: 48 }}> <span className="muted" style={{ fontSize: '0.8rem', minWidth: 48 }}>
{Math.min(2000, Math.max(600, Number(containerWidth) || 1200))}px {clampedWidth}px
</span> </span>
</div> </div>
</div> </div>
@@ -175,6 +200,8 @@ export default function SettingsModal({
<ConfirmModal <ConfirmModal
title="重置页面宽度" title="重置页面宽度"
message="是否重置页面宽度为默认值 1200px" message="是否重置页面宽度为默认值 1200px"
icon={<ResetIcon width="20" height="20" className="shrink-0 text-[var(--primary)]" />}
confirmVariant="primary"
onConfirm={() => { onConfirm={() => {
onResetContainerWidth(); onResetContainerWidth();
setResetWidthConfirmOpen(false); setResetWidthConfirmOpen(false);

View File

@@ -0,0 +1,43 @@
"use client"
import * as React from "react"
import { Progress as ProgressPrimitive } from "radix-ui"
import { cn } from "@/lib/utils"
function Progress({
className,
value,
...props
}) {
return (
<ProgressPrimitive.Root
data-slot="progress"
className={cn(
// 细高条,轻玻璃质感,统一用 CSS 变量
"relative w-full overflow-hidden rounded-full",
"h-1.5 sm:h-1.5",
"bg-[var(--input)]/70 dark:bg-[var(--input)]/40",
"border border-[var(--border)]/80 dark:border-[var(--border)]/80",
"shadow-[0_0_0_1px_rgba(15,23,42,0.02)] dark:shadow-[0_0_0_1px_rgba(15,23,42,0.6)]",
className
)}
{...props}>
<ProgressPrimitive.Indicator
data-slot="progress-indicator"
className={cn(
"h-full w-full flex-1",
// 金融风轻渐变,兼容明暗主题
"bg-gradient-to-r from-[var(--primary)] to-[var(--primary)]/80",
"dark:from-[var(--primary)] dark:to-[var(--secondary)]/90",
// 柔和发光,不喧宾夺主
"shadow-[0_0_8px_rgba(245,158,11,0.35)] dark:shadow-[0_0_14px_rgba(245,158,11,0.45)]",
// 平滑进度动画
"transition-[transform,box-shadow] duration-250 ease-out"
)}
style={{ transform: `translateX(-${100 - (value || 0)}%)` }} />
</ProgressPrimitive.Root>
);
}
export { Progress }