import { MoveStyleUtils, Rock, RockChildrenConfig, RockConfig } from "@ruiapp/move-style";
import RapidFileInfoRendererMeta from "./RapidFileInfoRendererMeta";
import type { RapidFileInfoRendererRockConfig } from "./rapid-file-info-renderer-types";
import { renderRock } from "@ruiapp/react-renderer";
import { isArray, isString, merge } from "lodash";
import { RapidFileInfo } from "../rapid-uploader-form-input/rapid-uploader-form-input-types";
import { formatFileSize } from "../../utils/format-utility";
import rapidAppDefinition from "../../rapidAppDefinition";
import { Button, Image, Modal, Space, message } from "antd";
import { useEffect, useState } from "react";
import { EyeOutlined, FilePdfOutlined, FileExcelOutlined, FileWordOutlined, FilePptOutlined, FileImageOutlined } from "@ant-design/icons";
export default {
$type: "rapidFileInfoRenderer",
Renderer(context, props: RapidFileInfoRendererRockConfig) {
const { framework, scope, page } = context;
const { value, showFileSize, fileSizeDecimalPlaces } = props;
const me = framework.getExpressionVars().me;
if (!value) {
return null;
}
if (isArray(value)) {
const arrayRendererProps = merge(props.arrayRendererProps || {}, {
item: {
$type: "rapidFileInfoRenderer",
showFileSize,
fileSizeDecimalPlaces,
showPreview: props.showPreview,
previewModalTitle: props.previewModalTitle,
previewModalWidth: props.previewModalWidth,
useBuiltInPreviewer: props.useBuiltInPreviewer,
previewMode: props.previewMode,
},
itemContainer: {
$type: "box",
},
noSeparator: true,
});
return renderRock({
context,
rockConfig: {
$type: "rapidArrayRenderer",
...arrayRendererProps,
value,
},
});
} else {
return ;
}
},
...RapidFileInfoRendererMeta,
} as Rock;
function RenderFileInfo({
fileInfo,
showFileSize,
fileSizeDecimalPlaces,
props,
me,
}: {
fileInfo: RapidFileInfo;
showFileSize: boolean | undefined;
fileSizeDecimalPlaces: number | undefined;
props?: RapidFileInfoRendererRockConfig;
me?: any;
}) {
const [downloadUrl, setDownloadUrl] = useState(null);
if (fileInfo && !fileInfo.key) {
return (
<>
{fileInfo.name.toString()}
{showFileSize ? ({formatFileSize(fileInfo.size, fileSizeDecimalPlaces)}) : null}
>
);
}
useEffect(() => {
const generateUrl = async () => {
const userId = me?.profile?.id || 0;
const apiBaseUrl = rapidAppDefinition.getApiBaseUrl();
const url = `${apiBaseUrl}/download/file?${fileInfo.id ? `fileId=${fileInfo.id}&` : ``}fileKey=${encodeURIComponent(
fileInfo.key,
)}&fileName=${encodeURIComponent(fileInfo.name)}`;
setDownloadUrl(url);
};
generateUrl();
}, [fileInfo.key, fileInfo.name, me?.profile?.id]);
if (!downloadUrl) {
return null;
}
// Determine file type for icon selection
const fileExt = fileInfo.name.split(".").pop()?.toLowerCase() || "";
const isImage = ["jpg", "jpeg", "png", "gif", "bmp", "webp"].includes(fileExt);
const isPdf = fileExt === "pdf";
const isExcel = ["xls", "xlsx"].includes(fileExt);
const isWord = ["doc", "docx"].includes(fileExt);
const isPpt = ["ppt", "pptx"].includes(fileExt);
// Get appropriate icon
const getIcon = () => {
if (isImage) return ;
if (isPdf) return ;
if (isExcel) return ;
if (isWord) return ;
if (isPpt) return ;
return ;
};
// Determine if preview should be shown based on previewMode
const previewMode = props?.previewMode || "auto";
let canPreview = false;
if (props?.showPreview) {
if (previewMode === "auto") {
canPreview = isImage || isPdf;
} else if (previewMode === "all") {
canPreview = true;
} else {
canPreview = false;
}
}
return (
);
}
interface FileItemWithPreviewProps {
fileInfo: RapidFileInfo;
downloadUrl: string;
showFileSize?: boolean;
fileSizeDecimalPlaces?: number;
canPreview: boolean;
isImage: boolean;
isPdf: boolean;
icon: React.ReactNode;
showPreview?: boolean;
previewModalTitle?: string;
previewModalWidth?: number | string;
useBuiltInPreviewer?: boolean;
previewMode?: "auto" | "all";
}
function FileItemWithPreview(props: FileItemWithPreviewProps) {
const {
fileInfo,
downloadUrl,
showFileSize,
fileSizeDecimalPlaces,
canPreview = true,
isImage,
isPdf,
icon,
previewModalTitle = "文件预览",
previewModalWidth = 1200,
} = props;
const [previewVisible, setPreviewVisible] = useState(false);
const [previewLoading, setPreviewLoading] = useState(false);
const handlePreview = () => {
setPreviewVisible(true);
};
const getPreviewContent = () => {
// const apiBaseUrl = rapidAppDefinition.getApiBaseUrl();
const previewUrl = `${downloadUrl}&inline=true`;
if (isImage) {
return (
);
}
if (isPdf) {
return (
);
}
// For other file types or if built-in previewer is disabled
return (
{icon}
{fileInfo.name}
此文件类型不支持在线预览
);
};
return (
<>
{fileInfo.name.toString()}
{showFileSize ? ({formatFileSize(fileInfo.size, fileSizeDecimalPlaces)}) : null}
{canPreview && (
} onClick={handlePreview}>
)}
setPreviewVisible(false)} footer={null} width={previewModalWidth} destroyOnClose>
{previewLoading && loading...
}
{!previewLoading && getPreviewContent()}
>
);
}