feat: 首页仪表盘接口对接完成

This commit is contained in:
landaiqing
2024-07-17 00:12:32 +08:00
parent d63b76b639
commit 359ef60128
36 changed files with 2510 additions and 1162 deletions

View File

@@ -1,23 +1,23 @@
# 开发环境配置 # 开发环境配置
VITE_NODE_ENV='development' VITE_NODE_ENV='development'
# 开发环境 # 开发环境
VITE_APP_BASE_API='/api' VITE_APP_BASE_API='/api'
# 页面 title 前缀 # 页面 title 前缀
VITE_APP_TITLE=开发环境 VITE_APP_TITLE=开发环境
# 网络请求公用地址 # 网络请求公用地址
VITE_API_BASE_URL='http://127.0.0.1:3000' VITE_API_BASE_URL='http://127.0.0.1:5050'
#VITE_API_BASE_URL='http://1.95.0.111:4000' #VITE_API_BASE_URL='http://1.95.0.111:4000'
VITE_TITLE_NAME='五味子云存储' VITE_TITLE_NAME='五味子云存储'
# token key # token key
VITE_APP_TOKEN_KEY='schisandra' VITE_APP_TOKEN_KEY='schisandra'
# the upload url # the upload url
VITE_UPLOAD_URL='http://127.0.0.1:3000' VITE_UPLOAD_URL='http://127.0.0.1:3000'
# the websocket url # the websocket url
VITE_WEB_SOCKET_URL='ws://127.0.0.1:3010/wx/socket' VITE_WEB_SOCKET_URL='ws://127.0.0.1:3010/wx/socket'

View File

@@ -1,3 +1,4 @@
node_modules node_modules
.eslintrc.cjs .eslintrc.cjs
dist dist
/src/components/Main/Home/index.tsx

View File

