From 3ff83f12b4c4baa454d31e5987e813c8c11960c6 Mon Sep 17 00:00:00 2001 From: loveuer Date: Mon, 14 Oct 2024 22:31:59 +0800 Subject: [PATCH] wip: file preview --- frontend/src/component/file/content.tsx | 14 ++- frontend/src/component/file/list_file.tsx | 100 ++++++++++--------- frontend/src/component/file/upload_files.tsx | 5 +- frontend/src/component/preview/preview.tsx | 20 +++- frontend/src/store/preview.tsx | 27 +++-- internal/s3/get.go | 16 +-- 6 files changed, 115 insertions(+), 67 deletions(-) diff --git a/frontend/src/component/file/content.tsx b/frontend/src/component/file/content.tsx index b30058c..6d208f3 100644 --- a/frontend/src/component/file/content.tsx +++ b/frontend/src/component/file/content.tsx @@ -4,6 +4,7 @@ import {makeStyles} from "@fluentui/react-components"; import {useStoreBucket} from "../../store/bucket"; import {ListFileComponent} from "./list_file"; import {useState} from "react"; +import {PreviewFile} from "../preview/preview"; const useStyles = makeStyles({ content: { @@ -18,14 +19,17 @@ const useStyles = makeStyles({ export function Content() { const styles = useStyles() - const {bucket_active } = useStoreBucket() + const [preview, set_preview] = useState<{ url: string, content_type: string }>({url: '', content_type: ''}) + const {bucket_active} = useStoreBucket() return
- + { - bucket_active ? - : - + preview.url ? : + ( + bucket_active ? + : + ) }
} \ No newline at end of file diff --git a/frontend/src/component/file/list_file.tsx b/frontend/src/component/file/list_file.tsx index 5dce090..57df0d8 100644 --- a/frontend/src/component/file/list_file.tsx +++ b/frontend/src/component/file/list_file.tsx @@ -24,6 +24,7 @@ import {TrimSuffix} from "../../hook/strings"; import {Dial} from "../../api"; import {useToast} from "../../message"; import {CanPreview} from "../../hook/preview"; +import {useStorePreview} from "../../store/preview"; const useStyles = makeStyles({ container: { @@ -87,7 +88,11 @@ const useStyles = makeStyles({ }) -export function ListFileComponent() { +export interface ListFileComponentProps { + set_preview_fn: React.Dispatch> +} + +export function ListFileComponent(props: ListFileComponentProps) { const styles = useStyles(); const {dispatchMessage} = useToast(); @@ -95,6 +100,8 @@ export function ListFileComponent() { const {bucket_active} = useStoreBucket() const {file_active, files_get, file_set, files_list} = useStoreFile() const {prefix, filter, prefix_set} = useStoreFileFilter() + const [preview_content_type, set_preview_content_type] = useState('') + const {preview_get} = useStorePreview() const [ctx_menu, set_ctx_menu] = useState<{ x: number, y: number, @@ -115,7 +122,7 @@ export function ListFileComponent() { useEffect(() => { set_loading(true) files_get(conn_active!, bucket_active!, prefix, filter).then(() => { - // set_loading(false) + set_loading(false) }) }, [conn_active, bucket_active, prefix, filter]); @@ -134,6 +141,7 @@ export function ListFileComponent() { async function handleRightClick(e: React.MouseEvent, item: S3File) { e.preventDefault() await file_set(item.key) + set_preview_content_type(CanPreview(item.name)) const ele = document.querySelector('#list-file-container') let eleX = ele ? ele.clientWidth : 0 let eleY = ele ? ele.clientHeight : 0 @@ -167,7 +175,16 @@ export function ListFileComponent() { } async function handlePreview() { - dispatchMessage('todo', 'warning') + const res = await Dial<{url:string, method: string}>('/api/file/get', { + conn_id: conn_active?.id, + bucket: bucket_active?.name, + key: file_active ?? "", + }) + if (res.status !== 200) { + dispatchMessage('预览失败', 'warning') + return + } + props.set_preview_fn({url: res.data.url, content_type: preview_content_type}) } return
@@ -183,7 +200,7 @@ export function ListFileComponent() { }} icon={}>下载 { await handlePreview() }} @@ -194,47 +211,40 @@ export function ListFileComponent() {
- { - // (!loading) && (files_list.length === 0) ? - //
- //
- // - //
- // - // 没有文件 - // - //
- // : <> - } - { - // (!loading && files_list) ? - // - // {(idx) => { - // return
{ - // await handleClick(files_list[idx]) - // }} - // onContextMenu={async (e) => { - // await handleRightClick(e, files_list[idx]) - // }}> - // : - // }> - // - // {filename(files_list[idx].key)} - // - // - //
- // }} - //
: <> - } - - +
+
+ +
+ + 没有文件 + +
+
+ + {(idx) => { + return
{ + await handleClick(files_list[idx]) + }} + onContextMenu={async (e) => { + await handleRightClick(e, files_list[idx]) + }}> + : + }> + + {filename(files_list[idx].key)} + + +
+ }} +
+
} diff --git a/frontend/src/component/file/upload_files.tsx b/frontend/src/component/file/upload_files.tsx index a8ebbf6..b0d5d02 100644 --- a/frontend/src/component/file/upload_files.tsx +++ b/frontend/src/component/file/upload_files.tsx @@ -12,7 +12,7 @@ import {useToast} from "../../message"; import {Dial} from "../../api"; import {useStoreConnection} from "../../store/connection"; import {useStoreBucket} from "../../store/bucket"; -import {useStoreFile} from "../../store/file"; +import {useStoreFile, useStoreFileFilter} from "../../store/file"; import {MoreHorizontalRegular} from "@fluentui/react-icons"; const useStyle = makeStyles({ @@ -43,7 +43,8 @@ export function UploadFiles(props: UploadFilesProps) { const { conn_active} = useStoreConnection(); const {bucket_active} = useStoreBucket(); - const {prefix, files_get} = useStoreFile() + const {files_get} = useStoreFile() + const {prefix } = useStoreFileFilter() const [selected, set_selected] = useState([]); diff --git a/frontend/src/component/preview/preview.tsx b/frontend/src/component/preview/preview.tsx index f8a75f6..2e43dc5 100644 --- a/frontend/src/component/preview/preview.tsx +++ b/frontend/src/component/preview/preview.tsx @@ -1,3 +1,21 @@ -export function PreviewFile() { +import {CardPreview, makeStyles} from "@fluentui/react-components"; +const useStyle = makeStyles({ + container: { + width: '100%', + height: '100%', + display: 'flex', + flexDirection: 'column', + alignItems: 'center', + justifyContent: 'center', + } +}) +export function PreviewFile(props: {url:string, content_type:string}) { + const styles = useStyle() + return
+ + + +
} \ No newline at end of file diff --git a/frontend/src/store/preview.tsx b/frontend/src/store/preview.tsx index ab7c798..bc77a60 100644 --- a/frontend/src/store/preview.tsx +++ b/frontend/src/store/preview.tsx @@ -1,18 +1,33 @@ import {create} from 'zustand' +import {Dial} from "../api"; import {Bucket, Connection} from "../interfaces/connection"; interface StorePreview { - preview_key: string; preview_url: string; preview_content_type: string; - preview_set: (key: string) => void; + preview_get: (conn:Connection,bucket: Bucket,key: string) => Promise; } export const useStorePreview = create()((set) => ({ - preview_key: '', preview_url: '', preview_content_type: '', - preview_set: async (key: string) => set(state => { - return {preview_key: key} - }), + preview_get: async (conn: Connection, bucket: Bucket,key: string) => { + if (key === '') { + return set(()=>{return {preview_url: ''}}) + } + + let res = await Dial<{url:string,method:string}>('/api/file/get', { + conn_id: conn.id, + bucket: bucket.name, + key: key + }) + + if(res.status!=200) { + return set(()=>{return {preview_url: ''}}) + } + + set(()=>{ + return {preview_url:res.data.url} + }) + }, })) diff --git a/internal/s3/get.go b/internal/s3/get.go index 7b682f1..22bffbc 100644 --- a/internal/s3/get.go +++ b/internal/s3/get.go @@ -12,10 +12,10 @@ import ( ) type ObjectInfo struct { - Bucket string - Key string - ContentType string - Expire int64 + Bucket string `json:"bucket"` + Key string `json:"key"` + ContentType string `json:"content_type"` + Expire int64 `json:"expire"` } func (c *Client) GetObjectInfo(ctx context.Context, bucket string, key string) (*ObjectInfo, error) { @@ -62,9 +62,9 @@ func (presigner *Presigner) GetObject(ctx context.Context, bucketName string, ob } type ObjectEntry struct { - URL string - Method string - Header http.Header + URL string `json:"url"` + Method string `json:"method"` + Header http.Header `json:"header"` } func (c *Client) GetObjectEntry(ctx context.Context, bucket string, key string, lifetimes ...int64) (*ObjectEntry, error) { @@ -92,7 +92,7 @@ func (c *Client) GetObjectEntry(ctx context.Context, bucket string, key string, type ObjectEntity struct { ObjectInfo - Body io.ReadCloser + Body io.ReadCloser `json:"body"` } func (c *Client) GetObject(ctx context.Context, bucket string, key string) (*ObjectEntity, error) {