fix divider css

This commit is contained in:
2026-03-18 10:42:25 +08:00
parent 5a470c146a
commit d03d1e75c2
3 changed files with 75 additions and 65 deletions

View File

@@ -19,13 +19,9 @@ interface FileItemProps {
onView?: () => void; onView?: () => void;
onDownload?: () => void; onDownload?: () => void;
isDownloading?: boolean; isDownloading?: boolean;
showDivider?: boolean;
} }
const useStyles = createStyles(({ token, css }) => ({ const useStyles = createStyles(({ token, css }) => ({
wrapper: css`
width: 100%;
`,
item: css` item: css`
display: flex; display: flex;
align-items: center; align-items: center;
@@ -34,16 +30,12 @@ const useStyles = createStyles(({ token, css }) => ({
width: 100%; width: 100%;
cursor: pointer; cursor: pointer;
transition: background-color 0.15s ease; transition: background-color 0.15s ease;
position: relative;
&:hover { &:hover {
background-color: ${token.colorBgTextHover}; background-color: ${token.colorBgTextHover};
} }
`, `,
divider: css`
height: 1px;
background-color: ${token.colorBorder};
margin: 0 ${token.paddingMD}px;
`,
fileInfo: css` fileInfo: css`
display: flex; display: flex;
align-items: center; align-items: center;
@@ -75,7 +67,7 @@ const formatFileSize = (size: number | undefined): string => {
return `${(size / (1024 * 1024)).toFixed(1)} MB`; return `${(size / (1024 * 1024)).toFixed(1)} MB`;
}; };
const FileItem: React.FC<FileItemProps> = ({ entry, onDelete, onRestore, onView, onDownload, isDownloading, showDivider = true }) => { const FileItem: React.FC<FileItemProps> = ({ entry, onDelete, onRestore, onView, onDownload, isDownloading }) => {
const { t } = useTranslation(["app", "common"]); const { t } = useTranslation(["app", "common"]);
const { styles, cx } = useStyles(); const { styles, cx } = useStyles();
const token = useTheme(); const token = useTheme();
@@ -103,8 +95,7 @@ const FileItem: React.FC<FileItemProps> = ({ entry, onDelete, onRestore, onView,
}; };
return ( return (
<div className={styles.wrapper}> <div className={styles.item} onClick={handleItemClick} data-file-item="true">
<div className={styles.item} onClick={handleItemClick}>
<div className={styles.fileInfo}> <div className={styles.fileInfo}>
<div onClick={handleDragHandleClick}> <div onClick={handleDragHandleClick}>
<SortableList.DragHandle /> <SortableList.DragHandle />
@@ -116,9 +107,7 @@ const FileItem: React.FC<FileItemProps> = ({ entry, onDelete, onRestore, onView,
> >
{entry.fileName} {entry.fileName}
</span> </span>
{entry.status === "added" && ( {entry.status === "added" && <Badge color={token.colorSuccess} text={t("statusAdded")} style={{ fontSize: token.fontSizeSM, whiteSpace: "nowrap" }} />}
<Badge color={token.colorSuccess} text={t("statusAdded")} style={{ fontSize: token.fontSizeSM, whiteSpace: "nowrap" }} />
)}
{entry.status === "deleted" && ( {entry.status === "deleted" && (
<Badge color={token.colorError} text={t("statusDeleted")} style={{ fontSize: token.fontSizeSM, whiteSpace: "nowrap" }} /> <Badge color={token.colorError} text={t("statusDeleted")} style={{ fontSize: token.fontSizeSM, whiteSpace: "nowrap" }} />
)} )}
@@ -148,8 +137,6 @@ const FileItem: React.FC<FileItemProps> = ({ entry, onDelete, onRestore, onView,
)} )}
</Space> </Space>
</div> </div>
{showDivider && <div className={styles.divider} />}
</div>
); );
}; };

View File

@@ -287,10 +287,9 @@ const FileSection: React.FC<FileSectionProps> = ({
// ── Render item ──────────────────────────────────────────────────────────── // ── Render item ────────────────────────────────────────────────────────────
const renderItem = useCallback( const renderItem = useCallback(
(entry: FileEntry, index: number, totalCount: number) => { (entry: FileEntry) => {
// Determine if file is viewable (has fileKey for Kintone files OR storagePath for local files) // Determine if file is viewable (has fileKey for Kintone files OR storagePath for local files)
const isViewable = entry.fileKey || entry.storagePath; const isViewable = entry.fileKey || entry.storagePath;
const isLast = index === totalCount - 1;
return ( return (
<FileItem <FileItem
@@ -300,7 +299,6 @@ const FileSection: React.FC<FileSectionProps> = ({
onView={isViewable ? () => onView(entry.fileKey, entry.fileName, entry.storagePath) : undefined} onView={isViewable ? () => onView(entry.fileKey, entry.fileName, entry.storagePath) : undefined}
onDownload={entry.fileKey ? () => onDownload(entry.fileKey!, entry.fileName) : undefined} onDownload={entry.fileKey ? () => onDownload(entry.fileKey!, entry.fileName) : undefined}
isDownloading={downloadingKey === entry.fileKey} isDownloading={downloadingKey === entry.fileKey}
showDivider={!isLast}
/> />
); );
}, },
@@ -367,7 +365,7 @@ const FileSection: React.FC<FileSectionProps> = ({
{files.length === 0 ? ( {files.length === 0 ? (
<div className={styles.emptySection}>{t("noConfig")}</div> <div className={styles.emptySection}>{t("noConfig")}</div>
) : ( ) : (
<SortableFileList items={files} onReorder={handleReorder} renderItem={renderItem} /> <SortableFileList items={files} onReorder={handleReorder} renderItem={renderItem} dividerColor={token.colorBorder} />
)} )}
{/* Click-to-add strip */} {/* Click-to-add strip */}

View File

@@ -10,16 +10,39 @@ import { SortableList } from "@lobehub/ui";
import { DndContext, KeyboardSensor, PointerSensor, useSensor, useSensors, DragEndEvent } from "@dnd-kit/core"; import { DndContext, KeyboardSensor, PointerSensor, useSensor, useSensors, DragEndEvent } from "@dnd-kit/core";
import { SortableContext, verticalListSortingStrategy, arrayMove, sortableKeyboardCoordinates } from "@dnd-kit/sortable"; import { SortableContext, verticalListSortingStrategy, arrayMove, sortableKeyboardCoordinates } from "@dnd-kit/sortable";
import { restrictToVerticalAxis, restrictToWindowEdges } from "@dnd-kit/modifiers"; import { restrictToVerticalAxis, restrictToWindowEdges } from "@dnd-kit/modifiers";
import { createStyles } from "antd-style";
import type { FileEntry } from "@renderer/stores"; import type { FileEntry } from "@renderer/stores";
const useStyles = createStyles(({ css }) => ({
fileList: css`
display: flex;
flex-direction: column;
width: 100%;
/* 分割线:非最后一个子元素的 .fileItem 显示 */
& > *:not(:last-child) [data-file-item="true"]::after {
content: "";
position: absolute;
bottom: 0;
left: 0;
right: 0;
height: 1px;
background-color: var(--divider-color, #d9d9d9);
}
`,
}));
// ── SortableFileList Component ──────────────────────────────────────────────── // ── SortableFileList Component ────────────────────────────────────────────────
interface SortableFileListProps { interface SortableFileListProps {
items: FileEntry[]; items: FileEntry[];
onReorder: (newOrder: string[], draggedItemId: string) => void; onReorder: (newOrder: string[], draggedItemId: string) => void;
renderItem: (entry: FileEntry, index: number, totalCount: number) => React.ReactNode; renderItem: (entry: FileEntry) => React.ReactNode;
dividerColor?: string;
} }
const SortableFileList: React.FC<SortableFileListProps> = ({ items, onReorder, renderItem }) => { const SortableFileList: React.FC<SortableFileListProps> = ({ items, onReorder, renderItem, dividerColor }) => {
const { styles } = useStyles();
const sensors = useSensors( const sensors = useSensors(
useSensor(PointerSensor), useSensor(PointerSensor),
useSensor(KeyboardSensor, { useSensor(KeyboardSensor, {
@@ -45,11 +68,13 @@ const SortableFileList: React.FC<SortableFileListProps> = ({ items, onReorder, r
return ( return (
<DndContext sensors={sensors} collisionDetection={undefined} onDragEnd={handleDragEnd} modifiers={[restrictToVerticalAxis, restrictToWindowEdges]}> <DndContext sensors={sensors} collisionDetection={undefined} onDragEnd={handleDragEnd} modifiers={[restrictToVerticalAxis, restrictToWindowEdges]}>
<SortableContext items={items} strategy={verticalListSortingStrategy}> <SortableContext items={items} strategy={verticalListSortingStrategy}>
{items.map((entry, index) => ( <div className={styles.fileList} style={dividerColor ? ({ "--divider-color": dividerColor } as React.CSSProperties) : undefined}>
{items.map((entry) => (
<SortableList.Item key={entry.id} id={entry.id}> <SortableList.Item key={entry.id} id={entry.id}>
{renderItem(entry, index, items.length)} {renderItem(entry)}
</SortableList.Item> </SortableList.Item>
))} ))}
</div>
</SortableContext> </SortableContext>
</DndContext> </DndContext>
); );