@@ -10,6 +10,7 @@
"preview": "vite preview" "preview": "vite preview"
}, },
"dependencies": { "dependencies": {
"@ant-design/charts": "^2.1.1",
"@ant-design/icons": "^5.3.7", "@ant-design/icons": "^5.3.7",
"@ant-design/pro-components": "^2.7.10", "@ant-design/pro-components": "^2.7.10",
"@ant-design/pro-provider": "^2.14.7", "@ant-design/pro-provider": "^2.14.7",

777
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,17 +1,17 @@
/** @format */ /** @format */
import { BrowserRouter } from "react-router-dom"; import { BrowserRouter } from "react-router-dom";
import GetRouter from "@/router/getRouter.tsx"; import GetRouter from "@/router/getRouter.tsx";
import AuthRoute from "@/router/useAuth.tsx"; import AuthRoute from "@/router/useAuth.tsx";
const App = () => { const App = () => {
return ( return (
<BrowserRouter> <BrowserRouter>
<AuthRoute> <AuthRoute>
<GetRouter /> <GetRouter />
</AuthRoute> </AuthRoute>
</BrowserRouter> </BrowserRouter>
); );
}; };
export default App; export default App;

61
src/api/oss/ali/index.ts Normal file
View File

@@ -0,0 +1,61 @@
/** @format */
import web from "@/utils/axios/web.ts";
/**
* 初始化ali oss
* @param data 用户id
*/
export const initAliOSS = (data: any) => {
return web.request({
url: "/oss/oss/ali/init",
method: "post",
params: {
userId: data,
},
});
};
/**
* 获取文件目录信息
* @param userId 用户id
* @param dirName 目录名称
* @param bucket 桶名称
*/
export const getDirAndFileList = (userId: any, dirName: any, bucket: any) => {
return web.request({
url: "/oss/oss/ali/listDir",
method: "get",
params: {
userId: userId,
dirName: dirName,
bucket: bucket,
},
});
};
/**
* 查询Ali OSS所有桶
* @param userId
*/
export const getAllAliOSsBucket = (userId: any) => {
return web.request({
url: `/oss/oss/ali/seleteBucket`,
method: "post",
params: {
userId: userId,
},
});
};
/**
* 获取所有阿里云oss配置
* @param userId
*/
export const getAllAliOSSConfig = (userId: any) => {
return web.request({
url: `/oss/oss/ali/return_online`,
method: "get",
params: {
userId: userId,
},
});
};

169
src/api/oss/index.ts Normal file
View File

@@ -0,0 +1,169 @@
/** @format */
import web from "@/utils/axios/web.ts";
/**
* 获取用户存储商
* @param data 用户id
*/
export const getAllStorage = (data: any) => {
return web.request({
url: "/oss/oss/user/selectUserOSSType",
method: "get",
params: {
userId: data,
},
});
};
/**
* 获取存储商所有存储桶
* @param data 用户id
* @param type
*/
export const getStorageBuckets = (data: any, type: any) => {
return web.request({
url: "/oss/oss/" + type + "/seleteBucket",
method: "post",
params: {
userId: data,
},
});
};
/**
* 获取存储桶所有文件
* @param userId
* @param type
* @param bucket
* @param dirName
*/
export const getBucketFiles = (userId: any, bucket: any, dirName: any, type: any) => {
return web.request({
url: "/oss/oss/" + type + "/listDir",
method: "get",
params: {
userId: userId,
bucket: bucket,
dirName: dirName,
},
});
};
/**
* 获取存储商所有存储桶个数
* @param userId
*/
export const getStorageAndBuckets = (userId: any) => {
return web.request({
url: "/oss/oss/user/selectUserOSSType",
method: "get",
params: {
userId: userId,
},
});
};
/**
* 获取用户文件热力图
* @param userId
*/
export const getUserFileHeatMap = (userId: any) => {
return web.request({
url: "/oss/oss/user/selectUserFileHeat",
method: "get",
params: {
userId: userId,
},
});
};
/**
* 获取用户文件流量
* @param userId
*/
export const getUserFileFlow = (userId: any) => {
return web.request({
url: "/oss/oss/user/selectFileFlow",
method: "get",
params: {
userId: userId,
},
});
};
/**
* 获取用户文件个数
* @param userId
*/
export const getUserFileCount = (userId: any) => {
return web.request({
url: "/oss/oss/user/selectFileCount",
method: "get",
params: {
userId: userId,
},
});
};
/**
* 获取用户每月上传文件个数
* @param userId
*/
export const getUserUploadFileDiagramPerMonth = (userId: any) => {
return web.request({
url: "/oss/oss/user/selectUploadFileDiagramPerMonth",
method: "get",
params: {
userId: userId,
},
});
};
/**
* 获取用户每月下载文件个数
* @param userId
*/
export const getUserDownloadFileDiagramPerMonth = (userId: any) => {
return web.request({
url: "/oss/oss/user/selectDownloadFileDiagramPerMonth",
method: "get",
params: {
userId: userId,
},
});
};
/**
* 获取用户最近下载文件
* @param userId
*/
export const getUserRecentDownloadFile = (userId: any) => {
return web.request({
url: "/oss/oss/user/selectRecentDownloadFile",
method: "get",
params: {
userId: userId,
},
});
};
/**
* 获取用户最近上传文件
* @param userId
*/
export const getUserRecentUploadFile = (userId: any) => {
return web.request({
url: "/oss/oss/user/selectRecentUploadFile",
method: "get",
params: {
userId: userId,
},
});
};
/**
* 获取用户最近预览文件
* @param userId
*/
export const getUserRecentPreviewFile = (userId: any) => {
return web.request({
url: "/oss/oss/user/selectPreviewFile",
method: "get",
params: {
userId: userId,
},
});
};

View File

@@ -6,7 +6,7 @@ import web from "@/utils/axios/web.ts";
* 初始化minio * 初始化minio
* @param data 用户id * @param data 用户id
*/ */
export const initMinio = (data: any) => { export const initMinioOSS = (data: any) => {
return web.request({ return web.request({
url: "/oss/oss/minio/init", url: "/oss/oss/minio/init",
method: "post", method: "post",
@@ -33,12 +33,25 @@ export const getDirAndFileList = (userId: any, dirName: any, bucket: any) => {
}); });
}; };
/** /**
* 获取用户拥有的厂商 * 查询MinIO所有桶
* @param userId * @param userId
*/ */
export const getBrandsList = (userId: any) => { export const getAllMinioBucket = (userId: any) => {
return web.request({ return web.request({
url: "/oss/oss/minio/userId", url: `/oss/oss/minio/seleteBucket`,
method: "post",
params: {
userId: userId,
},
});
};
/**
* 获取MinIO配置信息
* @param userId
*/
export const getAllMinioConfig = (userId: any) => {
return web.request({
url: `/oss/oss/minio/return_online`,
method: "get", method: "get",
params: { params: {
userId: userId, userId: userId,

View File

@@ -0,0 +1,57 @@
/** @format */
import web from "@/utils/axios/web.ts";
/**
* 初始化qiniu
* @param data 用户id
*/
export const initQiniuOSS = (data: any) => {
return web.request({
url: "/oss/oss/qiniu/init",
method: "post",
params: {
userId: data,
},
});
};
/**
* 获取文件目录信息
* @param userId 用户id
* @param dirName 目录名称
* @param bucket 桶名称
*/
export const getDirAndFileList = (userId: any, dirName: any, bucket: any) => {
return web.request({
url: "/oss/oss/qiniu/listMinioDir",
method: "get",
params: {
userId: userId,
dirName: dirName,
bucket: bucket,
},
});
};
/**
* 查询qiniu所有桶
* @param userId
*/
export const getAllQiniuBucket = (userId: any) => {
return web.request({
url: `/oss/oss/qiniu/seleteBucket`,
method: "post",
params: {
userId: userId,
},
});
};
export const getAllQiniuConfigs = (userId: any) => {
return web.request({
url: `/oss/oss/qiniu/return_online`,
method: "get",
params: {
userId: userId,
},
});
};

View File

@@ -0,0 +1,60 @@
/** @format */
import web from "@/utils/axios/web.ts";
/**
* 初始化Tencent oss
* @param data 用户id
*/
export const initTencentOSS = (data: any) => {
return web.request({
url: "/oss/oss/ali/tencent",
method: "post",
params: {
userId: data,
},
});
};
/**
* 获取文件目录信息
* @param userId 用户id
* @param dirName 目录名称
* @param bucket 桶名称
*/
export const getDirAndFileList = (userId: any, dirName: any, bucket: any) => {
return web.request({
url: "/oss/oss/tencent/listDir",
method: "get",
params: {
userId: userId,
dirName: dirName,
bucket: bucket,
},
});
};
/**
* 查询Tencent OSS所有桶
* @param userId
*/
export const getAllTencentOSsBucket = (userId: any) => {
return web.request({
url: `/oss/oss/tencent/seleteBucket`,
method: "post",
params: {
userId: userId,
},
});
};
/**
* 查询Tencent OSS所有配置
* @param userId
*/
export const getAllTencentOSsConfig = (userId: any) => {
return web.request({
url: `/oss/oss/tencent/return_online`,
method: "get",
params: {
userId: userId,
},
});
};

47
src/api/oss/up/index.ts Normal file
View File

@@ -0,0 +1,47 @@
/** @format */
import web from "@/utils/axios/web.ts";
/**
* 初始化Up oss
* @param data 用户id
*/
export const initUpOSS = (data: any) => {
return web.request({
url: "/oss/oss/up/tencent",
method: "post",
params: {
userId: data,
},
});
};
/**
* 获取文件目录信息
* @param userId 用户id
* @param dirName 目录名称
* @param bucket 桶名称
*/
export const getDirAndFileList = (userId: any, dirName: any, bucket: any) => {
return web.request({
url: "/oss/oss/up/listDir",
method: "get",
params: {
userId: userId,
dirName: dirName,
bucket: bucket,
},
});
};
/**
* 查询Tencent OSS所有桶
* @param userId
*/
export const getAllUpOSsBucket = (userId: any) => {
return web.request({
url: `/oss/oss/up/seleteBucket`,
method: "post",
params: {
userId: userId,
},
});
};

View File

@@ -1,137 +1,150 @@
/** @format */ /** @format */
import web from "@/utils/axios/web.ts"; import web from "@/utils/axios/web.ts";
/** /**
* 第三方登录 * 第三方登录
* @param type * @param type
*/ */
export const oauthLogin = (type: string) => { export const oauthLogin = (type: string) => {
return web.request({ return web.request({
url: "/auth/oauth/render/" + type, url: "/auth/auth/oauth/render/" + type,
method: "get", method: "get",
}); });
}; };
/** /**
* 获取短信验证码 * 获取短信验证码
* @param data * @param data
*/ */
export const getSms = (data: any) => { export const getSms = (data: any) => {
return web.request({ return web.request({
url: "/auth/sms/sendByTemplate/", url: "/auth/sms/sendByTemplate/",
method: "post", method: "post",
headers: { headers: {
"Content-Type": "application/json;charset=UTF-8", "Content-Type": "application/json;charset=UTF-8",
}, },
data: data, data: data,
}); });
}; };
/** /**
* 注册 * 注册
* @param data * @param data
*/ */
export const register = (data: API.PhoneRegisterRequest) => { export const register = (data: API.PhoneRegisterRequest) => {
return web.request({ return web.request({
url: "/auth/auth/user/register", url: "/auth/auth/user/register",
method: "post", method: "post",
data: data, data: data,
}); });
}; };
/** /**
* 登录 * 登录
* @param data * @param data
*/ */
export const login = (data: API.LoginRequest) => { export const login = (data: API.LoginRequest) => {
return web.request({ return web.request({
url: "/auth/auth/user/login", url: "/auth/auth/user/login",
method: "post", method: "post",
data: data, data: data,
}); });
}; };
/** /**
* 手机号登录 * 手机号登录
* @param data * @param data
*/ */
export const loginByPhone = (data: API.LoginByPhoneRequest) => { export const loginByPhone = (data: API.LoginByPhoneRequest) => {
return web.request({ return web.request({
url: "/auth/auth/user/loginByPhone", url: "/auth/auth/user/loginByPhone",
method: "post", method: "post",
data: data, data: data,
}); });
}; };
/** /**
* 找回密码 * 找回密码
* @param data * @param data
*/ */
export const findPassword = (data: API.findPasswordRequest) => { export const findPassword = (data: API.findPasswordRequest) => {
return web.request({ return web.request({
url: "/auth/auth/user/findPassword", url: "/auth/auth/user/findPassword",
method: "post", method: "post",
data: data, data: data,
}); });
}; };
/** /**
* 生成客户端id * 生成客户端id
*/ */
export const createClientId = () => { export const createClientId = () => {
return web.request({ return web.request({
url: "/auth/auth/user/createClientId", url: "/auth/auth/user/createClientId",
method: "get", method: "get",
}); });
}; };
/** /**
* 获取客户端id * 获取客户端id
* @param clientId * @param clientId
*/ */
export const getClientId = (clientId: string) => { export const getClientId = (clientId: string) => {
return web.request({ return web.request({
url: "/auth/auth/user/getClientId", url: "/auth/auth/user/getClientId",
method: "post", method: "post",
data: { data: {
clientId: clientId, clientId: clientId,
}, },
}); });
}; };
/** /**
* 获取客户端token * 获取客户端token
* @param clientId * @param clientId
*/ */
export const getClientToken = (clientId: string) => { export const getClientToken = (clientId: string) => {
return web.request({ return web.request({
url: "/auth/auth/user/getClientToken", url: "/auth/auth/user/getClientToken",
method: "post", method: "post",
params: { params: {
clientId: clientId, clientId: clientId,
}, },
}); });
}; };
/** /**
* 生成微信登录二维码 * 生成微信登录二维码
* @param clientId * @param clientId
*/ */
export const generateQRCode = (clientId: string) => { export const generateQRCode = (clientId: string) => {
return web.request({ return web.request({
url: "/wechat/wx/generateQRCode", url: "/wechat/wx/generateQRCode",
method: "get", method: "get",
params: { params: {
clientId: clientId, clientId: clientId,
}, },
}); });
}; };
/** /**
* 获取用户操蛋权限 * 获取用户菜单权限
* @param userId * @param userId
*/ */
export const getUserMenuPermission = (userId: string): any => { export const getUserMenuPermission = (userId: string): any => {
return web.request({ return web.request({
url: "/auth/permission/selectUserPermission", url: "/auth/auth/permission/selectUserPermission",
method: "get", method: "get",
params: { params: {
userId: userId, userId: userId,
}, },
}); });
}; };
/**
* 获取用户信息
* @param userId
*/
export const getUserInfoApi = (userId: string): any => {
return web.request({
url: "/auth/auth/user/getUserInfo",
method: "get",
params: {
userId: userId,
},
});
};

View File

@@ -0,0 +1 @@
<svg t="1721106120251" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="11406" width="200" height="200"><path d="M860 64H164c-55.2 0-100 44.8-100 100v696c0 55.2 44.8 100 100 100h696c55.2 0 100-44.8 100-100V164c0-55.2-44.8-100-100-100zM709.5 566.4L536.9 764.3c-13.2 15.1-36.6 15.1-49.8 0L314.5 566.4c-15.5-17.8-2.9-45.5 20.7-45.5h119.7V284.5c0-19.9 16.1-36.1 36.1-36.1h42c19.9 0 36.1 16.1 36.1 36.1v236.4h119.7c23.6-0.1 36.2 27.7 20.7 45.5z" fill="#40D786" p-id="11407"></path></svg>

After

Width:  |  Height:  |  Size: 527 B

View File

@@ -0,0 +1 @@
<svg t="1721105828851" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="7265" width="200" height="200"><path d="M758.9376 951.4496H272.6912c-107.264 0-194.2016-86.9376-194.2016-194.2016V271.0016C78.4896 163.7376 165.4272 76.8 272.6912 76.8h486.2464c107.264 0 194.2016 86.9376 194.2016 194.2016v486.2464c0 107.264-86.9376 194.2016-194.2016 194.2016z" fill="#F78748" p-id="7266"></path><path d="M745.1136 444.0576c-14.5408-113.9712-111.6672-200.9088-228.4544-200.9088S302.6944 330.0352 288.2048 444.0576c-75.264 13.1584-131.84 78.9504-131.84 157.0304 0 87.9104 71.5264 159.4368 159.4368 159.4368h58.2656c13.6704 0 24.7296-11.0592 24.7296-24.7296s-11.0592-24.7296-24.7296-24.7296H315.8016c-60.6208 0-109.9776-49.3056-109.9776-109.9776 0-58.0608 45.3632-106.2912 103.2704-109.7216a28.62592 28.62592 0 0 0 26.9312-27.136c4.864-96.2048 84.224-171.5712 180.5824-171.5712s175.7184 75.3664 180.5824 171.6224c0.768 14.592 12.3392 26.2656 26.88 27.0848 57.9584 3.4304 103.3216 51.6608 103.3216 109.7216 0 60.6208-49.3056 109.9776-109.9776 109.9776h-54.9376c-13.6704 0-24.7296 11.0592-24.7296 24.7296s11.0592 24.7296 24.7296 24.7296h54.9376c87.9104 0 159.4368-71.5264 159.4368-159.4368 0.1536-78.1312-56.4736-143.872-131.7376-157.0304z" fill="#F7F8F8" p-id="7267"></path><path d="M532.3776 513.792a24.7296 24.7296 0 0 0-34.4576 0.512l-82.0224 81.8176a24.80128 24.80128 0 0 0-0.0512 35.0208c9.6256 9.6768 25.344 9.6768 35.0208 0.0512l42.24-42.1376v167.0656c0 13.6704 11.0592 24.7296 24.7296 24.7296s24.7296-11.0592 24.7296-24.7296v-164.6592l42.752 40.2432c4.7616 4.5056 10.8544 6.7072 16.9472 6.7072 6.6048 0 13.1584-2.6112 18.0224-7.7824 9.3696-9.9328 8.9088-25.6-1.0752-34.9696l-86.8352-81.8688z" fill="#F7F8F8" p-id="7268"></path></svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@@ -1,16 +1,12 @@
/** @format */ /** @format */
import { Avatar, Button, message } from "antd"; import { Avatar, Button, message, Skeleton } from "antd";
import { import { DrawerForm, ProCard, ProForm, ProFormText } from "@ant-design/pro-components";
DrawerForm, import React, { createContext, useContext, useEffect, useState } from "react";
ProCard,
ProForm,
ProFormText,
} from "@ant-design/pro-components";
import React, { createContext, useContext, useState } from "react";
import { EditOutlined, EllipsisOutlined, SettingOutlined } from "@ant-design/icons";
import bucket from "../../../../assets/icons/bucket.svg";
import styles from "./index.module.less"; import styles from "./index.module.less";
import bucket from "@/assets/icons/bucket.svg";
import { getAllAliOSsBucket } from "@/api/oss/ali";
import { EditOutlined, EllipsisOutlined, ReloadOutlined, SettingOutlined } from "@ant-design/icons";
const DrawerContext = createContext<{ const DrawerContext = createContext<{
drawerVisit: boolean; drawerVisit: boolean;
@@ -26,58 +22,77 @@ const AliDrawer = () => {
}; };
const ProCardComponent = () => { const ProCardComponent = () => {
const { drawerVisit, setDrawerVisit } = useContext(DrawerContext); const { drawerVisit, setDrawerVisit } = useContext(DrawerContext);
const list = [ const [buckets, setBuckets] = useState<any>([]);
"test1", const [loading, setLoading] = useState<boolean>(true);
"test2",
"test3",
"test1",
"test2",
"test3",
"test1",
"test2",
"test3",
"test1",
"test2",
"test3",
"test3",
"test1",
"test2",
"test3",
];
async function getAllBucket() {
getAllAliOSsBucket("2").then((res: any) => {
if (res && res.success) {
setBuckets(res.data);
setLoading(false);
}
});
}
useEffect(() => {
getAllBucket().then();
}, []);
const bucketList = () => { const bucketList = () => {
return ( return (
<ProCard <ProCard
title={"存储桶列表"} title={"阿里云OSS存储桶列表"}
headerBordered headerBordered
extra={ extra={
<Button type="primary" onClick={() => setDrawerVisit(true)}> <>
<Button
</Button> type="default"
shape={"circle"}
style={{ marginRight: 20 }}
onClick={() => {
setLoading(false);
getAllBucket().then();
}}
icon={<ReloadOutlined />}></Button>
<Button type="primary" onClick={() => setDrawerVisit(true)}>
</Button>
</>
}> }>
<div className={styles.div_proCard}> <div className={styles.div_proCard}>
{list.map((item, index) => { <Skeleton loading={loading} paragraph={{ rows: 13 }} active>
return ( {buckets &&
<ProCard Array.from(buckets).map((item: any, index: number) => {
headStyle={{ backgroundColor: "#f0f2f5" }} return (
hoverable <>
bordered <div key={index}>
key={index} <ProCard
title={<b>{item}</b>} headStyle={{ backgroundColor: "#f0f2f5" }}
style={{ hoverable
width: "180px", bordered
borderWidth: "1px", title={<b>{item.name}</b>}
}} style={{
actions={[ width: "180px",
<SettingOutlined key="setting" />, height: 150,
<EditOutlined key="edit" />, borderWidth: "1px",
<EllipsisOutlined key="ellipsis" />, marginLeft: 10,
]}> }}
<Avatar shape={"square"} src={bucket} size={"large"} /> actions={[
<b style={{ marginLeft: 10 }}> size</b> <SettingOutlined key="setting" />,
</ProCard> <EditOutlined key="edit" />,
); <EllipsisOutlined key="ellipsis" />,
})} ]}>
<Avatar
shape={"square"}
src={bucket as any}
size={"large"}
/>
<b style={{ marginLeft: 10 }}>{item.size}</b>
</ProCard>
</div>
</>
);
})}
</Skeleton>
</div> </div>
</ProCard> </ProCard>
); );

View File

@@ -1,11 +1,12 @@
/** @format */ /** @format */
import { Avatar, Button, message } from "antd"; import { Avatar, Button, message, Skeleton } from "antd";
import { DrawerForm, ProCard, ProForm, ProFormText } from "@ant-design/pro-components"; import { DrawerForm, ProCard, ProForm, ProFormText } from "@ant-design/pro-components";
import React, { createContext, useContext, useState } from "react"; import React, { createContext, useContext, useEffect, useState } from "react";
import { EditOutlined, EllipsisOutlined, SettingOutlined } from "@ant-design/icons"; import { EditOutlined, EllipsisOutlined, ReloadOutlined, SettingOutlined } from "@ant-design/icons";
import bucket from "../../../../assets/icons/bucket.svg"; import bucket from "@/assets/icons/bucket.svg";
import styles from "./index.module.less"; import styles from "./index.module.less";
import { getAllMinioBucket } from "@/api/oss/minio";
const DrawerContext = createContext<{ const DrawerContext = createContext<{
drawerVisit: boolean; drawerVisit: boolean;
@@ -21,58 +22,74 @@ const MinioDrawer = () => {
}; };
const ProCardComponent = () => { const ProCardComponent = () => {
const { drawerVisit, setDrawerVisit } = useContext(DrawerContext); const { drawerVisit, setDrawerVisit } = useContext(DrawerContext);
const list = [ const [buckets, setBuckets] = useState<any>([]);
"test1", const [loading, setLoading] = useState<boolean>(true);
"test2",
"test3", async function getAllBucket() {
"test1", getAllMinioBucket("1").then((res: any) => {
"test2", if (res && res.success) {
"test3", setBuckets(res.data);
"test1", setLoading(false);
"test2", }
"test3", });
"test1", }
"test2", useEffect(() => {
"test3", getAllBucket().then();
"test3", }, []);
"test1",
"test2",
"test3",
];
const bucketList = () => { const bucketList = () => {
return ( return (
<ProCard <ProCard
title={"存储桶列表"} title={"MinIO存储桶列表"}
headerBordered headerBordered
extra={ extra={
<Button type="primary" onClick={() => setDrawerVisit(true)}> <>
<Button
</Button> type="default"
shape={"circle"}
style={{ marginRight: 20 }}
onClick={() => {
setLoading(false);
getAllBucket().then();
}}
icon={<ReloadOutlined />}></Button>
<Button type="primary" onClick={() => setDrawerVisit(true)}>
</Button>
</>
}> }>
<div className={styles.div_proCard}> <div className={styles.div_proCard}>
{list.map((item, index) => { <Skeleton loading={loading} paragraph={{ rows: 13 }} active>
return ( {buckets &&
<ProCard Array.from(buckets).map((item: any, index: number) => {
headStyle={{ backgroundColor: "#f0f2f5" }} return (
hoverable <div key={index}>
bordered <ProCard
key={index} headStyle={{ backgroundColor: "#f0f2f5" }}
title={<b>{item}</b>} hoverable
style={{ bordered
width: "180px", title={<b>{item.name}</b>}
borderWidth: "1px", style={{
}} width: "180px",
actions={[ height: "150px",
<SettingOutlined key="setting" />, marginLeft: 10,
<EditOutlined key="edit" />, }}
<EllipsisOutlined key="ellipsis" />, actions={[
]}> <SettingOutlined key="setting" />,
<Avatar shape={"square"} src={bucket} size={"large"} /> <EditOutlined key="edit" />,
<b style={{ marginLeft: 10 }}> size</b> <EllipsisOutlined key="ellipsis" />,
</ProCard> ]}>
); <Avatar
})} shape={"square"}
src={bucket as any}
size={"large"}
/>
<b style={{ marginLeft: 10 }}>{item.size}</b>
</ProCard>
</div>
);
})}
</Skeleton>
</div> </div>
</ProCard> </ProCard>
); );

View File

@@ -1,16 +1,13 @@
/** @format */ /** @format */
import { Avatar, Button, message } from "antd"; import { Avatar, Button, message, Skeleton } from "antd";
import { import { DrawerForm, ProCard, ProForm, ProFormText } from "@ant-design/pro-components";
DrawerForm, import React, { createContext, useContext, useEffect, useState } from "react";
ProCard, import { EditOutlined, EllipsisOutlined, ReloadOutlined, SettingOutlined } from "@ant-design/icons";
ProForm, import bucket from "@/assets/icons/bucket.svg";
ProFormText,
} from "@ant-design/pro-components";
import React, { createContext, useContext, useState } from "react";
import { EditOutlined, EllipsisOutlined, SettingOutlined } from "@ant-design/icons";
import bucket from "../../../../assets/icons/bucket.svg";
import styles from "./index.module.less"; import styles from "./index.module.less";
import { getAllMinioBucket } from "@/api/oss/minio";
import { getAllQiniuBucket } from "@/api/oss/qiniu";
const DrawerContext = createContext<{ const DrawerContext = createContext<{
drawerVisit: boolean; drawerVisit: boolean;
@@ -26,24 +23,20 @@ const QingyunDrawer = () => {
}; };
const ProCardComponent = () => { const ProCardComponent = () => {
const { drawerVisit, setDrawerVisit } = useContext(DrawerContext); const { drawerVisit, setDrawerVisit } = useContext(DrawerContext);
const list = [ const [buckets, setBuckets] = useState<any>([]);
"test1", const [loading, setLoading] = useState<boolean>(true);
"test2",
"test3", async function getAllBucket() {
"test1", getAllQiniuBucket("1").then((res: any) => {
"test2", if (res && res.success) {
"test3", setBuckets(res.data);
"test1", setLoading(false);
"test2", }
"test3", });
"test1", }
"test2", useEffect(() => {
"test3", getAllBucket().then();
"test3", }, []);
"test1",
"test2",
"test3",
];
const bucketList = () => { const bucketList = () => {
return ( return (
@@ -51,33 +44,53 @@ const ProCardComponent = () => {
title={"存储桶列表"} title={"存储桶列表"}
headerBordered headerBordered
extra={ extra={
<Button type="primary" onClick={() => setDrawerVisit(true)}> <>
<Button
</Button> type="default"
shape={"circle"}
style={{ marginRight: 20 }}
onClick={() => {
setLoading(false);
getAllBucket().then();
}}
icon={<ReloadOutlined />}></Button>
<Button type="primary" onClick={() => setDrawerVisit(true)}>
</Button>
</>
}> }>
<div className={styles.div_proCard}> <div className={styles.div_proCard}>
{list.map((item, index) => { <Skeleton loading={loading} paragraph={{ rows: 13 }} active>
return ( {buckets &&
<ProCard Array.from(buckets).map((item: any, index: number) => {
headStyle={{ backgroundColor: "#f0f2f5" }} return (
hoverable <div key={index}>
bordered <ProCard
key={index} headStyle={{ backgroundColor: "#f0f2f5" }}
title={<b>{item}</b>} hoverable
style={{ bordered
width: "180px", title={<b>{item.name}</b>}
borderWidth: "1px", style={{
}} width: "180px",
actions={[ height: "150px",
<SettingOutlined key="setting" />, marginLeft: 10,
<EditOutlined key="edit" />, }}
<EllipsisOutlined key="ellipsis" />, actions={[
]}> <SettingOutlined key="setting" />,
<Avatar shape={"square"} src={bucket} size={"large"} /> <EditOutlined key="edit" />,
<b style={{ marginLeft: 10 }}> size</b> <EllipsisOutlined key="ellipsis" />,
</ProCard> ]}>
); <Avatar
})} shape={"square"}
src={bucket as any}
size={"large"}
/>
<b style={{ marginLeft: 10 }}>{item.size}</b>
</ProCard>
</div>
);
})}
</Skeleton>
</div> </div>
</ProCard> </ProCard>
); );

View File

@@ -1,16 +1,12 @@
/** @format */ /** @format */
import { Avatar, Button, message } from "antd"; import { Avatar, Button, message, Skeleton } from "antd";
import { import { DrawerForm, ProCard, ProForm, ProFormText } from "@ant-design/pro-components";
DrawerForm, import React, { createContext, useContext, useEffect, useState } from "react";
ProCard,
ProForm,
ProFormText,
} from "@ant-design/pro-components";
import React, { createContext, useContext, useState } from "react";
import { EditOutlined, EllipsisOutlined, SettingOutlined } from "@ant-design/icons"; import { EditOutlined, EllipsisOutlined, SettingOutlined } from "@ant-design/icons";
import bucket from "../../../../assets/icons/bucket.svg"; import bucket from "../../../../assets/icons/bucket.svg";
import styles from "./index.module.less"; import styles from "./index.module.less";
import { getAllTencentOSsBucket } from "@/api/oss/tencent";
const DrawerContext = createContext<{ const DrawerContext = createContext<{
drawerVisit: boolean; drawerVisit: boolean;
@@ -26,29 +22,26 @@ const TencentDrawer = () => {
}; };
const ProCardComponent = () => { const ProCardComponent = () => {
const { drawerVisit, setDrawerVisit } = useContext(DrawerContext); const { drawerVisit, setDrawerVisit } = useContext(DrawerContext);
const list = [ const [buckets, setBuckets] = useState<any>([]);
"test1", const [loading, setLoading] = useState<boolean>(true);
"test2",
"test3", async function getAllBucket() {
"test1", getAllTencentOSsBucket("1").then((res: any) => {
"test2", if (res && res.success) {
"test3", setBuckets(res.data);
"test1", setLoading(false);
"test2", }
"test3", });
"test1", }
"test2",
"test3", useEffect(() => {
"test3", getAllBucket().then();
"test1", }, []);
"test2",
"test3",
];
const bucketList = () => { const bucketList = () => {
return ( return (
<ProCard <ProCard
title={"存储桶列表"} title={"腾讯云COS存储桶列表"}
headerBordered headerBordered
extra={ extra={
<Button type="primary" onClick={() => setDrawerVisit(true)}> <Button type="primary" onClick={() => setDrawerVisit(true)}>
@@ -56,28 +49,37 @@ const ProCardComponent = () => {
</Button> </Button>
}> }>
<div className={styles.div_proCard}> <div className={styles.div_proCard}>
{list.map((item, index) => { <Skeleton loading={loading} paragraph={{ rows: 13 }} active>
return ( {buckets &&
<ProCard Array.from(buckets).map((item: any, index: number) => {
headStyle={{ backgroundColor: "#f0f2f5" }} return (
hoverable <div key={index}>
bordered <ProCard
key={index} headStyle={{ backgroundColor: "#f0f2f5" }}
title={<b>{item}</b>} hoverable
style={{ bordered
width: "180px", title={<b>{item.name}</b>}
borderWidth: "1px", style={{
}} width: "180px",
actions={[ height: "150px",
<SettingOutlined key="setting" />, marginLeft: 10,
<EditOutlined key="edit" />, }}
<EllipsisOutlined key="ellipsis" />, actions={[
]}> <SettingOutlined key="setting" />,
<Avatar shape={"square"} src={bucket} size={"large"} /> <EditOutlined key="edit" />,
<b style={{ marginLeft: 10 }}> size</b> <EllipsisOutlined key="ellipsis" />,
</ProCard> ]}>
); <Avatar
})} shape={"square"}
src={bucket as any}
size={"large"}
/>
<b style={{ marginLeft: 10 }}>{item.size}</b>
</ProCard>
</div>
);
})}
</Skeleton>
</div> </div>
</ProCard> </ProCard>
); );

View File

@@ -1,11 +1,12 @@
/** @format */ /** @format */
import { Avatar, Button, message } from "antd"; import { Avatar, Button, message, Skeleton } from "antd";
import { DrawerForm, ProCard, ProForm, ProFormText } from "@ant-design/pro-components"; import { DrawerForm, ProCard, ProForm, ProFormText } from "@ant-design/pro-components";
import React, { createContext, useContext, useState } from "react"; import React, { createContext, useContext, useEffect, useState } from "react";
import { EditOutlined, EllipsisOutlined, SettingOutlined } from "@ant-design/icons"; import { EditOutlined, EllipsisOutlined, ReloadOutlined, SettingOutlined } from "@ant-design/icons";
import bucket from "../../../../assets/icons/bucket.svg"; import bucket from "../../../../assets/icons/bucket.svg";
import styles from "./index.module.less"; import styles from "./index.module.less";
import { getAllQiniuBucket } from "@/api/oss/qiniu";
const DrawerContext = createContext<{ const DrawerContext = createContext<{
drawerVisit: boolean; drawerVisit: boolean;
@@ -21,24 +22,20 @@ const UpDrawer = () => {
}; };
const ProCardComponent = () => { const ProCardComponent = () => {
const { drawerVisit, setDrawerVisit } = useContext(DrawerContext); const { drawerVisit, setDrawerVisit } = useContext(DrawerContext);
const list = [ const [buckets, setBuckets] = useState<any>([]);
"test1", const [loading, setLoading] = useState<boolean>(true);
"test2",
"test3", async function getAllBucket() {
"test1", getAllQiniuBucket("1").then((res: any) => {
"test2", if (res && res.success) {
"test3", setBuckets(res.data);
"test1", setLoading(false);
"test2", }
"test3", });
"test1", }
"test2", useEffect(() => {
"test3", getAllBucket().then();
"test3", }, []);
"test1",
"test2",
"test3",
];
const bucketList = () => { const bucketList = () => {
return ( return (
@@ -46,33 +43,53 @@ const ProCardComponent = () => {
title={"存储桶列表"} title={"存储桶列表"}
headerBordered headerBordered
extra={ extra={
<Button type="primary" onClick={() => setDrawerVisit(true)}> <>
<Button
</Button> type="default"
shape={"circle"}
style={{ marginRight: 20 }}
onClick={() => {
setLoading(false);
getAllBucket().then();
}}
icon={<ReloadOutlined />}></Button>
<Button type="primary" onClick={() => setDrawerVisit(true)}>
</Button>
</>
}> }>
<div className={styles.div_proCard}> <div className={styles.div_proCard}>
{list.map((item, index) => { <Skeleton loading={loading} paragraph={{ rows: 13 }} active>
return ( {buckets &&
<ProCard Array.from(buckets).map((item: any, index: number) => {
headStyle={{ backgroundColor: "#f0f2f5" }} return (
hoverable <div key={index}>
bordered <ProCard
key={index} headStyle={{ backgroundColor: "#f0f2f5" }}
title={<b>{item}</b>} hoverable
style={{ bordered
width: "180px", title={<b>{item.name}</b>}
borderWidth: "1px", style={{
}} width: "180px",
actions={[ height: "150px",
<SettingOutlined key="setting" />, marginLeft: 10,
<EditOutlined key="edit" />, }}
<EllipsisOutlined key="ellipsis" />, actions={[
]}> <SettingOutlined key="setting" />,
<Avatar shape={"square"} src={bucket} size={"large"} /> <EditOutlined key="edit" />,
<b style={{ marginLeft: 10 }}> size</b> <EllipsisOutlined key="ellipsis" />,
</ProCard> ]}>
); <Avatar
})} shape={"square"}
src={bucket as any}
size={"large"}
/>
<b style={{ marginLeft: 10 }}>{item.size}</b>
</ProCard>
</div>
);
})}
</Skeleton>
</div> </div>
</ProCard> </ProCard>
); );

View File

@@ -1,19 +1,12 @@
.div_proCard{ .div_proCard{
height: 62vh; width: 100%;
max-height: 62vh; min-height: 62vh;
gap: 20px;
width: 105%;
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
flex-direction: row; flex-direction: row;
overflow-y:scroll; overflow-y:scroll;
overflow-x: hidden; overflow-x: hidden;
justify-content: space-around; justify-content: flex-start;
} }
.proCard{
height: 75vh;
max-height: 75vh;
width: 105%;
}

View File

@@ -1,6 +1,6 @@
.proCard{ .proCard{
max-width: 30%; max-width: 30%;
min-height: 84vh;
} }
.proCardBucket{ .proCardBucket{
@@ -14,8 +14,6 @@
} }
.div_checkCardArea{ .div_checkCardArea{
height: 68vh;
max-height: 68vh;
overflow-y:scroll; overflow-y:scroll;
overflow-x: hidden; overflow-x: hidden;
} }

View File

@@ -1,45 +1,66 @@
/** @format */ /** @format */
import { FunctionComponent, Suspense } from "react"; import { FunctionComponent, Suspense, useEffect, useState } from "react";
import { CheckCard, ProCard } from "@ant-design/pro-components"; import { CheckCard, ProCard } from "@ant-design/pro-components";
import styles from "./index.module.less"; import styles from "./index.module.less";
import { Outlet, useNavigate } from "react-router-dom"; import { Outlet, useNavigate } from "react-router-dom";
import { Button, Empty } from "antd"; import { Button, Empty, Skeleton } from "antd";
import StorageIcon from "@/constant/stroage-icon.ts"; import StorageIcon from "@/constant/stroage-icon.ts";
import { ReloadOutlined } from "@ant-design/icons"; import { ReloadOutlined } from "@ant-design/icons";
import { getAllStorage } from "@/api/oss";
const Bucket: FunctionComponent = () => { const Bucket: FunctionComponent = () => {
const navigate = useNavigate(); const navigate = useNavigate();
const checkList = ["minio", "ali", "tencent", "huawei", "baidu", "jd"]; const [userStorage, setUserStorage] = useState<any>([]);
const [loading, setLoading] = useState<boolean>(true);
async function getUserStorage() {
getAllStorage("1").then((res: any) => {
if (res && res.success) {
setUserStorage(res.data);
setLoading(false);
}
});
}
useEffect(() => {
getUserStorage().then();
}, []);
return ( return (
<div className={styles.div_proCard}> <div className={styles.div_proCard}>
<ProCard <ProCard
extra={<Button type="primary" shape={"circle"} icon={<ReloadOutlined />}></Button>} extra={
<Button
type="primary"
shape={"circle"}
onClick={() => {
getUserStorage().then();
}}
icon={<ReloadOutlined />}></Button>
}
title="存储商" title="存储商"
headerBordered headerBordered
className={styles.proCard} className={styles.proCard}
boxShadow={true} boxShadow={true}
colSpan={"100%"} colSpan={"100%"}
bordered> bordered>
<CheckCard.Group> <Skeleton loading={loading} paragraph={{ rows: 14 }} active>
<div className={styles.div_checkCardArea}> <CheckCard.Group style={{ width: "100%" }}>
{checkList.map((item) => { {userStorage.map((item: any, index: number) => {
return ( return (
<CheckCard <CheckCard
key={item} key={index}
avatar={StorageIcon[item]} avatar={StorageIcon[item.ossType]}
style={{ width: "100%" }} style={{ width: "100%" }}
title={item} title={item.name}
description="点击查看" description="点击查看"
value={item} value={item.ossType}
onChange={() => { onChange={() => {
navigate(`/main/bucket/${item}`); navigate(`/main/bucket/${item.ossType}`);
}} }}
/> />
); );
})} })}
</div> </CheckCard.Group>
</CheckCard.Group> </Skeleton>
</ProCard> </ProCard>
<ProCard className={styles.proCardBucket} bordered boxShadow> <ProCard className={styles.proCardBucket} bordered boxShadow>
{location.pathname === "/main/bucket" || location.pathname === "/main/bucket/" ? ( {location.pathname === "/main/bucket" || location.pathname === "/main/bucket/" ? (

View File

@@ -1,5 +1,5 @@
/** @format */ /** @format */
import { FunctionComponent, useEffect, useState } from "react"; import React, { FunctionComponent, useEffect, useState } from "react";
import { CheckCard, ProCard } from "@ant-design/pro-components"; import { CheckCard, ProCard } from "@ant-design/pro-components";
import styles from "./index.module.less"; import styles from "./index.module.less";
import { import {
@@ -8,6 +8,7 @@ import {
Card, Card,
Divider, Divider,
Dropdown, Dropdown,
Empty,
Flex, Flex,
FloatButton, FloatButton,
Input, Input,
@@ -16,9 +17,7 @@ import {
Select, Select,
Tooltip, Tooltip,
} from "antd"; } from "antd";
import ali from "@/assets/icons/aliyun.svg";
import bucket from "@/assets/icons/bucket.svg"; import bucket from "@/assets/icons/bucket.svg";
import tencent from "@/assets/icons/tencent.svg";
import { import {
CloudUploadOutlined, CloudUploadOutlined,
CopyOutlined, CopyOutlined,
@@ -29,6 +28,7 @@ import {
LeftOutlined, LeftOutlined,
QrcodeOutlined, QrcodeOutlined,
RedoOutlined, RedoOutlined,
ReloadOutlined,
ScissorOutlined, ScissorOutlined,
SearchOutlined, SearchOutlined,
SnippetsOutlined, SnippetsOutlined,
@@ -39,46 +39,8 @@ import { observer } from "mobx-react";
import FileIcon from "@/constant/file-icon.ts"; import FileIcon from "@/constant/file-icon.ts";
import file_icon from "@/assets/icons/files/file.svg"; import file_icon from "@/assets/icons/files/file.svg";
import FileUpload from "@/components/Main/File/components/FileUpload.tsx"; import FileUpload from "@/components/Main/File/components/FileUpload.tsx";
const dataList: any = [ import { getAllStorage, getBucketFiles, getStorageBuckets } from "@/api/oss";
{ import StorageIcon from "@/constant/stroage-icon.ts";
name: "demo01.java",
isDir: false,
path: "demo0.java",
length: "346",
createTime: "2024-06-26T08:22:13.244Z",
},
{
name: "测试.pdf",
isDir: false,
path: "测试.pdf",
length: "346",
createTime: "2024-06-26T08:22:13.244Z",
},
{
name: "test.jpg",
isDir: false,
path: "test.jpg",
length: "2057535",
createTime: "2024-06-27T02:27:05.472Z",
},
{
name: "test1.png",
isDir: false,
path: "test1.png",
length: "1766511",
createTime: "2024-06-29T10:28:03.224Z",
},
{
name: "schisandra",
isDir: true,
path: "schisandra/",
},
{
name: "测试文件夹",
isDir: true,
path: "测试文件夹/",
},
];
const fileList: any = [ const fileList: any = [
{ {
name: "test1.png", name: "test1.png",
@@ -98,148 +60,197 @@ const File: FunctionComponent = () => {
const store = useStore("file"); const store = useStore("file");
const [files, setFiles] = useState<any>([]); const [files, setFiles] = useState<any>([]);
const [loading, setLoading] = useState<boolean>(true); const [loading, setLoading] = useState<boolean>(true);
const [bucketLoading, setBucketLoading] = useState<boolean>(true);
const [open, setOpen] = useState<boolean>(false); const [open, setOpen] = useState<boolean>(false);
async function getFile() { const [userStorage, setUserStorage] = useState([]);
setFiles(dataList); const [buckets, setBuckets] = useState<any[]>([]);
const [currentStorage, setCurrentStorage] = useState<any>(null);
const [currentBucket, setCurrentBucket] = useState<any>(null);
async function getUserStorage() {
getAllStorage("1").then((res: any) => {
if (res && res.success) {
setUserStorage(res.data);
setLoading(false);
}
});
}
async function getFiles(bucket: any, dirName: any, type: any) {
return getBucketFiles("1", bucket, dirName, type).then((res: any) => {
if (res && res.success) {
setFiles(res.data);
}
});
} }
function getFileExtension(filename: any): string { function getFileExtension(filename: any): string {
const dotIndex = filename.lastIndexOf("."); const dotIndex = filename.lastIndexOf(".");
return dotIndex !== -1 ? filename.slice(dotIndex + 1) : ""; return dotIndex !== -1 ? filename.slice(dotIndex + 1) : "";
} }
async function getBuckets(type: any) {
getStorageBuckets("1", type).then((res: any) => {
if (res && res.success) {
setBuckets(res.data);
setBucketLoading(false);
}
});
}
useEffect(() => { useEffect(() => {
getFile().then(); getUserStorage().then();
setTimeout(() => {
setLoading(false);
}, 2000);
}, []); }, []);
return ( return (
<> <>
<div className={styles.file_main}> <div className={styles.file_main}>
<div className={styles.file_content_left}> <div className={styles.file_content_left}>
<ProCard bordered boxShadow style={{ height: "83vh" }}> <ProCard bordered boxShadow style={{ minHeight: "83vh" }}>
<Select <Flex vertical={false} align={"center"}>
size="large" <Select
status="warning" size="large"
style={{ status="warning"
width: "100%", style={{
display: "flex", width: "100%",
flexDirection: "row", display: "flex",
alignItems: "center", flexDirection: "row",
}} alignItems: "center",
showSearch={true} }}
allowClear={true} showSearch={true}
notFoundContent={"未找到,请先配置存储商"} allowClear={true}
placeholder={"请选择存储商"}> onSelect={(value: any) => {
<Select.Option value="ali"> setCurrentStorage(value);
<Card getBuckets(value).then();
bordered={false} }}
style={{ onClear={() => {
height: 35, setCurrentStorage(null);
display: "flex", setBuckets([]);
alignItems: "center", }}
flexDirection: "row", onChange={(value: any) => {
}} setCurrentStorage(value);
size={"small"}> // getBuckets(value).then();
<Avatar src={ali as any} size={"small"} /> }}
<span style={{ marginLeft: "10px", fontWeight: "bolder" }}> notFoundContent={"未找到,请先配置存储商"}
OSS placeholder={"请选择存储商"}>
</span> {userStorage &&
</Card> userStorage.map((item: any, index: number) => {
</Select.Option> return (
<Select.Option value="腾讯"> <>
<Card <Select.Option value={item.ossType} key={index}>
style={{ <Card
height: 35, key={item}
display: "flex", bordered={false}
alignItems: "center", style={{
flexDirection: "row", height: 35,
}} display: "flex",
bordered={false} alignItems: "center",
size={"small"}> flexDirection: "row",
<Avatar src={tencent as any} size={"small"} />{" "} }}
<span style={{ marginLeft: "10px", fontWeight: "bolder" }}> size={"small"}>
COS <Avatar
</span> src={StorageIcon[item.ossType]}
</Card> size={"small"}
</Select.Option> />
</Select> <span
style={{
marginLeft: "10px",
fontWeight: "bolder",
}}>
{item.name}
</span>
</Card>
</Select.Option>
</>
);
})}
</Select>
<Button
type="default"
shape={"circle"}
style={{ marginLeft: 10 }}
onClick={() => {
if (currentStorage != null) {
getBuckets(currentStorage).then();
}
}}
icon={<ReloadOutlined />}></Button>
</Flex>
<Divider></Divider> <Divider></Divider>
<div> <div>
<CheckCard.Group <CheckCard.Group
defaultValue="A"
size={"small"} size={"small"}
loading={bucketLoading}
onChange={(value: any) => {
store.clearAllFilePath();
store.setFilePath(`/${value}`);
setCurrentBucket(value);
console.log(value);
if (value !== undefined) {
getFiles(value, "", currentStorage).then();
}
}}
style={{ width: "100%" }}> style={{ width: "100%" }}>
<CheckCard {buckets.length === 0 ? (
style={{ width: "100%" }} <>
title="schisandra" <Empty description={"请选择存储商"} />
avatar={bucket as any} </>
description="100Mb" ) : (
value="schisandra" <>
extra={ {buckets &&
<Dropdown Array.from(buckets).map((item: any, index: number) => {
placement="top" return (
menu={{ <>
onClick: ({ domEvent }) => { <div key={index}>
domEvent.stopPropagation(); <CheckCard
message.info("menu click"); style={{ width: "100%" }}
}, title={item.name}
items: [ avatar={bucket as any}
{ description={item.size}
label: "删除", value={item.name}
key: "1", extra={
}, <Dropdown
{ placement="top"
label: "编辑", menu={{
key: "2", onClick: ({
}, domEvent,
], }) => {
}}> domEvent.stopPropagation();
<EllipsisOutlined message.info(
style={{ fontSize: 22, color: "rgba(0,0,0,0.5)" }} "menu click",
onClick={(e) => e.stopPropagation()} );
/> },
</Dropdown> items: [
} {
/> label: "删除",
<CheckCard key: "1",
style={{ width: "100%" }} },
title="schisandra2" {
avatar={bucket as any} label: "查看",
description="100Mb" key: "2",
value="schisandra2" },
extra={ ],
<Dropdown }}>
placement="top" <EllipsisOutlined
menu={{ style={{
onClick: ({ domEvent }) => { fontSize: 22,
domEvent.stopPropagation(); color: "rgba(0,0,0,0.5)",
message.info("menu click"); }}
}, onClick={(e) =>
items: [ e.stopPropagation()
{ }
label: "删除", />
key: "1", </Dropdown>
}, }
{ />
label: "编辑", </div>
key: "2", </>
}, );
], })}
}}> </>
<EllipsisOutlined )}
style={{ fontSize: 22, color: "rgba(0,0,0,0.5)" }}
onClick={(e) => e.stopPropagation()}
/>
</Dropdown>
}
/>
</CheckCard.Group> </CheckCard.Group>
</div> </div>
</ProCard> </ProCard>
</div> </div>
<div className={styles.file_content_right}> <div className={styles.file_content_right}>
<ProCard bordered boxShadow style={{ height: "83vh" }}> <ProCard bordered boxShadow style={{ minHeight: "83vh" }}>
<div className={styles.file_right_header}> <div className={styles.file_right_header}>
<Flex vertical={false} align={"center"} justify={"flex-start"}> <Flex vertical={false} align={"center"} justify={"flex-start"}>
<Flex vertical={false} align={"center"}> <Flex vertical={false} align={"center"}>
@@ -247,8 +258,13 @@ const File: FunctionComponent = () => {
shape="circle" shape="circle"
icon={<LeftOutlined />} icon={<LeftOutlined />}
onClick={() => { onClick={() => {
setFiles(dataList); getFiles(
store.clearFilePath(); currentBucket,
store.getMiddlePath(),
currentStorage,
).then(() => {
store.clearFilePath();
});
}} }}
/> />
<Button <Button
@@ -348,8 +364,13 @@ const File: FunctionComponent = () => {
<div <div
style={{ marginLeft: 10 }} style={{ marginLeft: 10 }}
onDoubleClick={() => { onDoubleClick={() => {
store.setFilePath(file.name); getFiles(
setFiles(fileList); currentBucket,
`${file.name}/`,
currentStorage,
).then(() => {
store.setFilePath(file.name);
});
}}> }}>
<CheckCard <CheckCard
size={"small"} size={"small"}

View File

@@ -31,3 +31,12 @@
margin-top: 30px; margin-top: 30px;
} }
.home_content_icon{
font-size: 20px;
color: lightgrey;
}
.home_content_icon:hover{
color: #ff6700;
}

View File

@@ -1,6 +1,6 @@
/** @format */ /** @format */
import React, { useEffect, useState } from "react"; import React, { memo, useEffect, useState } from "react";
import { Avatar, Card, Flex, Skeleton, Space, Tag } from "antd"; import { Avatar, Card, Flex, message, Skeleton, Space, Tag, Tooltip } from "antd";
import styles from "./index.module.less"; import styles from "./index.module.less";
import ReactECharts from "echarts-for-react"; import ReactECharts from "echarts-for-react";
import { ProCard, ProList } from "@ant-design/pro-components"; import { ProCard, ProList } from "@ant-design/pro-components";
@@ -8,49 +8,132 @@ import storage from "@/assets/icons/storage.svg";
import bucket from "@/assets/icons/bucket.svg"; import bucket from "@/assets/icons/bucket.svg";
import file from "@/assets/icons/file.svg"; import file from "@/assets/icons/file.svg";
import flux from "@/assets/icons/flux.svg"; import flux from "@/assets/icons/flux.svg";
import aliyun from "@/assets/icons/aliyun.svg";
// import * as echarts from "echarts/core";
import CalendarHeatmap from "react-calendar-heatmap"; import CalendarHeatmap from "react-calendar-heatmap";
import "react-calendar-heatmap/dist/styles.css"; import "react-calendar-heatmap/dist/styles.css";
import { Tiny } from "@ant-design/plots"; import upload from "@/assets/icons/upload.svg";
const defaultData = [ import download from "@/assets/icons/download.svg";
{ import {
id: "1", getStorageAndBuckets,
name: "语雀的天空", getUserDownloadFileDiagramPerMonth,
image: aliyun, getUserFileCount,
desc: "我是一条测试的描述", getUserFileFlow,
}, getUserFileHeatMap, getUserRecentDownloadFile, getUserRecentPreviewFile, getUserRecentUploadFile,
{ getUserUploadFileDiagramPerMonth
id: "2", } from "@/api/oss";
name: "Ant Design", import { Link, useNavigate } from "react-router-dom";
image: "https://gw.alipayobjects.com/zos/antfincdn/efFD%24IOql2/weixintupian_20170331104822.jpg", import { EyeOutlined, InfoCircleOutlined } from "@ant-design/icons";
desc: "我是一条测试的描述", import FileIcon from "@/constant/file-icon.ts";
}, import file_icon from "@/assets/icons/files/file.svg";
{
id: "3",
name: "蚂蚁金服体验科技",
image: "https://gw.alipayobjects.com/zos/antfincdn/efFD%24IOql2/weixintupian_20170331104822.jpg",
desc: "我是一条测试的描述",
},
{
id: "4",
name: "TechUI",
image: "https://gw.alipayobjects.com/zos/antfincdn/efFD%24IOql2/weixintupian_20170331104822.jpg",
desc: "我是一条测试的描述",
},
];
type DataItem = (typeof defaultData)[number];
const MainHome: React.FC = () => { const MainHome: React.FC = () => {
const navigate = useNavigate();
const [loading, setLoading] = useState(true); const [loading, setLoading] = useState(true);
const [dataSource, setDataSource] = useState<DataItem[]>(defaultData); const [loadingEChart, setLoadingEChart] = useState(true);
const [loadingHeatmap, setLoadingHeatmap] = useState(true);
const [loadingRecentFile, setLoadingRecentFile] = useState(true);
const [loadingPreviewFile, setLoadingPreviewFile] = useState(true);
const [storageCount, setStorageCount] = useState<any>(null);
const [bucketCount, setBucketCount] = useState<any>(null);
const [fileHeatmap, setFileHeatmap] = useState<any>([]);
const [downloadFlow, setDownloadFlow] = useState<any>(null);
const [uploadFlow, setUploadFlow] = useState<any>(null);
const [uploadFile, setUploadFile] = useState<any>(null);
const [downloadFile, setDownloadFile] = useState<any>(null);
const [monthUpload, setMonthUpload] = useState<any>([]);
const [monthDownload, setMonthDownload] = useState<any>([]);
const [recentUploadFile, setRecentUploadFile] = useState<any>([]);
const [recentDownloadFile, setRecentDownloadFile] = useState<any>([]);
const [recentPreviewFile, setRecentPreviewFile] = useState<any>([]);
// 获取存储同和存储商的个数
async function getStorageAndBucketsCount() {
return getStorageAndBuckets("1").then((res: any) => {
if (res && res.success && res.data) {
const from: any = Array.from(res.data);
setStorageCount(from.length);
const count = from.reduce(
(count: any, item: any) => (count += item.bucketCount),
0,
);
setBucketCount(count);
}
});
}
// 获取文件上传热力图
async function getFileHeatMap() {
return getUserFileHeatMap("1").then((res: any) => {
if (res && res.success && res.data) {
setFileHeatmap(res.data.upload);
}
});
}
// 获取文件上传下载流量
async function getUploadDownloadFlux() {
return getUserFileFlow("1").then((res: any) => {
if (res && res.success && res.data) {
setUploadFlow(res.data.uploadflow);
setDownloadFlow(res.data.downloadflow);
}
});
}
// 获取文件上传下载个数
async function getUploadDownloadCount() {
return getUserFileCount("1").then((res: any) => {
if (res && res.success && res.data) {
setUploadFile(res.data.upload);
setDownloadFile(res.data.download);
}
});
}
// 获取每月用户下载数量
async function getDownloadCountByMonth() {
getUserDownloadFileDiagramPerMonth(1).then((res: any) => {
if (res && res.success && res.data) {
setMonthDownload(res.data);
}
});
}
// 获取每月用户上传数量
async function getUploadCountByMonth() {
getUserUploadFileDiagramPerMonth(1).then((res: any) => {
if (res && res.success && res.data) {
setMonthUpload(res.data);
}
})
}
// 获取用户最近上传文件
async function getRecentUploadFile() {
getUserRecentUploadFile(1).then((res: any) => {
if (res && res.success && res.data) {
setRecentUploadFile(res.data);
}
})
}
//获取用户最近下载文件
async function getRecentDownloadFile() {
getUserRecentDownloadFile(1).then((res: any)=>{
if(res && res.success && res.data){
setRecentDownloadFile(res.data);
}
})
}
//获取用户最近预览文件
async function getRecentPreviewFile() {
getUserRecentPreviewFile(1).then((res:any)=>{
if(res && res.success && res.data){
setRecentPreviewFile(res.data);
}
})
}
const option = { const option = {
tooltip: { tooltip: {
trigger: "axis", trigger: "axis",
}, },
legend: { legend: {
color: ["#F58080", "#47D8BE", "#F9A589"], color: ["#F58080", "#47D8BE", "#F9A589"],
data: ["文件", "流量", "存储桶"], data: ["上传", "下载"],
left: "center", left: "center",
bottom: "bottom", bottom: "bottom",
}, },
@@ -62,15 +145,15 @@ const MainHome: React.FC = () => {
height: "80%", height: "80%",
containLabel: true, containLabel: true,
}, },
xAxis: { xAxis: [{
type: "category", type: "time",
data: [100, 200, 20, 30, 60, 89], // data: month,
axisLine: { axisLine: {
lineStyle: { lineStyle: {
color: "#999", color: "#999",
}, },
}, },
}, }],
yAxis: { yAxis: {
type: "value", type: "value",
@@ -95,9 +178,9 @@ const MainHome: React.FC = () => {
}, },
series: [ series: [
{ {
name: "文件", name: "下载",
type: "line", type: "line",
data: [800, 900, 220, 130, 660, 289], data: monthDownload,
color: "#F58080", color: "#F58080",
lineStyle: { lineStyle: {
width: 5, width: 5,
@@ -134,9 +217,9 @@ const MainHome: React.FC = () => {
smooth: true, smooth: true,
}, },
{ {
name: "流量", name: "上传",
type: "line", type: "line",
data: [123, 568, 111, 222, 123, 56], data: monthUpload,
lineStyle: { lineStyle: {
width: 5, width: 5,
color: { color: {
@@ -171,67 +254,48 @@ const MainHome: React.FC = () => {
}, },
smooth: true, smooth: true,
}, },
{
name: "存储桶",
type: "line",
data: [125, 568, 25, 36, 784, 56],
lineStyle: {
width: 5,
color: {
type: "linear",
colorStops: [
{
offset: 0,
color: "#F6D06F", // 0% 处的颜色
},
{
offset: 0.4,
color: "#F9A589", // 100% 处的颜色
},
{
offset: 1,
color: "#F9A589", // 100% 处的颜色
},
],
globalCoord: false, // 缺省为 false
},
shadowColor: "rgba(249,165,137, 0.5)",
shadowBlur: 10,
shadowOffsetY: 7,
},
itemStyle: {
color: "#F6D06F",
borderWidth: 10,
/*shadowColor: 'rgba(72,216,191, 0.3)',
shadowBlur: 100,*/
borderColor: "#F6D06F",
},
smooth: true,
},
], ],
}; };
const data = [
264, 417, 438, 887, 309, 397, 550, 575, 563, 430, 525, 592, 492, 467, 513, 546,
].map((value, index) => ({ value, index }));
const config = {
data,
padding: 10,
width: 150,
height: 80,
shapeField: "smooth",
xField: "index",
yField: "value",
style: {
fill: "linear-gradient(-90deg, white 0%, orange 100%)",
fillOpacity: 0.6,
},
};
useEffect(() => { useEffect(() => {
setTimeout(() => { getStorageAndBucketsCount().then(()=>{
setLoading(false); getUploadDownloadFlux().then(() => {
}, 2000); getUploadDownloadCount().then(() => {
setLoading(false);
});
});
});
}, []); }, []);
useEffect(() => {
getFileHeatMap().then(()=>{
setLoadingHeatmap(false);
});
}, []);
useEffect(() => {
getDownloadCountByMonth().then(()=>{
getUploadCountByMonth().then(()=>{
setLoadingEChart(false);
});
});
}, []);
useEffect(() => {
getRecentUploadFile().then(()=>{
setLoadingRecentFile(false);
});
getRecentPreviewFile().then(()=>{
setLoadingPreviewFile(false);
});
}, []);
function getFileExtension(filename: any): string {
const dotIndex = filename.lastIndexOf(".");
return dotIndex !== -1 ? filename.slice(dotIndex + 1) : "";
}
return ( return (
<> <>
<div className={styles.home_content_main}> <div className={styles.home_content_main}>
@@ -272,18 +336,19 @@ const MainHome: React.FC = () => {
color: "coral", color: "coral",
fontWeight: "bolder", fontWeight: "bolder",
}}> }}>
{2} {storageCount}
</span> </span>
} }
/ /
</span> </span>
</Flex> </Flex>
</Flex> </Flex>
<Flex <Flex vertical={false} align={"center"} justify={"flex-end"} style={{marginTop: 50}}>
vertical={false} <Tooltip title={"存储商个数,点击查看详情"} color={"#47D8BE"}>
align={"center"} <InfoCircleOutlined onClick={()=>{
style={{ width: "150px", height: "80px" }}> navigate("/main/setting")
<Tiny.Area {...config} /> }} className={styles.home_content_icon}/>
</Tooltip>
</Flex> </Flex>
</Flex> </Flex>
</Skeleton> </Skeleton>
@@ -323,18 +388,19 @@ const MainHome: React.FC = () => {
color: "lightblue", color: "lightblue",
fontWeight: "bolder", fontWeight: "bolder",
}}> }}>
{2} {bucketCount}
</span> </span>
} }
/ /
</span> </span>
</Flex> </Flex>
</Flex> </Flex>
<Flex <Flex vertical={false} align={"center"} justify={"flex-end"} style={{marginTop: 50}}>
vertical={false} <Tooltip title={"存储桶个数,点击查看详情"} color={"#47D8BE"}>
align={"center"} <InfoCircleOutlined onClick={()=>{
style={{ width: "10vw", height: "11vh" }}> navigate("/main/bucket")
<Tiny.Area {...config} /> }} className={styles.home_content_icon}/>
</Tooltip>
</Flex> </Flex>
</Flex> </Flex>
</Skeleton> </Skeleton>
@@ -365,27 +431,40 @@ const MainHome: React.FC = () => {
</span> </span>
</Flex> </Flex>
</Flex>
<Flex vertical={true} style={{ marginLeft: 8, marginTop: 10 }}>
<Flex vertical={false} align={"center"}> <Flex vertical={false} align={"center"}>
<span style={{ fontSize: 15 }}> <Avatar
{ src={upload as any}
<span shape={"square"}
style={{ size={"small"}>
fontSize: 30, {" "}
color: "orange", </Avatar>
fontWeight: "bolder", <span
}}> style={{
{2} fontSize: 18,
</span> color: "orange",
} marginLeft: 5,
/ }}>
{uploadFile}
</span>
</Flex>
<Flex vertical={false} align={"center"}>
<Avatar
src={download as any}
shape={"square"}
size={"small"}>
{" "}
</Avatar>
<span
style={{
fontSize: 18,
color: "green",
marginLeft: 5,
}}>
{downloadFile}
</span> </span>
</Flex> </Flex>
</Flex>
<Flex
vertical={false}
align={"center"}
style={{ width: "10vw", height: "11vh" }}>
<Tiny.Area {...config} />
</Flex> </Flex>
</Flex> </Flex>
</Skeleton> </Skeleton>
@@ -413,30 +492,43 @@ const MainHome: React.FC = () => {
fontWeight: "bolder", fontWeight: "bolder",
}}> }}>
{" "} {" "}
</span>
</Flex>
<Flex vertical={false} align={"center"}>
<span style={{ fontSize: 15 }}>
{
<span
style={{
fontSize: 30,
color: "lightgreen",
fontWeight: "bolder",
}}>
{2}
</span>
}
/M
</span> </span>
</Flex> </Flex>
</Flex> </Flex>
<Flex <Flex vertical={true} style={{ marginLeft: 8, marginTop: 10 }}>
vertical={false} <Flex vertical={false} align={"center"}>
align={"center"} <Avatar
style={{ width: "10vw", height: "11vh" }}> src={upload as any}
<Tiny.Area {...config} /> shape={"square"}
size={"small"}>
{" "}
</Avatar>
<span
style={{
fontSize: 18,
color: "orange",
marginLeft: 5,
}}>
{uploadFlow}
</span>
</Flex>
<Flex vertical={false} align={"center"}>
<Avatar
src={download as any}
shape={"square"}
size={"small"}>
{" "}
</Avatar>
<span
style={{
fontSize: 18,
color: "green",
marginLeft: 5,
}}>
{downloadFlow}
</span>
</Flex>
</Flex> </Flex>
</Flex> </Flex>
</Skeleton> </Skeleton>
@@ -445,7 +537,7 @@ const MainHome: React.FC = () => {
<div style={{ width: "55%" }}> <div style={{ width: "55%" }}>
<ProCard bordered boxShadow> <ProCard bordered boxShadow>
<Skeleton <Skeleton
loading={loading} loading={loadingEChart}
active active
paragraph={{ paragraph={{
rows: 7, rows: 7,
@@ -464,17 +556,37 @@ const MainHome: React.FC = () => {
}} }}
title={"文件上传热力图"}> title={"文件上传热力图"}>
<Skeleton <Skeleton
loading={loading} loading={loadingHeatmap}
active active
paragraph={{ paragraph={{
rows: 3, rows: 3,
}}> }}>
<CalendarHeatmap <CalendarHeatmap
startDate={new Date("2024-01-01")} startDate={new Date(`${new Date().getFullYear()}-01-01`)}
endDate={new Date("2024-12-31")} endDate={new Date(`${new Date().getFullYear()}-12-31`)}
showMonthLabels={true} showMonthLabels={true}
horizontal={true} horizontal={true}
showWeekdayLabels={false} showWeekdayLabels={false}
onClick={(value:any)=>{
if(value!==null) {
message.open({
content: (<>
<Flex vertical={true}>
<Flex vertical={false} align={"center"}>
{value.date}
</Flex>
<Flex vertical={false} align={"center"}>
{value.count}
</Flex>
</Flex>
</>),
type:"success",
duration: 2,
}).then();
}
}}
monthLabels={[ monthLabels={[
"一月", "一月",
"二月", "二月",
@@ -499,101 +611,107 @@ const MainHome: React.FC = () => {
"周六", "周六",
]} ]}
gutterSize={3} gutterSize={3}
values={ values={fileHeatmap}></CalendarHeatmap>
[
{ date: "2024-01-02", count: 12 },
{ date: "2024-05-3", count: 122 },
{ date: "2024-06-30", count: 38 },
] as any
}></CalendarHeatmap>
</Skeleton> </Skeleton>
</ProCard> </ProCard>
</div> </div>
<div className={styles.home_content_list}> <div className={styles.home_content_list}>
<ProCard bordered boxShadow style={{ width: "49%" }}> <ProCard bordered boxShadow style={{ width: "49%" }}>
<Skeleton <Skeleton
loading={loading} loading={loadingRecentFile}
active active
paragraph={{ paragraph={{
rows: 8, rows: 8,
}}> }}>
<ProList<DataItem> <ProList
rowKey="id" rowKey="id"
headerTitle="最近上传文件" headerTitle="最近上传文件"
dataSource={dataSource} dataSource={recentUploadFile}
showActions="hover"
editable={{
onSave: async (key, record, originRow) => {
console.log(key, record, originRow);
return true;
},
}}
onDataSourceChange={setDataSource}
metas={{ metas={{
title: { title: {
dataIndex: "name", dataIndex: "fileName",
}, },
avatar: { avatar: {
dataIndex: "image", render: (text: any,record: any) => {
editable: false, if(record.fileName) {
return (<>
<Avatar
src={
FileIcon[getFileExtension(record.fileName)] || file_icon
}
shape={"square"}
size={"large"}
/>
</>)
}else {
return (<>
<Avatar
src={file_icon as any}
shape={"square"}
size={"large"}
/>
</>)
}
}
}, },
description: { description: {
dataIndex: "desc", dataIndex: "size",
}, valueType: "text"
subTitle: {
render: () => {
return (
<Space size={0}>
<Tag color="blue">Ant Design</Tag>
<Tag color="#5BD8A6">TechUI</Tag>
</Space>
);
},
}, },
content: {
dataIndex: "time"
}
}} }}
/> />
</Skeleton> </Skeleton>
</ProCard> </ProCard>
<ProCard bordered boxShadow style={{ width: "49%" }}> <ProCard bordered boxShadow style={{ width: "49%" }}>
<Skeleton <Skeleton
loading={loading} loading={loadingPreviewFile}
active active
paragraph={{ paragraph={{
rows: 8, rows: 8,
}}> }}>
<ProList<DataItem> <ProList
rowKey="id" rowKey="id"
headerTitle="最近浏览文件" headerTitle="最近浏览文件"
dataSource={dataSource} dataSource={recentPreviewFile}
showActions="hover"
editable={{
onSave: async (key, record, originRow) => {
console.log(key, record, originRow);
return true;
},
}}
onDataSourceChange={setDataSource}
metas={{ metas={{
title: { title: {
dataIndex: "name", dataIndex: "fileName",
}, },
avatar: { avatar: {
dataIndex: "image", render: (text: any,record: any) => {
editable: false, if(record.fileName) {
return (<>
<Avatar
src={
FileIcon[getFileExtension(record.fileName)] || file_icon
}
shape={"square"}
size={"large"}
/>
</>)
}else {
return (<>
<Avatar
src={file_icon as any}
shape={"square"}
size={"large"}
/>
</>)
}
}
}, },
description: { description: {
dataIndex: "desc", dataIndex: "size",
}, valueType: "text",
subTitle: {
render: () => {
return (
<Space size={0}>
<Tag color="blue">Ant Design</Tag>
<Tag color="#5BD8A6">TechUI</Tag>
</Space>
);
},
}, },
content: {
dataIndex: "time"
}
}} }}
/> />
</Skeleton> </Skeleton>
@@ -603,4 +721,4 @@ const MainHome: React.FC = () => {
</> </>
); );
}; };
export default MainHome; export default memo(MainHome);

View File

@@ -3,7 +3,8 @@ import { PlusOutlined } from "@ant-design/icons";
import type { ActionType, ProColumns } from "@ant-design/pro-components"; import type { ActionType, ProColumns } from "@ant-design/pro-components";
import { ProTable, TableDropdown } from "@ant-design/pro-components"; import { ProTable, TableDropdown } from "@ant-design/pro-components";
import { Button, Col, Drawer, Form, Input, Row, Space } from "antd"; import { Button, Col, Drawer, Form, Input, Row, Space } from "antd";
import React, { useRef, useState } from "react"; import React, { useEffect, useRef, useState } from "react";
import { getAllAliOSSConfig } from "@/api/oss/ali";
type AliOssConfigItem = { type AliOssConfigItem = {
id: number; id: number;
@@ -12,21 +13,9 @@ type AliOssConfigItem = {
accessKeyId: string; accessKeyId: string;
accessKeySecret: string; accessKeySecret: string;
createdTime: string; createdTime: string;
updatedTime: string; updateTime: string;
status: string; status: string;
}; };
const data: AliOssConfigItem[] = [
{
id: 1,
userId: 1,
endpoint: "https://oss.aliyuncs.com",
accessKeyId: "LTAI5tG3",
accessKeySecret: "G3",
createdTime: "2024-06-28 10:51:59",
updatedTime: "2024-06-29 10:51:59",
status: "正常",
},
];
const columns: ProColumns<AliOssConfigItem>[] = [ const columns: ProColumns<AliOssConfigItem>[] = [
{ {
@@ -47,6 +36,7 @@ const columns: ProColumns<AliOssConfigItem>[] = [
dataIndex: "endpoint", dataIndex: "endpoint",
tooltip: "endpoint", tooltip: "endpoint",
ellipsis: true, ellipsis: true,
copyable: true,
}, },
{ {
disable: true, disable: true,
@@ -54,6 +44,7 @@ const columns: ProColumns<AliOssConfigItem>[] = [
dataIndex: "accessKeyId", dataIndex: "accessKeyId",
tooltip: "access key id", tooltip: "access key id",
ellipsis: true, ellipsis: true,
copyable: true,
}, },
{ {
disable: true, disable: true,
@@ -61,12 +52,7 @@ const columns: ProColumns<AliOssConfigItem>[] = [
dataIndex: "accessKeySecret", dataIndex: "accessKeySecret",
tooltip: "access key secret", tooltip: "access key secret",
ellipsis: true, ellipsis: true,
}, copyable: true,
{
disable: true,
title: "状态",
dataIndex: "status",
search: true,
}, },
{ {
title: "创建时间", title: "创建时间",
@@ -76,10 +62,16 @@ const columns: ProColumns<AliOssConfigItem>[] = [
}, },
{ {
title: "更新时间", title: "更新时间",
dataIndex: "updatedTime", dataIndex: "updateTime",
valueType: "dateTime", valueType: "dateTime",
sorter: true, sorter: true,
}, },
{
disable: true,
title: "状态",
dataIndex: "status",
search: true,
},
{ {
title: "操作", title: "操作",
valueType: "option", valueType: "option",
@@ -112,13 +104,25 @@ const columns: ProColumns<AliOssConfigItem>[] = [
const AliSettings: React.FC = () => { const AliSettings: React.FC = () => {
const actionRef = useRef<ActionType>(); const actionRef = useRef<ActionType>();
const [open, setOpen] = useState(false); const [open, setOpen] = useState(false);
const [configs, setConfigs] = useState<AliOssConfigItem[]>([]);
async function getAllConfig() {
getAllAliOSSConfig(1).then((res) => {
console.log(res);
if (res && res.success && res.data) {
setConfigs(res.data);
}
});
}
const showDrawer = () => { const showDrawer = () => {
setOpen(true); setOpen(true);
}; };
const onClose = () => { const onClose = () => {
setOpen(false); setOpen(false);
}; };
useEffect(() => {
getAllConfig();
}, []);
const AddAliOssConfigDrawer = () => { const AddAliOssConfigDrawer = () => {
return ( return (
<> <>
@@ -179,7 +183,7 @@ const AliSettings: React.FC = () => {
<div style={{ height: "65vh" }}> <div style={{ height: "65vh" }}>
<ProTable<AliOssConfigItem> <ProTable<AliOssConfigItem>
columns={columns} columns={columns}
dataSource={data} dataSource={configs}
actionRef={actionRef} actionRef={actionRef}
cardBordered={true} cardBordered={true}
editable={{ editable={{

View File

@@ -3,7 +3,8 @@ import { PlusOutlined } from "@ant-design/icons";
import type { ActionType, ProColumns } from "@ant-design/pro-components"; import type { ActionType, ProColumns } from "@ant-design/pro-components";
import { ProTable, TableDropdown } from "@ant-design/pro-components"; import { ProTable, TableDropdown } from "@ant-design/pro-components";
import { Button, Col, Drawer, Form, Input, Row, Space } from "antd"; import { Button, Col, Drawer, Form, Input, Row, Space } from "antd";
import React, { ReactNode, useRef, useState } from "react"; import React, { ReactNode, useEffect, useRef, useState } from "react";
import { getAllMinioConfig } from "@/api/oss/minio";
type MinioOssConfigItem = { type MinioOssConfigItem = {
id: number; id: number;
@@ -12,21 +13,9 @@ type MinioOssConfigItem = {
accessKey: string; accessKey: string;
secretKey: string; secretKey: string;
createdTime: string; createdTime: string;
updatedTime: string; updateTime: string;
status: string; status: string;
}; };
const data: MinioOssConfigItem[] = [
{
id: 1,
userId: 1,
endpoint: "https://oss.aliyuncs.com",
accessKey: "LTAI5tG3",
secretKey: "G3",
createdTime: "2022-01-01",
updatedTime: "2022-01-01",
status: "正常",
},
];
const columns: ProColumns<MinioOssConfigItem>[] = [ const columns: ProColumns<MinioOssConfigItem>[] = [
{ {
@@ -46,6 +35,7 @@ const columns: ProColumns<MinioOssConfigItem>[] = [
title: "服务地址", title: "服务地址",
dataIndex: "endpoint", dataIndex: "endpoint",
tooltip: "endpoint", tooltip: "endpoint",
copyable: true,
ellipsis: true, ellipsis: true,
}, },
{ {
@@ -54,6 +44,7 @@ const columns: ProColumns<MinioOssConfigItem>[] = [
dataIndex: "accessKey", dataIndex: "accessKey",
tooltip: "access key", tooltip: "access key",
ellipsis: true, ellipsis: true,
copyable: true,
}, },
{ {
disable: true, disable: true,
@@ -61,6 +52,7 @@ const columns: ProColumns<MinioOssConfigItem>[] = [
dataIndex: "secretKey", dataIndex: "secretKey",
tooltip: "secret key", tooltip: "secret key",
ellipsis: true, ellipsis: true,
copyable: true,
}, },
{ {
disable: true, disable: true,
@@ -77,7 +69,7 @@ const columns: ProColumns<MinioOssConfigItem>[] = [
}, },
{ {
title: "更新时间", title: "更新时间",
dataIndex: "updatedTime", dataIndex: "updateTime",
valueType: "dateTime", valueType: "dateTime",
sorter: true, sorter: true,
}, },
@@ -113,6 +105,7 @@ const columns: ProColumns<MinioOssConfigItem>[] = [
const MinioSettings: React.FC = () => { const MinioSettings: React.FC = () => {
const actionRef = useRef<ActionType>(); const actionRef = useRef<ActionType>();
const [open, setOpen] = useState(false); const [open, setOpen] = useState(false);
const [configs, setConfigs] = useState<MinioOssConfigItem[]>([]);
const showDrawer = () => { const showDrawer = () => {
setOpen(true); setOpen(true);
}; };
@@ -120,6 +113,18 @@ const MinioSettings: React.FC = () => {
const onClose = () => { const onClose = () => {
setOpen(false); setOpen(false);
}; };
async function getAllConfig() {
getAllMinioConfig(1).then((res: any) => {
if (res && res.success && res.data) {
setConfigs(res.data);
}
});
}
useEffect(() => {
getAllConfig().then();
}, []);
const AddMinioOssConfigDrawer = () => { const AddMinioOssConfigDrawer = () => {
return ( return (
<> <>
@@ -180,7 +185,7 @@ const MinioSettings: React.FC = () => {
<div style={{ height: "65vh" }}> <div style={{ height: "65vh" }}>
<ProTable<MinioOssConfigItem> <ProTable<MinioOssConfigItem>
columns={columns} columns={columns}
dataSource={data} dataSource={configs}
actionRef={actionRef} actionRef={actionRef}
cardBordered={true} cardBordered={true}
editable={{ editable={{

View File

@@ -3,7 +3,8 @@ import { PlusOutlined } from "@ant-design/icons";
import type { ActionType, ProColumns } from "@ant-design/pro-components"; import type { ActionType, ProColumns } from "@ant-design/pro-components";
import { ProTable, TableDropdown } from "@ant-design/pro-components"; import { ProTable, TableDropdown } from "@ant-design/pro-components";
import { Button, Col, Drawer, Form, Input, Row, Space } from "antd"; import { Button, Col, Drawer, Form, Input, Row, Space } from "antd";
import React, { ReactNode, useRef, useState } from "react"; import React, { ReactNode, useEffect, useRef, useState } from "react";
import { getAllQiniuConfigs } from "@/api/oss/qiniu";
type QiniuOssConfigItem = { type QiniuOssConfigItem = {
id: number; id: number;
@@ -12,21 +13,9 @@ type QiniuOssConfigItem = {
accessKey: string; accessKey: string;
secretKey: string; secretKey: string;
createdTime: string; createdTime: string;
updatedTime: string; updateTime: string;
status: string; status: string;
}; };
const data: QiniuOssConfigItem[] = [
{
id: 1,
userId: 1,
bucketName: "https://oss.aliyuncs.com",
accessKey: "LTAI5tG3",
secretKey: "G3",
createdTime: "2022-01-01",
updatedTime: "2022-01-01",
status: "正常",
},
];
const columns: ProColumns<QiniuOssConfigItem>[] = [ const columns: ProColumns<QiniuOssConfigItem>[] = [
{ {
@@ -46,20 +35,23 @@ const columns: ProColumns<QiniuOssConfigItem>[] = [
title: "服务地址", title: "服务地址",
dataIndex: "endpoint", dataIndex: "endpoint",
tooltip: "endpoint", tooltip: "endpoint",
copyable: true,
ellipsis: true, ellipsis: true,
}, },
{ {
disable: true, disable: true,
title: "密钥ID", title: "密钥ID",
dataIndex: "accessKeyId", dataIndex: "accessKey",
tooltip: "access key id", tooltip: "access key id",
copyable: true,
ellipsis: true, ellipsis: true,
}, },
{ {
disable: true, disable: true,
title: "密钥值", title: "密钥值",
dataIndex: "accessKeySecret", dataIndex: "secretKey",
tooltip: "access key secret", tooltip: "access key secret",
copyable: true,
ellipsis: true, ellipsis: true,
}, },
{ {
@@ -77,7 +69,7 @@ const columns: ProColumns<QiniuOssConfigItem>[] = [
}, },
{ {
title: "更新时间", title: "更新时间",
dataIndex: "updatedTime", dataIndex: "updateTime",
valueType: "dateTime", valueType: "dateTime",
sorter: true, sorter: true,
}, },
@@ -113,6 +105,7 @@ const columns: ProColumns<QiniuOssConfigItem>[] = [
const QiniuSettings: React.FC = () => { const QiniuSettings: React.FC = () => {
const actionRef = useRef<ActionType>(); const actionRef = useRef<ActionType>();
const [open, setOpen] = useState(false); const [open, setOpen] = useState(false);
const [config, setConfig] = useState<QiniuOssConfigItem[]>([]);
const showDrawer = () => { const showDrawer = () => {
setOpen(true); setOpen(true);
}; };
@@ -120,6 +113,17 @@ const QiniuSettings: React.FC = () => {
const onClose = () => { const onClose = () => {
setOpen(false); setOpen(false);
}; };
async function getAllCOnfigs() {
getAllQiniuConfigs(1).then((res: any) => {
if (res && res.success && res.data) {
setConfig(res.data);
}
});
}
useEffect(() => {
getAllCOnfigs().then();
}, []);
const AddQiniuOssConfigDrawer = () => { const AddQiniuOssConfigDrawer = () => {
return ( return (
<> <>
@@ -180,7 +184,7 @@ const QiniuSettings: React.FC = () => {
<div style={{ height: "65vh" }}> <div style={{ height: "65vh" }}>
<ProTable<QiniuOssConfigItem> <ProTable<QiniuOssConfigItem>
columns={columns} columns={columns}
dataSource={data} dataSource={config}
actionRef={actionRef} actionRef={actionRef}
cardBordered={true} cardBordered={true}
editable={{ editable={{

View File

@@ -3,30 +3,18 @@ import { PlusOutlined } from "@ant-design/icons";
import type { ActionType, ProColumns } from "@ant-design/pro-components"; import type { ActionType, ProColumns } from "@ant-design/pro-components";
import { ProTable, TableDropdown } from "@ant-design/pro-components"; import { ProTable, TableDropdown } from "@ant-design/pro-components";
import { Button, Col, Drawer, Form, Input, Row, Space } from "antd"; import { Button, Col, Drawer, Form, Input, Row, Space } from "antd";
import React, { ReactNode, useRef, useState } from "react"; import React, { ReactNode, useEffect, useRef, useState } from "react";
import { getAllTencentOSsConfig } from "@/api/oss/tencent";
type TencentOssConfigItem = { type TencentOssConfigItem = {
id: number; id: number;
userId: number; userId: number;
bucketName: string;
secretId: string; secretId: string;
secretKey: string; secretKey: string;
createdTime: string; createdTime: string;
updatedTime: string; updateTime: string;
status: string; status: string;
}; };
const data: TencentOssConfigItem[] = [
{
id: 1,
userId: 1,
bucketName: "https://oss.aliyuncs.com",
secretId: "LTAI5tG3",
secretKey: "G3",
createdTime: "2022-01-01",
updatedTime: "2022-01-01",
status: "正常",
},
];
const columns: ProColumns<TencentOssConfigItem>[] = [ const columns: ProColumns<TencentOssConfigItem>[] = [
{ {
@@ -41,17 +29,11 @@ const columns: ProColumns<TencentOssConfigItem>[] = [
ellipsis: true, ellipsis: true,
tooltip: "Id", tooltip: "Id",
}, },
{
disable: true,
title: "存储桶",
dataIndex: "bucketName",
tooltip: "bucketName",
ellipsis: true,
},
{ {
disable: true, disable: true,
title: "密钥ID", title: "密钥ID",
dataIndex: "secretId", dataIndex: "secretId",
copyable: true,
tooltip: "secret Id", tooltip: "secret Id",
ellipsis: true, ellipsis: true,
}, },
@@ -60,6 +42,7 @@ const columns: ProColumns<TencentOssConfigItem>[] = [
title: "密钥值", title: "密钥值",
dataIndex: "secretKey", dataIndex: "secretKey",
tooltip: "secret Key", tooltip: "secret Key",
copyable: true,
ellipsis: true, ellipsis: true,
}, },
{ {
@@ -77,7 +60,7 @@ const columns: ProColumns<TencentOssConfigItem>[] = [
}, },
{ {
title: "更新时间", title: "更新时间",
dataIndex: "updatedTime", dataIndex: "updateTime",
valueType: "dateTime", valueType: "dateTime",
sorter: true, sorter: true,
}, },
@@ -113,6 +96,7 @@ const columns: ProColumns<TencentOssConfigItem>[] = [
const TencentSettings: React.FC = () => { const TencentSettings: React.FC = () => {
const actionRef = useRef<ActionType>(); const actionRef = useRef<ActionType>();
const [open, setOpen] = useState(false); const [open, setOpen] = useState(false);
const [configs, setConfigs] = useState<TencentOssConfigItem[]>([]);
const showDrawer = () => { const showDrawer = () => {
setOpen(true); setOpen(true);
}; };
@@ -120,6 +104,17 @@ const TencentSettings: React.FC = () => {
const onClose = () => { const onClose = () => {
setOpen(false); setOpen(false);
}; };
async function getAllConfigs() {
getAllTencentOSsConfig(5).then((res: any) => {
if (res && res.success && res.data) {
setConfigs(res.data);
}
});
}
useEffect(() => {
getAllConfigs().then();
}, []);
const AddTencentOssConfigDrawer = () => { const AddTencentOssConfigDrawer = () => {
return ( return (
<> <>
@@ -170,7 +165,7 @@ const TencentSettings: React.FC = () => {
<div style={{ height: "65vh" }}> <div style={{ height: "65vh" }}>
<ProTable<TencentOssConfigItem> <ProTable<TencentOssConfigItem>
columns={columns} columns={columns}
dataSource={data} dataSource={configs}
actionRef={actionRef} actionRef={actionRef}
cardBordered={true} cardBordered={true}
editable={{ editable={{

View File

@@ -8,53 +8,53 @@ const selectOptions = [
name: "腾讯云COS", name: "腾讯云COS",
value: "tencent", value: "tencent",
}, },
{ // {
name: "华为云OBS", // name: "华为云OBS",
value: "huawei", // value: "huawei",
}, // },
{ // {
name: "百度云BOS", // name: "百度云BOS",
value: "baidu", // value: "baidu",
}, // },
{ {
name: "MinIO", name: "MinIO",
value: "minio", value: "minio",
}, },
{ // {
name: "京东云OSS", // name: "京东云OSS",
value: "jd", // value: "jd",
}, // },
{ // {
name: "亚马逊S3", // name: "亚马逊S3",
value: "aws", // value: "aws",
}, // },
{ // {
name: "网易数帆NOS", // name: "网易数帆NOS",
value: "wangyi", // value: "wangyi",
}, // },
{ {
name: "七牛云Kodo", name: "七牛云Kodo",
value: "qiniu", value: "qiniu",
}, },
{ // {
name: "又拍云USS", // name: "又拍云USS",
value: "up", // value: "up",
}, // },
{ // {
name: "平安云OSS", // name: "平安云OSS",
value: "pinan", // value: "pinan",
}, // },
{ // {
name: "青云QingCloud", // name: "青云QingCloud",
value: "qingyun", // value: "qingyun",
}, // },
{ // {
name: "UCloud US3", // name: "UCloud US3",
value: "ucloud", // value: "ucloud",
}, // },
{ // {
name: "金山云OBS", // name: "金山云OBS",
value: "jinshan", // value: "jinshan",
}, // },
]; ];
export default selectOptions; export default selectOptions;

View File

@@ -29,6 +29,15 @@ const ShareAdd: React.FunctionComponent = () => {
enable: true, enable: true,
items: ["ai", "Bold", "Italic", "Underline", "Strike", "code", "comment"], items: ["ai", "Bold", "Italic", "Underline", "Strike", "code", "comment"],
}, },
ai: {
models: {
wenxin: {
access_token: "****",
protocol: "ws",
version: "v3.5",
},
},
},
onChange: async (value: any) => { onChange: async (value: any) => {
fromRef.current.setFieldsValue({ fromRef.current.setFieldsValue({
content: value.getHtml(), content: value.getHtml(),

View File

@@ -128,7 +128,7 @@ export default () => {
vertical={false} vertical={false}
align={"center"} align={"center"}
justify={"space-between"} justify={"space-between"}
style={{ width: "25%" }}> style={{ width: "300px" }}>
<Flex vertical={false} align={"center"}> <Flex vertical={false} align={"center"}>
<Avatar <Avatar
src={logo as any} src={logo as any}

View File

@@ -13,9 +13,6 @@ import Meta from "antd/es/card/Meta";
const MainShare: FunctionComponent = () => { const MainShare: FunctionComponent = () => {
const navigate = useNavigate(); const navigate = useNavigate();
const [open, setOpen] = useState(false); const [open, setOpen] = useState(false);
// const showDrawer = () => {
// setOpen(true);
// };
const onClose = () => { const onClose = () => {
setOpen(false); setOpen(false);

View File

@@ -1,125 +1,163 @@
/** @format */ /** @format */
import { FunctionComponent, useEffect, useState } from "react"; import { FunctionComponent, useEffect, useState } from "react";
import { Avatar, Card, Empty, List, Skeleton } from "antd"; import { Avatar, Card, Empty, Flex, List, Skeleton } from "antd";
import { import {
AntDesignOutlined, AntDesignOutlined,
BankOutlined, BankOutlined,
BulbOutlined, BulbOutlined,
EnvironmentOutlined, EnvironmentOutlined,
} from "@ant-design/icons"; } from "@ant-design/icons";
import styles from "./index.module.less"; import styles from "./index.module.less";
import { ProCard } from "@ant-design/pro-components"; import { ProCard } from "@ant-design/pro-components";
import Meta from "antd/es/card/Meta"; import Meta from "antd/es/card/Meta";
import gitee from "@/assets/icons/gitee.svg"; import gitee from "@/assets/icons/gitee.svg";
import { Link } from "react-router-dom"; import { Link, useNavigate } from "react-router-dom";
import { getAllStorage } from "@/api/oss";
const UserInfo: FunctionComponent = () => { import StorageIcon from "@/constant/stroage-icon.ts";
const [loading, setLoading] = useState(true); import { getUserInfoApi } from "@/api/user";
const data = [
{ const UserInfo: FunctionComponent = () => {
title: "Ant Design Title 1", const navigate = useNavigate();
}, const [loading, setLoading] = useState(true);
{ const [userStorage, setUserStorage] = useState([]);
title: "Ant Design Title 2", const [userInfo, setUserInfo] = useState<any>({} as any);
}, const data = [
{ {
title: "Ant Design Title 3", title: "Ant Design Title 1",
}, },
{ {
title: "Ant Design Title 4", title: "Ant Design Title 2",
}, },
]; {
useEffect(() => { title: "Ant Design Title 3",
setTimeout(() => { },
setLoading(false); {
}, 2000); title: "Ant Design Title 4",
}, []); },
return ( ];
<> async function getUserStorage() {
<div className={styles.user_info_header}> const res = await getAllStorage("1");
<div className={styles.user_info_header_avatar}> if (res.success) {
<Avatar setUserStorage(res.data);
size={{ xs: 24, sm: 32, md: 40, lg: 64, xl: 80, xxl: 100 }} setLoading(false);
icon={<AntDesignOutlined />} }
/> }
<span className={styles.user_info_header_name}></span> const getUserInfo = async () => {
<div className={styles.user_info_header_desc}> const res = await getUserInfoApi("9");
<div> if (res.success) {
<BulbOutlined /> setUserInfo(res.data);
</div> }
<div> };
<EnvironmentOutlined /> useEffect(() => {
</div> getUserInfo().then();
<div> getUserStorage().then();
<BankOutlined /> }, []);
</div> return (
</div> <>
</div> <div className={styles.user_info_header}>
</div> <div className={styles.user_info_header_avatar}>
<div className={styles.user_info_center_content}> <Avatar
<ProCard size={{ xs: 24, sm: 32, md: 40, lg: 64, xl: 80, xxl: 100 }}
bordered icon={<AntDesignOutlined />}
style={{ maxWidth: "64%" }} />
title="我的存储商" <span className={styles.user_info_header_name}></span>
boxShadow <div className={styles.user_info_header_desc}>
extra={<Link to={"#"}></Link>}> <div>
<Skeleton loading={loading} active> <BulbOutlined />
<Card style={{ width: 300, marginTop: 16 }} hoverable={true}> </div>
<Meta <div>
avatar={<Avatar src={gitee} />} <EnvironmentOutlined />
title="Card title" </div>
description="This is the description" <div>
/> <BankOutlined />
</Card> </div>
</Skeleton> </div>
</ProCard> </div>
</div>
<ProCard bordered style={{ maxWidth: "34%" }} title="我的存储桶" boxShadow> <div className={styles.user_info_center_content}>
<Skeleton loading={loading} active> <ProCard
<Card style={{ width: 300, marginTop: 16 }} hoverable={true}> bordered
<Meta style={{ maxWidth: "64%" }}
avatar={ title="我的存储商"
<Avatar src="https://api.dicebear.com/7.x/miniavs/svg?seed=1" /> boxShadow
} extra={<Link to={"/main/setting"}></Link>}>
title="Card title" <Flex vertical={false} align={"center"} justify={"space-between"} wrap={true}>
description="This is the description" <Skeleton loading={loading} active>
/> {userStorage.map((item: any, index: number) => {
</Card> return (
</Skeleton> <>
</ProCard> <Card
</div> key={index}
<div className={styles.user_info_bottom_content}> onClick={() => {
<ProCard navigate(`/main/setting/${item.ossType}`);
bordered }}
style={{ maxWidth: "64%" }} style={{ width: 350, marginTop: 16, marginLeft: 10 }}
title="最近动态" hoverable={true}>
boxShadow <Meta
extra={<Link to={"#"}></Link>}> avatar={<Avatar src={StorageIcon[item.ossType]} />}
<Skeleton loading={loading} active avatar> title={item.name}
<List description={
itemLayout="horizontal" <>
dataSource={data} <span> {item.configCount}</span>
renderItem={(item, index) => ( <span style={{ marginLeft: 10 }}>
<List.Item> {item.bucketCount}
<List.Item.Meta </span>
avatar={ </>
<Avatar }></Meta>
src={`https://api.dicebear.com/7.x/miniavs/svg?seed=${index}`} </Card>
/> </>
} );
title={<a href="https://ant.design">{item.title}</a>} })}
description="Ant Design, a design language for background applications, is refined by Ant UED Team" </Skeleton>
/> </Flex>
</List.Item> </ProCard>
)}
/> <ProCard bordered style={{ maxWidth: "34%" }} title="我的存储桶" boxShadow>
</Skeleton> <Skeleton loading={loading} active>
</ProCard> <Card style={{ width: 300, marginTop: 16 }} hoverable={true}>
<ProCard bordered style={{ maxWidth: "34%" }} title="站内通知" boxShadow> <Meta
<Empty image={Empty.PRESENTED_IMAGE_SIMPLE}></Empty> avatar={
</ProCard> <Avatar src="https://api.dicebear.com/7.x/miniavs/svg?seed=1" />
</div> }
</> title="Card title"
); description="This is the description"
}; />
export default UserInfo; </Card>
</Skeleton>
</ProCard>
</div>
<div className={styles.user_info_bottom_content}>
<ProCard
bordered
style={{ maxWidth: "64%" }}
title="最近动态"
boxShadow
extra={<Link to={"#"}></Link>}>
<Skeleton loading={loading} active avatar>
<List
itemLayout="horizontal"
dataSource={data}
renderItem={(item, index) => (
<List.Item>
<List.Item.Meta
avatar={
<Avatar
src={`https://api.dicebear.com/7.x/miniavs/svg?seed=${index}`}
/>
}
title={<a href="https://ant.design">{item.title}</a>}
description="Ant Design, a design language for background applications, is refined by Ant UED Team"
/>
</List.Item>
)}
/>
</Skeleton>
</ProCard>
<ProCard bordered style={{ maxWidth: "34%" }} title="站内通知" boxShadow>
<Empty image={Empty.PRESENTED_IMAGE_SIMPLE}></Empty>
</ProCard>
</div>
</>
);
};
export default UserInfo;

View File

@@ -5,7 +5,7 @@ import { isHydrated, makePersistable } from "mobx-persist-store";
import { handleLocalforage } from "@/utils/localforage"; import { handleLocalforage } from "@/utils/localforage";
export class useFileStore { export class useFileStore {
filePath: [any] = ["/root"]; filePath: [any] = [];
constructor() { constructor() {
makeObservable(this, { makeObservable(this, {
@@ -14,6 +14,8 @@ export class useFileStore {
getFilePath: action, getFilePath: action,
clearFilePath: action, clearFilePath: action,
getFilePathSecondLast: action, getFilePathSecondLast: action,
getMiddlePath: action,
clearAllFilePath: action,
isHydrated: action, isHydrated: action,
}); });
makePersistable( makePersistable(
@@ -54,10 +56,21 @@ export class useFileStore {
} }
this.filePath.pop(); this.filePath.pop();
} }
// 清空所有文件路径
clearAllFilePath() {
this.filePath.splice(0);
}
// 获取文件路径倒数第二个 // 获取文件路径倒数第二个
getFilePathSecondLast() { getFilePathSecondLast() {
return this.filePath.slice(0, -1).pop(); return this.filePath.slice(0, -1).pop();
} }
// 获取文件路径中间路径
getMiddlePath() {
if (this.filePath.length <= 2) {
return " ";
}
return this.filePath.slice(1, this.filePath.length - 1).join("/");
}
isHydrated() { isHydrated() {
return isHydrated(this); return isHydrated(this);

View File

@@ -6,7 +6,13 @@ import {
LogoutOutlined, LogoutOutlined,
QuestionCircleFilled, QuestionCircleFilled,
} from "@ant-design/icons"; } from "@ant-design/icons";
import { DefaultFooter, PageContainer, ProCard, ProLayout } from "@ant-design/pro-components"; import {
DefaultFooter,
PageContainer,
ProCard,
ProLayout,
SettingDrawer,
} from "@ant-design/pro-components";
import { Link, Outlet, useLocation } from "react-router-dom"; import { Link, Outlet, useLocation } from "react-router-dom";
import logo from "@/assets/images/logo.png"; import logo from "@/assets/images/logo.png";
import { Suspense } from "react"; import { Suspense } from "react";